@@ -227,6 +227,10 @@ func (c *Cluster) initUsers() error {
227227 }
228228
229229 if err := c .initHumanUsers (); err != nil {
230+ // remember all cached users in c.pgUsers
231+ for cachedUserName , cachedUser := range c .pgUsersCache {
232+ c .pgUsers [cachedUserName ] = cachedUser
233+ }
230234 return fmt .Errorf ("could not init human users: %v" , err )
231235 }
232236
@@ -748,6 +752,7 @@ func (c *Cluster) compareServices(old, new *v1.Service) (bool, string) {
748752// for a cluster that had no such job before. In this case a missing job is not an error.
749753func (c * Cluster ) Update (oldSpec , newSpec * acidv1.Postgresql ) error {
750754 updateFailed := false
755+ userInitFailed := false
751756 syncStatefulSet := false
752757
753758 c .mu .Lock ()
@@ -785,32 +790,39 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
785790 }
786791 }
787792
788- // check if users need to be synced
789- sameUsers := reflect .DeepEqual (oldSpec .Spec .Users , newSpec .Spec .Users ) &&
790- reflect .DeepEqual (oldSpec .Spec .PreparedDatabases , newSpec .Spec .PreparedDatabases )
791- sameRotatedUsers := reflect .DeepEqual (oldSpec .Spec .UsersWithSecretRotation , newSpec .Spec .UsersWithSecretRotation ) &&
792- reflect .DeepEqual (oldSpec .Spec .UsersWithInPlaceSecretRotation , newSpec .Spec .UsersWithInPlaceSecretRotation )
793-
794- // connection pooler needs one system user created, which is done in
795- // initUsers. Check if it needs to be called.
796- needConnectionPooler := needMasterConnectionPoolerWorker (& newSpec .Spec ) ||
797- needReplicaConnectionPoolerWorker (& newSpec .Spec )
798-
799- if ! sameUsers || ! sameRotatedUsers || needConnectionPooler {
800- c .logger .Debugf ("initialize users" )
801- if err := c .initUsers (); err != nil {
802- c .logger .Errorf ("could not init users: %v" , err )
803- updateFailed = true
804- }
805-
806- c .logger .Debugf ("syncing secrets" )
793+ // Users
794+ func () {
795+ // check if users need to be synced during update
796+ sameUsers := reflect .DeepEqual (oldSpec .Spec .Users , newSpec .Spec .Users ) &&
797+ reflect .DeepEqual (oldSpec .Spec .PreparedDatabases , newSpec .Spec .PreparedDatabases )
798+ sameRotatedUsers := reflect .DeepEqual (oldSpec .Spec .UsersWithSecretRotation , newSpec .Spec .UsersWithSecretRotation ) &&
799+ reflect .DeepEqual (oldSpec .Spec .UsersWithInPlaceSecretRotation , newSpec .Spec .UsersWithInPlaceSecretRotation )
800+
801+ // connection pooler needs one system user created who is initialized in initUsers
802+ // only when disabled in oldSpec and enabled in newSpec
803+ needPoolerUser := c .needConnectionPoolerUser (& oldSpec .Spec , & newSpec .Spec )
804+
805+ // streams new replication user created who is initialized in initUsers
806+ // only when streams were not specified in oldSpec but in newSpec
807+ needStreamUser := len (oldSpec .Spec .Streams ) == 0 && len (newSpec .Spec .Streams ) > 0
808+
809+ if ! sameUsers || ! sameRotatedUsers || needPoolerUser || needStreamUser {
810+ c .logger .Debugf ("initialize users" )
811+ if err := c .initUsers (); err != nil {
812+ c .logger .Errorf ("could not init users - skipping sync of secrets and databases: %v" , err )
813+ userInitFailed = true
814+ updateFailed = true
815+ return
816+ }
807817
808- //TODO: mind the secrets of the deleted/new users
809- if err := c .syncSecrets (); err != nil {
810- c .logger .Errorf ("could not sync secrets: %v" , err )
811- updateFailed = true
818+ c .logger .Debugf ("syncing secrets" )
819+ //TODO: mind the secrets of the deleted/new users
820+ if err := c .syncSecrets (); err != nil {
821+ c .logger .Errorf ("could not sync secrets: %v" , err )
822+ updateFailed = true
823+ }
812824 }
813- }
825+ }()
814826
815827 // Volume
816828 if c .OpConfig .StorageResizeMode != "off" {
@@ -892,7 +904,7 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
892904 }()
893905
894906 // Roles and Databases
895- if ! (c .databaseAccessDisabled () || c .getNumberOfInstances (& c .Spec ) <= 0 || c .Spec .StandbyCluster != nil ) {
907+ if ! userInitFailed && ! (c .databaseAccessDisabled () || c .getNumberOfInstances (& c .Spec ) <= 0 || c .Spec .StandbyCluster != nil ) {
896908 c .logger .Debugf ("syncing roles" )
897909 if err := c .syncRoles (); err != nil {
898910 c .logger .Errorf ("could not sync roles: %v" , err )
@@ -920,13 +932,12 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
920932 // need to process. In the future we may want to do this more careful and
921933 // check which databases we need to process, but even repeating the whole
922934 // installation process should be good enough.
923-
924935 if _ , err := c .syncConnectionPooler (oldSpec , newSpec , c .installLookupFunction ); err != nil {
925936 c .logger .Errorf ("could not sync connection pooler: %v" , err )
926937 updateFailed = true
927938 }
928939
929- if len (c .Spec .Streams ) > 0 {
940+ if len (newSpec .Spec .Streams ) > 0 {
930941 if err := c .syncStreams (); err != nil {
931942 c .logger .Errorf ("could not sync streams: %v" , err )
932943 updateFailed = true
@@ -1094,28 +1105,10 @@ func (c *Cluster) initSystemUsers() {
10941105 Password : util .RandomPassword (constants .PasswordLength ),
10951106 }
10961107
1097- // Connection pooler user is an exception, if requested it's going to be
1098- // created by operator as a normal pgUser
1108+ // Connection pooler user is an exception
1109+ // if requested it's going to be created by operator
10991110 if needConnectionPooler (& c .Spec ) {
1100- connectionPoolerSpec := c .Spec .ConnectionPooler
1101- if connectionPoolerSpec == nil {
1102- connectionPoolerSpec = & acidv1.ConnectionPooler {}
1103- }
1104-
1105- // Using superuser as pooler user is not a good idea. First of all it's
1106- // not going to be synced correctly with the current implementation,
1107- // and second it's a bad practice.
1108- username := c .OpConfig .ConnectionPooler .User
1109-
1110- isSuperUser := connectionPoolerSpec .User == c .OpConfig .SuperUsername
1111- isProtectedUser := c .shouldAvoidProtectedOrSystemRole (
1112- connectionPoolerSpec .User , "connection pool role" )
1113-
1114- if ! isSuperUser && ! isProtectedUser {
1115- username = util .Coalesce (
1116- connectionPoolerSpec .User ,
1117- c .OpConfig .ConnectionPooler .User )
1118- }
1111+ username := c .poolerUser (& c .Spec )
11191112
11201113 // connection pooler application should be able to login with this role
11211114 connectionPoolerUser := spec.PgUser {
0 commit comments