Logical backup secret (#2051)

* Add logical backup secret
This commit is contained in:
Stef Graces 2024-01-04 11:09:16 +01:00 committed by GitHub
parent f6add42b7e
commit bbba15f9bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 145 additions and 0 deletions

View File

@ -539,6 +539,8 @@ spec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
default: "30 00 * * *"
logical_backup_cronjob_environment_secret:
type: string
debug:
type: object
properties:

View File

@ -376,6 +376,8 @@ configLogicalBackup:
logical_backup_s3_retention_time: ""
# backup schedule in the cron format
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
configTeamsApi:

View File

@ -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)
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
Options to aid debugging of the operator itself. Grouped under the `debug` key.

View File

@ -94,6 +94,7 @@ data:
logical_backup_s3_sse: "AES256"
# logical_backup_s3_retention_time: ""
logical_backup_schedule: "30 00 * * *"
# logical_backup_cronjob_environment_secret: ""
major_version_upgrade_mode: "manual"
# major_version_upgrade_team_allow_list: ""
master_dns_name_format: "{cluster}.{namespace}.{hostedzone}"

View File

@ -537,6 +537,8 @@ spec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
default: "30 00 * * *"
logical_backup_cronjob_environment_secret:
type: string
debug:
type: object
properties:

View File

@ -175,6 +175,7 @@ configuration:
logical_backup_s3_sse: "AES256"
# logical_backup_s3_retention_time: ""
logical_backup_schedule: "30 00 * * *"
# logical_backup_cronjob_environment_secret: ""
debug:
debug_logging: true
enable_database_access: true

View File

@ -1746,6 +1746,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
Type: "string",
Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$",
},
"logical_backup_cronjob_environment_secret": {
Type: "string",
},
},
},
"debug": {

View File

@ -233,6 +233,7 @@ type OperatorLogicalBackupConfiguration struct {
RetentionTime string `json:"logical_backup_s3_retention_time,omitempty"`
GoogleApplicationCredentials string `json:"logical_backup_google_application_credentials,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"`
MemoryRequest string `json:"logical_backup_memory_request,omitempty"`
CPULimit string `json:"logical_backup_cpu_limit,omitempty"`

View File

@ -1137,6 +1137,37 @@ func (c *Cluster) getPodEnvironmentSecretVariables() ([]v1.EnvVar, error) {
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 {
name := sidecar.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)
}
secretEnvVarsList, err := c.getCronjobEnvironmentSecretVariables()
if err != nil {
return nil, err
}
envVars := c.generateLogicalBackupPodEnvVars()
envVars = append(envVars, secretEnvVarsList...)
logicalBackupContainer := generateContainer(
logicalBackupContainerName,
&c.OpConfig.LogicalBackup.LogicalBackupDockerImage,

View File

@ -192,6 +192,7 @@ func TestExtractPgVersionFromBinPath(t *testing.T) {
const (
testPodEnvironmentConfigMapName = "pod_env_cm"
testPodEnvironmentSecretName = "pod_env_sc"
testCronjobEnvironmentSecretName = "pod_env_sc"
testPodEnvironmentObjectNotExists = "idonotexist"
testPodEnvironmentSecretNameAPIError = "pod_env_sc_apierror"
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 {
required := map[string]bool{
"PGHOST": false,

View File

@ -189,6 +189,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
result.LogicalBackupS3RetentionTime = fromCRD.LogicalBackup.RetentionTime
result.LogicalBackupGoogleApplicationCredentials = fromCRD.LogicalBackup.GoogleApplicationCredentials
result.LogicalBackupJobPrefix = util.Coalesce(fromCRD.LogicalBackup.JobPrefix, "logical-backup-")
result.LogicalBackupCronjobEnvironmentSecret = fromCRD.LogicalBackup.CronjobEnvironmentSecret
result.LogicalBackupCPURequest = fromCRD.LogicalBackup.CPURequest
result.LogicalBackupMemoryRequest = fromCRD.LogicalBackup.MemoryRequest
result.LogicalBackupCPULimit = fromCRD.LogicalBackup.CPULimit

View File

@ -140,6 +140,7 @@ type LogicalBackup struct {
LogicalBackupS3RetentionTime string `name:"logical_backup_s3_retention_time" default:""`
LogicalBackupGoogleApplicationCredentials string `name:"logical_backup_google_application_credentials" default:""`
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"`
LogicalBackupMemoryRequest string `name:"logical_backup_memory_request"`
LogicalBackupCPULimit string `name:"logical_backup_cpu_limit"`