diff --git a/cmd/ate-setup/internal/config/config.go b/cmd/ate-setup/internal/config/config.go index 5f13ac365..fc05546fe 100644 --- a/cmd/ate-setup/internal/config/config.go +++ b/cmd/ate-setup/internal/config/config.go @@ -49,6 +49,10 @@ const DefaultRolloutTimeout = 60 * time.Second // podidentity credential bundle. const DefaultPostgresConnectionString = "postgresql://postgres@postgres.ate-system.svc:5432/atepg?sslmode=verify-full&sslrootcert=/run/servicedns.podcert.ate.dev/trust-bundle.pem&sslcert=/run/podidentity.podcert.ate.dev/credential-bundle.pem&sslkey=/run/podidentity.podcert.ate.dev/credential-bundle.pem" +// DefaultPostgresSchema mirrors the shell installer's default for +// ATE_API_POSTGRES_SCHEMA, the PostgreSQL schema holding the Substrate tables. +const DefaultPostgresSchema = "public" + // devEnvFile is the optional per-developer environment script at the repo root. const devEnvFile = ".ate-dev-env.sh" @@ -96,6 +100,9 @@ type Config struct { // PostgresConnectionString is the apiserver's store connection string. // Empty means use DefaultPostgresConnectionString. PostgresConnectionString string + // PostgresSchema is the PostgreSQL schema for the Substrate tables + // (ATE_API_POSTGRES_SCHEMA). Empty means DefaultPostgresSchema. + PostgresSchema string // RolloutTimeout is the timeout duration for rollout status checks. RolloutTimeout time.Duration @@ -214,6 +221,7 @@ func Load(opts Options) (*Config, error) { KODefaultPlatforms: env["KO_DEFAULTPLATFORMS"], Images: loadImageSource(opts, env), PostgresConnectionString: env["ATE_API_POSTGRES_CONNECTION_STRING"], + PostgresSchema: env["ATE_API_POSTGRES_SCHEMA"], RolloutTimeout: rolloutTimeout, rolloutTimeoutSet: timeoutStr != "", PodcertWorkersPerSigner: podcertWorkers, @@ -312,6 +320,15 @@ func (c *Config) PostgresConnString() string { return DefaultPostgresConnectionString } +// PostgresSchemaName returns the configured schema, falling back to the +// shell installer's default. ate-api-server rejects an empty value. +func (c *Config) PostgresSchemaName() string { + if c.PostgresSchema != "" { + return c.PostgresSchema + } + return DefaultPostgresSchema +} + // WaitTimeout returns how long to wait for a workload whose historical timeout // was historical. // diff --git a/cmd/ate-setup/internal/config/config_test.go b/cmd/ate-setup/internal/config/config_test.go index 288fef34f..7173e1e19 100644 --- a/cmd/ate-setup/internal/config/config_test.go +++ b/cmd/ate-setup/internal/config/config_test.go @@ -41,6 +41,7 @@ func loadEnv(t *testing.T) { "ANTHROPIC_API_KEY", "ATE_ADDITIONAL_EGRESS_EXTPROC_SERVICE", "ATE_API_POSTGRES_CONNECTION_STRING", + "ATE_API_POSTGRES_SCHEMA", "ATE_ATENET_ROUTER", "ATE_EXPERIMENTAL_USE_SDSMINT", "ATE_IMAGE_REPO", @@ -115,6 +116,28 @@ func TestLoadPostgresConnectionStringOverride(t *testing.T) { } } +// ATE_API_POSTGRES_SCHEMA defaults to public, as in the shell installer, and +// an explicit value wins. +func TestLoadPostgresSchema(t *testing.T) { + loadEnv(t) + cfg, err := Load(Options{}) + if err != nil { + t.Fatalf("Load() error = %v", err) + } + if cfg.PostgresSchemaName() != DefaultPostgresSchema { + t.Errorf("PostgresSchemaName() = %q, want %q", cfg.PostgresSchemaName(), DefaultPostgresSchema) + } + + t.Setenv("ATE_API_POSTGRES_SCHEMA", "substrate") + cfg, err = Load(Options{}) + if err != nil { + t.Fatalf("Load() error = %v", err) + } + if cfg.PostgresSchemaName() != "substrate" { + t.Errorf("PostgresSchemaName() = %q, want %q", cfg.PostgresSchemaName(), "substrate") + } +} + // ate-setup's own client resolves $KUBECONFIG through the client-go loading // rules, so the value has to reach ScriptEnv as well. Otherwise a developer who // exports KUBECONFIG without passing --kubeconfig gets an install split across diff --git a/cmd/ate-setup/internal/steps/create.go b/cmd/ate-setup/internal/steps/create.go index 9add90796..b43a0f506 100644 --- a/cmd/ate-setup/internal/steps/create.go +++ b/cmd/ate-setup/internal/steps/create.go @@ -121,7 +121,8 @@ func (e *Env) CreateActorIDCACertsSecret(ctx context.Context) error { // CreateAPIServerEnvVars writes the ConfigMap that tells ate-api-server how to // reach its PostgreSQL store. ate-api-server.yaml pulls it in via an optional -// envFrom and resolves --postgres-connection-string=@env from it. +// envFrom and resolves --postgres-connection-string=@env and +// --postgres-schema=@env from it. func (e *Env) CreateAPIServerEnvVars(ctx context.Context) error { log.Step("create_api_server_env_vars") if err := e.Kube.EnsureNamespace(ctx, NamespaceAteSystem); err != nil { @@ -131,16 +132,19 @@ func (e *Env) CreateAPIServerEnvVars(ctx context.Context) error { connString := e.Cfg.PostgresConnString() log.Infof("POSTGRES_CONNECTION_STRING: %s", connString) - return e.Kube.ApplyConfigMap(ctx, NamespaceAteSystem, ConfigMapAPIEnvVars, buildAPIServerEnvVars(connString)) + return e.Kube.ApplyConfigMap(ctx, NamespaceAteSystem, ConfigMapAPIEnvVars, + buildAPIServerEnvVars(connString, e.Cfg.PostgresSchemaName())) } -// buildAPIServerEnvVars is the ConfigMap payload. ate-api-server takes only the -// connection string from it; an unrecognized key here reaches the container as -// a stray environment variable, so the set stays exactly what the shell -// installer's create_api_server_env_vars wrote. -func buildAPIServerEnvVars(connString string) map[string]string { +// buildAPIServerEnvVars is the ConfigMap payload. ate-api-server takes the +// connection string and the schema from it, and exits on an empty schema; an +// unrecognized key here reaches the container as a stray environment variable, +// so the set stays exactly what the shell installer's +// create_api_server_env_vars writes. +func buildAPIServerEnvVars(connString, schema string) map[string]string { return map[string]string{ "ATE_API_POSTGRES_CONNECTION_STRING": connString, + "ATE_API_POSTGRES_SCHEMA": schema, } } diff --git a/cmd/ate-setup/internal/steps/create_test.go b/cmd/ate-setup/internal/steps/create_test.go index 3998cb31a..e21200483 100644 --- a/cmd/ate-setup/internal/steps/create_test.go +++ b/cmd/ate-setup/internal/steps/create_test.go @@ -23,22 +23,26 @@ import ( "github.com/agent-substrate/substrate/internal/localca" ) -// ate-api-server resolves --postgres-connection-string=@env from this -// ConfigMap. It is the only key the shell installer wrote, and an empty value -// makes the apiserver exit with "--postgres-connection-string is required", so -// both the key set and the value are pinned here. +// ate-api-server resolves --postgres-connection-string=@env and +// --postgres-schema=@env from this ConfigMap. These are the keys the shell +// installer writes, and an empty value for either makes the apiserver exit +// ("--postgres-connection-string is required", "PostgreSQL schema must not be +// empty"), so both the key set and the values are pinned here. func TestBuildAPIServerEnvVars(t *testing.T) { const dsn = "postgresql://postgres@postgres.ate-system.svc:5432/atepg?sslmode=verify-full" - got := buildAPIServerEnvVars(dsn) + got := buildAPIServerEnvVars(dsn, "public") - want := []string{"ATE_API_POSTGRES_CONNECTION_STRING"} + want := []string{"ATE_API_POSTGRES_CONNECTION_STRING", "ATE_API_POSTGRES_SCHEMA"} if keys := slices.Sorted(maps.Keys(got)); !slices.Equal(keys, want) { t.Errorf("keys = %v, want %v", keys, want) } if got["ATE_API_POSTGRES_CONNECTION_STRING"] != dsn { t.Errorf("ATE_API_POSTGRES_CONNECTION_STRING = %q, want %q", got["ATE_API_POSTGRES_CONNECTION_STRING"], dsn) } + if got["ATE_API_POSTGRES_SCHEMA"] != "public" { + t.Errorf("ATE_API_POSTGRES_SCHEMA = %q, want %q", got["ATE_API_POSTGRES_SCHEMA"], "public") + } } // The expected strings here are what the shell installer's