Skip to content

Commit 76a99d7

Browse files
committed
feat: AWS RDS pg_repack additional support
1 parent 615a675 commit 76a99d7

3 files changed

Lines changed: 73 additions & 4 deletions

File tree

internal/controller/postgres_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
181181
if err != nil {
182182
return requeue(errors.NewInternalError(err))
183183
}
184-
// Alter database owner if the owner role was changed
185-
err = r.pg.AlterDatabaseOwner(instance.Spec.Database, instance.Status.Roles.Owner)
184+
// Alter database owner to desiredOwner if the owner role was changed
185+
err = r.pg.AlterDatabaseOwner(instance.Spec.Database, desiredOwner)
186186
if err != nil {
187187
return requeue(errors.NewInternalError(err))
188188
}

internal/controller/postgres_controller_test.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ var _ = Describe("PostgresReconciler", func() {
7171
// Gomock
7272
mockCtrl = gomock.NewController(GinkgoT())
7373
pg = mockpg.NewMockPG(mockCtrl)
74-
pg.EXPECT().AlterDatabaseOwner(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
75-
pg.EXPECT().ReassignDatabaseOwner(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
7674
cl = k8sClient
7775
// Create runtime scheme
7876
sc = scheme.Scheme
@@ -365,6 +363,32 @@ var _ = Describe("PostgresReconciler", func() {
365363
})
366364
})
367365

366+
Context("MasterRole is changed for existing database", func() {
367+
BeforeEach(func() {
368+
modPostgres := postgresCR.DeepCopy()
369+
modPostgres.Spec.MasterRole = "new-master-role"
370+
modPostgres.Status = v1alpha1.PostgresStatus{
371+
Succeeded: true,
372+
Roles: v1alpha1.PostgresRoles{
373+
Owner: "old-master-role",
374+
},
375+
}
376+
initClient(modPostgres, false)
377+
})
378+
379+
It("should alter database owner to the desired role", func() {
380+
pg.EXPECT().RenameGroupRole("old-master-role", "new-master-role").Return(nil).Times(1)
381+
pg.EXPECT().AlterDatabaseOwner(name, "new-master-role").Return(nil).Times(1)
382+
383+
err := runReconcile(rp, ctx, req)
384+
Expect(err).NotTo(HaveOccurred())
385+
386+
foundPostgres := &v1alpha1.Postgres{}
387+
Expect(cl.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, foundPostgres)).To(BeNil())
388+
Expect(foundPostgres.Status.Roles.Owner).To(Equal("new-master-role"))
389+
})
390+
})
391+
368392
Context("Correct annotation filter is set", func() {
369393
BeforeEach(func() {
370394
// Create client

pkg/postgres/aws.go

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

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/lib/pq"
78
)
@@ -10,6 +11,11 @@ type awspg struct {
1011
pg
1112
}
1213

14+
const (
15+
AWS_ALTER_REPACK_DEFAULT_PRIVS_TABLES = `ALTER DEFAULT PRIVILEGES FOR ROLE "%s" IN SCHEMA "repack" GRANT INSERT ON TABLES TO PUBLIC`
16+
AWS_ALTER_REPACK_DEFAULT_PRIVS_SEQUENCES = `ALTER DEFAULT PRIVILEGES FOR ROLE "%s" IN SCHEMA "repack" GRANT USAGE, SELECT ON SEQUENCES TO PUBLIC`
17+
)
18+
1319
func newAWSPG(postgres *pg) PG {
1420
return &awspg{
1521
*postgres,
@@ -38,6 +44,45 @@ func (c *awspg) CreateDB(dbname, role string) error {
3844
return c.pg.CreateDB(dbname, role)
3945
}
4046

47+
func (c *awspg) CreateExtension(dbname, extension string) error {
48+
// Keep standard extension creation behavior for AWS as well.
49+
err := c.pg.CreateExtension(dbname, extension)
50+
if err != nil {
51+
return err
52+
}
53+
54+
// AWS-specific workaround is only required for pg_repack.
55+
if !strings.EqualFold(extension, "pg_repack") {
56+
return nil
57+
}
58+
59+
var owner string
60+
// Resolve current database owner role to target ALTER DEFAULT PRIVILEGES FOR ROLE.
61+
err = c.db.QueryRow(fmt.Sprintf(GET_DB_OWNER, dbname)).Scan(&owner)
62+
if err != nil {
63+
return err
64+
}
65+
66+
// Execute pg_repack privilege statements in the target database.
67+
tmpDb, err := GetConnection(c.user, c.pass, c.host, dbname, c.args)
68+
if err != nil {
69+
return err
70+
}
71+
defer tmpDb.Close()
72+
73+
_, err = tmpDb.Exec(fmt.Sprintf(AWS_ALTER_REPACK_DEFAULT_PRIVS_TABLES, owner))
74+
if err != nil {
75+
return err
76+
}
77+
78+
_, err = tmpDb.Exec(fmt.Sprintf(AWS_ALTER_REPACK_DEFAULT_PRIVS_SEQUENCES, owner))
79+
if err != nil {
80+
return err
81+
}
82+
83+
return nil
84+
}
85+
4186
func (c *awspg) CreateUserRole(role, password string) (string, error) {
4287
returnedRole, err := c.pg.CreateUserRole(role, password)
4388
if err != nil {

0 commit comments

Comments
 (0)