Skip to content

Commit 2297402

Browse files
GCP wrapper (#83)
* GCP wrapper Add a GCP wrapper to work on Google SQL instances * PR fixes mod doc to readme and query to const
1 parent 57dc133 commit 2297402

File tree

5 files changed

+109
-0
lines changed

5 files changed

+109
-0
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ unit-test:
1111
go tool cover -func coverage.out
1212
unit-test-coverage: unit-test
1313
go tool cover -html coverage.out
14+
linux-build:
15+
@GOBIN=/work/bin GO111MODULE=on GOOS=linux GOARC=x86_64 go build --mod=vendor -o operator github.com/movetokube/postgres-operator/cmd/manager
16+
docker-build:
17+
docker run -ti -v $(PWD):/work -w /work golang:1.13.15-stretch make linux-build

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ In order for this operator to work correctly with Azure managed PostgreSQL datab
2323
* `POSTGRES_CLOUD_PROVIDER` set to `Azure`
2424
* `POSTGRES_DEFAULT_DATABASE` set to your default database, i.e. `postgres`
2525

26+
### GCP
27+
28+
In order for this operator to work correctly with GCP, you need to set `POSTGRES_CLOUD_PROVIDER` to `GCP`
29+
30+
To have operator work with GCP properly you have to:
31+
* use postgresql connection in secret
32+
* manually create a Master role e.g. "devops-operators"
33+
* use such role in database CR e.g. spec.masterRole: devops-operator
34+
35+
DropRole method will check for db owner and will skip master role dropping
36+
2637
## Installation
2738

2839
This operator requires a Kubernetes Secret to be created in the same namespace as operator itself.

pkg/postgres/database.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const (
1616
GRANT_USAGE_SCHEMA = `GRANT USAGE ON SCHEMA "%s" TO "%s"`
1717
GRANT_ALL_TABLES = `GRANT %s ON ALL TABLES IN SCHEMA "%s" TO "%s"`
1818
DEFAULT_PRIVS_SCHEMA = `ALTER DEFAULT PRIVILEGES FOR ROLE "%s" IN SCHEMA "%s" GRANT %s ON TABLES TO "%s"`
19+
REVOKE_CONNECT = `REVOKE CONNECT ON DATABASE "%s" FROM public`
20+
TERMINATE_BACKEND = `SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = "%s" AND pid <> pg_backend_pid()`
21+
GET_DB_OWNER = `SELECT pg_catalog.pg_get_userbyid(d.datdba) FROM pg_catalog.pg_database d WHERE d.datname = "%s"`
1922
GRANT_CREATE_SCHEMA = `GRANT CREATE ON DATABASE "%s" TO "%s"`
2023
)
2124

pkg/postgres/gcp.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package postgres
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/go-logr/logr"
7+
"github.com/lib/pq"
8+
)
9+
10+
type gcppg struct {
11+
pg
12+
}
13+
14+
func newGCPPG(postgres *pg) PG {
15+
return &gcppg{
16+
*postgres,
17+
}
18+
}
19+
20+
func (c *gcppg) DropDatabase(database string, logger logr.Logger) error {
21+
22+
_, err := c.db.Exec(fmt.Sprintf(REVOKE_CONNECT, database))
23+
// Error code 3D000 is returned if database doesn't exist
24+
if err != nil && err.(*pq.Error).Code != "3D000" {
25+
return err
26+
}
27+
28+
_, err = c.db.Exec(fmt.Sprintf(TERMINATE_BACKEND, database))
29+
// Error code 3D000 is returned if database doesn't exist
30+
if err != nil && err.(*pq.Error).Code != "3D000" {
31+
return err
32+
}
33+
_, err = c.db.Exec(fmt.Sprintf(DROP_DATABASE, database))
34+
// Error code 3D000 is returned if database doesn't exist
35+
if err != nil && err.(*pq.Error).Code != "3D000" {
36+
return err
37+
}
38+
39+
logger.Info(fmt.Sprintf("Dropped database %s", database))
40+
41+
return nil
42+
}
43+
44+
func (c *gcppg) CreateDB(dbname, role string) error {
45+
46+
err := c.GrantRole(role, c.user)
47+
if err != nil {
48+
return err
49+
}
50+
err = c.pg.CreateDB(dbname, role)
51+
if err != nil {
52+
return err
53+
}
54+
return nil
55+
}
56+
57+
func (c *gcppg) DropRole(role, newOwner, database string, logger logr.Logger) error {
58+
59+
tmpDb, err := GetConnection(c.user, c.pass, c.host, database, c.args, logger)
60+
q := fmt.Sprintf(GET_DB_OWNER, database)
61+
logger.Info("Checking master role: "+ q)
62+
rows, err := tmpDb.Query(q)
63+
if err != nil {
64+
return err
65+
}
66+
var masterRole string
67+
for rows.Next() {
68+
rows.Scan(&masterRole)
69+
}
70+
71+
if( role != masterRole){
72+
q = fmt.Sprintf(DROP_ROLE, role)
73+
logger.Info("GCP Drop Role: "+ q)
74+
_, err = tmpDb.Exec(q)
75+
// Check if error exists and if different from "ROLE NOT FOUND" => 42704
76+
if err != nil && err.(*pq.Error).Code != "42704" {
77+
return err
78+
}
79+
80+
defer tmpDb.Close()
81+
} else {
82+
logger.Info(fmt.Sprintf("GCP refusing DropRole on master role " + masterRole))
83+
}
84+
return nil
85+
}

pkg/postgres/postgres.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,16 @@ func NewPG(host, user, password, uri_args, default_database, cloud_type string,
5353

5454
switch cloud_type {
5555
case "AWS":
56+
logger.Info("Using AWS wrapper")
5657
return newAWSPG(postgres), nil
5758
case "Azure":
59+
logger.Info("Using Azure wrapper")
5860
return newAzurePG(postgres), nil
61+
case "GCP":
62+
logger.Info("Using GCP wrapper")
63+
return newGCPPG(postgres), nil
5964
default:
65+
logger.Info("Using default postgres implementation")
6066
return postgres, nil
6167
}
6268
}

0 commit comments

Comments
 (0)