fix(sandbox-controller): emit canonical SANDBOX_* env vars for MCP plugin (Refs #1986)
TBD-P4 B4 — env-var name drift between the sandbox-controller and the
MCP plugin silently degraded every MCP tool family to "not configured"
at runtime. The controller emitted bare `ORG_ID` and `SOVEREIGN_FQDN`
on every rendered MCP Deployment while the MCP binary
(products/sandbox/mcp-server/internal/tools/env.go) reads the
namespaced canonical `SANDBOX_ORG_ID` / `SANDBOX_SOVEREIGN_FQDN`. Per
agent a99ea3aa's investigation, six additional env-var families the
MCP requires were never wired at all.
Surgical alignment across renderer + chart + controller wiring:
1. core/controllers/sandbox/internal/gitops/manifests.go — MCP
Deployment template renamed the bare names AND grew env entries
for the canonical set the MCP plugin reads:
Rename (MCP Deployment only; pty-server StatefulSet keeps the bare
names since they are inherited into the user's agent shell — that
is a distinct contract):
ORG_ID -> SANDBOX_ORG_ID (tool family: all)
SOVEREIGN_FQDN -> SANDBOX_SOVEREIGN_FQDN (tool family: all)
Added (the MCP plugin was reading them; controller wasn't emitting):
SANDBOX_ID -> identifies the Sandbox CR
SANDBOX_NAMESPACE -> rendered ns sandbox-<owner-uid>
SANDBOX_TENANT_ID -> scopes marketplace/byod handler
SANDBOX_GITEA_BASE_URL -> sandbox.deploy / gitea tool family
SANDBOX_GITEA_TOKEN (secret) -> ditto, via secretKeyRef optional
SANDBOX_DOMAIN_API_URL -> marketplace tool family
SANDBOX_MARKETPLACE_API_URL -> marketplace tool family
SANDBOX_STORAGE_S3_ENDPOINT -> sandbox.storage tool family
SANDBOX_STORAGE_S3_REGION -> ditto
SANDBOX_STORAGE_S3_USE_TLS -> ditto
SANDBOX_STORAGE_S3_ACCESS_KEY -> ditto, via secretKeyRef optional
SANDBOX_STORAGE_S3_SECRET_KEY -> ditto, via secretKeyRef optional
KEYCLOAK_ADMIN_URL -> sandbox.auth tool family
KEYCLOAK_PARENT_REALM -> ditto
KEYCLOAK_ADMIN_TOKEN (secret) -> ditto, via secretKeyRef optional
2. platform/sandbox/chart — bp-sandbox HR surfaces the new wiring as
chart-level values (mcp.giteaBaseURL, mcp.domainAPIURL,
mcp.storage.*, mcp.keycloak.*) defaulting to the in-cluster Service
DNS of a stock Sovereign install. Per-Sovereign overlays may
override any value. Secrets are NEVER written from this chart —
name+key references only with `optional: true` so a fresh-prov
Sovereign with a credential source in flight does NOT crash the
per-Sandbox MCP Pod; the affected tool family surfaces a clean
"not configured" error at call time (matches the MCP plugin's
existing per-tool guard pattern).
3. Chart.yaml + bootstrap-kit pin (19a-bp-sandbox.yaml) bumped to
0.2.0 so the per-Sovereign overlay picks up the new env surface
on the next reconcile.
4. sandbox_controller_test.go — extended deployment-mcp.yaml assertion
block to assert the canonical SANDBOX_* env-var set + value
plumbing AND added a negative assertion that the bare `ORG_ID` /
`SOVEREIGN_FQDN` names MUST NOT appear on the MCP Deployment
(they remain on the pty-server StatefulSet, distinct contract).
Regression test against future re-introduction of the drift.
Validation:
- go test ./sandbox/... — all green (controller / gitops / idlescaler
/ newapi / sandboxapi).
- helm template platform/sandbox/chart --set enabled=true ... — clean
render, 16 SANDBOX_MCP_* env vars emitted on the controller
Deployment.
Hard rules honoured:
- READ-ONLY against existing cluster (no kubectl writes).
- No Secret writes — name+key references only, all `optional: true`.
- emrah.baysal mailbox + Stalwart admin untouched.
- Principle #12 fresh clone validation.
Refs #1986
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6fc50b2719
commit
88453dc4c2
@ -68,7 +68,7 @@ spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: sandbox
|
||||
version: 0.1.0
|
||||
version: 0.2.0
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bp-sandbox
|
||||
|
||||
@ -98,6 +98,28 @@ func main() {
|
||||
primaryRegion := envOr("SOVEREIGN_PRIMARY_REGION", "")
|
||||
replicaRegion := envOr("SOVEREIGN_REPLICA_REGION", "")
|
||||
|
||||
// TBD-P4 B4 — canonical SANDBOX_* env wiring for the MCP plugin
|
||||
// (products/sandbox/mcp-server/internal/tools/env.go). All have
|
||||
// in-cluster defaults; per-Sovereign overlays may override via
|
||||
// bp-sandbox HR values. Empty leaves the MCP's per-tool guard to
|
||||
// surface "not configured" at call time rather than crashing the
|
||||
// controller at startup.
|
||||
mcpGiteaBaseURL := envOr("SANDBOX_MCP_GITEA_BASE_URL", giteaURL)
|
||||
mcpGiteaTokenSecretName := envOr("SANDBOX_MCP_GITEA_TOKEN_SECRET_NAME", "catalyst-gitea-token")
|
||||
mcpGiteaTokenSecretKey := envOr("SANDBOX_MCP_GITEA_TOKEN_SECRET_KEY", "token")
|
||||
mcpDomainAPIURL := envOr("SANDBOX_MCP_DOMAIN_API_URL", "http://domain.sme.svc.cluster.local:8086")
|
||||
mcpMarketplaceAPIURL := envOr("SANDBOX_MCP_MARKETPLACE_API_URL", "http://marketplace-api.marketplace.svc.cluster.local:8082")
|
||||
mcpStorageS3Endpoint := envOr("SANDBOX_MCP_STORAGE_S3_ENDPOINT", "http://seaweedfs.storage.svc.cluster.local:8333")
|
||||
mcpStorageS3Region := envOr("SANDBOX_MCP_STORAGE_S3_REGION", "us-east-1")
|
||||
mcpStorageS3UseTLS := envOr("SANDBOX_MCP_STORAGE_S3_USE_TLS", "false")
|
||||
mcpStorageS3CredsSecret := envOr("SANDBOX_MCP_STORAGE_S3_CREDS_SECRET_NAME", "")
|
||||
mcpStorageS3AccessKeyKey := envOr("SANDBOX_MCP_STORAGE_S3_ACCESS_KEY_KEY", "AWS_ACCESS_KEY_ID")
|
||||
mcpStorageS3SecretKeyKey := envOr("SANDBOX_MCP_STORAGE_S3_SECRET_KEY_KEY", "AWS_SECRET_ACCESS_KEY")
|
||||
mcpKeycloakAdminURL := envOr("SANDBOX_MCP_KEYCLOAK_ADMIN_URL", "http://keycloak.keycloak.svc.cluster.local:8080")
|
||||
mcpKeycloakParentRealm := envOr("SANDBOX_MCP_KEYCLOAK_PARENT_REALM", "master")
|
||||
mcpKeycloakAdminTokenSecret := envOr("SANDBOX_MCP_KEYCLOAK_ADMIN_TOKEN_SECRET_NAME", "")
|
||||
mcpKeycloakAdminTokenSecretKey := envOr("SANDBOX_MCP_KEYCLOAK_ADMIN_TOKEN_SECRET_KEY", "token")
|
||||
|
||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||
Scheme: scheme,
|
||||
Metrics: metricsserver.Options{BindAddress: metricsAddr},
|
||||
@ -153,6 +175,22 @@ func main() {
|
||||
EnableHotStandby: enableHotStandby,
|
||||
PrimaryRegion: primaryRegion,
|
||||
ReplicaRegion: replicaRegion,
|
||||
// TBD-P4 B4 — canonical SANDBOX_* env-var wiring for MCP plugin.
|
||||
GiteaBaseURL: mcpGiteaBaseURL,
|
||||
GiteaTokenSecretName: mcpGiteaTokenSecretName,
|
||||
GiteaTokenSecretKey: mcpGiteaTokenSecretKey,
|
||||
DomainAPIURL: mcpDomainAPIURL,
|
||||
MarketplaceAPIURL: mcpMarketplaceAPIURL,
|
||||
StorageS3Endpoint: mcpStorageS3Endpoint,
|
||||
StorageS3Region: mcpStorageS3Region,
|
||||
StorageS3UseTLS: mcpStorageS3UseTLS,
|
||||
StorageS3CredsSecretName: mcpStorageS3CredsSecret,
|
||||
StorageS3AccessKeyKey: mcpStorageS3AccessKeyKey,
|
||||
StorageS3SecretKeyKey: mcpStorageS3SecretKeyKey,
|
||||
KeycloakAdminURL: mcpKeycloakAdminURL,
|
||||
KeycloakParentRealm: mcpKeycloakParentRealm,
|
||||
KeycloakAdminTokenSecret: mcpKeycloakAdminTokenSecret,
|
||||
KeycloakAdminTokenSecretKey: mcpKeycloakAdminTokenSecretKey,
|
||||
}
|
||||
if err := r.SetupWithManager(mgr); err != nil {
|
||||
log.Error(err, "setup reconciler")
|
||||
|
||||
@ -91,6 +91,31 @@ type Reconciler struct {
|
||||
PrimaryRegion string
|
||||
ReplicaRegion string
|
||||
|
||||
// TBD-P4 B4 — canonical SANDBOX_* env wiring the controller threads
|
||||
// into every per-Sandbox MCP Pod. Without these, the MCP plugin's
|
||||
// per-tool guards (gitea, domain, storage, keycloak) silently
|
||||
// degrade to "not configured" because the controller used to emit
|
||||
// `ORG_ID` / `SOVEREIGN_FQDN` while the MCP binary reads the
|
||||
// `SANDBOX_*` namespaced variants. Sourced from chart-level env on
|
||||
// the bp-sandbox HelmRelease (deployment.yaml `runtime.*` + new
|
||||
// `*Secret` blocks). All fields permit empty — MCP surfaces a clean
|
||||
// "not configured" error from the affected tool family.
|
||||
GiteaBaseURL string
|
||||
GiteaTokenSecretName string
|
||||
GiteaTokenSecretKey string
|
||||
DomainAPIURL string
|
||||
MarketplaceAPIURL string
|
||||
StorageS3Endpoint string
|
||||
StorageS3Region string
|
||||
StorageS3UseTLS string
|
||||
StorageS3CredsSecretName string
|
||||
StorageS3AccessKeyKey string
|
||||
StorageS3SecretKeyKey string
|
||||
KeycloakAdminURL string
|
||||
KeycloakParentRealm string
|
||||
KeycloakAdminTokenSecret string
|
||||
KeycloakAdminTokenSecretKey string
|
||||
|
||||
// Wave 9 — NewAPI bridge client used by Reconcile to mint
|
||||
// per-Sandbox LLM-gateway tokens (POST /admin/tokens/sandbox,
|
||||
// PR #1638). When nil the reconciler renders the Wave 1+8
|
||||
@ -264,6 +289,22 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
EnableHotStandby: r.EnableHotStandby,
|
||||
PrimaryRegion: r.PrimaryRegion,
|
||||
ReplicaRegion: r.ReplicaRegion,
|
||||
// TBD-P4 B4 — canonical SANDBOX_* env-var wiring for MCP plugin.
|
||||
GiteaBaseURL: r.GiteaBaseURL,
|
||||
GiteaTokenSecretName: r.GiteaTokenSecretName,
|
||||
GiteaTokenSecretKey: r.GiteaTokenSecretKey,
|
||||
DomainAPIURL: r.DomainAPIURL,
|
||||
MarketplaceAPIURL: r.MarketplaceAPIURL,
|
||||
StorageS3Endpoint: r.StorageS3Endpoint,
|
||||
StorageS3Region: r.StorageS3Region,
|
||||
StorageS3UseTLS: r.StorageS3UseTLS,
|
||||
StorageS3CredsSecretName: r.StorageS3CredsSecretName,
|
||||
StorageS3AccessKeyKey: r.StorageS3AccessKeyKey,
|
||||
StorageS3SecretKeyKey: r.StorageS3SecretKeyKey,
|
||||
KeycloakAdminURL: r.KeycloakAdminURL,
|
||||
KeycloakParentRealm: r.KeycloakParentRealm,
|
||||
KeycloakAdminTokenSecret: r.KeycloakAdminTokenSecret,
|
||||
KeycloakAdminTokenSecretKey: r.KeycloakAdminTokenSecretKey,
|
||||
}
|
||||
manifests, err := gitops.Render(in)
|
||||
if err != nil {
|
||||
|
||||
@ -211,6 +211,22 @@ func makeReconciler(t *testing.T, objs ...client.Object) (*Reconciler, *giteaSer
|
||||
LLMGatewayTokenSecret: "sandbox-tokens",
|
||||
BYOSSecretPrefix: "sandbox-byos-claude-code",
|
||||
IdleTimeoutMinutes: 30,
|
||||
// TBD-P4 B4 — canonical SANDBOX_* env-var wiring (chart defaults).
|
||||
GiteaBaseURL: "http://gitea-http.gitea.svc.cluster.local:3000",
|
||||
GiteaTokenSecretName: "catalyst-gitea-token",
|
||||
GiteaTokenSecretKey: "token",
|
||||
DomainAPIURL: "http://domain.sme.svc.cluster.local:8086",
|
||||
MarketplaceAPIURL: "http://marketplace-api.marketplace.svc.cluster.local:8082",
|
||||
StorageS3Endpoint: "http://seaweedfs.storage.svc.cluster.local:8333",
|
||||
StorageS3Region: "us-east-1",
|
||||
StorageS3UseTLS: "false",
|
||||
StorageS3CredsSecretName: "sandbox-storage-s3",
|
||||
StorageS3AccessKeyKey: "AWS_ACCESS_KEY_ID",
|
||||
StorageS3SecretKeyKey: "AWS_SECRET_ACCESS_KEY",
|
||||
KeycloakAdminURL: "http://keycloak.keycloak.svc.cluster.local:8080",
|
||||
KeycloakParentRealm: "master",
|
||||
KeycloakAdminTokenSecret: "keycloak-admin-token",
|
||||
KeycloakAdminTokenSecretKey: "token",
|
||||
}
|
||||
return r, gs
|
||||
}
|
||||
@ -465,12 +481,61 @@ func TestReconcile_Wave8RuntimeShape(t *testing.T) {
|
||||
`image: "ghcr.io/openova-io/openova/sandbox-mcp:test-sha"`,
|
||||
"PTY_SERVER_URL",
|
||||
"pty-server.sandbox-ceo-at-acme-com.svc.cluster.local:7681",
|
||||
// TBD-P4 B4 regression — the MCP Deployment MUST emit the
|
||||
// canonical SANDBOX_* env-var set the MCP plugin's
|
||||
// products/sandbox/mcp-server/internal/tools/env.go reads.
|
||||
// Before this slice the controller emitted bare `ORG_ID` and
|
||||
// `SOVEREIGN_FQDN` on the MCP Pod → MCP read the wrong keys →
|
||||
// every tool family silently degraded to "not configured" at
|
||||
// runtime. Asserting on the canonical names here prevents the
|
||||
// drift from reappearing.
|
||||
"name: SANDBOX_ORG_ID",
|
||||
"name: SANDBOX_SOVEREIGN_FQDN",
|
||||
"name: SANDBOX_ID",
|
||||
"name: SANDBOX_NAMESPACE",
|
||||
"name: SANDBOX_TENANT_ID",
|
||||
"name: SANDBOX_GITEA_BASE_URL",
|
||||
"name: SANDBOX_GITEA_TOKEN",
|
||||
"name: SANDBOX_DOMAIN_API_URL",
|
||||
"name: SANDBOX_MARKETPLACE_API_URL",
|
||||
"name: SANDBOX_STORAGE_S3_ENDPOINT",
|
||||
"name: SANDBOX_STORAGE_S3_REGION",
|
||||
"name: SANDBOX_STORAGE_S3_USE_TLS",
|
||||
"name: SANDBOX_STORAGE_S3_ACCESS_KEY",
|
||||
"name: SANDBOX_STORAGE_S3_SECRET_KEY",
|
||||
"name: KEYCLOAK_ADMIN_URL",
|
||||
"name: KEYCLOAK_PARENT_REALM",
|
||||
"name: KEYCLOAK_ADMIN_TOKEN",
|
||||
// Values plumbed from the controller's chart-level env.
|
||||
"http://gitea-http.gitea.svc.cluster.local:3000",
|
||||
"http://domain.sme.svc.cluster.local:8086",
|
||||
"http://seaweedfs.storage.svc.cluster.local:8333",
|
||||
"http://keycloak.keycloak.svc.cluster.local:8080",
|
||||
`name: "catalyst-gitea-token"`,
|
||||
`name: "sandbox-storage-s3"`,
|
||||
`name: "keycloak-admin-token"`,
|
||||
} {
|
||||
if !strings.Contains(dep, want) {
|
||||
t.Errorf("deployment-mcp.yaml missing %q", want)
|
||||
}
|
||||
}
|
||||
|
||||
// TBD-P4 B4 — the OLD bare names MUST NOT appear on the MCP
|
||||
// Deployment. They remain on the pty-server StatefulSet (inherited
|
||||
// by user shells, distinct contract). Any future renderer change
|
||||
// that puts them back onto the MCP Deployment regresses the MCP
|
||||
// plugin's tool gates, so the negative assertion is load-bearing.
|
||||
for _, banned := range []string{
|
||||
"- name: ORG_ID\n",
|
||||
"- name: SOVEREIGN_FQDN\n",
|
||||
} {
|
||||
if strings.Contains(dep, banned) {
|
||||
t.Errorf("deployment-mcp.yaml MUST NOT contain bare %q "+
|
||||
"(MCP plugin reads canonical SANDBOX_ORG_ID / SANDBOX_SOVEREIGN_FQDN)",
|
||||
strings.TrimSpace(banned))
|
||||
}
|
||||
}
|
||||
|
||||
svc := get("service-pty-server.yaml")
|
||||
for _, want := range []string{
|
||||
"kind: Service",
|
||||
|
||||
@ -94,6 +94,35 @@ type Inputs struct {
|
||||
EnableHotStandby string
|
||||
PrimaryRegion string
|
||||
ReplicaRegion string
|
||||
|
||||
// TBD-P4 B4 — canonical SANDBOX_* env-var wiring for the MCP plugin
|
||||
// (products/sandbox/mcp-server/internal/tools/env.go). Without these,
|
||||
// every tool family (gitea / domain / storage / keycloak) silently
|
||||
// degrades to "not configured" at call time because the controller
|
||||
// previously emitted bare `ORG_ID` / `SOVEREIGN_FQDN` while the MCP
|
||||
// binary reads `SANDBOX_ORG_ID` / `SANDBOX_SOVEREIGN_FQDN` etc.
|
||||
//
|
||||
// Each value is plumbed by the controller from its chart-level env
|
||||
// (deployment.yaml `runtime.*` + new `*Secret` blocks). Empty leaves
|
||||
// the canonical var as an empty string on the MCP Pod, which the
|
||||
// MCP's per-tool requireX guard surfaces as a clear "not configured"
|
||||
// error — same behaviour as before, just now reachable instead of
|
||||
// silently misnamed.
|
||||
GiteaBaseURL string
|
||||
GiteaTokenSecretName string
|
||||
GiteaTokenSecretKey string
|
||||
DomainAPIURL string
|
||||
MarketplaceAPIURL string
|
||||
StorageS3Endpoint string
|
||||
StorageS3Region string
|
||||
StorageS3UseTLS string
|
||||
StorageS3CredsSecretName string
|
||||
StorageS3AccessKeyKey string
|
||||
StorageS3SecretKeyKey string
|
||||
KeycloakAdminURL string
|
||||
KeycloakParentRealm string
|
||||
KeycloakAdminTokenSecret string
|
||||
KeycloakAdminTokenSecretKey string
|
||||
}
|
||||
|
||||
const namespaceTemplate = `apiVersion: v1
|
||||
@ -409,10 +438,85 @@ spec:
|
||||
value: {{ .OwnerUID | quote }}
|
||||
- name: SANDBOX_OWNER_EMAIL
|
||||
value: {{ .OwnerEmail | quote }}
|
||||
- name: ORG_ID
|
||||
# ── TBD-P4 B4 — canonical SANDBOX_* names the MCP plugin
|
||||
# reads (products/sandbox/mcp-server/internal/tools/env.go).
|
||||
# ORG_ID + SOVEREIGN_FQDN were the original names and
|
||||
# silently degraded every MCP tool family to "not configured".
|
||||
- name: SANDBOX_ORG_ID
|
||||
value: {{ .OrgSlug | quote }}
|
||||
- name: SOVEREIGN_FQDN
|
||||
- name: SANDBOX_SOVEREIGN_FQDN
|
||||
value: {{ .SovereignFQDN | quote }}
|
||||
- name: SANDBOX_ID
|
||||
value: {{ .Name | quote }}
|
||||
- name: SANDBOX_NAMESPACE
|
||||
value: {{ .NamespaceName | quote }}
|
||||
# SANDBOX_TENANT_ID scopes the MCP's domain/byod handler
|
||||
# (marketplace.go:93). The per-Org slug is the tenant key in
|
||||
# the chroot Organization controller's wiring; the MCP
|
||||
# treats this opaquely.
|
||||
- name: SANDBOX_TENANT_ID
|
||||
value: {{ .OrgSlug | quote }}
|
||||
# ── Gitea wiring — SANDBOX_GITEA_BASE_URL is unauthed in
|
||||
# the in-cluster path; the matching token is mounted from
|
||||
# the existing catalyst-gitea-token Secret (single source
|
||||
# of truth shared with the controller itself; never written
|
||||
# here per Inviolable Principle #4 — Secrets are owned by
|
||||
# bp-catalyst-platform seed jobs).
|
||||
- name: SANDBOX_GITEA_BASE_URL
|
||||
value: {{ .GiteaBaseURL | quote }}
|
||||
{{- if .GiteaTokenSecretName }}
|
||||
- name: SANDBOX_GITEA_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .GiteaTokenSecretName | quote }}
|
||||
key: {{ .GiteaTokenSecretKey | quote }}
|
||||
optional: true
|
||||
{{- end }}
|
||||
# ── Domain + marketplace REST surfaces (services that
|
||||
# already run in-cluster; per-Sovereign overlays may pin
|
||||
# alternate ClusterIPs via the bp-sandbox HR values).
|
||||
- name: SANDBOX_DOMAIN_API_URL
|
||||
value: {{ .DomainAPIURL | quote }}
|
||||
- name: SANDBOX_MARKETPLACE_API_URL
|
||||
value: {{ .MarketplaceAPIURL | quote }}
|
||||
# ── Storage (SeaweedFS S3). Endpoint + region are public;
|
||||
# credentials are sourced from an existing per-Sandbox IAM
|
||||
# Secret when present. Empty creds surface a clear "not
|
||||
# configured" error from the MCP's storage tool family.
|
||||
- name: SANDBOX_STORAGE_S3_ENDPOINT
|
||||
value: {{ .StorageS3Endpoint | quote }}
|
||||
- name: SANDBOX_STORAGE_S3_REGION
|
||||
value: {{ .StorageS3Region | quote }}
|
||||
- name: SANDBOX_STORAGE_S3_USE_TLS
|
||||
value: {{ .StorageS3UseTLS | quote }}
|
||||
{{- if .StorageS3CredsSecretName }}
|
||||
- name: SANDBOX_STORAGE_S3_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .StorageS3CredsSecretName | quote }}
|
||||
key: {{ .StorageS3AccessKeyKey | quote }}
|
||||
optional: true
|
||||
- name: SANDBOX_STORAGE_S3_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .StorageS3CredsSecretName | quote }}
|
||||
key: {{ .StorageS3SecretKeyKey | quote }}
|
||||
optional: true
|
||||
{{- end }}
|
||||
# ── Keycloak admin surface. URL + parent realm are public;
|
||||
# the admin bearer is sourced from an existing Secret.
|
||||
- name: KEYCLOAK_ADMIN_URL
|
||||
value: {{ .KeycloakAdminURL | quote }}
|
||||
- name: KEYCLOAK_PARENT_REALM
|
||||
value: {{ .KeycloakParentRealm | quote }}
|
||||
{{- if .KeycloakAdminTokenSecret }}
|
||||
- name: KEYCLOAK_ADMIN_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .KeycloakAdminTokenSecret | quote }}
|
||||
key: {{ .KeycloakAdminTokenSecretKey | quote }}
|
||||
optional: true
|
||||
{{- end }}
|
||||
- name: PTY_SERVER_URL
|
||||
value: "http://pty-server.{{ .NamespaceName }}.svc.cluster.local:7681"
|
||||
- name: LLM_GATEWAY_TOKEN
|
||||
|
||||
@ -24,8 +24,8 @@ annotations:
|
||||
# (see issue #181 + docs/BLUEPRINT-AUTHORING.md §11.1).
|
||||
catalyst.openova.io/no-upstream: "true"
|
||||
catalyst.openova.io/smoke-render-mode: "default-off"
|
||||
version: 0.1.0
|
||||
appVersion: "0.1.0"
|
||||
version: 0.2.0
|
||||
appVersion: "0.2.0"
|
||||
keywords:
|
||||
- catalyst
|
||||
- sandbox
|
||||
|
||||
@ -112,6 +112,52 @@ spec:
|
||||
value: {{ (.Values.cnpg).activeHotStandby.primaryRegion | default "" | quote }}
|
||||
- name: SOVEREIGN_REPLICA_REGION
|
||||
value: {{ (.Values.cnpg).activeHotStandby.replicaRegion | default "" | quote }}
|
||||
# TBD-P4 B4 — canonical SANDBOX_* env-var wiring for the MCP
|
||||
# plugin. The controller passes these straight through to
|
||||
# every per-Sandbox MCP Deployment via gitops.Inputs so the
|
||||
# plugin's per-tool guards (gitea / domain / storage /
|
||||
# keycloak) see the canonical names defined in
|
||||
# products/sandbox/mcp-server/internal/tools/env.go. Before
|
||||
# this slice the renderer emitted `ORG_ID` / `SOVEREIGN_FQDN`
|
||||
# while the MCP read `SANDBOX_ORG_ID` / `SANDBOX_SOVEREIGN_FQDN`
|
||||
# → every tool family silently degraded to "not configured".
|
||||
#
|
||||
# Values are env vars on the CONTROLLER (this Deployment);
|
||||
# the controller reads each and passes via gitops.Inputs into
|
||||
# the rendered MCP Deployment template. Secrets are NEVER
|
||||
# written from the controller — name + key references only,
|
||||
# `optional: true` on the per-Sandbox secretKeyRef so missing
|
||||
# secrets surface a clean "not configured" error from the MCP.
|
||||
- name: SANDBOX_MCP_GITEA_BASE_URL
|
||||
value: {{ .Values.mcp.giteaBaseURL | default "http://gitea-http.gitea.svc.cluster.local:3000" | quote }}
|
||||
- name: SANDBOX_MCP_GITEA_TOKEN_SECRET_NAME
|
||||
value: {{ .Values.mcp.giteaTokenSecret.name | default "catalyst-gitea-token" | quote }}
|
||||
- name: SANDBOX_MCP_GITEA_TOKEN_SECRET_KEY
|
||||
value: {{ .Values.mcp.giteaTokenSecret.key | default "token" | quote }}
|
||||
- name: SANDBOX_MCP_DOMAIN_API_URL
|
||||
value: {{ .Values.mcp.domainAPIURL | default "http://domain.sme.svc.cluster.local:8086" | quote }}
|
||||
- name: SANDBOX_MCP_MARKETPLACE_API_URL
|
||||
value: {{ .Values.mcp.marketplaceAPIURL | default "http://marketplace-api.marketplace.svc.cluster.local:8082" | quote }}
|
||||
- name: SANDBOX_MCP_STORAGE_S3_ENDPOINT
|
||||
value: {{ .Values.mcp.storage.s3Endpoint | default "http://seaweedfs.storage.svc.cluster.local:8333" | quote }}
|
||||
- name: SANDBOX_MCP_STORAGE_S3_REGION
|
||||
value: {{ .Values.mcp.storage.s3Region | default "us-east-1" | quote }}
|
||||
- name: SANDBOX_MCP_STORAGE_S3_USE_TLS
|
||||
value: {{ .Values.mcp.storage.s3UseTLS | default "false" | quote }}
|
||||
- name: SANDBOX_MCP_STORAGE_S3_CREDS_SECRET_NAME
|
||||
value: {{ .Values.mcp.storage.credsSecret.name | default "" | quote }}
|
||||
- name: SANDBOX_MCP_STORAGE_S3_ACCESS_KEY_KEY
|
||||
value: {{ .Values.mcp.storage.credsSecret.accessKeyKey | default "AWS_ACCESS_KEY_ID" | quote }}
|
||||
- name: SANDBOX_MCP_STORAGE_S3_SECRET_KEY_KEY
|
||||
value: {{ .Values.mcp.storage.credsSecret.secretKeyKey | default "AWS_SECRET_ACCESS_KEY" | quote }}
|
||||
- name: SANDBOX_MCP_KEYCLOAK_ADMIN_URL
|
||||
value: {{ .Values.mcp.keycloak.adminURL | default "http://keycloak.keycloak.svc.cluster.local:8080" | quote }}
|
||||
- name: SANDBOX_MCP_KEYCLOAK_PARENT_REALM
|
||||
value: {{ .Values.mcp.keycloak.parentRealm | default "master" | quote }}
|
||||
- name: SANDBOX_MCP_KEYCLOAK_ADMIN_TOKEN_SECRET_NAME
|
||||
value: {{ .Values.mcp.keycloak.adminTokenSecret.name | default "" | quote }}
|
||||
- name: SANDBOX_MCP_KEYCLOAK_ADMIN_TOKEN_SECRET_KEY
|
||||
value: {{ .Values.mcp.keycloak.adminTokenSecret.key | default "token" | quote }}
|
||||
{{- range $k, $v := .Values.extraEnv }}
|
||||
- name: {{ $k | quote }}
|
||||
value: {{ $v | quote }}
|
||||
|
||||
@ -186,4 +186,45 @@ serviceMonitor:
|
||||
labels: {}
|
||||
# namespace override — defaults to .Release.Namespace.
|
||||
namespace: ""
|
||||
# TBD-P4 B4 — canonical SANDBOX_* env-var wiring for the MCP plugin
|
||||
# (products/sandbox/mcp-server/internal/tools/env.go). Surfaced by the
|
||||
# controller as env vars; the controller in turn passes each through to
|
||||
# every per-Sandbox MCP Deployment via gitops.Inputs so the MCP plugin's
|
||||
# per-tool guards (gitea / domain / storage / keycloak) see the canonical
|
||||
# names instead of the legacy `ORG_ID` / `SOVEREIGN_FQDN` shape.
|
||||
#
|
||||
# Defaults match the in-cluster Service DNS for a stock Sovereign install
|
||||
# (bp-gitea / bp-newapi / bp-seaweedfs / bp-keycloak / bp-marketplace).
|
||||
# Per-Sovereign overlays may override any value. Secrets are NEVER written
|
||||
# from this chart — name+key references only with `optional: true` so a
|
||||
# fresh-prov Sovereign with a credential source still in flight does NOT
|
||||
# crash the per-Sandbox MCP Pod; the affected tool family surfaces a clean
|
||||
# "not configured" error.
|
||||
mcp:
|
||||
giteaBaseURL: "http://gitea-http.gitea.svc.cluster.local:3000"
|
||||
giteaTokenSecret:
|
||||
name: "catalyst-gitea-token"
|
||||
key: "token"
|
||||
domainAPIURL: "http://domain.sme.svc.cluster.local:8086"
|
||||
marketplaceAPIURL: "http://marketplace-api.marketplace.svc.cluster.local:8082"
|
||||
storage:
|
||||
s3Endpoint: "http://seaweedfs.storage.svc.cluster.local:8333"
|
||||
s3Region: "us-east-1"
|
||||
s3UseTLS: "false"
|
||||
credsSecret:
|
||||
# Empty default — when set, the controller stamps SANDBOX_STORAGE_S3_
|
||||
# ACCESS_KEY / SECRET_KEY secretKeyRefs on every per-Sandbox MCP Pod.
|
||||
# Empty leaves the MCP storage tool family in "not configured" mode.
|
||||
name: ""
|
||||
accessKeyKey: "AWS_ACCESS_KEY_ID"
|
||||
secretKeyKey: "AWS_SECRET_ACCESS_KEY"
|
||||
keycloak:
|
||||
adminURL: "http://keycloak.keycloak.svc.cluster.local:8080"
|
||||
parentRealm: "master"
|
||||
adminTokenSecret:
|
||||
# Empty default — when set, the controller stamps a KEYCLOAK_ADMIN_TOKEN
|
||||
# secretKeyRef on every per-Sandbox MCP Pod. Empty leaves the MCP
|
||||
# keycloak tool family in "not configured" mode.
|
||||
name: ""
|
||||
key: "token"
|
||||
extraEnv: {}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user