From 7d8c70a23b0d60ab01e8ed8c7c62efbd1cf8c9a8 Mon Sep 17 00:00:00 2001 From: Philipp Eberle Date: Mon, 22 Feb 2021 09:44:54 +0100 Subject: [PATCH] Initial modifications for logical backups --- api/v1/zalandopostgres_types.go | 13 +++++++------ controllers/postgres_controller.go | 16 +++++++++++++++- pkg/operatormanager/operatormanager.go | 25 ++++++++++++++++++------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/api/v1/zalandopostgres_types.go b/api/v1/zalandopostgres_types.go index 4373f8a9..f13f4152 100644 --- a/api/v1/zalandopostgres_types.go +++ b/api/v1/zalandopostgres_types.go @@ -31,12 +31,13 @@ type ZalandoPostgres struct { } type ZalandoPostgresSpec struct { - MaintenanceWindows []MaintenanceWindow `json:"maintenanceWindows,omitempty"` - NumberOfInstances int32 `json:"numberOfInstances"` - PostgresqlParam PostgresqlParam `json:"postgresql"` - Resources *Resources `json:"resources,omitempty"` - TeamID string `json:"teamId"` - Volume Volume `json:"volume"` + MaintenanceWindows []MaintenanceWindow `json:"maintenanceWindows,omitempty"` + NumberOfInstances int32 `json:"numberOfInstances"` + PostgresqlParam PostgresqlParam `json:"postgresql"` + Resources *Resources `json:"resources,omitempty"` + TeamID string `json:"teamId"` + Volume Volume `json:"volume"` + EnableLogicalBackup bool `json:"enableLogicalBackup,omitempty"` } type MaintenanceWindow struct { diff --git a/controllers/postgres_controller.go b/controllers/postgres_controller.go index ed6ff518..f3e9f3bd 100644 --- a/controllers/postgres_controller.go +++ b/controllers/postgres_controller.go @@ -198,6 +198,10 @@ func (r *PostgresReconciler) createZalandoPostgresql(ctx context.Context, instan } } + // TODO make configurable + log.Info("Enabling logical backup", "zalando", z) + z.Spec.EnableLogicalBackup = true + u, err := z.ToUnstructured() if err != nil { log.Error(err, "error while converting to unstructured") @@ -248,8 +252,18 @@ func (r *PostgresReconciler) ensureZalandoDependencies(ctx context.Context, p *p backupSchedule := string(backupSecret.Data[pg.BackupSecretSchedule]) backupNumToRetain := string(backupSecret.Data[pg.BackupSecretRetention]) + backupConf := operatormanager.LogicalBackupConfig{ + S3Endpoint: awsEndpoint, + // TODO use different bucket for logical backups? + S3BucketName: bucketName, + S3AccessKeyID: awsAccessKeyID, + S3SecretAccessKey: awsSecretAccessKey, + // TODO use different schedule + Schedule: "*/5 * * * *", + } + if !isInstalled { - _, err := r.InstallOperator(ctx, namespace, awsEndpoint+"/"+bucketName) // TODO check the s3BucketUrl... + _, err := r.InstallOperator(ctx, namespace, backupConf) if err != nil { return fmt.Errorf("error while installing zalando dependencies: %v", err) } diff --git a/pkg/operatormanager/operatormanager.go b/pkg/operatormanager/operatormanager.go index 4b24c66e..4ef12053 100644 --- a/pkg/operatormanager/operatormanager.go +++ b/pkg/operatormanager/operatormanager.go @@ -75,7 +75,7 @@ func New(client client.Client, fileName string, scheme *runtime.Scheme, log logr } // InstallOperator installs the operator Stored in `OperatorManager` -func (m *OperatorManager) InstallOperator(ctx context.Context, namespace, s3BucketURL string) ([]runtime.Object, error) { +func (m *OperatorManager) InstallOperator(ctx context.Context, namespace string, backupConfig LogicalBackupConfig) ([]runtime.Object, error) { objs := []runtime.Object{} // Make sure the namespace exists. @@ -97,7 +97,7 @@ func (m *OperatorManager) InstallOperator(ctx context.Context, namespace, s3Buck return objs, fmt.Errorf("error while converting yaml to `runtime.Object`: %v", err) } - if objs, err := m.createNewRuntimeObject(ctx, objs, obj, namespace, s3BucketURL); err != nil { + if objs, err := m.createNewRuntimeObject(ctx, objs, obj, namespace, backupConfig); err != nil { return objs, fmt.Errorf("error while creating the `runtime.Object`: %v", err) } } @@ -209,7 +209,7 @@ func (m *OperatorManager) UninstallOperator(ctx context.Context, namespace strin } // createNewRuntimeObject adds namespace to obj and creates or patches it -func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []runtime.Object, obj runtime.Object, namespace, s3BucketURL string) ([]runtime.Object, error) { +func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []runtime.Object, obj runtime.Object, namespace string, backupConf LogicalBackupConfig) ([]runtime.Object, error) { if err := m.ensureCleanMetadata(obj); err != nil { return objs, fmt.Errorf("error while ensuring the metadata of the `runtime.Object` is clean: %v", err) } @@ -264,7 +264,7 @@ func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []run } case *v1.ConfigMap: m.Log.Info("handling ConfigMap") - m.editConfigMap(v, namespace, s3BucketURL) + m.editConfigMap(v, namespace, backupConf) err = m.Get(ctx, key, &v1.ConfigMap{}) case *v1.Service: m.Log.Info("handling Service") @@ -292,10 +292,21 @@ func (m *OperatorManager) createNewRuntimeObject(ctx context.Context, objs []run return objs, nil } +type LogicalBackupConfig struct { + S3Endpoint string + S3BucketName string + S3AccessKeyID string + S3SecretAccessKey string + Schedule string +} + // editConfigMap adds info to cm -func (m *OperatorManager) editConfigMap(cm *v1.ConfigMap, namespace, s3BucketURL string) { - // TODO re-enable - // cm.Data["logical_backup_s3_bucket"] = s3BucketURL +func (m *OperatorManager) editConfigMap(cm *v1.ConfigMap, namespace string, config LogicalBackupConfig) { + cm.Data["logical_backup_s3_access_key_id"] = config.S3AccessKeyID + cm.Data["logical_backup_s3_secret_access_key"] = config.S3SecretAccessKey + cm.Data["logical_backup_s3_endpoint"] = config.S3Endpoint + cm.Data["logical_backup_s3_bucket"] = config.S3BucketName + cm.Data["logical_backup_schedule"] = config.Schedule cm.Data["watched_namespace"] = namespace // TODO don't use the same serviceaccount for operator and databases, see #88 cm.Data["pod_service_account_name"] = serviceAccountName