reflect code review

This commit is contained in:
Felix Kunde 2020-03-16 18:50:20 +01:00
parent 353eb6994d
commit e246ba7c3f
6 changed files with 61 additions and 48 deletions

View File

@ -85,7 +85,7 @@ type PreparedDatabase struct {
Extensions map[string]string `json:"extensions,omitempty"` Extensions map[string]string `json:"extensions,omitempty"`
} }
// PreparedSchema describes elements to be bootstrapped in the schema // PreparedSchema describes elements to be bootstrapped per schema
type PreparedSchema struct { type PreparedSchema struct {
DefaultRoles *bool `json:"defaultRoles,omitempty" defaults:"true"` DefaultRoles *bool `json:"defaultRoles,omitempty" defaults:"true"`
DefaultUsers bool `json:"defaultUsers,omitempty" defaults:"false"` DefaultUsers bool `json:"defaultUsers,omitempty" defaults:"false"`

View File

@ -837,8 +837,17 @@ func (c *Cluster) initPreparedDatabaseRoles() error {
c.Spec.PreparedDatabases = preparedDatabases c.Spec.PreparedDatabases = preparedDatabases
} }
defaultRoles := map[string]string{"_owner": "", "_reader": "", "_writer": "_reader"} // create maps with default roles/users as keys and their membership as values
defaultUsers := map[string]string{"_owner_user": "_owner", "_reader_user": "_reader", "_writer_user": "_writer"} defaultRoles := map[string]string{
constants.OwnerRoleNameSuffix: "",
constants.ReaderRoleNameSuffix: "",
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,
}
for preparedDbName, preparedDB := range preparedDatabases { for preparedDbName, preparedDB := range preparedDatabases {
// default roles per database // default roles per database
@ -858,11 +867,15 @@ func (c *Cluster) initPreparedDatabaseRoles() error {
} }
for preparedSchemaName, preparedSchema := range preparedSchemas { for preparedSchemaName, preparedSchema := range preparedSchemas {
if preparedSchema.DefaultRoles == nil || *preparedSchema.DefaultRoles { if preparedSchema.DefaultRoles == nil || *preparedSchema.DefaultRoles {
if err := c.initDefaultRoles(defaultRoles, preparedDbName+"_owner", preparedDbName+"_"+preparedSchemaName); err != nil { if err := c.initDefaultRoles(defaultRoles,
preparedDbName+constants.OwnerRoleNameSuffix,
preparedDbName+"_"+preparedSchemaName); err != nil {
return fmt.Errorf("could not initialize default roles for database schema %s: %v", preparedSchemaName, err) return fmt.Errorf("could not initialize default roles for database schema %s: %v", preparedSchemaName, err)
} }
if preparedSchema.DefaultUsers { if preparedSchema.DefaultUsers {
if err := c.initDefaultRoles(defaultUsers, preparedDbName+"_owner", preparedDbName+"_"+preparedSchemaName); err != nil { if err := c.initDefaultRoles(defaultUsers,
preparedDbName+constants.OwnerRoleNameSuffix,
preparedDbName+"_"+preparedSchemaName); err != nil {
return fmt.Errorf("could not initialize default users for database schema %s: %v", preparedSchemaName, err) return fmt.Errorf("could not initialize default users for database schema %s: %v", preparedSchemaName, err)
} }
} }
@ -879,7 +892,7 @@ func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix
roleName := prefix + defaultRole roleName := prefix + defaultRole
flags := []string{constants.RoleFlagNoLogin} flags := []string{constants.RoleFlagNoLogin}
if defaultRole[len(defaultRole)-5:] == "_user" { if defaultRole[len(defaultRole)-5:] == constants.UserRoleNameSuffix {
flags = []string{constants.RoleFlagLogin} flags = []string{constants.RoleFlagLogin}
} }
@ -889,10 +902,10 @@ func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix
} }
adminRole := "" adminRole := ""
if strings.Contains(defaultRole, "_owner") { if strings.Contains(defaultRole, constants.OwnerRoleNameSuffix) {
adminRole = admin adminRole = admin
} else { } else {
adminRole = prefix + "_owner" adminRole = prefix + constants.OwnerRoleNameSuffix
} }
newRole := spec.PgUser{ newRole := spec.PgUser{

View File

@ -320,13 +320,13 @@ func (c *Cluster) databaseSchemaNameValid(schemaName string) bool {
func (c *Cluster) execAlterSchemaDefaultPrivileges(schemaName, owner, rolePrefix string) error { func (c *Cluster) execAlterSchemaDefaultPrivileges(schemaName, owner, rolePrefix string) error {
if _, err := c.pgDb.Exec(fmt.Sprintf(schemaDefaultPrivilegesSQL, owner, if _, err := c.pgDb.Exec(fmt.Sprintf(schemaDefaultPrivilegesSQL, owner,
schemaName, rolePrefix+"_writer", rolePrefix+"_reader", // schema schemaName, rolePrefix+constants.ReaderRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix, // schema
schemaName, rolePrefix+"_reader", // tables schemaName, rolePrefix+constants.ReaderRoleNameSuffix, // tables
schemaName, rolePrefix+"_reader", // sequences schemaName, rolePrefix+constants.ReaderRoleNameSuffix, // sequences
schemaName, rolePrefix+"_writer", // tables schemaName, rolePrefix+constants.WriterRoleNameSuffix, // tables
schemaName, rolePrefix+"_writer", // sequences schemaName, rolePrefix+constants.WriterRoleNameSuffix, // sequences
schemaName, rolePrefix+"_reader", rolePrefix+"_writer", // types schemaName, rolePrefix+constants.ReaderRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix, // types
schemaName, rolePrefix+"_reader", rolePrefix+"_writer")); err != nil { // functions schemaName, rolePrefix+constants.ReaderRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix)); err != nil { // functions
return fmt.Errorf("could not alter default privileges for database schema %s: %v", schemaName, err) return fmt.Errorf("could not alter default privileges for database schema %s: %v", schemaName, err)
} }
@ -335,13 +335,13 @@ func (c *Cluster) execAlterSchemaDefaultPrivileges(schemaName, owner, rolePrefix
func (c *Cluster) execAlterGlobalDefaultPrivileges(owner, rolePrefix string) error { func (c *Cluster) execAlterGlobalDefaultPrivileges(owner, rolePrefix string) error {
if _, err := c.pgDb.Exec(fmt.Sprintf(globalDefaultPrivilegesSQL, owner, if _, err := c.pgDb.Exec(fmt.Sprintf(globalDefaultPrivilegesSQL, owner,
rolePrefix+"_writer", rolePrefix+"_reader", // schemas rolePrefix+constants.WriterRoleNameSuffix, rolePrefix+constants.ReaderRoleNameSuffix, // schemas
rolePrefix+"_reader", // tables rolePrefix+constants.ReaderRoleNameSuffix, // tables
rolePrefix+"_reader", // sequences rolePrefix+constants.ReaderRoleNameSuffix, // sequences
rolePrefix+"_writer", // tables rolePrefix+constants.WriterRoleNameSuffix, // tables
rolePrefix+"_writer", // sequences rolePrefix+constants.WriterRoleNameSuffix, // sequences
rolePrefix+"_reader", rolePrefix+"_writer", // types rolePrefix+constants.ReaderRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix, // types
rolePrefix+"_reader", rolePrefix+"_writer")); err != nil { // functions rolePrefix+constants.ReaderRoleNameSuffix, rolePrefix+constants.WriterRoleNameSuffix)); err != nil { // functions
return fmt.Errorf("could not alter default privileges for database %s: %v", rolePrefix, err) return fmt.Errorf("could not alter default privileges for database %s: %v", rolePrefix, err)
} }

View File

@ -524,7 +524,7 @@ func (c *Cluster) syncDatabases() error {
for preparedDatname := range c.Spec.PreparedDatabases { for preparedDatname := range c.Spec.PreparedDatabases {
_, exists := currentDatabases[preparedDatname] _, exists := currentDatabases[preparedDatname]
if !exists { if !exists {
createDatabases[preparedDatname] = preparedDatname + "_owner" createDatabases[preparedDatname] = preparedDatname + constants.OwnerRoleNameSuffix
} }
} }
@ -568,7 +568,7 @@ func (c *Cluster) syncPreparedDatabases() error {
}() }()
// first, set default privileges for prepared database // first, set default privileges for prepared database
c.execAlterGlobalDefaultPrivileges(preparedDbName+"_owner", preparedDbName) c.execAlterGlobalDefaultPrivileges(preparedDbName+constants.OwnerRoleNameSuffix, preparedDbName)
// now, prepare defined schemas // now, prepare defined schemas
preparedSchemas := preparedDB.PreparedSchemas preparedSchemas := preparedDB.PreparedSchemas
@ -604,7 +604,7 @@ func (c *Cluster) syncPreparedSchemas(datname string, preparedSchemas map[string
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 := "_owner" owner := constants.OwnerRoleNameSuffix
dbOwner := datname + owner dbOwner := datname + owner
if preparedSchemas[schemaName].DefaultRoles == nil || *preparedSchemas[schemaName].DefaultRoles { if preparedSchemas[schemaName].DefaultRoles == nil || *preparedSchemas[schemaName].DefaultRoles {
owner = datname + "_" + schemaName + owner owner = datname + "_" + schemaName + owner
@ -621,14 +621,14 @@ func (c *Cluster) syncPreparedSchemas(datname string, preparedSchemas map[string
} }
func (c *Cluster) syncExtensions(extensions map[string]string) error { func (c *Cluster) syncExtensions(extensions map[string]string) error {
c.setProcessName("syncing extensions") c.setProcessName("syncing database extensions")
createExtensions := make(map[string]string) createExtensions := make(map[string]string)
alterExtensions := make(map[string]string) alterExtensions := make(map[string]string)
currentExtensions, err := c.getExtensions() currentExtensions, err := c.getExtensions()
if err != nil { if err != nil {
return fmt.Errorf("could not get current extensions: %v", err) return fmt.Errorf("could not get current database extensions: %v", err)
} }
for extName, newSchema := range extensions { for extName, newSchema := range extensions {
@ -640,10 +640,6 @@ func (c *Cluster) syncExtensions(extensions map[string]string) error {
} }
} }
if len(createExtensions)+len(alterExtensions) == 0 {
return nil
}
for extName, schema := range createExtensions { for extName, schema := range createExtensions {
if err = c.executeCreateExtension(extName, schema); err != nil { if err = c.executeCreateExtension(extName, schema); err != nil {
return err return err

View File

@ -13,4 +13,8 @@ const (
RoleFlagCreateDB = "CREATEDB" RoleFlagCreateDB = "CREATEDB"
RoleFlagReplication = "REPLICATION" RoleFlagReplication = "REPLICATION"
RoleFlagByPassRLS = "BYPASSRLS" RoleFlagByPassRLS = "BYPASSRLS"
OwnerRoleNameSuffix = "_owner"
ReaderRoleNameSuffix = "_reader"
WriterRoleNameSuffix = "_writer"
UserRoleNameSuffix = "_user"
) )

View File

@ -73,37 +73,37 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM
} }
// ExecuteSyncRequests makes actual database changes from the requests passed in its arguments. // ExecuteSyncRequests makes actual database changes from the requests passed in its arguments.
func (strategy DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []spec.PgSyncUserRequest, db *sql.DB) error { func (strategy DefaultUserSyncStrategy) ExecuteSyncRequests(requests []spec.PgSyncUserRequest, db *sql.DB) error {
var rr []spec.PgSyncUserRequest var reqretries []spec.PgSyncUserRequest
var errors []string var errors []string
for _, r := range reqs { for _, request := range requests {
switch r.Kind { switch request.Kind {
case spec.PGSyncUserAdd: case spec.PGSyncUserAdd:
if err := strategy.createPgUser(r.User, db); err != nil { if err := strategy.createPgUser(request.User, db); err != nil {
rr = append(rr, r) reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not create user %q: %v", r.User.Name, err)) errors = append(errors, fmt.Sprintf("could not create user %q: %v", request.User.Name, err))
} }
case spec.PGsyncUserAlter: case spec.PGsyncUserAlter:
if err := strategy.alterPgUser(r.User, db); err != nil { if err := strategy.alterPgUser(request.User, db); err != nil {
rr = append(rr, r) reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not alter user %q: %v", r.User.Name, err)) errors = append(errors, fmt.Sprintf("could not alter user %q: %v", request.User.Name, err))
} }
case spec.PGSyncAlterSet: case spec.PGSyncAlterSet:
if err := strategy.alterPgUserSet(r.User, db); err != nil { if err := strategy.alterPgUserSet(request.User, db); err != nil {
rr = append(rr, r) reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not set custom user %q parameters: %v", r.User.Name, err)) errors = append(errors, fmt.Sprintf("could not set custom user %q parameters: %v", request.User.Name, err))
} }
default: default:
return fmt.Errorf("unrecognized operation: %v", r.Kind) return fmt.Errorf("unrecognized operation: %v", request.Kind)
} }
} }
// creating roles might fail if group role members are created before the parent role // creating roles might fail if group role members are created before the parent role
// retry adding roles as long as the number of failed attempts is shrinking // retry adding roles as long as the number of failed attempts is shrinking
if len(rr) > 0 { if len(reqretries) > 0 {
if len(rr) < len(reqs) { if len(reqretries) < len(requests) {
if err := strategy.ExecuteSyncRequests(rr, db); err != nil { if err := strategy.ExecuteSyncRequests(reqretries, db); err != nil {
return err return err
} }
} else { } else {