Skip to content

Commit 8d7ef54

Browse files
authored
create partman extension in partman schema and grant access (#233)
* create partman extension in partman schema and grant access * update golang version * pinned version of envtest to avoid kubernetes-sigs/controller-runtime#2720
1 parent 71be670 commit 8d7ef54

File tree

7 files changed

+94
-21
lines changed

7 files changed

+94
-21
lines changed

Makefile

+5-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,11 @@ kustomize: ## Download kustomize locally if necessary.
230230
ENVTEST = $(shell pwd)/bin/setup-envtest
231231
.PHONY: envtest
232232
envtest: ## Download envtest-setup locally if necessary.
233-
$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)
233+
#commenting out the latest setup-envttest to use elease-0.16- because of https://github.com/kubernetes-sigs/controller-runtime/issues/2720
234+
#$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)
235+
#TODO- reuse the above command after fix from controller-runtime or after we go to go 1.22
236+
$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/[email protected])
237+
234238

235239
# go-get-tool will 'go get' any package $2 and install it to $1.
236240
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))

controllers/databaseclaim_controller.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -1587,10 +1587,17 @@ func (r *DatabaseClaimReconciler) manageUser(dbClient dbclient.Client, status *p
15871587
rotationTime := r.getPasswordRotationTime()
15881588

15891589
// create role
1590-
_, err := dbClient.CreateGroup(dbName, baseUsername)
1590+
roleCreated, err := dbClient.CreateGroup(dbName, baseUsername)
15911591
if err != nil {
15921592
return err
15931593
}
1594+
if roleCreated {
1595+
// take care of special extentions related to the user
1596+
err = dbClient.CreateSpecialExtentions(dbName, baseUsername)
1597+
if err != nil {
1598+
return err
1599+
}
1600+
}
15941601

15951602
if dbu.IsUserChanged(*status) {
15961603
oldUsername := dbu.TrimUserSuffix(status.ConnectionInfo.Username)

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ require (
125125
golang.org/x/oauth2 v0.8.0 // indirect
126126
golang.org/x/sys v0.14.0 // indirect
127127
golang.org/x/term v0.13.0 // indirect
128-
golang.org/x/text v0.13.0 // indirect
128+
golang.org/x/text v0.13.0
129129
golang.org/x/time v0.3.0 // indirect
130130
golang.org/x/tools v0.14.0 // indirect
131131
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect

helm/db-controller/values.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ controllerConfig:
128128
authSource: secret
129129
# if aws authorization is used iam role must be provided
130130
#iamRole: rds-role
131-
caCertificateIdentifier: "rds-ca-2019"
131+
caCertificateIdentifier: "rds-ca-rsa2048-g1"
132132
dbMultiAZEnabled: false
133133
dbSubnetGroupNameRef:
134134
defaultBackupPolicyValue: Bronze

pkg/dbclient/client.go

+72-10
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ const (
2121
RDSSuperUserRole = "rds_superuser"
2222
)
2323

24-
var extensions = []string{"citext", "uuid-ossp",
24+
var defaultExtensions = []string{"citext", "uuid-ossp",
2525
"pgcrypto", "hstore", "pg_stat_statements",
26-
"plpgsql", "pg_partman", "hll", "pg_cron"}
26+
"plpgsql", "hll"}
27+
28+
var specialExtensionsMap = map[string]func(*client, string, string) error{
29+
"pg_partman": (*client).pg_partman,
30+
"pg_cron": (*client).pg_cron,
31+
}
2732

2833
type client struct {
2934
dbType string
@@ -110,8 +115,9 @@ func (pc *client) CreateDataBase(name string) (bool, error) {
110115
return pc.CreateDatabase(name)
111116
}
112117

118+
// unit test override
113119
var getDefaulExtensions = func() []string {
114-
return extensions
120+
return defaultExtensions
115121
}
116122

117123
func (pc *client) CreateDatabase(dbName string) (bool, error) {
@@ -157,21 +163,77 @@ func (pc *client) CreateDefaultExtentions(dbName string) error {
157163
}
158164
pc.log.Info("created extension " + s)
159165
}
160-
var exists bool
161-
err = db.QueryRow("SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = $1)", "pg_cron").Scan(&exists)
166+
167+
return nil
168+
}
169+
170+
func (pc *client) CreateSpecialExtentions(dbName string, role string) error {
171+
db, err := pc.getDB(dbName)
162172
if err != nil {
173+
pc.log.Error(err, "could not connect to db", "database", dbName)
163174
return err
164175
}
165-
if exists {
166-
// pg_cron extension is enabled - grant permission
167-
_, err = db.Exec("GRANT USAGE ON SCHEMA cron TO public")
168-
if err != nil {
169-
pc.log.Error(err, "could not GRANT USAGE ON SCHEMA cron TO public")
176+
pc.log.Info("connected to " + dbName)
177+
defer db.Close()
178+
for functionName := range specialExtensionsMap {
179+
if err := specialExtensionsMap[functionName](pc, dbName, role); err != nil {
180+
pc.log.Error(err, "error creating extention %s", functionName)
170181
return err
171182
}
172183
}
173184
return nil
174185
}
186+
func (pc *client) pg_cron(dbName string, role string) error {
187+
// create extension pg_cron and grant usage to public
188+
db, err := pc.getDB(dbName)
189+
if err != nil {
190+
pc.log.Error(err, "Failed to connect to database", "database", dbName)
191+
return err
192+
}
193+
defer db.Close()
194+
195+
pc.log.Info("Connected to database", "database", dbName)
196+
197+
_, err = db.Exec(fmt.Sprintf(`
198+
CREATE EXTENSION IF NOT EXISTS pg_cron;
199+
GRANT USAGE ON SCHEMA cron TO %s;
200+
`, pq.QuoteIdentifier(role)))
201+
if err != nil {
202+
pc.log.Error(err, "Failed to create extension pg_cron and grant usage on schema cron to public", "database", dbName)
203+
return fmt.Errorf("failed to create extension pg_cron and grant usage on schema cron to public: %w", err)
204+
}
205+
206+
pc.log.Info("Created pg_cron extension and granted usage on schema cron", "role", role)
207+
208+
return nil
209+
}
210+
func (pc *client) pg_partman(dbName string, role string) error {
211+
212+
db, err := pc.getDB(dbName)
213+
if err != nil {
214+
pc.log.Error(err, "could not connect to db", "database", dbName)
215+
return err
216+
}
217+
defer db.Close()
218+
createPartman := fmt.Sprintf(`
219+
CREATE SCHEMA IF NOT EXISTS partman;
220+
CREATE EXTENSION IF NOT EXISTS pg_partman WITH SCHEMA partman;
221+
GRANT ALL ON SCHEMA partman TO %s;
222+
GRANT ALL ON ALL TABLES IN SCHEMA partman TO %s;
223+
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA partman TO %s;
224+
GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA partman TO %s;
225+
`, pq.QuoteIdentifier(role), pq.QuoteIdentifier(role),
226+
pq.QuoteIdentifier(role), pq.QuoteIdentifier(role))
227+
228+
_, err = db.Exec(createPartman)
229+
if err != nil {
230+
pc.log.Error(err, "could not create extension pg_partman")
231+
return err
232+
}
233+
pc.log.Info("Created pg_partmann extension and granted usage on schema partman", "role", role)
234+
235+
return nil
236+
}
175237

176238
func (pc *client) ManageSystemFunctions(dbName string, functions map[string]string) error {
177239
db, err := pc.getDB(dbName)

pkg/dbclient/interface.go

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ type Client interface {
77
CreateUser(username, role, userPassword string) (bool, error)
88
CreateGroup(dbName, username string) (bool, error)
99
CreateDefaultExtentions(dbName string) error
10+
CreateSpecialExtentions(dbName string, role string) error
1011
RenameUser(oldUsername string, newUsername string) error
1112
UpdateUser(oldUsername, newUsername, rolename, password string) error
1213
UpdatePassword(username string, userPassword string) error

pkg/pgctl/pgdump.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,12 @@ func (x *Dump) modifyPgDumpInfo() error {
133133
return fmt.Errorf("error running sed command to comment create policy: %w", err)
134134
}
135135

136-
// If pg_cron is installed, grant usage on schema cron to public
137-
grantCmd := exec.Command("sed", "-i", "/^CREATE EXTENSION IF NOT EXISTS pg_cron/a GRANT USAGE ON SCHEMA cron TO public;", filePath)
138-
grantCmd.Stderr = os.Stderr
139-
grantCmd.Stdout = os.Stdout
140-
141-
if err := grantCmd.Run(); err != nil {
142-
return fmt.Errorf("error running sed command to grant usage on schema cron: %w", err)
136+
// add if not exists to partman schema creation
137+
replaceCmd := exec.Command("sed", "-i", "s/CREATE SCHEMA partman;/CREATE SCHEMA IF NOT EXISTS partman;/", filePath)
138+
replaceCmd.Stderr = os.Stderr
139+
replaceCmd.Stdout = os.Stdout
140+
if err := replaceCmd.Run(); err != nil {
141+
return fmt.Errorf("error running sed command add if not exists to partman schema creation: %w", err)
143142
}
144143

145144
return nil

0 commit comments

Comments
 (0)