diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 424c8e89a..75a906924 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -74,6 +74,7 @@ type Cluster struct { eventRecorder record.EventRecorder patroni patroni.Interface pgUsers map[string]spec.PgUser + pgUsersCache map[string]spec.PgUser systemUsers map[string]spec.PgUser podSubscribers map[spec.NamespacedName]chan PodEvent podSubscribersMu sync.RWMutex @@ -642,7 +643,15 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error { needConnectionPooler := needMasterConnectionPoolerWorker(&newSpec.Spec) || needReplicaConnectionPoolerWorker(&newSpec.Spec) if !sameUsers || needConnectionPooler { - c.logger.Debugf("syncing secrets") + c.logger.Debugf("initialize users") + // save current state of pgUsers to check for deleted roles later + if len(c.pgUsers) > 0 { + usersCache := map[string]spec.PgUser{} + for k, v := range c.pgUsers { + usersCache[k] = v + } + c.pgUsersCache = usersCache + } if err := c.initUsers(); err != nil { c.logger.Errorf("could not init users: %v", err) updateFailed = true diff --git a/pkg/cluster/database.go b/pkg/cluster/database.go index f6a55a644..760b68d72 100644 --- a/pkg/cluster/database.go +++ b/pkg/cluster/database.go @@ -24,8 +24,7 @@ const ( JOIN pg_catalog.pg_authid b ON (m.roleid = b.oid) WHERE m.member = a.oid) as memberof FROM pg_catalog.pg_authid a LEFT JOIN pg_db_role_setting s ON (a.oid = s.setrole AND s.setdatabase = 0::oid) - WHERE a.rolname != ALL($1) - AND (rolcanlogin OR (NOT rolcanlogin AND rolpassword IS NOT NULL)) + WHERE a.rolname = ANY($1) ORDER BY 1;` getDatabasesSQL = `SELECT datname, pg_get_userbyid(datdba) AS owner FROM pg_database;` diff --git a/pkg/cluster/sync.go b/pkg/cluster/sync.go index f7daa5012..2c35b6a54 100644 --- a/pkg/cluster/sync.go +++ b/pkg/cluster/sync.go @@ -37,6 +37,14 @@ func (c *Cluster) Sync(newSpec *acidv1.Postgresql) error { } }() + // save current state of pgUsers to check for deleted roles later + if len(c.pgUsers) > 0 { + usersCache := map[string]spec.PgUser{} + for k, v := range c.pgUsers { + usersCache[k] = v + } + c.pgUsersCache = usersCache + } if err = c.initUsers(); err != nil { err = fmt.Errorf("could not init users: %v", err) return err @@ -557,8 +565,8 @@ func (c *Cluster) syncRoles() (err error) { c.setProcessName("syncing roles") var ( - dbUsers spec.PgUserMap - systemUserNames []string + dbUsers spec.PgUserMap + userNames []string ) err = c.initDbConn() @@ -576,35 +584,35 @@ func (c *Cluster) syncRoles() (err error) { } }() - for _, u := range c.systemUsers { - systemUserNames = append(systemUserNames, u.Name) + for _, u := range c.pgUsers { + userNames = append(userNames, u.Name) } - dbUsers, err = c.readPgUsersFromDatabase(systemUserNames) - if err != nil { - return fmt.Errorf("error getting users from the database: %v", err) + // add removed additional team members from cache + // to trigger a rename of the role in ProduceSyncRequests + for _, cachedUser := range c.pgUsersCache { + if cachedUser.Origin != spec.RoleOriginTeamsAPI { + continue + } + if _, exists := c.pgUsers[cachedUser.Name]; !exists { + userNames = append(userNames, cachedUser.Name) + } } if needMasterConnectionPooler(&c.Spec) || needReplicaConnectionPooler(&c.Spec) { connectionPoolerUser := c.systemUsers[constants.ConnectionPoolerUserKeyName] + userNames = append(userNames, connectionPoolerUser.Name) - // check if pooler user exists in the database - dbPoolerUserMap, err := c.readPgUsersFromDatabase([]string{}) - if err != nil { - return fmt.Errorf("error getting pooler user from the database: %v", err) - } - - // if yes add role to dbUsers list so that there will be no add request - if _, exists := dbPoolerUserMap[connectionPoolerUser.Name]; exists { - dbUsers[connectionPoolerUser.Name] = dbPoolerUserMap[connectionPoolerUser.Name] - } - - // add to pgUsers to trigger add request in case no pooler user exists in DB if _, exists := c.pgUsers[connectionPoolerUser.Name]; !exists { c.pgUsers[connectionPoolerUser.Name] = connectionPoolerUser } } + dbUsers, err = c.readPgUsersFromDatabase(userNames) + if err != nil { + return fmt.Errorf("error getting users from the database: %v", err) + } + pgSyncRequests := c.userSyncStrategy.ProduceSyncRequests(dbUsers, c.pgUsers) if err = c.userSyncStrategy.ExecuteSyncRequests(pgSyncRequests, c.pgDb); err != nil { return fmt.Errorf("error executing sync statements: %v", err)