mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-10-18 03:28:00 +02:00
skip db sync on failed initUsers during UPDATE (#2083)
* skip db sync on failed initUsers during UPDATE * provide unit test for teams API being unavailable * add test for 404 case
This commit is contained in:
+40
-47
@@ -227,6 +227,10 @@ func (c *Cluster) initUsers() error {
|
||||
}
|
||||
|
||||
if err := c.initHumanUsers(); err != nil {
|
||||
// remember all cached users in c.pgUsers
|
||||
for cachedUserName, cachedUser := range c.pgUsersCache {
|
||||
c.pgUsers[cachedUserName] = cachedUser
|
||||
}
|
||||
return fmt.Errorf("could not init human users: %v", err)
|
||||
}
|
||||
|
||||
@@ -748,6 +752,7 @@ func (c *Cluster) compareServices(old, new *v1.Service) (bool, string) {
|
||||
// for a cluster that had no such job before. In this case a missing job is not an error.
|
||||
func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
||||
updateFailed := false
|
||||
userInitFailed := false
|
||||
syncStatefulSet := false
|
||||
|
||||
c.mu.Lock()
|
||||
@@ -785,32 +790,39 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
||||
}
|
||||
}
|
||||
|
||||
// check if users need to be synced
|
||||
sameUsers := reflect.DeepEqual(oldSpec.Spec.Users, newSpec.Spec.Users) &&
|
||||
reflect.DeepEqual(oldSpec.Spec.PreparedDatabases, newSpec.Spec.PreparedDatabases)
|
||||
sameRotatedUsers := reflect.DeepEqual(oldSpec.Spec.UsersWithSecretRotation, newSpec.Spec.UsersWithSecretRotation) &&
|
||||
reflect.DeepEqual(oldSpec.Spec.UsersWithInPlaceSecretRotation, newSpec.Spec.UsersWithInPlaceSecretRotation)
|
||||
// Users
|
||||
func() {
|
||||
// check if users need to be synced during update
|
||||
sameUsers := reflect.DeepEqual(oldSpec.Spec.Users, newSpec.Spec.Users) &&
|
||||
reflect.DeepEqual(oldSpec.Spec.PreparedDatabases, newSpec.Spec.PreparedDatabases)
|
||||
sameRotatedUsers := reflect.DeepEqual(oldSpec.Spec.UsersWithSecretRotation, newSpec.Spec.UsersWithSecretRotation) &&
|
||||
reflect.DeepEqual(oldSpec.Spec.UsersWithInPlaceSecretRotation, newSpec.Spec.UsersWithInPlaceSecretRotation)
|
||||
|
||||
// connection pooler needs one system user created, which is done in
|
||||
// initUsers. Check if it needs to be called.
|
||||
needConnectionPooler := needMasterConnectionPoolerWorker(&newSpec.Spec) ||
|
||||
needReplicaConnectionPoolerWorker(&newSpec.Spec)
|
||||
// connection pooler needs one system user created who is initialized in initUsers
|
||||
// only when disabled in oldSpec and enabled in newSpec
|
||||
needPoolerUser := c.needConnectionPoolerUser(&oldSpec.Spec, &newSpec.Spec)
|
||||
|
||||
if !sameUsers || !sameRotatedUsers || needConnectionPooler {
|
||||
c.logger.Debugf("initialize users")
|
||||
if err := c.initUsers(); err != nil {
|
||||
c.logger.Errorf("could not init users: %v", err)
|
||||
updateFailed = true
|
||||
// streams new replication user created who is initialized in initUsers
|
||||
// only when streams were not specified in oldSpec but in newSpec
|
||||
needStreamUser := len(oldSpec.Spec.Streams) == 0 && len(newSpec.Spec.Streams) > 0
|
||||
|
||||
if !sameUsers || !sameRotatedUsers || needPoolerUser || needStreamUser {
|
||||
c.logger.Debugf("initialize users")
|
||||
if err := c.initUsers(); err != nil {
|
||||
c.logger.Errorf("could not init users - skipping sync of secrets and databases: %v", err)
|
||||
userInitFailed = true
|
||||
updateFailed = true
|
||||
return
|
||||
}
|
||||
|
||||
c.logger.Debugf("syncing secrets")
|
||||
//TODO: mind the secrets of the deleted/new users
|
||||
if err := c.syncSecrets(); err != nil {
|
||||
c.logger.Errorf("could not sync secrets: %v", err)
|
||||
updateFailed = true
|
||||
}
|
||||
}
|
||||
|
||||
c.logger.Debugf("syncing secrets")
|
||||
|
||||
//TODO: mind the secrets of the deleted/new users
|
||||
if err := c.syncSecrets(); err != nil {
|
||||
c.logger.Errorf("could not sync secrets: %v", err)
|
||||
updateFailed = true
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Volume
|
||||
if c.OpConfig.StorageResizeMode != "off" {
|
||||
@@ -892,7 +904,7 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
||||
}()
|
||||
|
||||
// Roles and Databases
|
||||
if !(c.databaseAccessDisabled() || c.getNumberOfInstances(&c.Spec) <= 0 || c.Spec.StandbyCluster != nil) {
|
||||
if !userInitFailed && !(c.databaseAccessDisabled() || c.getNumberOfInstances(&c.Spec) <= 0 || c.Spec.StandbyCluster != nil) {
|
||||
c.logger.Debugf("syncing roles")
|
||||
if err := c.syncRoles(); err != nil {
|
||||
c.logger.Errorf("could not sync roles: %v", err)
|
||||
@@ -920,13 +932,12 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
||||
// need to process. In the future we may want to do this more careful and
|
||||
// check which databases we need to process, but even repeating the whole
|
||||
// installation process should be good enough.
|
||||
|
||||
if _, err := c.syncConnectionPooler(oldSpec, newSpec, c.installLookupFunction); err != nil {
|
||||
c.logger.Errorf("could not sync connection pooler: %v", err)
|
||||
updateFailed = true
|
||||
}
|
||||
|
||||
if len(c.Spec.Streams) > 0 {
|
||||
if len(newSpec.Spec.Streams) > 0 {
|
||||
if err := c.syncStreams(); err != nil {
|
||||
c.logger.Errorf("could not sync streams: %v", err)
|
||||
updateFailed = true
|
||||
@@ -1094,28 +1105,10 @@ func (c *Cluster) initSystemUsers() {
|
||||
Password: util.RandomPassword(constants.PasswordLength),
|
||||
}
|
||||
|
||||
// Connection pooler user is an exception, if requested it's going to be
|
||||
// created by operator as a normal pgUser
|
||||
// Connection pooler user is an exception
|
||||
// if requested it's going to be created by operator
|
||||
if needConnectionPooler(&c.Spec) {
|
||||
connectionPoolerSpec := c.Spec.ConnectionPooler
|
||||
if connectionPoolerSpec == nil {
|
||||
connectionPoolerSpec = &acidv1.ConnectionPooler{}
|
||||
}
|
||||
|
||||
// Using superuser as pooler user is not a good idea. First of all it's
|
||||
// not going to be synced correctly with the current implementation,
|
||||
// and second it's a bad practice.
|
||||
username := c.OpConfig.ConnectionPooler.User
|
||||
|
||||
isSuperUser := connectionPoolerSpec.User == c.OpConfig.SuperUsername
|
||||
isProtectedUser := c.shouldAvoidProtectedOrSystemRole(
|
||||
connectionPoolerSpec.User, "connection pool role")
|
||||
|
||||
if !isSuperUser && !isProtectedUser {
|
||||
username = util.Coalesce(
|
||||
connectionPoolerSpec.User,
|
||||
c.OpConfig.ConnectionPooler.User)
|
||||
}
|
||||
username := c.poolerUser(&c.Spec)
|
||||
|
||||
// connection pooler application should be able to login with this role
|
||||
connectionPoolerUser := spec.PgUser{
|
||||
|
||||
Reference in New Issue
Block a user