refactor spilo env generation

This commit is contained in:
Felix Kunde 2022-04-12 17:18:58 +02:00
parent 483bf624ee
commit a8b264de29
4 changed files with 988 additions and 824 deletions

View File

@ -1318,7 +1318,7 @@ func (c *Cluster) initAdditionalOwnerRoles() {
} }
} }
if len(memberOf) > 1 { if len(memberOf) > 0 {
namespace := c.Namespace namespace := c.Namespace
additionalOwnerPgUser := spec.PgUser{ additionalOwnerPgUser := spec.PgUser{
Origin: spec.RoleOriginSpilo, Origin: spec.RoleOriginSpilo,

View File

@ -26,6 +26,8 @@ import (
const ( const (
superUserName = "postgres" superUserName = "postgres"
replicationUserName = "standby" replicationUserName = "standby"
exampleSpiloConfig = `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_connections":"100","max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`
spiloConfigDiff = `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`
) )
var logger = logrus.New().WithField("test", "cluster") var logger = logrus.New().WithField("test", "cluster")
@ -957,7 +959,7 @@ func TestCompareEnv(t *testing.T) {
}, },
{ {
Name: "SPILO_CONFIGURATION", Name: "SPILO_CONFIGURATION",
Value: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_connections":"100","max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`, Value: exampleSpiloConfig,
}, },
}, },
ExpectedResult: true, ExpectedResult: true,
@ -978,7 +980,7 @@ func TestCompareEnv(t *testing.T) {
}, },
{ {
Name: "SPILO_CONFIGURATION", Name: "SPILO_CONFIGURATION",
Value: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`, Value: spiloConfigDiff,
}, },
}, },
ExpectedResult: true, ExpectedResult: true,
@ -999,7 +1001,7 @@ func TestCompareEnv(t *testing.T) {
}, },
{ {
Name: "SPILO_CONFIGURATION", Name: "SPILO_CONFIGURATION",
Value: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`, Value: exampleSpiloConfig,
}, },
}, },
ExpectedResult: false, ExpectedResult: false,
@ -1024,7 +1026,7 @@ func TestCompareEnv(t *testing.T) {
}, },
{ {
Name: "SPILO_CONFIGURATION", Name: "SPILO_CONFIGURATION",
Value: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_connections":"100","max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`, Value: exampleSpiloConfig,
}, },
}, },
ExpectedResult: false, ExpectedResult: false,
@ -1041,7 +1043,7 @@ func TestCompareEnv(t *testing.T) {
}, },
{ {
Name: "SPILO_CONFIGURATION", Name: "SPILO_CONFIGURATION",
Value: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/12/bin","parameters":{"autovacuum_analyze_scale_factor":"0.1"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"test":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"postgresql":{"parameters":{"max_connections":"100","max_locks_per_transaction":"64","max_worker_processes":"4"}}}}}`, Value: exampleSpiloConfig,
}, },
}, },
ExpectedResult: false, ExpectedResult: false,

View File

@ -766,9 +766,10 @@ func (c *Cluster) generateSpiloPodEnvVars(
uid types.UID, uid types.UID,
spiloConfiguration string, spiloConfiguration string,
cloneDescription *acidv1.CloneDescription, cloneDescription *acidv1.CloneDescription,
standbyDescription *acidv1.StandbyDescription, standbyDescription *acidv1.StandbyDescription) []v1.EnvVar {
customPodEnvVarsList []v1.EnvVar) []v1.EnvVar {
// hard-coded set of environment variables we need
// to guarantee core functionality of the operator
envVars := []v1.EnvVar{ envVars := []v1.EnvVar{
{ {
Name: "SCOPE", Name: "SCOPE",
@ -871,58 +872,77 @@ func (c *Cluster) generateSpiloPodEnvVars(
envVars = append(envVars, v1.EnvVar{Name: "KUBERNETES_USE_CONFIGMAPS", Value: "true"}) envVars = append(envVars, v1.EnvVar{Name: "KUBERNETES_USE_CONFIGMAPS", Value: "true"})
} }
if cloneDescription != nil && cloneDescription.ClusterName != "" { // fetch cluster-specific variables that will override all subsequent global variables
envVars = append(envVars, c.generateCloneEnvironment(cloneDescription)...)
}
if c.Spec.StandbyCluster != nil {
envVars = append(envVars, c.generateStandbyEnvironment(standbyDescription)...)
}
if len(c.Spec.Env) > 0 { if len(c.Spec.Env) > 0 {
envVars = appendEnvVars(envVars, c.Spec.Env...) envVars = appendEnvVars(envVars, c.Spec.Env...)
} }
// add vars taken from pod_environment_configmap and pod_environment_secret first // fetch variables from custom environment Secret
// (to allow them to override the globals set in the operator config) // that will override all subsequent global variables
if len(customPodEnvVarsList) > 0 { secretEnvVarsList, err := c.getPodEnvironmentSecretVariables()
envVars = appendEnvVars(envVars, customPodEnvVarsList...) if err != nil {
c.logger.Warningf("%v", err)
} }
envVars = appendEnvVars(envVars, secretEnvVarsList...)
// fetch variables from custom environment ConfigMap
// that will override all subsequent global variables
configMapEnvVarsList, err := c.getPodEnvironmentConfigMapVariables()
if err != nil {
c.logger.Warningf("%v", err)
}
envVars = appendEnvVars(envVars, configMapEnvVarsList...)
// global variables derived from operator configuration
opConfigEnvVars := make([]v1.EnvVar, 0)
if c.OpConfig.WALES3Bucket != "" { if c.OpConfig.WALES3Bucket != "" {
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_S3_BUCKET", Value: c.OpConfig.WALES3Bucket}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_S3_BUCKET", Value: c.OpConfig.WALES3Bucket})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""})
} }
if c.OpConfig.WALGSBucket != "" { if c.OpConfig.WALGSBucket != "" {
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_GS_BUCKET", Value: c.OpConfig.WALGSBucket}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_GS_BUCKET", Value: c.OpConfig.WALGSBucket})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""})
} }
if c.OpConfig.WALAZStorageAccount != "" { if c.OpConfig.WALAZStorageAccount != "" {
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "AZURE_STORAGE_ACCOUNT", Value: c.OpConfig.WALAZStorageAccount}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "AZURE_STORAGE_ACCOUNT", Value: c.OpConfig.WALAZStorageAccount})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""})
} }
if c.OpConfig.GCPCredentials != "" { if c.OpConfig.GCPCredentials != "" {
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: c.OpConfig.GCPCredentials}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: c.OpConfig.GCPCredentials})
} }
if c.OpConfig.LogS3Bucket != "" { if c.OpConfig.LogS3Bucket != "" {
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "LOG_S3_BUCKET", Value: c.OpConfig.LogS3Bucket}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "LOG_S3_BUCKET", Value: c.OpConfig.LogS3Bucket})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "LOG_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "LOG_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))})
envVars = appendEnvVars(envVars, v1.EnvVar{Name: "LOG_BUCKET_SCOPE_PREFIX", Value: ""}) opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "LOG_BUCKET_SCOPE_PREFIX", Value: ""})
} }
if cloneDescription != nil && cloneDescription.ClusterName != "" {
opConfigEnvVars = append(opConfigEnvVars, c.generateCloneEnvironment(cloneDescription)...)
}
if c.Spec.StandbyCluster != nil {
opConfigEnvVars = append(opConfigEnvVars, c.generateStandbyEnvironment(standbyDescription)...)
}
envVars = appendEnvVars(envVars, opConfigEnvVars...)
//sort.Slice(envVars,
// func(i, j int) bool { return envVars[i].Name < envVars[j].Name })
return envVars return envVars
} }
func appendEnvVars(envs []v1.EnvVar, appEnv ...v1.EnvVar) []v1.EnvVar { func appendEnvVars(envs []v1.EnvVar, appEnv ...v1.EnvVar) []v1.EnvVar {
jenvs := envs jenvs := envs
for _, env := range appEnv { for _, env := range appEnv {
env.Name = strings.ToUpper(env.Name)
if !isEnvVarPresent(jenvs, env.Name) { if !isEnvVarPresent(jenvs, env.Name) {
jenvs = append(jenvs, env) jenvs = append(jenvs, env)
} }
@ -960,12 +980,14 @@ func (c *Cluster) getPodEnvironmentConfigMapVariables() ([]v1.EnvVar, error) {
metav1.GetOptions{}) metav1.GetOptions{})
} }
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read PodEnvironmentConfigMap: %v", err) return configMapPodEnvVarsList, fmt.Errorf("could not read PodEnvironmentConfigMap: %v", err)
} }
} }
for k, v := range cm.Data { for k, v := range cm.Data {
configMapPodEnvVarsList = append(configMapPodEnvVarsList, v1.EnvVar{Name: k, Value: v}) configMapPodEnvVarsList = append(configMapPodEnvVarsList, v1.EnvVar{Name: k, Value: v})
} }
sort.Slice(configMapPodEnvVarsList, func(i, j int) bool { return configMapPodEnvVarsList[i].Name < configMapPodEnvVarsList[j].Name })
return configMapPodEnvVarsList, nil return configMapPodEnvVarsList, nil
} }
@ -1000,7 +1022,7 @@ func (c *Cluster) getPodEnvironmentSecretVariables() ([]v1.EnvVar, error) {
err = errors.Wrap(notFoundErr, err.Error()) err = errors.Wrap(notFoundErr, err.Error())
} }
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read Secret PodEnvironmentSecretName") return secretPodEnvVarsList, errors.Wrap(err, "could not read Secret PodEnvironmentSecretName")
} }
for k := range secret.Data { for k := range secret.Data {
@ -1015,6 +1037,7 @@ func (c *Cluster) getPodEnvironmentSecretVariables() ([]v1.EnvVar, error) {
}}) }})
} }
sort.Slice(secretPodEnvVarsList, func(i, j int) bool { return secretPodEnvVarsList[i].Name < secretPodEnvVarsList[j].Name })
return secretPodEnvVarsList, nil return secretPodEnvVarsList, nil
} }
@ -1104,23 +1127,6 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef
initContainers = spec.InitContainers initContainers = spec.InitContainers
} }
// fetch env vars from custom ConfigMap
configMapEnvVarsList, err := c.getPodEnvironmentConfigMapVariables()
if err != nil {
return nil, err
}
// fetch env vars from custom ConfigMap
secretEnvVarsList, err := c.getPodEnvironmentSecretVariables()
if err != nil {
return nil, err
}
// concat all custom pod env vars and sort them
customPodEnvVarsList := append(configMapEnvVarsList, secretEnvVarsList...)
sort.Slice(customPodEnvVarsList,
func(i, j int) bool { return customPodEnvVarsList[i].Name < customPodEnvVarsList[j].Name })
// backward compatible check for InitContainers // backward compatible check for InitContainers
if spec.InitContainersOld != nil { if spec.InitContainersOld != nil {
msg := "manifest parameter init_containers is deprecated." msg := "manifest parameter init_containers is deprecated."
@ -1153,9 +1159,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef
c.Postgresql.GetUID(), c.Postgresql.GetUID(),
spiloConfiguration, spiloConfiguration,
spec.Clone, spec.Clone,
spec.StandbyCluster, spec.StandbyCluster)
customPodEnvVarsList,
)
// pickup the docker image for the spilo container // pickup the docker image for the spilo container
effectiveDockerImage := util.Coalesce(spec.DockerImage, c.OpConfig.DockerImage) effectiveDockerImage := util.Coalesce(spec.DockerImage, c.OpConfig.DockerImage)

File diff suppressed because it is too large Load Diff