Skip to content

Commit 8220fab

Browse files
committed
feat: wip
1 parent 1a420d6 commit 8220fab

File tree

3 files changed

+194
-49
lines changed

3 files changed

+194
-49
lines changed

internal/controller/postgresql/postgres/database.go

Lines changed: 123 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package postgres
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67

78
"github.com/lib/pq"
@@ -12,12 +13,14 @@ const (
1213
RestrictKeyword = "RESTRICT"
1314
CreateDBSQLTemplate = `CREATE DATABASE "%s" WITH OWNER = "%s"`
1415
ChangeDBOwnerSQLTemplate = `ALTER DATABASE "%s" OWNER TO "%s"`
15-
IsDatabaseExistSQLTemplate = `SELECT 1 FROM pg_database WHERE datname='%s'`
16+
GetDatabaseOwnerSQLTemplate = `SELECT pg_catalog.pg_get_userbyid(datdba) as owner FROM pg_database WHERE datname='%s'`
1617
RenameDatabaseSQLTemplate = `ALTER DATABASE "%s" RENAME TO "%s"`
1718
CreateSchemaSQLTemplate = `CREATE SCHEMA IF NOT EXISTS "%s" AUTHORIZATION "%s"`
1819
CreateExtensionSQLTemplate = `CREATE EXTENSION IF NOT EXISTS "%s"`
1920
DropDatabaseSQLTemplate = `DROP DATABASE "%s"`
21+
GetExtensionListSQLTemplate = `SELECT extname FROM pg_extension;`
2022
DropExtensionSQLTemplate = `DROP EXTENSION IF EXISTS "%s" %s`
23+
GetSchemaListSQLTemplate = `SELECT schema_name FROM information_schema.schemata`
2124
DropSchemaSQLTemplate = `DROP SCHEMA IF EXISTS "%s" %s`
2225
GrantUsageSchemaSQLTemplate = `GRANT USAGE ON SCHEMA "%s" TO "%s"`
2326
GrantAllTablesSQLTemplate = `GRANT %s ON ALL TABLES IN SCHEMA "%s" TO "%s"`
@@ -35,23 +38,60 @@ AND n.nspname = '%s';`
3538
DuplicateDatabaseErrorCode = "42P04"
3639
)
3740

38-
func (c *pg) IsDatabaseExist(ctx context.Context, dbname string) (bool, error) {
41+
func (c *pg) GetDatabaseOwner(ctx context.Context, dbname string) (string, error) {
3942
err := c.connect(c.defaultDatabase)
4043
if err != nil {
41-
return false, err
44+
return "", err
4245
}
4346

44-
res, err := c.db.ExecContext(ctx, fmt.Sprintf(IsDatabaseExistSQLTemplate, dbname))
47+
rows, err := c.db.QueryContext(ctx, fmt.Sprintf(GetDatabaseOwnerSQLTemplate, dbname))
4548
if err != nil {
46-
return false, err
49+
return "", err
50+
}
51+
52+
defer rows.Close()
53+
54+
res := []string{}
55+
56+
for rows.Next() {
57+
it := ""
58+
// Scan
59+
err = rows.Scan(&it)
60+
// Check error
61+
if err != nil {
62+
return "", err
63+
}
64+
// Save
65+
res = append(res, it)
66+
}
67+
68+
// Rows error
69+
err = rows.Err()
70+
// Check error
71+
if err != nil {
72+
return "", err
73+
}
74+
75+
if len(res) != 1 {
76+
return "", errors.New("select on database mustn't give more than one result. there is a severe issue somewhere")
77+
}
78+
79+
// Check length
80+
if len(res) == 0 {
81+
return "", nil
4782
}
48-
// Get affected rows
49-
nb, err := res.RowsAffected()
83+
84+
return res[0], nil
85+
}
86+
87+
func (c *pg) IsDatabaseExist(ctx context.Context, dbname string) (bool, error) {
88+
o, err := c.GetDatabaseOwner(ctx, dbname)
89+
// Check error
5090
if err != nil {
51-
return false, err
91+
return false, nil
5292
}
5393

54-
return nb == 1, nil
94+
return o != "", nil
5595
}
5696

5797
func (c *pg) RenameDatabase(ctx context.Context, oldname, newname string) error {
@@ -280,6 +320,80 @@ func (c *pg) DropSchema(ctx context.Context, database, schema string, cascade bo
280320
return nil
281321
}
282322

323+
func (c *pg) ListSchema(ctx context.Context, database string) ([]string, error) {
324+
err := c.connect(database)
325+
if err != nil {
326+
return nil, err
327+
}
328+
329+
rows, err := c.db.QueryContext(ctx, GetSchemaListSQLTemplate)
330+
if err != nil {
331+
return nil, err
332+
}
333+
334+
defer rows.Close()
335+
336+
res := []string{}
337+
338+
for rows.Next() {
339+
it := ""
340+
// Scan
341+
err = rows.Scan(&it)
342+
// Check error
343+
if err != nil {
344+
return nil, err
345+
}
346+
// Save
347+
res = append(res, it)
348+
}
349+
350+
// Rows error
351+
err = rows.Err()
352+
// Check error
353+
if err != nil {
354+
return nil, err
355+
}
356+
357+
return res, nil
358+
}
359+
360+
func (c *pg) ListExtensions(ctx context.Context, database string) ([]string, error) {
361+
err := c.connect(database)
362+
if err != nil {
363+
return nil, err
364+
}
365+
366+
rows, err := c.db.QueryContext(ctx, GetExtensionListSQLTemplate)
367+
if err != nil {
368+
return nil, err
369+
}
370+
371+
defer rows.Close()
372+
373+
res := []string{}
374+
375+
for rows.Next() {
376+
it := ""
377+
// Scan
378+
err = rows.Scan(&it)
379+
// Check error
380+
if err != nil {
381+
return nil, err
382+
}
383+
// Save
384+
res = append(res, it)
385+
}
386+
387+
// Rows error
388+
err = rows.Err()
389+
// Check error
390+
if err != nil {
391+
return nil, err
392+
}
393+
394+
return res, nil
395+
}
396+
283397
func (c *pg) CreateExtension(ctx context.Context, db, extension string) error {
284398
err := c.connect(db)
285399
if err != nil {

internal/controller/postgresql/postgres/postgres.go

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,44 +28,47 @@ type TypeOwnership struct {
2828

2929
type PG interface { //nolint:interfacebloat // This is needed
3030
CreateDB(ctx context.Context, dbname, username string) error
31-
ChangeDBOwner(ctx context.Context, dbname, owner string) error
32-
IsDatabaseExist(ctx context.Context, dbname string) (bool, error)
33-
RenameDatabase(ctx context.Context, oldname, newname string) error
34-
CreateSchema(ctx context.Context, db, role, schema string) error
35-
CreateExtension(ctx context.Context, db, extension string) error
36-
CreateGroupRole(ctx context.Context, role string) error
37-
CreateUserRole(ctx context.Context, role, password string, attributes *RoleAttributes) (string, error)
38-
AlterRoleAttributes(ctx context.Context, role string, attributes *RoleAttributes) error
31+
GetDatabaseOwner(ctx context.Context, dbname string) (string, error)
32+
// ChangeDBOwner(ctx context.Context, dbname, owner string) error
33+
// IsDatabaseExist(ctx context.Context, dbname string) (bool, error)
34+
// RenameDatabase(ctx context.Context, oldname, newname string) error
35+
// CreateSchema(ctx context.Context, db, role, schema string) error
36+
// CreateExtension(ctx context.Context, db, extension string) error
37+
// CreateGroupRole(ctx context.Context, role string) error
38+
// CreateUserRole(ctx context.Context, role, password string, attributes *RoleAttributes) (string, error)
39+
// AlterRoleAttributes(ctx context.Context, role string, attributes *RoleAttributes) error
3940
GetRoleAttributes(ctx context.Context, role string) (*RoleAttributes, error)
4041
IsRoleExist(ctx context.Context, role string) (bool, error)
41-
RenameRole(ctx context.Context, oldname, newname string) error
42-
UpdatePassword(ctx context.Context, role, password string) error
43-
GrantRole(ctx context.Context, role, grantee string, withAdminOption bool) error
44-
SetSchemaPrivileges(ctx context.Context, db, creator, role, schema, privs string) error
45-
RevokeRole(ctx context.Context, role, userRole string) error
46-
AlterDefaultLoginRole(ctx context.Context, role, setRole string) error
47-
AlterDefaultLoginRoleOnDatabase(ctx context.Context, role, setRole, database string) error
48-
RevokeUserSetRoleOnDatabase(ctx context.Context, role, database string) error
42+
// RenameRole(ctx context.Context, oldname, newname string) error
43+
// UpdatePassword(ctx context.Context, role, password string) error
44+
// GrantRole(ctx context.Context, role, grantee string, withAdminOption bool) error
45+
// SetSchemaPrivileges(ctx context.Context, db, creator, role, schema, privs string) error
46+
// RevokeRole(ctx context.Context, role, userRole string) error
47+
// AlterDefaultLoginRole(ctx context.Context, role, setRole string) error
48+
// AlterDefaultLoginRoleOnDatabase(ctx context.Context, role, setRole, database string) error
49+
// RevokeUserSetRoleOnDatabase(ctx context.Context, role, database string) error
4950
DoesRoleHaveActiveSession(ctx context.Context, role string) (bool, error)
50-
DropDatabase(ctx context.Context, db string) error
51-
DropRoleAndDropAndChangeOwnedBy(ctx context.Context, role, newOwner, database string) error
52-
ChangeAndDropOwnedBy(ctx context.Context, role, newOwner, database string) error
51+
// DropDatabase(ctx context.Context, db string) error
52+
// DropRoleAndDropAndChangeOwnedBy(ctx context.Context, role, newOwner, database string) error
53+
// ChangeAndDropOwnedBy(ctx context.Context, role, newOwner, database string) error
5354
GetSetRoleOnDatabasesRoleSettings(ctx context.Context, role string) ([]*SetRoleOnDatabaseRoleSetting, error)
54-
DropRole(ctx context.Context, role string) error
55-
DropSchema(ctx context.Context, database, schema string, cascade bool) error
56-
DropExtension(ctx context.Context, database, extension string, cascade bool) error
55+
// DropRole(ctx context.Context, role string) error
56+
// DropSchema(ctx context.Context, database, schema string, cascade bool) error
57+
ListSchema(ctx context.Context, database string) ([]string, error)
58+
ListExtensions(ctx context.Context, database string) ([]string, error)
59+
// DropExtension(ctx context.Context, database, extension string, cascade bool) error
5760
GetRoleMembership(ctx context.Context, role string) ([]string, error)
5861
GetTablesInSchema(ctx context.Context, db, schema string) ([]*TableOwnership, error)
59-
ChangeTableOwner(ctx context.Context, db, table, owner string) error
62+
// ChangeTableOwner(ctx context.Context, db, table, owner string) error
6063
GetTypesInSchema(ctx context.Context, db, schema string) ([]*TypeOwnership, error)
61-
ChangeTypeOwnerInSchema(ctx context.Context, db, schema, typeName, owner string) error
62-
DropPublication(ctx context.Context, dbname, name string) error
63-
RenamePublication(ctx context.Context, dbname, oldname, newname string) error
64+
// ChangeTypeOwnerInSchema(ctx context.Context, db, schema, typeName, owner string) error
65+
// DropPublication(ctx context.Context, dbname, name string) error
66+
// RenamePublication(ctx context.Context, dbname, oldname, newname string) error
6467
GetPublication(ctx context.Context, dbname, name string) (*PublicationResult, error)
65-
CreatePublication(ctx context.Context, dbname string, builder *CreatePublicationBuilder) error
66-
UpdatePublication(ctx context.Context, dbname, publicationName string, builder *UpdatePublicationBuilder) error
67-
DropReplicationSlot(ctx context.Context, name string) error
68-
CreateReplicationSlot(ctx context.Context, dbname, name, plugin string) error
68+
// CreatePublication(ctx context.Context, dbname string, builder *CreatePublicationBuilder) error
69+
// UpdatePublication(ctx context.Context, dbname, publicationName string, builder *UpdatePublicationBuilder) error
70+
// DropReplicationSlot(ctx context.Context, name string) error
71+
// CreateReplicationSlot(ctx context.Context, dbname, name, plugin string) error
6972
GetReplicationSlot(ctx context.Context, name string) (*ReplicationSlotResult, error)
7073
GetUser() string
7174
GetHost() string

internal/controller/postgresql/postgresqldatabase_controller.go

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,19 @@ func (*PostgresqlDatabaseReconciler) manageDBCreationOrUpdate(
315315
return err
316316
}
317317
} else {
318-
// Ensure owner is correct
319-
err := pg.ChangeDBOwner(ctx, instance.Spec.Database, owner)
318+
// Get database owner
319+
currentOwner, err := pg.GetDatabaseOwner(ctx, instance.Spec.Database)
320320
if err != nil {
321321
return err
322322
}
323+
// Check if owner needs to be changed
324+
if owner != currentOwner {
325+
// Ensure owner is correct
326+
err = pg.ChangeDBOwner(ctx, instance.Spec.Database, owner)
327+
if err != nil {
328+
return err
329+
}
330+
}
323331
}
324332

325333
// Update status
@@ -583,11 +591,21 @@ func (*PostgresqlDatabaseReconciler) manageSchemas(ctx context.Context, pg postg
583591
writer = instance.Status.Roles.Writer
584592
)
585593

594+
// List all schema in database
595+
currentSchemaList, err := pg.ListSchema(ctx, instance.Spec.Database)
596+
// Check error
597+
if err != nil {
598+
return err
599+
}
600+
586601
for _, schema := range instance.Spec.Schemas.List {
587-
// Create schema
588-
err := pg.CreateSchema(ctx, instance.Spec.Database, owner, schema)
589-
if err != nil {
590-
return err
602+
// Check if schema is already created in database
603+
if !funk.ContainsString(currentSchemaList, schema) {
604+
// Create schema
605+
err = pg.CreateSchema(ctx, instance.Spec.Database, owner, schema)
606+
if err != nil {
607+
return err
608+
}
591609
}
592610

593611
// Set privileges on schema
@@ -670,13 +688,23 @@ func (*PostgresqlDatabaseReconciler) manageExtensions(ctx context.Context, pg po
670688
instance.Status.Extensions = newStatusExtensions
671689
}
672690

691+
// List extensions
692+
currentExtensionList, err := pg.ListExtensions(ctx, instance.Spec.Database)
693+
if err != nil {
694+
return err
695+
}
696+
673697
// Manage extensions creation
674698
for _, extension := range instance.Spec.Extensions.List {
675-
// Execute create extension SQL statement
676-
err := pg.CreateExtension(ctx, instance.Spec.Database, extension)
677-
if err != nil {
678-
return err
699+
// Check if extension isn't already in database
700+
if !funk.ContainsString(currentExtensionList, extension) {
701+
// Execute create extension SQL statement
702+
err := pg.CreateExtension(ctx, instance.Spec.Database, extension)
703+
if err != nil {
704+
return err
705+
}
679706
}
707+
680708
// Check if extension was added. Skip if already added
681709
if !funk.ContainsString(instance.Status.Extensions, extension) {
682710
instance.Status.Extensions = append(instance.Status.Extensions, extension)

0 commit comments

Comments
 (0)