diff --git a/docs/administrator.md b/docs/administrator.md index 373e691a8..4ea7b24dd 100644 --- a/docs/administrator.md +++ b/docs/administrator.md @@ -628,11 +628,11 @@ order (e.g. a variable defined in 4. overrides a variable with the same name in 5.): 1. Assigned by the operator -2. Clone section (with WAL settings from operator config when `s3_wal_path` is empty) -3. Standby section -4. `env` section in cluster manifest -5. Pod environment secret via operator config -6. Pod environment config map via operator config +2. `env` section in cluster manifest +3. Pod environment secret via operator config +4. Pod environment config map via operator config +5. Clone section (with WAL settings from operator config when `s3_wal_path` is empty) +6. Standby section 7. WAL and logical backup settings from operator config ### Via ConfigMap diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index aa3229848..81732c204 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -904,15 +904,7 @@ func (c *Cluster) generateSpiloPodEnvVars( if c.patroniKubernetesUseConfigMaps() { envVars = append(envVars, v1.EnvVar{Name: "KUBERNETES_USE_CONFIGMAPS", Value: "true"}) } - - if spec.Clone != nil && spec.Clone.ClusterName != "" { - envVars = append(envVars, c.generateCloneEnvironment(spec.Clone)...) - } - - if spec.StandbyCluster != nil { - envVars = append(envVars, c.generateStandbyEnvironment(spec.StandbyCluster)...) - } - + // fetch cluster-specific variables that will override all subsequent global variables if len(spec.Env) > 0 { envVars = appendEnvVars(envVars, spec.Env...) @@ -934,6 +926,14 @@ func (c *Cluster) generateSpiloPodEnvVars( } envVars = appendEnvVars(envVars, configMapEnvVarsList...) + if spec.Clone != nil && spec.Clone.ClusterName != "" { + envVars = append(envVars, c.generateCloneEnvironment(spec.Clone)...) + } + + if spec.StandbyCluster != nil { + envVars = append(envVars, c.generateStandbyEnvironment(spec.StandbyCluster)...) + } + // global variables derived from operator configuration opConfigEnvVars := make([]v1.EnvVar, 0) if c.OpConfig.WALES3Bucket != "" { diff --git a/pkg/cluster/k8sres_test.go b/pkg/cluster/k8sres_test.go index 797c1426c..0b3a2fbd8 100644 --- a/pkg/cluster/k8sres_test.go +++ b/pkg/cluster/k8sres_test.go @@ -549,37 +549,54 @@ func TestGenerateSpiloPodEnvVars(t *testing.T) { envVarConstant: "CLONE_WALE_S3_PREFIX", envVarValue: "s3://another-bucket", }, + { + envIndex: 20, + envVarConstant: "CLONE_AWS_ENDPOINT", + envVarValue: "s3.eu-central-1.amazonaws.com", + }, { envIndex: 19, envVarConstant: "CLONE_WAL_BUCKET_SCOPE_PREFIX", envVarValue: "", }, + } + expectedCloneEnvWithPrefixSpec := []ExpectedValue{ { envIndex: 20, - envVarConstant: "CLONE_AWS_ENDPOINT", - envVarValue: "s3.eu-central-1.amazonaws.com", + envVarConstant: "CLONE_WALE_S3_PREFIX", + envVarValue: "s3://another-bucket", + }, + { + envIndex: 16, + envVarConstant: "clone_aws_endpoint", + envVarValue: "s3.eu-west-1.amazonaws.com", + }, + { + envIndex: 15, + envVarConstant: "CLONE_WAL_BUCKET_SCOPE_PREFIX", + envVarValue: "spec-env-test", }, } expectedCloneEnvConfigMap := []ExpectedValue{ { - envIndex: 16, + envIndex: 19, envVarConstant: "CLONE_WAL_S3_BUCKET", envVarValue: "global-s3-bucket", }, { - envIndex: 17, + envIndex: 20, envVarConstant: "CLONE_WAL_BUCKET_SCOPE_SUFFIX", envVarValue: fmt.Sprintf("/%s", dummyUUID), }, { - envIndex: 21, + envIndex: 15, envVarConstant: "clone_aws_endpoint", envVarValue: "s3.eu-west-1.amazonaws.com", }, } expectedCloneEnvSecret := []ExpectedValue{ { - envIndex: 21, + envIndex: 15, envVarConstant: "clone_aws_access_key_id", envVarValueRef: &v1.EnvVarSource{ SecretKeyRef: &v1.SecretKeySelector{ @@ -593,12 +610,12 @@ func TestGenerateSpiloPodEnvVars(t *testing.T) { } expectedStandbyEnvSecret := []ExpectedValue{ { - envIndex: 15, + envIndex: 18, envVarConstant: "STANDBY_WALE_GS_PREFIX", envVarValue: "gs://some/path/", }, { - envIndex: 20, + envIndex: 17, envVarConstant: "standby_google_application_credentials", envVarValueRef: &v1.EnvVarSource{ SecretKeyRef: &v1.SecretKeySelector{ @@ -761,14 +778,36 @@ func TestGenerateSpiloPodEnvVars(t *testing.T) { }, }, { - subTest: "will set CLONE_ parameters from spec and not global config or pod environment config map", + subTest: "will set CLONE_ parameters from spec, if nothing env is set", + opConfig: config.Config{}, + cloneDescription: &acidv1.CloneDescription{ + ClusterName: "test-cluster", + EndTimestamp: "somewhen", + UID: dummyUUID, + S3WalPath: "s3://another-bucket", + S3Endpoint: "s3.eu-central-1.amazonaws.com", + }, + standbyDescription: &acidv1.StandbyDescription{}, + expectedValues: expectedCloneEnvSpec, + }, + { + subTest: "will set CLONE_ parameters from spec and override scope prefix", opConfig: config.Config{ Resources: config.Resources{ PodEnvironmentConfigMap: spec.NamespacedName{ Name: testPodEnvironmentConfigMapName, }, }, - WALES3Bucket: "global-s3-bucket", + }, + pgsql: acidv1.Postgresql{ + Spec: acidv1.PostgresSpec{ + Env: []v1.EnvVar{ + { + Name: "CLONE_WAL_BUCKET_SCOPE_PREFIX", + Value: "spec-env-test", + }, + }, + }, }, cloneDescription: &acidv1.CloneDescription{ ClusterName: "test-cluster", @@ -778,7 +817,7 @@ func TestGenerateSpiloPodEnvVars(t *testing.T) { S3Endpoint: "s3.eu-central-1.amazonaws.com", }, standbyDescription: &acidv1.StandbyDescription{}, - expectedValues: expectedCloneEnvSpec, + expectedValues: expectedCloneEnvWithPrefixSpec, }, { subTest: "will set CLONE_AWS_ENDPOINT parameter from pod environment config map", @@ -835,36 +874,39 @@ func TestGenerateSpiloPodEnvVars(t *testing.T) { } for _, tt := range tests { - c := newMockCluster(tt.opConfig) - pgsql := tt.pgsql - pgsql.Spec.Clone = tt.cloneDescription - pgsql.Spec.StandbyCluster = tt.standbyDescription - c.Postgresql = pgsql - - actualEnvs, err := c.generateSpiloPodEnvVars(&pgsql.Spec, types.UID(dummyUUID), exampleSpiloConfig) - assert.NoError(t, err) - - for _, ev := range tt.expectedValues { - env := actualEnvs[ev.envIndex] + t.Run(tt.subTest, func(t *testing.T) { + c := newMockCluster(tt.opConfig) + pgsql := tt.pgsql + pgsql.Spec.Clone = tt.cloneDescription + pgsql.Spec.StandbyCluster = tt.standbyDescription + c.Postgresql = pgsql + + actualEnvs, err := c.generateSpiloPodEnvVars(&pgsql.Spec, types.UID(dummyUUID), exampleSpiloConfig) + assert.NoError(t, err) + + for _, ev := range tt.expectedValues { + env := actualEnvs[ev.envIndex] + + if env.Name != ev.envVarConstant { + t.Errorf("%s %s: expected env name %s, have %s instead", + testName, tt.subTest, ev.envVarConstant, env.Name) + } - if env.Name != ev.envVarConstant { - t.Errorf("%s %s: expected env name %s, have %s instead", - testName, tt.subTest, ev.envVarConstant, env.Name) - } + if ev.envVarValueRef != nil { + if !reflect.DeepEqual(env.ValueFrom, ev.envVarValueRef) { + t.Errorf("%s %s: expected env value reference %#v, have %#v instead", + testName, tt.subTest, ev.envVarValueRef, env.ValueFrom) + } + continue + } - if ev.envVarValueRef != nil { - if !reflect.DeepEqual(env.ValueFrom, ev.envVarValueRef) { - t.Errorf("%s %s: expected env value reference %#v, have %#v instead", - testName, tt.subTest, ev.envVarValueRef, env.ValueFrom) + if env.Value != ev.envVarValue { + t.Errorf("%s %s: expected env value %s, have %s instead", + testName, tt.subTest, ev.envVarValue, env.Value) } - continue } - if env.Value != ev.envVarValue { - t.Errorf("%s %s: expected env value %s, have %s instead", - testName, tt.subTest, ev.envVarValue, env.Value) - } - } + }) } } @@ -1060,19 +1102,21 @@ func TestCloneEnv(t *testing.T) { }, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder) for _, tt := range tests { - envs := cluster.generateCloneEnvironment(tt.cloneOpts) + t.Run(tt.subTest, func(t *testing.T) { + envs := cluster.generateCloneEnvironment(tt.cloneOpts) - env := envs[tt.envPos] + env := envs[tt.envPos] - if env.Name != tt.env.Name { - t.Errorf("%s %s: Expected env name %s, have %s instead", - testName, tt.subTest, tt.env.Name, env.Name) - } + if env.Name != tt.env.Name { + t.Errorf("%s %s: Expected env name %s, have %s instead", + testName, tt.subTest, tt.env.Name, env.Name) + } - if env.Value != tt.env.Value { - t.Errorf("%s %s: Expected env value %s, have %s instead", - testName, tt.subTest, tt.env.Value, env.Value) - } + if env.Value != tt.env.Value { + t.Errorf("%s %s: Expected env value %s, have %s instead", + testName, tt.subTest, tt.env.Value, env.Value) + } + }) } }