Skip to content

Commit 91c7fb4

Browse files
committed
feat: support schemas
1 parent ffdd11f commit 91c7fb4

10 files changed

+128
-12
lines changed

api/v1beta1/database_types.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
DatabaseReadyConditionType = "DatabaseReady"
1616
UserReadyConditionType = "UserReady"
1717
ExtensionReadyConditionType = "ExtensionReady"
18+
SchemaReadyConditionType = "SchemaReady"
1819
)
1920

2021
// Status reasons
@@ -28,8 +29,11 @@ const (
2829
UserProvisioningSuccessfulReason = "UserProvisioningSuccessful"
2930
CredentialsNotFoundReason = "CredentialsNotFound"
3031
CreateDatabaseFailedReason = "CreateDatabaseFailed"
31-
CreateExtensionFailedReason = "CreateExtensionFailed"
32+
CreateExtensionsFailedReason = "CreateExtensionsFailed"
33+
CreateSchemasFailedReason = "CreateSchemasFailed"
3234
ProgressingReason = "ProgressingReason"
35+
CreateExtensionsSuccessfulReason = "CreateExtensionsSuccessful"
36+
CreateSchemasSuccessfulReason = "CreateSchemasSuccessful"
3337
)
3438

3539
// DatabaseSpec defines the desired state of a *Database

api/v1beta1/postgresqldatabase_types.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,26 @@ type Extension struct {
2828
// Extensions is a collection of Extension types
2929
type Extensions []Extension
3030

31+
// Schema is a resource representing database schema
32+
type Schema struct {
33+
Name string `json:"name"`
34+
}
35+
36+
// Schemas is a collection of Schema types
37+
type Schemas []Schema
38+
3139
// PostgreSQLDatabaseSpec defines the desired state of PostgreSQLDatabase
3240
type PostgreSQLDatabaseSpec struct {
3341
*DatabaseSpec `json:",inline"`
3442

3543
// Database extensions
3644
// +optional
3745
Extensions Extensions `json:"extensions,omitempty"`
46+
47+
// Database schemas
48+
// +kubebuilder:default:={{name: public}}
49+
// +optional
50+
Schemas Schemas `json:"schemas,omitempty"`
3851
}
3952

4053
// GetStatusConditions returns a pointer to the Status.Conditions slice
@@ -104,6 +117,18 @@ func ExtensionNotReadyCondition(in conditionalResource, reason, message string)
104117
setResourceCondition(in, ExtensionReadyConditionType, metav1.ConditionFalse, reason, message)
105118
}
106119

120+
func SchemaNotReadyCondition(in conditionalResource, reason, message string) {
121+
setResourceCondition(in, SchemaReadyConditionType, metav1.ConditionFalse, reason, message)
122+
}
123+
124+
func ExtensionReadyCondition(in conditionalResource, reason, message string) {
125+
setResourceCondition(in, ExtensionReadyConditionType, metav1.ConditionTrue, reason, message)
126+
}
127+
128+
func SchemaReadyCondition(in conditionalResource, reason, message string) {
129+
setResourceCondition(in, SchemaReadyConditionType, metav1.ConditionTrue, reason, message)
130+
}
131+
107132
func (d *PostgreSQLDatabase) SetDefaults() error {
108133
if d.Spec.DatabaseName == "" {
109134
d.Spec.DatabaseName = d.GetName()

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chart/k8sdb-controller/crds/dbprovisioning.infra.doodle.com_postgresqldatabases.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ spec:
8383
required:
8484
- name
8585
type: object
86+
schemas:
87+
default:
88+
- name: public
89+
description: Database schemas
90+
items:
91+
description: Schema is a resource representing database schema
92+
properties:
93+
name:
94+
type: string
95+
required:
96+
- name
97+
type: object
98+
type: array
8699
required:
87100
- rootSecret
88101
type: object

common/database/postgresql.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ func (s *PostgreSQLRepository) DropUser(ctx context.Context, user PostgresqlUser
143143
return nil
144144
}
145145

146+
func (s *PostgreSQLRepository) CreateSchema(ctx context.Context, db, name string) error {
147+
_, err := s.conn.Exec(ctx, fmt.Sprintf("CREATE SCHEMA IF NOT EXISTS %s;", (pgx.Identifier{name}).Sanitize()))
148+
return err
149+
}
150+
146151
func (s *PostgreSQLRepository) EnableExtension(ctx context.Context, db, name string) error {
147152
if extensionExists, err := s.doesExtensionExist(ctx, db, name); err != nil {
148153
return err

config/base/crd/bases/dbprovisioning.infra.doodle.com_postgresqldatabases.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ spec:
8383
required:
8484
- name
8585
type: object
86+
schemas:
87+
default:
88+
- name: public
89+
description: Database schemas
90+
items:
91+
description: Schema is a resource representing database schema
92+
properties:
93+
name:
94+
type: string
95+
required:
96+
- name
97+
type: object
98+
type: array
8699
required:
87100
- rootSecret
88101
type: object

controllers/mongodbuser_controller.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func (r *MongoDBUserReconciler) reconcile(ctx context.Context, user infrav1beta1
192192

193193
err := r.Client.Get(ctx, databaseName, &db)
194194
if err != nil {
195-
err = fmt.Errorf("Referencing database was not found: %w", err)
195+
err = fmt.Errorf("referencing database was not found: %w", err)
196196
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.DatabaseNotFoundReason, err.Error())
197197
return user, err
198198
}
@@ -236,7 +236,7 @@ func (r *MongoDBUserReconciler) reconcileGenericUser(ctx context.Context, user i
236236

237237
err = dbHandler.SetupUser(ctx, db.GetDatabaseName(), usr, pw, extractMongoDBUserRoles(user.GetRoles()))
238238
if err != nil {
239-
err = fmt.Errorf("Failed to provision user account: %w", err)
239+
err = fmt.Errorf("failed to provision user account: %w", err)
240240
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.ConnectionFailedReason, err.Error())
241241
return user, err
242242
}
@@ -278,7 +278,7 @@ func (r *MongoDBUserReconciler) reconcileAtlasUser(ctx context.Context, user inf
278278

279279
err = dbHandler.SetupUser(ctx, db.GetDatabaseName(), usr, pw, extractMongoDBUserRoles(user.GetRoles()))
280280
if err != nil {
281-
err = fmt.Errorf("Failed to provison user account: %w", err)
281+
err = fmt.Errorf("failed to provison user account: %w", err)
282282
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.ConnectionFailedReason, err.Error())
283283
return user, err
284284
}
@@ -291,7 +291,7 @@ func (r *MongoDBUserReconciler) reconcileAtlasUser(ctx context.Context, user inf
291291
func (r *MongoDBUserReconciler) finalizeUser(ctx context.Context, user infrav1beta1.MongoDBUser, db infrav1beta1.MongoDBDatabase, userDropper userDropper) (infrav1beta1.MongoDBUser, error) {
292292
err := userDropper.DropUser(ctx, db.GetDatabaseName(), user.Status.Username)
293293
if err != nil {
294-
err = fmt.Errorf("Failed to remove user account: %w", err)
294+
err = fmt.Errorf("failed to remove user account: %w", err)
295295
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.ConnectionFailedReason, err.Error())
296296
return user, err
297297
}

controllers/postgresqldatabase_controller.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func (r *PostgreSQLDatabaseReconciler) reconcile(ctx context.Context, db infrav1
168168

169169
err = rootDBHandler.CreateDatabaseIfNotExists(ctx, db.GetDatabaseName())
170170
if err != nil {
171-
err = fmt.Errorf("Failed to provision database: %w", err)
171+
err = fmt.Errorf("failed to provision database: %w", err)
172172
infrav1beta1.DatabaseNotReadyCondition(&db, infrav1beta1.CreateDatabaseFailedReason, err.Error())
173173
return db, err
174174
}
@@ -184,12 +184,24 @@ func (r *PostgreSQLDatabaseReconciler) reconcile(ctx context.Context, db infrav1
184184

185185
for _, ext := range db.Spec.Extensions {
186186
if err := dbHandler.EnableExtension(ctx, db.GetDatabaseName(), ext.Name); err != nil {
187-
err = fmt.Errorf("Failed to create extension %s in database: %w", ext.Name, err)
188-
infrav1beta1.ExtensionNotReadyCondition(&db, infrav1beta1.CreateExtensionFailedReason, err.Error())
187+
err = fmt.Errorf("failed to create extension %s in database: %w", ext.Name, err)
188+
infrav1beta1.ExtensionNotReadyCondition(&db, infrav1beta1.CreateExtensionsFailedReason, err.Error())
189189
return db, err
190190
}
191191
}
192192

193+
infrav1beta1.ExtensionReadyCondition(&db, infrav1beta1.CreateExtensionsSuccessfulReason, "")
194+
195+
for _, schema := range db.Spec.Schemas {
196+
if err := dbHandler.CreateSchema(ctx, db.GetDatabaseName(), schema.Name); err != nil {
197+
err = fmt.Errorf("failed to create schemas %s in database: %w", schema.Name, err)
198+
infrav1beta1.SchemaNotReadyCondition(&db, infrav1beta1.CreateSchemasFailedReason, err.Error())
199+
return db, err
200+
}
201+
}
202+
203+
infrav1beta1.SchemaReadyCondition(&db, infrav1beta1.CreateSchemasSuccessfulReason, "")
204+
193205
return db, nil
194206
}
195207

controllers/postgresqluser_controller.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func (r *PostgreSQLUserReconciler) reconcile(ctx context.Context, user infrav1be
201201

202202
err := r.Client.Get(ctx, databaseName, &db)
203203
if err != nil {
204-
err = fmt.Errorf("Referencing database was not found: %w", err)
204+
err = fmt.Errorf("referencing database was not found: %w", err)
205205
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.DatabaseNotFoundReason, err.Error())
206206
return user, err
207207
}
@@ -260,7 +260,7 @@ func (r *PostgreSQLUserReconciler) reconcile(ctx context.Context, user infrav1be
260260

261261
err = dbHandler.SetupUser(ctx, userSpec)
262262
if err != nil {
263-
err = fmt.Errorf("Failed to provison user account: %w", err)
263+
err = fmt.Errorf("failed to provison user account: %w", err)
264264
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.ConnectionFailedReason, err.Error())
265265
return user, err
266266
}
@@ -295,15 +295,15 @@ func (r *PostgreSQLUserReconciler) finalizeUser(ctx context.Context, user infrav
295295
//Instead privileges are revoked and the password gets randomized
296296
err := dbHandler.SetupUser(ctx, userSpec)
297297
if err != nil {
298-
err = fmt.Errorf("Failed to update user account: %w", err)
298+
err = fmt.Errorf("failed to update user account: %w", err)
299299
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.ConnectionFailedReason, err.Error())
300300
return user, err
301301
}
302302

303303
err = dbHandler.RevokeAllPrivileges(ctx, userSpec)
304304

305305
if err != nil {
306-
err = fmt.Errorf("Failed to revoke privileges from user account: %w", err)
306+
err = fmt.Errorf("failed to revoke privileges from user account: %w", err)
307307
infrav1beta1.UserNotReadyCondition(&user, infrav1beta1.ConnectionFailedReason, err.Error())
308308
return user, err
309309
}

renovate.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
{
1818
"semanticCommitScope": "deps-dev",
1919
"matchManagers": ["github-actions"]
20+
},
21+
{
22+
"description": "Automerge non-major updates",
23+
"matchUpdateTypes": ["minor", "patch"],
24+
"automerge": true
2025
}
2126
],
2227
"postUpdateOptions": [

0 commit comments

Comments
 (0)