@@ -25,6 +25,7 @@ import (
25
25
"k8s.io/apimachinery/pkg/types"
26
26
"k8s.io/apimachinery/pkg/util/sets"
27
27
"k8s.io/apimachinery/pkg/util/validation/field"
28
+ "k8s.io/client-go/util/retry"
28
29
"sigs.k8s.io/controller-runtime/pkg/client"
29
30
30
31
"github.com/percona/percona-postgresql-operator/internal/feature"
@@ -49,6 +50,7 @@ import (
49
50
func (r * Reconciler ) generatePostgresUserSecret (
50
51
cluster * v1beta1.PostgresCluster , spec * v1beta1.PostgresUserSpec , existing * corev1.Secret ,
51
52
) (* corev1.Secret , error ) {
53
+ log := logging .FromContext (context .Background ())
52
54
username := string (spec .Name )
53
55
// K8SPG-359
54
56
intent := & corev1.Secret {}
@@ -75,10 +77,12 @@ func (r *Reconciler) generatePostgresUserSecret(
75
77
if existing != nil {
76
78
intent .Data ["password" ] = existing .Data ["password" ]
77
79
intent .Data ["verifier" ] = existing .Data ["verifier" ]
80
+ log .Info ("password located for existing secret" , "secret" , existing .String ())
78
81
}
79
82
80
83
// When password is unset, generate a new one according to the specified policy.
81
84
if len (intent .Data ["password" ]) == 0 {
85
+ log .Info ("password is going to be generated for secret" )
82
86
// NOTE: The tests around ASCII passwords are lacking. When changing
83
87
// this, make sure that ASCII is the default.
84
88
generate := util .GenerateASCIIPassword
@@ -496,6 +500,9 @@ func (r *Reconciler) reconcilePostgresUserSecrets(
496
500
userSpecs [string (specUsers [i ].Name )] = & specUsers [i ]
497
501
}
498
502
503
+ // K8SPG-570 for secrets that were created manually, update them
504
+ // with the right labels so that the selector called next to track them
505
+ // and utilize their data.
499
506
for _ , user := range specUsers {
500
507
if user .SecretName != "" {
501
508
if err := r .updateCustomSecretLabels (ctx , cluster , user ); err != nil {
@@ -590,9 +597,10 @@ func (r *Reconciler) reconcilePostgresUserSecrets(
590
597
return specUsers , userSecrets , err
591
598
}
592
599
593
- // updateCustomSecretLabels checks if a custom secret exists - can be created manually through kubectl apply
594
- // and updates it with required labels if they are missing that enabled the
595
- // naming.AsSelector(naming.ClusterPostgresUsers(cluster.Name)) to identify them.
600
+ // K8SPG-570
601
+ // updateCustomSecretLabels checks if a custom secret exists - can be created manually through
602
+ // kubectl apply - and updates it with required labels if they are missing. This enables the
603
+ // naming.AsSelector(naming.ClusterPostgresUsers(cluster.Name)) to identify these secrets.
596
604
func (r * Reconciler ) updateCustomSecretLabels (
597
605
ctx context.Context , cluster * v1beta1.PostgresCluster , user v1beta1.PostgresUserSpec ,
598
606
) error {
@@ -611,11 +619,10 @@ func (r *Reconciler) updateCustomSecretLabels(
611
619
return errors .Wrap (err , fmt .Sprintf ("failed to get user %s secret %s" , userName , secretName ))
612
620
}
613
621
614
- orig := secret .DeepCopy ()
615
-
616
622
requiredLabels := map [string ]string {
617
623
naming .LabelCluster : cluster .Name ,
618
624
naming .LabelPostgresUser : userName ,
625
+ naming .LabelRole : naming .RolePostgresUser ,
619
626
}
620
627
621
628
needsUpdate := false
@@ -631,7 +638,58 @@ func (r *Reconciler) updateCustomSecretLabels(
631
638
}
632
639
633
640
if needsUpdate {
634
- return errors .WithStack (r .Client .Patch (ctx , secret .DeepCopy (), client .MergeFrom (orig )))
641
+ err := retry .RetryOnConflict (retry .DefaultRetry , func () error {
642
+ current := & corev1.Secret {}
643
+ if err := r .Client .Get (ctx , types.NamespacedName {
644
+ Name : secretName ,
645
+ Namespace : cluster .Namespace ,
646
+ }, current ); err != nil {
647
+ return err
648
+ }
649
+
650
+ currentOrig := current .DeepCopy ()
651
+ if current .Labels == nil {
652
+ current .Labels = make (map [string ]string )
653
+ }
654
+
655
+ updateNeeded := false
656
+ for labelKey , labelValue := range requiredLabels {
657
+ if existing , exists := current .Labels [labelKey ]; ! exists || existing != labelValue {
658
+ current .Labels [labelKey ] = labelValue
659
+ updateNeeded = true
660
+ }
661
+ }
662
+
663
+ if ! updateNeeded {
664
+ return nil
665
+ }
666
+
667
+ return r .Client .Patch (ctx , current , client .MergeFrom (currentOrig ))
668
+ })
669
+
670
+ if err != nil {
671
+ return errors .Wrap (err , fmt .Sprintf ("failed to update secret %s" , secretName ))
672
+ }
673
+
674
+ verifyErr := retry .RetryOnConflict (retry .DefaultRetry , func () error {
675
+ verifySecret := & corev1.Secret {}
676
+ if err := r .Client .Get (ctx , types.NamespacedName {
677
+ Name : secretName ,
678
+ Namespace : cluster .Namespace ,
679
+ }, verifySecret ); err != nil {
680
+ return err
681
+ }
682
+
683
+ for labelKey , labelValue := range requiredLabels {
684
+ if existing , exists := verifySecret .Labels [labelKey ]; ! exists || existing != labelValue {
685
+ return errors .Errorf ("secret %s label %s not yet propagated" , secretName , labelKey )
686
+ }
687
+ }
688
+
689
+ return nil
690
+ })
691
+
692
+ return errors .Wrap (verifyErr , "failed to update secret" )
635
693
}
636
694
637
695
return nil
0 commit comments