diff --git a/pkg/config/config.go b/pkg/config/config.go index 5b63497c..0c5cee71 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -32,6 +32,7 @@ const ( CloudProviderAWS CloudProvider = "AWS" CloudProviderAzure CloudProvider = "Azure" CloudProviderGCP CloudProvider = "GCP" + CloudProviderOCI CloudProvider = "OCI" ) func Get() *Cfg { @@ -61,6 +62,8 @@ func ParseCloudProvider(s string) CloudProvider { return CloudProviderAzure case "gcp": return CloudProviderGCP + case "oci": + return CloudProviderOCI default: return CloudProviderNone } diff --git a/pkg/postgres/oci.go b/pkg/postgres/oci.go new file mode 100644 index 00000000..9c192177 --- /dev/null +++ b/pkg/postgres/oci.go @@ -0,0 +1,50 @@ +package postgres + +import ( + "fmt" + + "github.com/lib/pq" +) + +type ocipg struct { + pg +} + +func newOCIPG(postgres *pg) PG { + return &ocipg{ + *postgres, + } +} + +func (c *ocipg) CreateDB(dbname, role string) error { + // OCI managed Postgres admin user is not a true superuser; must belong to + // the role before ALTER DATABASE ... OWNER TO succeeds + err := c.GrantRole(role, c.user) + if err != nil { + return err + } + + return c.pg.CreateDB(dbname, role) +} + +func (c *ocipg) DropRole(role, newOwner, database string) error { + // Must belong to both roles for REASSIGN OWNED BY to succeed + err := c.GrantRole(role, c.user) + if err != nil && err.(*pq.Error).Code != "0LP01" { + if err.(*pq.Error).Code == "42704" { + return nil + } + return err + } + err = c.GrantRole(newOwner, c.user) + if err != nil && err.(*pq.Error).Code != "0LP01" { + if err.(*pq.Error).Code == "42704" { + c.log.Info(fmt.Sprintf("not granting %s to %s as %s does not exist", role, newOwner, newOwner)) + return nil + } + return err + } + defer c.RevokeRole(newOwner, c.user) + + return c.pg.DropRole(role, newOwner, database) +} diff --git a/pkg/postgres/postgres.go b/pkg/postgres/postgres.go index dd5886a5..1f24f1b6 100644 --- a/pkg/postgres/postgres.go +++ b/pkg/postgres/postgres.go @@ -79,6 +79,9 @@ func NewPG(cfg *config.Cfg, logger logr.Logger) (PG, error) { case config.CloudProviderGCP: logger.Info("Using GCP wrapper") return newGCPPG(postgres), nil + case config.CloudProviderOCI: + logger.Info("Using OCI wrapper") + return newOCIPG(postgres), nil default: logger.Info("Using default postgres implementation") return postgres, nil