parent
f6add42b7e
commit
bbba15f9bf
|
|
@ -539,6 +539,8 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
||||||
default: "30 00 * * *"
|
default: "30 00 * * *"
|
||||||
|
logical_backup_cronjob_environment_secret:
|
||||||
|
type: string
|
||||||
debug:
|
debug:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,8 @@ configLogicalBackup:
|
||||||
logical_backup_s3_retention_time: ""
|
logical_backup_s3_retention_time: ""
|
||||||
# backup schedule in the cron format
|
# backup schedule in the cron format
|
||||||
logical_backup_schedule: "30 00 * * *"
|
logical_backup_schedule: "30 00 * * *"
|
||||||
|
# secret to be used as reference for env variables in cronjob
|
||||||
|
logical_backup_cronjob_environment_secret: ""
|
||||||
|
|
||||||
# automate creation of human users with teams API service
|
# automate creation of human users with teams API service
|
||||||
configTeamsApi:
|
configTeamsApi:
|
||||||
|
|
|
||||||
|
|
@ -825,6 +825,9 @@ grouped under the `logical_backup` key.
|
||||||
[reference schedule format](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#schedule)
|
[reference schedule format](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#schedule)
|
||||||
into account. Default: "30 00 \* \* \*"
|
into account. Default: "30 00 \* \* \*"
|
||||||
|
|
||||||
|
* **logical_backup_cronjob_environment_secret**
|
||||||
|
Reference to a Kubernetes secret, which keys will be added as environment variables to the cronjob. Default: ""
|
||||||
|
|
||||||
## Debugging the operator
|
## Debugging the operator
|
||||||
|
|
||||||
Options to aid debugging of the operator itself. Grouped under the `debug` key.
|
Options to aid debugging of the operator itself. Grouped under the `debug` key.
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ data:
|
||||||
logical_backup_s3_sse: "AES256"
|
logical_backup_s3_sse: "AES256"
|
||||||
# logical_backup_s3_retention_time: ""
|
# logical_backup_s3_retention_time: ""
|
||||||
logical_backup_schedule: "30 00 * * *"
|
logical_backup_schedule: "30 00 * * *"
|
||||||
|
# logical_backup_cronjob_environment_secret: ""
|
||||||
major_version_upgrade_mode: "manual"
|
major_version_upgrade_mode: "manual"
|
||||||
# major_version_upgrade_team_allow_list: ""
|
# major_version_upgrade_team_allow_list: ""
|
||||||
master_dns_name_format: "{cluster}.{namespace}.{hostedzone}"
|
master_dns_name_format: "{cluster}.{namespace}.{hostedzone}"
|
||||||
|
|
|
||||||
|
|
@ -537,6 +537,8 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
||||||
default: "30 00 * * *"
|
default: "30 00 * * *"
|
||||||
|
logical_backup_cronjob_environment_secret:
|
||||||
|
type: string
|
||||||
debug:
|
debug:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ configuration:
|
||||||
logical_backup_s3_sse: "AES256"
|
logical_backup_s3_sse: "AES256"
|
||||||
# logical_backup_s3_retention_time: ""
|
# logical_backup_s3_retention_time: ""
|
||||||
logical_backup_schedule: "30 00 * * *"
|
logical_backup_schedule: "30 00 * * *"
|
||||||
|
# logical_backup_cronjob_environment_secret: ""
|
||||||
debug:
|
debug:
|
||||||
debug_logging: true
|
debug_logging: true
|
||||||
enable_database_access: true
|
enable_database_access: true
|
||||||
|
|
|
||||||
|
|
@ -1746,6 +1746,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
|
||||||
Type: "string",
|
Type: "string",
|
||||||
Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$",
|
Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$",
|
||||||
},
|
},
|
||||||
|
"logical_backup_cronjob_environment_secret": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ type OperatorLogicalBackupConfiguration struct {
|
||||||
RetentionTime string `json:"logical_backup_s3_retention_time,omitempty"`
|
RetentionTime string `json:"logical_backup_s3_retention_time,omitempty"`
|
||||||
GoogleApplicationCredentials string `json:"logical_backup_google_application_credentials,omitempty"`
|
GoogleApplicationCredentials string `json:"logical_backup_google_application_credentials,omitempty"`
|
||||||
JobPrefix string `json:"logical_backup_job_prefix,omitempty"`
|
JobPrefix string `json:"logical_backup_job_prefix,omitempty"`
|
||||||
|
CronjobEnvironmentSecret string `json:"logical_backup_cronjob_environment_secret,omitempty"`
|
||||||
CPURequest string `json:"logical_backup_cpu_request,omitempty"`
|
CPURequest string `json:"logical_backup_cpu_request,omitempty"`
|
||||||
MemoryRequest string `json:"logical_backup_memory_request,omitempty"`
|
MemoryRequest string `json:"logical_backup_memory_request,omitempty"`
|
||||||
CPULimit string `json:"logical_backup_cpu_limit,omitempty"`
|
CPULimit string `json:"logical_backup_cpu_limit,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -1137,6 +1137,37 @@ func (c *Cluster) getPodEnvironmentSecretVariables() ([]v1.EnvVar, error) {
|
||||||
return secretPodEnvVarsList, nil
|
return secretPodEnvVarsList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return list of variables the cronjob received from the configured Secret
|
||||||
|
func (c *Cluster) getCronjobEnvironmentSecretVariables() ([]v1.EnvVar, error) {
|
||||||
|
secretCronjobEnvVarsList := make([]v1.EnvVar, 0)
|
||||||
|
|
||||||
|
if c.OpConfig.LogicalBackupCronjobEnvironmentSecret == "" {
|
||||||
|
return secretCronjobEnvVarsList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, err := c.KubeClient.Secrets(c.Namespace).Get(
|
||||||
|
context.TODO(),
|
||||||
|
c.OpConfig.LogicalBackupCronjobEnvironmentSecret,
|
||||||
|
metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read Secret CronjobEnvironmentSecretName: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k := range secret.Data {
|
||||||
|
secretCronjobEnvVarsList = append(secretCronjobEnvVarsList,
|
||||||
|
v1.EnvVar{Name: k, ValueFrom: &v1.EnvVarSource{
|
||||||
|
SecretKeyRef: &v1.SecretKeySelector{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: c.OpConfig.LogicalBackupCronjobEnvironmentSecret,
|
||||||
|
},
|
||||||
|
Key: k,
|
||||||
|
},
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
|
||||||
|
return secretCronjobEnvVarsList, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getSidecarContainer(sidecar acidv1.Sidecar, index int, resources *v1.ResourceRequirements) *v1.Container {
|
func getSidecarContainer(sidecar acidv1.Sidecar, index int, resources *v1.ResourceRequirements) *v1.Container {
|
||||||
name := sidecar.Name
|
name := sidecar.Name
|
||||||
if name == "" {
|
if name == "" {
|
||||||
|
|
@ -2172,7 +2203,13 @@ func (c *Cluster) generateLogicalBackupJob() (*batchv1.CronJob, error) {
|
||||||
return nil, fmt.Errorf("could not generate resource requirements for logical backup pods: %v", err)
|
return nil, fmt.Errorf("could not generate resource requirements for logical backup pods: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secretEnvVarsList, err := c.getCronjobEnvironmentSecretVariables()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
envVars := c.generateLogicalBackupPodEnvVars()
|
envVars := c.generateLogicalBackupPodEnvVars()
|
||||||
|
envVars = append(envVars, secretEnvVarsList...)
|
||||||
logicalBackupContainer := generateContainer(
|
logicalBackupContainer := generateContainer(
|
||||||
logicalBackupContainerName,
|
logicalBackupContainerName,
|
||||||
&c.OpConfig.LogicalBackup.LogicalBackupDockerImage,
|
&c.OpConfig.LogicalBackup.LogicalBackupDockerImage,
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,7 @@ func TestExtractPgVersionFromBinPath(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
testPodEnvironmentConfigMapName = "pod_env_cm"
|
testPodEnvironmentConfigMapName = "pod_env_cm"
|
||||||
testPodEnvironmentSecretName = "pod_env_sc"
|
testPodEnvironmentSecretName = "pod_env_sc"
|
||||||
|
testCronjobEnvironmentSecretName = "pod_env_sc"
|
||||||
testPodEnvironmentObjectNotExists = "idonotexist"
|
testPodEnvironmentObjectNotExists = "idonotexist"
|
||||||
testPodEnvironmentSecretNameAPIError = "pod_env_sc_apierror"
|
testPodEnvironmentSecretNameAPIError = "pod_env_sc_apierror"
|
||||||
testResourceCheckInterval = 3
|
testResourceCheckInterval = 3
|
||||||
|
|
@ -448,6 +449,96 @@ func TestPodEnvironmentSecretVariables(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test if the keys of an existing secret are properly referenced
|
||||||
|
func TestCronjobEnvironmentSecretVariables(t *testing.T) {
|
||||||
|
testName := "TestCronjobEnvironmentSecretVariables"
|
||||||
|
tests := []struct {
|
||||||
|
subTest string
|
||||||
|
opConfig config.Config
|
||||||
|
envVars []v1.EnvVar
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
subTest: "No CronjobEnvironmentSecret configured",
|
||||||
|
envVars: []v1.EnvVar{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subTest: "Secret referenced by CronjobEnvironmentSecret does not exist",
|
||||||
|
opConfig: config.Config{
|
||||||
|
LogicalBackup: config.LogicalBackup{
|
||||||
|
LogicalBackupCronjobEnvironmentSecret: "idonotexist",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: fmt.Errorf("could not read Secret CronjobEnvironmentSecretName: secret.core \"idonotexist\" not found"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subTest: "Cronjob environment vars reference all keys from secret configured by CronjobEnvironmentSecret",
|
||||||
|
opConfig: config.Config{
|
||||||
|
LogicalBackup: config.LogicalBackup{
|
||||||
|
LogicalBackupCronjobEnvironmentSecret: testCronjobEnvironmentSecretName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
envVars: []v1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "clone_aws_access_key_id",
|
||||||
|
ValueFrom: &v1.EnvVarSource{
|
||||||
|
SecretKeyRef: &v1.SecretKeySelector{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: testPodEnvironmentSecretName,
|
||||||
|
},
|
||||||
|
Key: "clone_aws_access_key_id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "custom_variable",
|
||||||
|
ValueFrom: &v1.EnvVarSource{
|
||||||
|
SecretKeyRef: &v1.SecretKeySelector{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: testPodEnvironmentSecretName,
|
||||||
|
},
|
||||||
|
Key: "custom_variable",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "standby_google_application_credentials",
|
||||||
|
ValueFrom: &v1.EnvVarSource{
|
||||||
|
SecretKeyRef: &v1.SecretKeySelector{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: testPodEnvironmentSecretName,
|
||||||
|
},
|
||||||
|
Key: "standby_google_application_credentials",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
c := newMockCluster(tt.opConfig)
|
||||||
|
vars, err := c.getCronjobEnvironmentSecretVariables()
|
||||||
|
sort.Slice(vars, func(i, j int) bool { return vars[i].Name < vars[j].Name })
|
||||||
|
if !reflect.DeepEqual(vars, tt.envVars) {
|
||||||
|
t.Errorf("%s %s: expected `%v` but got `%v`",
|
||||||
|
testName, tt.subTest, tt.envVars, vars)
|
||||||
|
}
|
||||||
|
if tt.err != nil {
|
||||||
|
if err.Error() != tt.err.Error() {
|
||||||
|
t.Errorf("%s %s: expected error `%v` but got `%v`",
|
||||||
|
testName, tt.subTest, tt.err, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s %s: expected no error but got error: `%v`",
|
||||||
|
testName, tt.subTest, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func testEnvs(cluster *Cluster, podSpec *v1.PodTemplateSpec, role PostgresRole) error {
|
func testEnvs(cluster *Cluster, podSpec *v1.PodTemplateSpec, role PostgresRole) error {
|
||||||
required := map[string]bool{
|
required := map[string]bool{
|
||||||
"PGHOST": false,
|
"PGHOST": false,
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||||
result.LogicalBackupS3RetentionTime = fromCRD.LogicalBackup.RetentionTime
|
result.LogicalBackupS3RetentionTime = fromCRD.LogicalBackup.RetentionTime
|
||||||
result.LogicalBackupGoogleApplicationCredentials = fromCRD.LogicalBackup.GoogleApplicationCredentials
|
result.LogicalBackupGoogleApplicationCredentials = fromCRD.LogicalBackup.GoogleApplicationCredentials
|
||||||
result.LogicalBackupJobPrefix = util.Coalesce(fromCRD.LogicalBackup.JobPrefix, "logical-backup-")
|
result.LogicalBackupJobPrefix = util.Coalesce(fromCRD.LogicalBackup.JobPrefix, "logical-backup-")
|
||||||
|
result.LogicalBackupCronjobEnvironmentSecret = fromCRD.LogicalBackup.CronjobEnvironmentSecret
|
||||||
result.LogicalBackupCPURequest = fromCRD.LogicalBackup.CPURequest
|
result.LogicalBackupCPURequest = fromCRD.LogicalBackup.CPURequest
|
||||||
result.LogicalBackupMemoryRequest = fromCRD.LogicalBackup.MemoryRequest
|
result.LogicalBackupMemoryRequest = fromCRD.LogicalBackup.MemoryRequest
|
||||||
result.LogicalBackupCPULimit = fromCRD.LogicalBackup.CPULimit
|
result.LogicalBackupCPULimit = fromCRD.LogicalBackup.CPULimit
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ type LogicalBackup struct {
|
||||||
LogicalBackupS3RetentionTime string `name:"logical_backup_s3_retention_time" default:""`
|
LogicalBackupS3RetentionTime string `name:"logical_backup_s3_retention_time" default:""`
|
||||||
LogicalBackupGoogleApplicationCredentials string `name:"logical_backup_google_application_credentials" default:""`
|
LogicalBackupGoogleApplicationCredentials string `name:"logical_backup_google_application_credentials" default:""`
|
||||||
LogicalBackupJobPrefix string `name:"logical_backup_job_prefix" default:"logical-backup-"`
|
LogicalBackupJobPrefix string `name:"logical_backup_job_prefix" default:"logical-backup-"`
|
||||||
|
LogicalBackupCronjobEnvironmentSecret string `name:"logical_backup_cronjob_environment_secret" default:""`
|
||||||
LogicalBackupCPURequest string `name:"logical_backup_cpu_request"`
|
LogicalBackupCPURequest string `name:"logical_backup_cpu_request"`
|
||||||
LogicalBackupMemoryRequest string `name:"logical_backup_memory_request"`
|
LogicalBackupMemoryRequest string `name:"logical_backup_memory_request"`
|
||||||
LogicalBackupCPULimit string `name:"logical_backup_cpu_limit"`
|
LogicalBackupCPULimit string `name:"logical_backup_cpu_limit"`
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue