@@ -30,6 +30,7 @@ import (
3030 appsv1 "k8s.io/api/apps/v1"
3131 batchv1 "k8s.io/api/batch/v1"
3232 v1 "k8s.io/api/core/v1"
33+ apipolicyv1 "k8s.io/api/policy/v1"
3334 policyv1 "k8s.io/api/policy/v1"
3435 rbacv1 "k8s.io/api/rbac/v1"
3536 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -400,7 +401,7 @@ func (c *Cluster) Create() (err error) {
400401
401402 if len (c .Spec .Streams ) > 0 {
402403 // creating streams requires syncing the statefulset first
403- err = c .syncStatefulSet ()
404+ err = c .syncStatefulSet (true )
404405 if err != nil {
405406 return fmt .Errorf ("could not sync statefulset: %v" , err )
406407 }
@@ -493,7 +494,6 @@ func (c *Cluster) compareStatefulSetWith(statefulSet *appsv1.StatefulSet) *compa
493494 if changed , reason := c .compareAnnotations (c .Statefulset .Spec .Template .Annotations , statefulSet .Spec .Template .Annotations ); changed {
494495 match = false
495496 needsReplace = true
496- needsRollUpdate = true
497497 reasons = append (reasons , "new statefulset's pod template metadata annotations does not match " + reason )
498498 }
499499 if ! reflect .DeepEqual (c .Statefulset .Spec .Template .Spec .SecurityContext , statefulSet .Spec .Template .Spec .SecurityContext ) {
@@ -513,9 +513,9 @@ func (c *Cluster) compareStatefulSetWith(statefulSet *appsv1.StatefulSet) *compa
513513 reasons = append (reasons , fmt .Sprintf ("new statefulset's name for volume %d does not match the current one" , i ))
514514 continue
515515 }
516- if ! reflect . DeepEqual (c .Statefulset .Spec .VolumeClaimTemplates [i ].Annotations , statefulSet .Spec .VolumeClaimTemplates [i ].Annotations ) {
516+ if changed , reason := c . compareAnnotations (c .Statefulset .Spec .VolumeClaimTemplates [i ].Annotations , statefulSet .Spec .VolumeClaimTemplates [i ].Annotations ); changed {
517517 needsReplace = true
518- reasons = append (reasons , fmt .Sprintf ("new statefulset's annotations for volume %q does not match the current one" , name ))
518+ reasons = append (reasons , fmt .Sprintf ("new statefulset's annotations for volume %q does not match the current one: " , name )+ reason )
519519 }
520520 if ! reflect .DeepEqual (c .Statefulset .Spec .VolumeClaimTemplates [i ].Spec , statefulSet .Spec .VolumeClaimTemplates [i ].Spec ) {
521521 name := c .Statefulset .Spec .VolumeClaimTemplates [i ].Name
@@ -764,6 +764,16 @@ func (c *Cluster) compareAnnotations(old, new map[string]string) (bool, string)
764764
765765}
766766
767+ func (c * Cluster ) extractIgnoredAnnotations (annoList map [string ]string ) map [string ]string {
768+ result := make (map [string ]string )
769+ for _ , ignore := range c .OpConfig .IgnoredAnnotations {
770+ if _ , ok := annoList [ignore ]; ok {
771+ result [ignore ] = annoList [ignore ]
772+ }
773+ }
774+ return result
775+ }
776+
767777func (c * Cluster ) compareServices (old , new * v1.Service ) (bool , string ) {
768778 if old .Spec .Type != new .Spec .Type {
769779 return false , fmt .Sprintf ("new service's type %q does not match the current one %q" ,
@@ -818,6 +828,17 @@ func (c *Cluster) compareLogicalBackupJob(cur, new *batchv1.CronJob) (match bool
818828 return true , ""
819829}
820830
831+ func (c * Cluster ) ComparePodDisruptionBudget (cur , new * apipolicyv1.PodDisruptionBudget ) (bool , string ) {
832+ //TODO: improve comparison
833+ if match := reflect .DeepEqual (new .Spec , cur .Spec ); ! match {
834+ return false , "new PDB spec does not match the current one"
835+ }
836+ if changed , reason := c .compareAnnotations (cur .Annotations , new .Annotations ); changed {
837+ return false , "new PDB's annotations does not match the current one:" + reason
838+ }
839+ return true , ""
840+ }
841+
821842func getPgVersion (cronJob * batchv1.CronJob ) string {
822843 envs := cronJob .Spec .JobTemplate .Spec .Template .Spec .Containers [0 ].Env
823844 for _ , env := range envs {
@@ -922,12 +943,9 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
922943 }
923944
924945 // Service
925- if ! reflect .DeepEqual (c .generateService (Master , & oldSpec .Spec ), c .generateService (Master , & newSpec .Spec )) ||
926- ! reflect .DeepEqual (c .generateService (Replica , & oldSpec .Spec ), c .generateService (Replica , & newSpec .Spec )) {
927- if err := c .syncServices (); err != nil {
928- c .logger .Errorf ("could not sync services: %v" , err )
929- updateFailed = true
930- }
946+ if err := c .syncServices (); err != nil {
947+ c .logger .Errorf ("could not sync services: %v" , err )
948+ updateFailed = true
931949 }
932950
933951 // Users
@@ -946,15 +964,19 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
946964 // only when streams were not specified in oldSpec but in newSpec
947965 needStreamUser := len (oldSpec .Spec .Streams ) == 0 && len (newSpec .Spec .Streams ) > 0
948966
949- if ! sameUsers || ! sameRotatedUsers || needPoolerUser || needStreamUser {
967+ annotationsChanged , _ := c .compareAnnotations (oldSpec .Annotations , newSpec .Annotations )
968+
969+ initUsers := ! sameUsers || ! sameRotatedUsers || needPoolerUser || needStreamUser
970+ if initUsers {
950971 c .logger .Debugf ("initialize users" )
951972 if err := c .initUsers (); err != nil {
952973 c .logger .Errorf ("could not init users - skipping sync of secrets and databases: %v" , err )
953974 userInitFailed = true
954975 updateFailed = true
955976 return
956977 }
957-
978+ }
979+ if initUsers || annotationsChanged {
958980 c .logger .Debugf ("syncing secrets" )
959981 //TODO: mind the secrets of the deleted/new users
960982 if err := c .syncSecrets (); err != nil {
@@ -968,7 +990,7 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
968990 if c .OpConfig .StorageResizeMode != "off" {
969991 c .syncVolumes ()
970992 } else {
971- c .logger .Infof ("Storage resize is disabled (storage_resize_mode is off). Skipping volume sync." )
993+ c .logger .Infof ("Storage resize is disabled (storage_resize_mode is off). Skipping volume size sync." )
972994 }
973995
974996 // streams configuration
@@ -978,29 +1000,11 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
9781000
9791001 // Statefulset
9801002 func () {
981- oldSs , err := c .generateStatefulSet (& oldSpec .Spec )
982- if err != nil {
983- c .logger .Errorf ("could not generate old statefulset spec: %v" , err )
984- updateFailed = true
985- return
986- }
987-
988- newSs , err := c .generateStatefulSet (& newSpec .Spec )
989- if err != nil {
990- c .logger .Errorf ("could not generate new statefulset spec: %v" , err )
1003+ if err := c .syncStatefulSet (syncStatefulSet ); err != nil {
1004+ c .logger .Errorf ("could not sync statefulsets: %v" , err )
9911005 updateFailed = true
992- return
993- }
994-
995- if syncStatefulSet || ! reflect .DeepEqual (oldSs , newSs ) {
996- c .logger .Debugf ("syncing statefulsets" )
997- syncStatefulSet = false
998- // TODO: avoid generating the StatefulSet object twice by passing it to syncStatefulSet
999- if err := c .syncStatefulSet (); err != nil {
1000- c .logger .Errorf ("could not sync statefulsets: %v" , err )
1001- updateFailed = true
1002- }
10031006 }
1007+ syncStatefulSet = false
10041008 }()
10051009
10061010 // add or remove standby_cluster section from Patroni config depending on changes in standby section
@@ -1011,12 +1015,9 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
10111015 }
10121016
10131017 // pod disruption budget
1014- if oldSpec .Spec .NumberOfInstances != newSpec .Spec .NumberOfInstances {
1015- c .logger .Debug ("syncing pod disruption budgets" )
1016- if err := c .syncPodDisruptionBudget (true ); err != nil {
1017- c .logger .Errorf ("could not sync pod disruption budget: %v" , err )
1018- updateFailed = true
1019- }
1018+ if err := c .syncPodDisruptionBudget (true ); err != nil {
1019+ c .logger .Errorf ("could not sync pod disruption budget: %v" , err )
1020+ updateFailed = true
10201021 }
10211022
10221023 // logical backup job
0 commit comments