diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 6f9f17763..611295f5f 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -1127,7 +1127,7 @@ func (c *Cluster) initSystemUsers() { // replication users for event streams are another exception // the operator will create one replication user for all streams if len(c.Spec.Streams) > 0 { - username := constants.EventStreamSourceSlotPrefix + constants.UserRoleNameSuffix + username := fmt.Sprintf("%s%s", constants.EventStreamSourceSlotPrefix, constants.UserRoleNameSuffix) streamUser := spec.PgUser{ Origin: spec.RoleOriginStream, Name: username, @@ -1136,8 +1136,8 @@ func (c *Cluster) initSystemUsers() { Password: util.RandomPassword(constants.PasswordLength), } - if _, exists := c.systemUsers[username]; !exists { - c.systemUsers[username] = streamUser + if _, exists := c.systemUsers[constants.EventStreamUserKeyName]; !exists { + c.systemUsers[constants.EventStreamUserKeyName] = streamUser } } } @@ -1155,9 +1155,9 @@ func (c *Cluster) initPreparedDatabaseRoles() error { constants.WriterRoleNameSuffix: constants.ReaderRoleNameSuffix, } defaultUsers := map[string]string{ - constants.OwnerRoleNameSuffix + constants.UserRoleNameSuffix: constants.OwnerRoleNameSuffix, - constants.ReaderRoleNameSuffix + constants.UserRoleNameSuffix: constants.ReaderRoleNameSuffix, - constants.WriterRoleNameSuffix + constants.UserRoleNameSuffix: constants.WriterRoleNameSuffix, + fmt.Sprintf("%s%s", constants.OwnerRoleNameSuffix, constants.UserRoleNameSuffix): constants.OwnerRoleNameSuffix, + fmt.Sprintf("%s%s", constants.ReaderRoleNameSuffix, constants.UserRoleNameSuffix): constants.ReaderRoleNameSuffix, + fmt.Sprintf("%s%s", constants.WriterRoleNameSuffix, constants.UserRoleNameSuffix): constants.WriterRoleNameSuffix, } for preparedDbName, preparedDB := range c.Spec.PreparedDatabases { @@ -1218,7 +1218,7 @@ func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix c.logger.Warn("secretNamespace ignored because enable_cross_namespace_secret set to false. Creating secrets in cluster namespace.") } } - roleName := prefix + defaultRole + roleName := fmt.Sprintf("%s%s", prefix, defaultRole) flags := []string{constants.RoleFlagNoLogin} if defaultRole[len(defaultRole)-5:] == constants.UserRoleNameSuffix { @@ -1236,7 +1236,7 @@ func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix adminRole = admin isOwner = true } else { - adminRole = prefix + constants.OwnerRoleNameSuffix + adminRole = fmt.Sprintf("%s%s", prefix, constants.OwnerRoleNameSuffix) } newRole := spec.PgUser{ diff --git a/pkg/cluster/cluster_test.go b/pkg/cluster/cluster_test.go index 637c1f6e4..f36db09b0 100644 --- a/pkg/cluster/cluster_test.go +++ b/pkg/cluster/cluster_test.go @@ -759,11 +759,14 @@ func TestServiceAnnotations(t *testing.T) { func TestInitSystemUsers(t *testing.T) { testName := "Test system users initialization" - // default cluster without connection pooler + // default cluster without connection pooler and event streams cl.initSystemUsers() if _, exist := cl.systemUsers[constants.ConnectionPoolerUserKeyName]; exist { t.Errorf("%s, connection pooler user is present", testName) } + if _, exist := cl.systemUsers[constants.EventStreamUserKeyName]; exist { + t.Errorf("%s, stream user is present", testName) + } // cluster with connection pooler cl.Spec.EnableConnectionPooler = boolToPointer(true) @@ -805,6 +808,31 @@ func TestInitSystemUsers(t *testing.T) { if _, exist := cl.systemUsers["pooler"]; !exist { t.Errorf("%s, System users are not allowed to be a connection pool user", testName) } + + // using stream user in manifest but no streams defined should be treated like normal robot user + streamUser := fmt.Sprintf("%s%s", constants.EventStreamSourceSlotPrefix, constants.UserRoleNameSuffix) + cl.Spec.Users = map[string]acidv1.UserFlags{streamUser: []string{}} + cl.initSystemUsers() + if _, exist := cl.systemUsers[constants.EventStreamUserKeyName]; exist { + t.Errorf("%s, stream user is present", testName) + } + + // cluster with streams + cl.Spec.Streams = []acidv1.Stream{ + { + ApplicationId: "test-app", + Database: "test_db", + Tables: map[string]acidv1.StreamTable{ + "data.test_table": acidv1.StreamTable{ + EventType: "test_event", + }, + }, + }, + } + cl.initSystemUsers() + if _, exist := cl.systemUsers[constants.EventStreamUserKeyName]; !exist { + t.Errorf("%s, stream user is not present", testName) + } } func TestPreparedDatabases(t *testing.T) { diff --git a/pkg/cluster/connection_pooler.go b/pkg/cluster/connection_pooler.go index 66751653c..340f6a3ae 100644 --- a/pkg/cluster/connection_pooler.go +++ b/pkg/cluster/connection_pooler.go @@ -46,7 +46,7 @@ type ConnectionPoolerObjects struct { func (c *Cluster) connectionPoolerName(role PostgresRole) string { name := c.Name + "-pooler" if role == Replica { - name = name + "-repl" + name = fmt.Sprintf("%s-%s", name, "repl") } return name } diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index a3628efa4..d14bc1572 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -80,7 +80,7 @@ func (c *Cluster) statefulSetName() string { func (c *Cluster) endpointName(role PostgresRole) string { name := c.Name if role == Replica { - name = name + "-repl" + name = fmt.Sprintf("%s-%s", name, "repl") } return name @@ -89,7 +89,7 @@ func (c *Cluster) endpointName(role PostgresRole) string { func (c *Cluster) serviceName(role PostgresRole) string { name := c.Name if role == Replica { - name = name + "-repl" + name = fmt.Sprintf("%s-%s", name, "repl") } return name @@ -2238,7 +2238,7 @@ func (c *Cluster) generateLogicalBackupPodEnvVars() []v1.EnvVar { // getLogicalBackupJobName returns the name; the job itself may not exists func (c *Cluster) getLogicalBackupJobName() (jobName string) { - return trimCronjobName(c.OpConfig.LogicalBackupJobPrefix + c.clusterName().Name) + return trimCronjobName(fmt.Sprintf("%s%s", c.OpConfig.LogicalBackupJobPrefix, c.clusterName().Name)) } // Return an array of ownerReferences to make an arbitraty object dependent on diff --git a/pkg/cluster/streams_test.go b/pkg/cluster/streams_test.go index 0094708a4..674d2738d 100644 --- a/pkg/cluster/streams_test.go +++ b/pkg/cluster/streams_test.go @@ -40,7 +40,7 @@ var ( namespace string = "default" appId string = "test-app" dbName string = "foo" - fesUser string = constants.EventStreamSourceSlotPrefix + constants.UserRoleNameSuffix + fesUser string = fmt.Sprintf("%s%s", constants.EventStreamSourceSlotPrefix, constants.UserRoleNameSuffix) fesName string = fmt.Sprintf("%s-%s", clusterName, appId) slotName string = fmt.Sprintf("%s_%s_%s", constants.EventStreamSourceSlotPrefix, dbName, strings.Replace(appId, "-", "_", -1)) @@ -55,7 +55,7 @@ var ( }, Spec: acidv1.PostgresSpec{ Databases: map[string]string{ - dbName: dbName + constants.UserRoleNameSuffix, + dbName: fmt.Sprintf("%s%s", dbName, constants.UserRoleNameSuffix), }, Streams: []acidv1.Stream{ { diff --git a/pkg/cluster/sync.go b/pkg/cluster/sync.go index 1d73a2e0d..28bd05a5a 100644 --- a/pkg/cluster/sync.go +++ b/pkg/cluster/sync.go @@ -715,12 +715,16 @@ func (c *Cluster) updateSecret( } else if secretUsername == c.systemUsers[constants.ReplicationUserKeyName].Name { userKey = constants.ReplicationUserKeyName userMap = c.systemUsers - } else if secretUsername == constants.ConnectionPoolerUserName { - userKey = constants.ConnectionPoolerUserName - userMap = c.systemUsers - } else if secretUsername == constants.EventStreamSourceSlotPrefix+constants.UserRoleNameSuffix { - userKey = constants.EventStreamSourceSlotPrefix + constants.UserRoleNameSuffix - userMap = c.systemUsers + } else if _, exists := c.systemUsers[constants.ConnectionPoolerUserKeyName]; exists { + if secretUsername == c.systemUsers[constants.ConnectionPoolerUserKeyName].Name { + userKey = constants.ConnectionPoolerUserName + userMap = c.systemUsers + } + } else if _, exists := c.systemUsers[constants.EventStreamUserKeyName]; exists { + if secretUsername == c.systemUsers[constants.EventStreamUserKeyName].Name { + userKey = fmt.Sprintf("%s%s", constants.EventStreamSourceSlotPrefix, constants.UserRoleNameSuffix) + userMap = c.systemUsers + } } else { userKey = secretUsername userMap = c.pgUsers @@ -816,7 +820,7 @@ func (c *Cluster) rotatePasswordInSecret( // create rotation user if role is not listed for in-place password update if !util.SliceContains(c.Spec.UsersWithInPlaceSecretRotation, secretUsername) { rotationUser := secretPgUser - newRotationUsername := secretUsername + currentTime.Format("060102") + newRotationUsername := fmt.Sprintf("%s%s", secretUsername, currentTime.Format("060102")) rotationUser.Name = newRotationUsername rotationUser.MemberOf = []string{secretUsername} (*rotationUsers)[newRotationUsername] = rotationUser @@ -976,7 +980,7 @@ func (c *Cluster) syncDatabases() error { for preparedDatabaseName := range c.Spec.PreparedDatabases { _, exists := currentDatabases[preparedDatabaseName] if !exists { - createDatabases[preparedDatabaseName] = preparedDatabaseName + constants.OwnerRoleNameSuffix + createDatabases[preparedDatabaseName] = fmt.Sprintf("%s%s", preparedDatabaseName, constants.OwnerRoleNameSuffix) preparedDatabases = append(preparedDatabases, preparedDatabaseName) } } @@ -1077,9 +1081,9 @@ func (c *Cluster) syncPreparedSchemas(databaseName string, preparedSchemas map[s if createPreparedSchemas, equal := util.SubstractStringSlices(schemas, currentSchemas); !equal { for _, schemaName := range createPreparedSchemas { owner := constants.OwnerRoleNameSuffix - dbOwner := databaseName + owner + dbOwner := fmt.Sprintf("%s%s", databaseName, owner) if preparedSchemas[schemaName].DefaultRoles == nil || *preparedSchemas[schemaName].DefaultRoles { - owner = databaseName + "_" + schemaName + owner + owner = fmt.Sprintf("%s_%s%s", databaseName, schemaName, owner) } else { owner = dbOwner } diff --git a/pkg/util/constants/roles.go b/pkg/util/constants/roles.go index dd906fe80..8c81e2f04 100644 --- a/pkg/util/constants/roles.go +++ b/pkg/util/constants/roles.go @@ -4,8 +4,9 @@ package constants const ( PasswordLength = 64 SuperuserKeyName = "superuser" - ConnectionPoolerUserKeyName = "pooler" ReplicationUserKeyName = "replication" + ConnectionPoolerUserKeyName = "pooler" + EventStreamUserKeyName = "streamer" RoleFlagSuperuser = "SUPERUSER" RoleFlagInherit = "INHERIT" RoleFlagLogin = "LOGIN"