@@ -3,6 +3,7 @@ package cluster
33import (
44 "context"
55 "fmt"
6+ "reflect"
67 "strings"
78
89 "github.com/r3labs/diff"
@@ -60,7 +61,7 @@ func needMasterConnectionPooler(spec *acidv1.PostgresSpec) bool {
6061}
6162
6263func needMasterConnectionPoolerWorker (spec * acidv1.PostgresSpec ) bool {
63- return (nil != spec . EnableConnectionPooler && * spec .EnableConnectionPooler ) ||
64+ return (spec . EnableConnectionPooler != nil && * spec .EnableConnectionPooler ) ||
6465 (spec .ConnectionPooler != nil && spec .EnableConnectionPooler == nil )
6566}
6667
@@ -114,7 +115,7 @@ func (c *Cluster) createConnectionPooler(LookupFunction InstallFunction) (SyncRe
114115 c .setProcessName ("creating connection pooler" )
115116
116117 //this is essentially sync with nil as oldSpec
117- if reason , err := c .syncConnectionPooler (nil , & c .Postgresql , LookupFunction ); err != nil {
118+ if reason , err := c .syncConnectionPooler (& acidv1. Postgresql {} , & c .Postgresql , LookupFunction ); err != nil {
118119 return reason , err
119120 }
120121 return reason , nil
@@ -140,19 +141,23 @@ func (c *Cluster) createConnectionPooler(LookupFunction InstallFunction) (SyncRe
140141// RESERVE_SIZE is how many additional connections to allow for a pooler.
141142func (c * Cluster ) getConnectionPoolerEnvVars () []v1.EnvVar {
142143 spec := & c .Spec
144+ connectionPoolerSpec := spec .ConnectionPooler
145+ if connectionPoolerSpec == nil {
146+ connectionPoolerSpec = & acidv1.ConnectionPooler {}
147+ }
143148 effectiveMode := util .Coalesce (
144- spec . ConnectionPooler .Mode ,
149+ connectionPoolerSpec .Mode ,
145150 c .OpConfig .ConnectionPooler .Mode )
146151
147- numberOfInstances := spec . ConnectionPooler .NumberOfInstances
152+ numberOfInstances := connectionPoolerSpec .NumberOfInstances
148153 if numberOfInstances == nil {
149154 numberOfInstances = util .CoalesceInt32 (
150155 c .OpConfig .ConnectionPooler .NumberOfInstances ,
151156 k8sutil .Int32ToPointer (1 ))
152157 }
153158
154159 effectiveMaxDBConn := util .CoalesceInt32 (
155- spec . ConnectionPooler .MaxDBConnections ,
160+ connectionPoolerSpec .MaxDBConnections ,
156161 c .OpConfig .ConnectionPooler .MaxDBConnections )
157162
158163 if effectiveMaxDBConn == nil {
@@ -201,17 +206,21 @@ func (c *Cluster) getConnectionPoolerEnvVars() []v1.EnvVar {
201206func (c * Cluster ) generateConnectionPoolerPodTemplate (role PostgresRole ) (
202207 * v1.PodTemplateSpec , error ) {
203208 spec := & c .Spec
209+ connectionPoolerSpec := spec .ConnectionPooler
210+ if connectionPoolerSpec == nil {
211+ connectionPoolerSpec = & acidv1.ConnectionPooler {}
212+ }
204213 gracePeriod := int64 (c .OpConfig .PodTerminateGracePeriod .Seconds ())
205214 resources , err := generateResourceRequirements (
206- spec . ConnectionPooler .Resources ,
215+ connectionPoolerSpec .Resources ,
207216 makeDefaultConnectionPoolerResources (& c .OpConfig ))
208217
209218 effectiveDockerImage := util .Coalesce (
210- spec . ConnectionPooler .DockerImage ,
219+ connectionPoolerSpec .DockerImage ,
211220 c .OpConfig .ConnectionPooler .Image )
212221
213222 effectiveSchema := util .Coalesce (
214- spec . ConnectionPooler .Schema ,
223+ connectionPoolerSpec .Schema ,
215224 c .OpConfig .ConnectionPooler .Schema )
216225
217226 if err != nil {
@@ -220,7 +229,7 @@ func (c *Cluster) generateConnectionPoolerPodTemplate(role PostgresRole) (
220229
221230 secretSelector := func (key string ) * v1.SecretKeySelector {
222231 effectiveUser := util .Coalesce (
223- spec . ConnectionPooler .User ,
232+ connectionPoolerSpec .User ,
224233 c .OpConfig .ConnectionPooler .User )
225234
226235 return & v1.SecretKeySelector {
@@ -321,12 +330,13 @@ func (c *Cluster) generateConnectionPoolerDeployment(connectionPooler *Connectio
321330 // default values, initialize it to an empty structure. It could be done
322331 // anywhere, but here is the earliest common entry point between sync and
323332 // create code, so init here.
324- if spec .ConnectionPooler == nil {
325- spec .ConnectionPooler = & acidv1.ConnectionPooler {}
333+ connectionPoolerSpec := spec .ConnectionPooler
334+ if connectionPoolerSpec == nil {
335+ connectionPoolerSpec = & acidv1.ConnectionPooler {}
326336 }
327337 podTemplate , err := c .generateConnectionPoolerPodTemplate (connectionPooler .Role )
328338
329- numberOfInstances := spec . ConnectionPooler .NumberOfInstances
339+ numberOfInstances := connectionPoolerSpec .NumberOfInstances
330340 if numberOfInstances == nil {
331341 numberOfInstances = util .CoalesceInt32 (
332342 c .OpConfig .ConnectionPooler .NumberOfInstances ,
@@ -371,16 +381,6 @@ func (c *Cluster) generateConnectionPoolerDeployment(connectionPooler *Connectio
371381func (c * Cluster ) generateConnectionPoolerService (connectionPooler * ConnectionPoolerObjects ) * v1.Service {
372382
373383 spec := & c .Spec
374- // there are two ways to enable connection pooler, either to specify a
375- // connectionPooler section or enableConnectionPooler. In the second case
376- // spec.connectionPooler will be nil, so to make it easier to calculate
377- // default values, initialize it to an empty structure. It could be done
378- // anywhere, but here is the earliest common entry point between sync and
379- // create code, so init here.
380- if spec .ConnectionPooler == nil {
381- spec .ConnectionPooler = & acidv1.ConnectionPooler {}
382- }
383-
384384 serviceSpec := v1.ServiceSpec {
385385 Ports : []v1.ServicePort {
386386 {
@@ -668,12 +668,14 @@ func makeDefaultConnectionPoolerResources(config *config.Config) acidv1.Resource
668668
669669func logPoolerEssentials (log * logrus.Entry , oldSpec , newSpec * acidv1.Postgresql ) {
670670 var v []string
671-
672671 var input []* bool
672+
673+ newMasterConnectionPoolerEnabled := needMasterConnectionPoolerWorker (& newSpec .Spec )
673674 if oldSpec == nil {
674- input = []* bool {nil , nil , newSpec . Spec . EnableConnectionPooler , newSpec .Spec .EnableReplicaConnectionPooler }
675+ input = []* bool {nil , nil , & newMasterConnectionPoolerEnabled , newSpec .Spec .EnableReplicaConnectionPooler }
675676 } else {
676- input = []* bool {oldSpec .Spec .EnableConnectionPooler , oldSpec .Spec .EnableReplicaConnectionPooler , newSpec .Spec .EnableConnectionPooler , newSpec .Spec .EnableReplicaConnectionPooler }
677+ oldMasterConnectionPoolerEnabled := needMasterConnectionPoolerWorker (& oldSpec .Spec )
678+ input = []* bool {& oldMasterConnectionPoolerEnabled , oldSpec .Spec .EnableReplicaConnectionPooler , & newMasterConnectionPoolerEnabled , newSpec .Spec .EnableReplicaConnectionPooler }
677679 }
678680
679681 for _ , b := range input {
@@ -684,25 +686,16 @@ func logPoolerEssentials(log *logrus.Entry, oldSpec, newSpec *acidv1.Postgresql)
684686 }
685687 }
686688
687- log .Debugf ("syncing connection pooler from (%v, %v) to (%v, %v)" , v [0 ], v [1 ], v [2 ], v [3 ])
689+ log .Debugf ("syncing connection pooler (master, replica) from (%v, %v) to (%v, %v)" , v [0 ], v [1 ], v [2 ], v [3 ])
688690}
689691
690692func (c * Cluster ) syncConnectionPooler (oldSpec , newSpec * acidv1.Postgresql , LookupFunction InstallFunction ) (SyncReason , error ) {
691693
692694 var reason SyncReason
693695 var err error
694- var newNeedConnectionPooler , oldNeedConnectionPooler bool
695- oldNeedConnectionPooler = false
696-
697- if oldSpec == nil {
698- oldSpec = & acidv1.Postgresql {
699- Spec : acidv1.PostgresSpec {
700- ConnectionPooler : & acidv1.ConnectionPooler {},
701- },
702- }
703- }
696+ var connectionPoolerNeeded bool
704697
705- needSync , _ := needSyncConnectionPoolerSpecs (oldSpec .Spec .ConnectionPooler , newSpec .Spec .ConnectionPooler , c . logger )
698+ needSync := ! reflect . DeepEqual (oldSpec .Spec .ConnectionPooler , newSpec .Spec .ConnectionPooler )
706699 masterChanges , err := diff .Diff (oldSpec .Spec .EnableConnectionPooler , newSpec .Spec .EnableConnectionPooler )
707700 if err != nil {
708701 c .logger .Error ("Error in getting diff of master connection pooler changes" )
@@ -712,15 +705,14 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, Look
712705 c .logger .Error ("Error in getting diff of replica connection pooler changes" )
713706 }
714707
715- // skip pooler sync only
716- // 1. if there is no diff in spec, AND
717- // 2. if connection pooler is already there and is also required as per newSpec
718- //
719- // Handling the case when connectionPooler is not there but it is required
708+ // skip pooler sync when theres no diff or it's deactivated
709+ // but, handling the case when connectionPooler is not there but it is required
720710 // as per spec, hence do not skip syncing in that case, even though there
721711 // is no diff in specs
722712 if (! needSync && len (masterChanges ) <= 0 && len (replicaChanges ) <= 0 ) &&
723- (c .ConnectionPooler != nil && (needConnectionPooler (& newSpec .Spec ))) {
713+ ((! needConnectionPooler (& newSpec .Spec ) && (c .ConnectionPooler == nil || ! needConnectionPooler (& oldSpec .Spec ))) ||
714+ (c .ConnectionPooler != nil && needConnectionPooler (& newSpec .Spec ) &&
715+ (c .ConnectionPooler [Master ].LookupFunction || c .ConnectionPooler [Replica ].LookupFunction ))) {
724716 c .logger .Debugln ("syncing pooler is not required" )
725717 return nil , nil
726718 }
@@ -731,15 +723,9 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, Look
731723 for _ , role := range [2 ]PostgresRole {Master , Replica } {
732724
733725 if role == Master {
734- newNeedConnectionPooler = needMasterConnectionPoolerWorker (& newSpec .Spec )
735- if oldSpec != nil {
736- oldNeedConnectionPooler = needMasterConnectionPoolerWorker (& oldSpec .Spec )
737- }
726+ connectionPoolerNeeded = needMasterConnectionPoolerWorker (& newSpec .Spec )
738727 } else {
739- newNeedConnectionPooler = needReplicaConnectionPoolerWorker (& newSpec .Spec )
740- if oldSpec != nil {
741- oldNeedConnectionPooler = needReplicaConnectionPoolerWorker (& oldSpec .Spec )
742- }
728+ connectionPoolerNeeded = needReplicaConnectionPoolerWorker (& newSpec .Spec )
743729 }
744730
745731 // if the call is via createConnectionPooler, then it is required to initialize
@@ -759,24 +745,22 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, Look
759745 }
760746 }
761747
762- if newNeedConnectionPooler {
748+ if connectionPoolerNeeded {
763749 // Try to sync in any case. If we didn't needed connection pooler before,
764750 // it means we want to create it. If it was already present, still sync
765751 // since it could happen that there is no difference in specs, and all
766752 // the resources are remembered, but the deployment was manually deleted
767753 // in between
768754
769- // in this case also do not forget to install lookup function as for
770- // creating cluster
771- if ! oldNeedConnectionPooler || ! c .ConnectionPooler [role ].LookupFunction {
772- newConnectionPooler := newSpec .Spec .ConnectionPooler
773-
755+ // in this case also do not forget to install lookup function
756+ if ! c .ConnectionPooler [role ].LookupFunction {
757+ connectionPooler := c .Spec .ConnectionPooler
774758 specSchema := ""
775759 specUser := ""
776760
777- if newConnectionPooler != nil {
778- specSchema = newConnectionPooler .Schema
779- specUser = newConnectionPooler .User
761+ if connectionPooler != nil {
762+ specSchema = connectionPooler .Schema
763+ specUser = connectionPooler .User
780764 }
781765
782766 schema := util .Coalesce (
@@ -787,9 +771,10 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, Look
787771 specUser ,
788772 c .OpConfig .ConnectionPooler .User )
789773
790- if err = LookupFunction (schema , user , role ); err != nil {
774+ if err = LookupFunction (schema , user ); err != nil {
791775 return NoSync , err
792776 }
777+ c .ConnectionPooler [role ].LookupFunction = true
793778 }
794779
795780 if reason , err = c .syncConnectionPoolerWorker (oldSpec , newSpec , role ); err != nil {
@@ -808,8 +793,8 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, Look
808793 }
809794 }
810795 }
811- if ! needMasterConnectionPoolerWorker (& newSpec .Spec ) &&
812- ! needReplicaConnectionPoolerWorker (& newSpec .Spec ) {
796+ if ( needMasterConnectionPoolerWorker (& oldSpec .Spec ) || needReplicaConnectionPoolerWorker ( & oldSpec . Spec ) ) &&
797+ ! needMasterConnectionPoolerWorker ( & newSpec . Spec ) && ! needReplicaConnectionPoolerWorker (& newSpec .Spec ) {
813798 if err = c .deleteConnectionPoolerSecret (); err != nil {
814799 c .logger .Warningf ("could not remove connection pooler secret: %v" , err )
815800 }
@@ -874,8 +859,6 @@ func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql
874859 newConnectionPooler = & acidv1.ConnectionPooler {}
875860 }
876861
877- c .logger .Infof ("old: %+v, new %+v" , oldConnectionPooler , newConnectionPooler )
878-
879862 var specSync bool
880863 var specReason []string
881864
0 commit comments