Skip to content

Commit 52e24d2

Browse files
authored
Clone credentials (#416)
* Move standby and postgres usernames to const * Copy credentials when cloning * Refactor creation of secrets * Remove log output
1 parent 768945d commit 52e24d2

File tree

2 files changed

+84
-18
lines changed

2 files changed

+84
-18
lines changed

controllers/postgres_controller.go

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,10 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
221221
}
222222
}
223223

224-
// Make sure the standby secrets exist, if neccessary
225-
if err := r.ensureStandbySecrets(ctx, instance); err != nil {
226-
r.recorder.Eventf(instance, "Warning", "Error", "failed to create standby secrets: %v", err)
227-
return ctrl.Result{}, fmt.Errorf("error while creating standby secrets: %w", err)
224+
// Make sure the postgres secrets exist, if neccessary
225+
if err := r.ensurePostgresSecrets(ctx, instance); err != nil {
226+
r.recorder.Eventf(instance, "Warning", "Error", "failed to create postgres secrets: %v", err)
227+
return ctrl.Result{}, fmt.Errorf("error while creating postgres secrets: %w", err)
228228
}
229229

230230
if instance.IsReplicationPrimary() {
@@ -735,6 +735,20 @@ func (r *PostgresReconciler) getZPostgresqlByLabels(ctx context.Context, matchin
735735
return zpl.Items, nil
736736
}
737737

738+
func (r *PostgresReconciler) ensurePostgresSecrets(ctx context.Context, instance *pg.Postgres) error {
739+
740+
if err := r.ensureStandbySecrets(ctx, instance); err != nil {
741+
return err
742+
}
743+
744+
if err := r.ensureCloneSecrets(ctx, instance); err != nil {
745+
return err
746+
}
747+
748+
return nil
749+
750+
}
751+
738752
func (r *PostgresReconciler) ensureStandbySecrets(ctx context.Context, instance *pg.Postgres) error {
739753
if instance.IsReplicationPrimary() {
740754
// nothing is configured, or we are the leader. nothing to do.
@@ -747,7 +761,7 @@ func (r *PostgresReconciler) ensureStandbySecrets(ctx context.Context, instance
747761
}
748762

749763
// Check if secrets exist local in SERVICE Cluster
750-
localStandbySecretName := "standby." + instance.ToPeripheralResourceName() + ".credentials"
764+
localStandbySecretName := operatormanager.PostgresConfigReplicationUsername + "." + instance.ToPeripheralResourceName() + ".credentials"
751765
localSecretNamespace := instance.ToPeripheralResourceNamespace()
752766
localStandbySecret := &corev1.Secret{}
753767
r.Log.Info("checking for local standby secret", "namespace", localSecretNamespace, "name", localStandbySecretName)
@@ -765,26 +779,77 @@ func (r *PostgresReconciler) ensureStandbySecrets(ctx context.Context, instance
765779

766780
r.Log.Info("no local standby secret found, continuing to create one")
767781

782+
remoteSecretNamespacedName := types.NamespacedName{
783+
Namespace: instance.ObjectMeta.Namespace,
784+
Name: instance.Spec.PostgresConnection.ConnectionSecretName,
785+
}
786+
return r.copySecrets(ctx, remoteSecretNamespacedName, instance, false)
787+
788+
}
789+
790+
func (r *PostgresReconciler) ensureCloneSecrets(ctx context.Context, instance *pg.Postgres) error {
791+
if instance.Spec.PostgresRestore == nil {
792+
// not a clone. nothing to do.
793+
return nil
794+
}
795+
796+
// Check if instance.Spec.PostgresConnectionInfo.ConnectionSecretName is defined
797+
if instance.Spec.PostgresRestore.SourcePostgresID == "" {
798+
return errors.New("SourcePostgresID not configured")
799+
}
800+
801+
// Check if secrets exist local in SERVICE Cluster
802+
localStandbySecretName := operatormanager.PostresConfigSuperUsername + "." + instance.ToPeripheralResourceName() + ".credentials"
803+
localSecretNamespace := instance.ToPeripheralResourceNamespace()
804+
localStandbySecret := &corev1.Secret{}
805+
r.Log.Info("checking for local postgres secret", "namespace", localSecretNamespace, "name", localStandbySecretName)
806+
err := r.SvcClient.Get(ctx, types.NamespacedName{Namespace: localSecretNamespace, Name: localStandbySecretName}, localStandbySecret)
807+
808+
if err == nil {
809+
r.Log.Info("local postgres secret found, no action needed")
810+
return nil
811+
}
812+
813+
// we got an error other than not found, so we cannot continue!
814+
if !apierrors.IsNotFound(err) {
815+
return fmt.Errorf("error while fetching local stadnby secret from service cluster: %w", err)
816+
}
817+
818+
r.Log.Info("no local postgres secret found, continuing to create one")
819+
820+
remoteSecretName := strings.Replace(instance.ToUserPasswordsSecretName(), instance.Name, instance.Spec.PostgresRestore.SourcePostgresID, 1) // TODO this is hacky-wacky...
821+
remoteSecretNamespacedName := types.NamespacedName{
822+
Namespace: instance.ObjectMeta.Namespace,
823+
Name: remoteSecretName,
824+
}
825+
return r.copySecrets(ctx, remoteSecretNamespacedName, instance, true)
826+
827+
}
828+
829+
func (r *PostgresReconciler) copySecrets(ctx context.Context, sourceSecret types.NamespacedName, targetInstance *pg.Postgres, ignoreStandbyUser bool) error {
768830
// Check if secrets exist in remote CONTROL Cluster
769-
remoteSecretName := instance.Spec.PostgresConnection.ConnectionSecretName
770-
remoteSecretNamespace := instance.ObjectMeta.Namespace
771831
remoteSecret := &corev1.Secret{}
772-
r.Log.Info("fetching remote standby secret", "namespace", remoteSecretNamespace, "name", remoteSecretName)
773-
if err := r.CtrlClient.Get(ctx, types.NamespacedName{Namespace: remoteSecretNamespace, Name: remoteSecretName}, remoteSecret); err != nil {
832+
r.Log.Info("fetching remote postgres secret", "namespace", sourceSecret.Namespace, "name", sourceSecret.Name)
833+
if err := r.CtrlClient.Get(ctx, sourceSecret, remoteSecret); err != nil {
774834
// we cannot read the secret given in the configuration, so we cannot continue!
775-
return fmt.Errorf("error while fetching remote standby secret from control plane: %w", err)
835+
return fmt.Errorf("error while fetching remote postgres secret from control plane: %w", err)
776836
}
777837

778-
// copy ALL secrets...
838+
// copy all but the standby secrets...
779839
for username := range remoteSecret.Data {
840+
// check if we skip the standby user (e.g. to prevent old standby intances from connecting once a clone took over its sources ip/port)
841+
if ignoreStandbyUser && username == operatormanager.PostgresConfigReplicationUsername {
842+
continue
843+
}
844+
780845
r.Log.Info("creating local secret", "username", username)
781846

782-
currentSecretName := strings.ReplaceAll(username, "_", "-") + "." + instance.ToPeripheralResourceName() + ".credentials"
847+
currentSecretName := strings.ReplaceAll(username, "_", "-") + "." + targetInstance.ToPeripheralResourceName() + ".credentials"
783848
postgresSecret := &corev1.Secret{
784849
ObjectMeta: metav1.ObjectMeta{
785850
Name: currentSecretName,
786-
Namespace: localSecretNamespace,
787-
Labels: map[string]string(instance.ToZalandoPostgresqlMatchingLabels()),
851+
Namespace: targetInstance.ToPeripheralResourceNamespace(),
852+
Labels: map[string]string(targetInstance.ToZalandoPostgresqlMatchingLabels()),
788853
},
789854
Data: map[string][]byte{
790855
"username": []byte(username),
@@ -795,11 +860,9 @@ func (r *PostgresReconciler) ensureStandbySecrets(ctx context.Context, instance
795860
if err := r.SvcClient.Create(ctx, postgresSecret); err != nil {
796861
return fmt.Errorf("error while creating local secrets in service cluster: %w", err)
797862
}
798-
r.Log.Info("created local secret", "secret", postgresSecret)
799863
}
800864

801865
return nil
802-
803866
}
804867

805868
func (r *PostgresReconciler) updatePatroniConfig(ctx context.Context, instance *pg.Postgres) error {

pkg/operatormanager/operatormanager.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ const (
5151
SidecarsCMExporterQueriesKey string = "queries.yaml"
5252

5353
localSidecarsCMName = "postgres-sidecars-configmap"
54+
55+
PostresConfigSuperUsername = "postgres"
56+
PostgresConfigReplicationUsername = "standby"
5457
)
5558

5659
// operatorPodMatchingLabels is for listing operator pods
@@ -423,8 +426,8 @@ func (m *OperatorManager) editConfigMap(cm *corev1.ConfigMap, namespace string,
423426
cm.Data["major_version_upgrade_mode"] = options.MajorVersionUpgradeMode
424427

425428
// we specifically refer to those two users in the cloud-api, so we hardcode them here as well to be on the safe side.
426-
cm.Data["super_username"] = "postgres"
427-
cm.Data["replication_username"] = "standby"
429+
cm.Data["super_username"] = PostresConfigSuperUsername
430+
cm.Data["replication_username"] = PostgresConfigReplicationUsername
428431

429432
cm.Data["enable_pod_antiaffinity"] = strconv.FormatBool(options.PodAntiaffinity)
430433
}

0 commit comments

Comments
 (0)