fetch pooler and fes_user system user only when corresponding features are used (#2009)
* fetch pooler and fes_user system user only when corresponding features are used * cover error case in unit test * use string formatting instead of +
This commit is contained in:
		
							parent
							
								
									e11edcdcde
								
							
						
					
					
						commit
						ef324494a0
					
				|  | @ -1127,7 +1127,7 @@ func (c *Cluster) initSystemUsers() { | ||||||
| 	// replication users for event streams are another exception
 | 	// replication users for event streams are another exception
 | ||||||
| 	// the operator will create one replication user for all streams
 | 	// the operator will create one replication user for all streams
 | ||||||
| 	if len(c.Spec.Streams) > 0 { | 	if len(c.Spec.Streams) > 0 { | ||||||
| 		username := constants.EventStreamSourceSlotPrefix + constants.UserRoleNameSuffix | 		username := fmt.Sprintf("%s%s", constants.EventStreamSourceSlotPrefix, constants.UserRoleNameSuffix) | ||||||
| 		streamUser := spec.PgUser{ | 		streamUser := spec.PgUser{ | ||||||
| 			Origin:    spec.RoleOriginStream, | 			Origin:    spec.RoleOriginStream, | ||||||
| 			Name:      username, | 			Name:      username, | ||||||
|  | @ -1136,8 +1136,8 @@ func (c *Cluster) initSystemUsers() { | ||||||
| 			Password:  util.RandomPassword(constants.PasswordLength), | 			Password:  util.RandomPassword(constants.PasswordLength), | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if _, exists := c.systemUsers[username]; !exists { | 		if _, exists := c.systemUsers[constants.EventStreamUserKeyName]; !exists { | ||||||
| 			c.systemUsers[username] = streamUser | 			c.systemUsers[constants.EventStreamUserKeyName] = streamUser | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -1155,9 +1155,9 @@ func (c *Cluster) initPreparedDatabaseRoles() error { | ||||||
| 		constants.WriterRoleNameSuffix: constants.ReaderRoleNameSuffix, | 		constants.WriterRoleNameSuffix: constants.ReaderRoleNameSuffix, | ||||||
| 	} | 	} | ||||||
| 	defaultUsers := map[string]string{ | 	defaultUsers := map[string]string{ | ||||||
| 		constants.OwnerRoleNameSuffix + constants.UserRoleNameSuffix:  constants.OwnerRoleNameSuffix, | 		fmt.Sprintf("%s%s", constants.OwnerRoleNameSuffix, constants.UserRoleNameSuffix):  constants.OwnerRoleNameSuffix, | ||||||
| 		constants.ReaderRoleNameSuffix + constants.UserRoleNameSuffix: constants.ReaderRoleNameSuffix, | 		fmt.Sprintf("%s%s", constants.ReaderRoleNameSuffix, constants.UserRoleNameSuffix): constants.ReaderRoleNameSuffix, | ||||||
| 		constants.WriterRoleNameSuffix + constants.UserRoleNameSuffix: constants.WriterRoleNameSuffix, | 		fmt.Sprintf("%s%s", constants.WriterRoleNameSuffix, constants.UserRoleNameSuffix): constants.WriterRoleNameSuffix, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for preparedDbName, preparedDB := range c.Spec.PreparedDatabases { | 	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.") | 				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} | 		flags := []string{constants.RoleFlagNoLogin} | ||||||
| 		if defaultRole[len(defaultRole)-5:] == constants.UserRoleNameSuffix { | 		if defaultRole[len(defaultRole)-5:] == constants.UserRoleNameSuffix { | ||||||
|  | @ -1236,7 +1236,7 @@ func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix | ||||||
| 			adminRole = admin | 			adminRole = admin | ||||||
| 			isOwner = true | 			isOwner = true | ||||||
| 		} else { | 		} else { | ||||||
| 			adminRole = prefix + constants.OwnerRoleNameSuffix | 			adminRole = fmt.Sprintf("%s%s", prefix, constants.OwnerRoleNameSuffix) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		newRole := spec.PgUser{ | 		newRole := spec.PgUser{ | ||||||
|  |  | ||||||
|  | @ -759,11 +759,14 @@ func TestServiceAnnotations(t *testing.T) { | ||||||
| func TestInitSystemUsers(t *testing.T) { | func TestInitSystemUsers(t *testing.T) { | ||||||
| 	testName := "Test system users initialization" | 	testName := "Test system users initialization" | ||||||
| 
 | 
 | ||||||
| 	// default cluster without connection pooler
 | 	// default cluster without connection pooler and event streams
 | ||||||
| 	cl.initSystemUsers() | 	cl.initSystemUsers() | ||||||
| 	if _, exist := cl.systemUsers[constants.ConnectionPoolerUserKeyName]; exist { | 	if _, exist := cl.systemUsers[constants.ConnectionPoolerUserKeyName]; exist { | ||||||
| 		t.Errorf("%s, connection pooler user is present", testName) | 		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
 | 	// cluster with connection pooler
 | ||||||
| 	cl.Spec.EnableConnectionPooler = boolToPointer(true) | 	cl.Spec.EnableConnectionPooler = boolToPointer(true) | ||||||
|  | @ -805,6 +808,31 @@ func TestInitSystemUsers(t *testing.T) { | ||||||
| 	if _, exist := cl.systemUsers["pooler"]; !exist { | 	if _, exist := cl.systemUsers["pooler"]; !exist { | ||||||
| 		t.Errorf("%s, System users are not allowed to be a connection pool user", testName) | 		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) { | func TestPreparedDatabases(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ type ConnectionPoolerObjects struct { | ||||||
| func (c *Cluster) connectionPoolerName(role PostgresRole) string { | func (c *Cluster) connectionPoolerName(role PostgresRole) string { | ||||||
| 	name := c.Name + "-pooler" | 	name := c.Name + "-pooler" | ||||||
| 	if role == Replica { | 	if role == Replica { | ||||||
| 		name = name + "-repl" | 		name = fmt.Sprintf("%s-%s", name, "repl") | ||||||
| 	} | 	} | ||||||
| 	return name | 	return name | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ func (c *Cluster) statefulSetName() string { | ||||||
| func (c *Cluster) endpointName(role PostgresRole) string { | func (c *Cluster) endpointName(role PostgresRole) string { | ||||||
| 	name := c.Name | 	name := c.Name | ||||||
| 	if role == Replica { | 	if role == Replica { | ||||||
| 		name = name + "-repl" | 		name = fmt.Sprintf("%s-%s", name, "repl") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return name | 	return name | ||||||
|  | @ -89,7 +89,7 @@ func (c *Cluster) endpointName(role PostgresRole) string { | ||||||
| func (c *Cluster) serviceName(role PostgresRole) string { | func (c *Cluster) serviceName(role PostgresRole) string { | ||||||
| 	name := c.Name | 	name := c.Name | ||||||
| 	if role == Replica { | 	if role == Replica { | ||||||
| 		name = name + "-repl" | 		name = fmt.Sprintf("%s-%s", name, "repl") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return name | 	return name | ||||||
|  | @ -2238,7 +2238,7 @@ func (c *Cluster) generateLogicalBackupPodEnvVars() []v1.EnvVar { | ||||||
| 
 | 
 | ||||||
| // getLogicalBackupJobName returns the name; the job itself may not exists
 | // getLogicalBackupJobName returns the name; the job itself may not exists
 | ||||||
| func (c *Cluster) getLogicalBackupJobName() (jobName string) { | 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
 | // Return an array of ownerReferences to make an arbitraty object dependent on
 | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ var ( | ||||||
| 	namespace   string = "default" | 	namespace   string = "default" | ||||||
| 	appId       string = "test-app" | 	appId       string = "test-app" | ||||||
| 	dbName      string = "foo" | 	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) | 	fesName     string = fmt.Sprintf("%s-%s", clusterName, appId) | ||||||
| 	slotName    string = fmt.Sprintf("%s_%s_%s", constants.EventStreamSourceSlotPrefix, dbName, strings.Replace(appId, "-", "_", -1)) | 	slotName    string = fmt.Sprintf("%s_%s_%s", constants.EventStreamSourceSlotPrefix, dbName, strings.Replace(appId, "-", "_", -1)) | ||||||
| 
 | 
 | ||||||
|  | @ -55,7 +55,7 @@ var ( | ||||||
| 		}, | 		}, | ||||||
| 		Spec: acidv1.PostgresSpec{ | 		Spec: acidv1.PostgresSpec{ | ||||||
| 			Databases: map[string]string{ | 			Databases: map[string]string{ | ||||||
| 				dbName: dbName + constants.UserRoleNameSuffix, | 				dbName: fmt.Sprintf("%s%s", dbName, constants.UserRoleNameSuffix), | ||||||
| 			}, | 			}, | ||||||
| 			Streams: []acidv1.Stream{ | 			Streams: []acidv1.Stream{ | ||||||
| 				{ | 				{ | ||||||
|  |  | ||||||
|  | @ -715,12 +715,16 @@ func (c *Cluster) updateSecret( | ||||||
| 	} else if secretUsername == c.systemUsers[constants.ReplicationUserKeyName].Name { | 	} else if secretUsername == c.systemUsers[constants.ReplicationUserKeyName].Name { | ||||||
| 		userKey = constants.ReplicationUserKeyName | 		userKey = constants.ReplicationUserKeyName | ||||||
| 		userMap = c.systemUsers | 		userMap = c.systemUsers | ||||||
| 	} else if secretUsername == constants.ConnectionPoolerUserName { | 	} else if _, exists := c.systemUsers[constants.ConnectionPoolerUserKeyName]; exists { | ||||||
|  | 		if secretUsername == c.systemUsers[constants.ConnectionPoolerUserKeyName].Name { | ||||||
| 			userKey = constants.ConnectionPoolerUserName | 			userKey = constants.ConnectionPoolerUserName | ||||||
| 			userMap = c.systemUsers | 			userMap = c.systemUsers | ||||||
| 	} else if secretUsername == constants.EventStreamSourceSlotPrefix+constants.UserRoleNameSuffix { | 		} | ||||||
| 		userKey = constants.EventStreamSourceSlotPrefix + constants.UserRoleNameSuffix | 	} 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 | 			userMap = c.systemUsers | ||||||
|  | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		userKey = secretUsername | 		userKey = secretUsername | ||||||
| 		userMap = c.pgUsers | 		userMap = c.pgUsers | ||||||
|  | @ -816,7 +820,7 @@ func (c *Cluster) rotatePasswordInSecret( | ||||||
| 		// create rotation user if role is not listed for in-place password update
 | 		// create rotation user if role is not listed for in-place password update
 | ||||||
| 		if !util.SliceContains(c.Spec.UsersWithInPlaceSecretRotation, secretUsername) { | 		if !util.SliceContains(c.Spec.UsersWithInPlaceSecretRotation, secretUsername) { | ||||||
| 			rotationUser := secretPgUser | 			rotationUser := secretPgUser | ||||||
| 			newRotationUsername := secretUsername + currentTime.Format("060102") | 			newRotationUsername := fmt.Sprintf("%s%s", secretUsername, currentTime.Format("060102")) | ||||||
| 			rotationUser.Name = newRotationUsername | 			rotationUser.Name = newRotationUsername | ||||||
| 			rotationUser.MemberOf = []string{secretUsername} | 			rotationUser.MemberOf = []string{secretUsername} | ||||||
| 			(*rotationUsers)[newRotationUsername] = rotationUser | 			(*rotationUsers)[newRotationUsername] = rotationUser | ||||||
|  | @ -976,7 +980,7 @@ func (c *Cluster) syncDatabases() error { | ||||||
| 	for preparedDatabaseName := range c.Spec.PreparedDatabases { | 	for preparedDatabaseName := range c.Spec.PreparedDatabases { | ||||||
| 		_, exists := currentDatabases[preparedDatabaseName] | 		_, exists := currentDatabases[preparedDatabaseName] | ||||||
| 		if !exists { | 		if !exists { | ||||||
| 			createDatabases[preparedDatabaseName] = preparedDatabaseName + constants.OwnerRoleNameSuffix | 			createDatabases[preparedDatabaseName] = fmt.Sprintf("%s%s", preparedDatabaseName, constants.OwnerRoleNameSuffix) | ||||||
| 			preparedDatabases = append(preparedDatabases, preparedDatabaseName) | 			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 { | 	if createPreparedSchemas, equal := util.SubstractStringSlices(schemas, currentSchemas); !equal { | ||||||
| 		for _, schemaName := range createPreparedSchemas { | 		for _, schemaName := range createPreparedSchemas { | ||||||
| 			owner := constants.OwnerRoleNameSuffix | 			owner := constants.OwnerRoleNameSuffix | ||||||
| 			dbOwner := databaseName + owner | 			dbOwner := fmt.Sprintf("%s%s", databaseName, owner) | ||||||
| 			if preparedSchemas[schemaName].DefaultRoles == nil || *preparedSchemas[schemaName].DefaultRoles { | 			if preparedSchemas[schemaName].DefaultRoles == nil || *preparedSchemas[schemaName].DefaultRoles { | ||||||
| 				owner = databaseName + "_" + schemaName + owner | 				owner = fmt.Sprintf("%s_%s%s", databaseName, schemaName, owner) | ||||||
| 			} else { | 			} else { | ||||||
| 				owner = dbOwner | 				owner = dbOwner | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -4,8 +4,9 @@ package constants | ||||||
| const ( | const ( | ||||||
| 	PasswordLength              = 64 | 	PasswordLength              = 64 | ||||||
| 	SuperuserKeyName            = "superuser" | 	SuperuserKeyName            = "superuser" | ||||||
| 	ConnectionPoolerUserKeyName = "pooler" |  | ||||||
| 	ReplicationUserKeyName      = "replication" | 	ReplicationUserKeyName      = "replication" | ||||||
|  | 	ConnectionPoolerUserKeyName = "pooler" | ||||||
|  | 	EventStreamUserKeyName      = "streamer" | ||||||
| 	RoleFlagSuperuser           = "SUPERUSER" | 	RoleFlagSuperuser           = "SUPERUSER" | ||||||
| 	RoleFlagInherit             = "INHERIT" | 	RoleFlagInherit             = "INHERIT" | ||||||
| 	RoleFlagLogin               = "LOGIN" | 	RoleFlagLogin               = "LOGIN" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue