mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Clean up the DatabaseCreate call.
This commit is contained in:
parent
db5d7b0438
commit
e2448473cb
24
builtin/providers/postgresql/helpers.go
Normal file
24
builtin/providers/postgresql/helpers.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package postgresql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// pqQuoteLiteral returns a string literal safe for inclusion in a PostgreSQL
|
||||||
|
// query as a parameter. The resulting string still needs to be wrapped in
|
||||||
|
// single quotes in SQL (i.e. fmt.Sprintf(`'%s'`, pqQuoteLiteral("str"))). See
|
||||||
|
// quote_literal_internal() in postgresql/backend/utils/adt/quote.c:77.
|
||||||
|
func pqQuoteLiteral(in string) string {
|
||||||
|
in = strings.Replace(in, `\`, `\\`, -1)
|
||||||
|
in = strings.Replace(in, `'`, `''`, -1)
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateConnLimit(v interface{}, key string) (warnings []string, errors []error) {
|
||||||
|
value := v.(int)
|
||||||
|
if value < -1 {
|
||||||
|
errors = append(errors, fmt.Errorf("%d can not be less than -1", key))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package postgresql
|
package postgresql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -112,134 +113,70 @@ func resourcePostgreSQLDatabaseCreate(d *schema.ResourceData, meta interface{})
|
|||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
stringOpts := []struct {
|
dbName := d.Get(dbNameAttr).(string)
|
||||||
hclKey string
|
b := bytes.NewBufferString("CREATE DATABASE ")
|
||||||
sqlKey string
|
fmt.Fprint(b, pq.QuoteIdentifier(dbName))
|
||||||
}{
|
|
||||||
{dbOwnerAttr, "OWNER"},
|
|
||||||
{dbTemplateAttr, "TEMPLATE"},
|
|
||||||
{dbEncodingAttr, "ENCODING"},
|
|
||||||
{dbCollationAttr, "LC_COLLATE"},
|
|
||||||
{dbCTypeAttr, "LC_CTYPE"},
|
|
||||||
{dbTablespaceAttr, "TABLESPACE"},
|
|
||||||
}
|
|
||||||
intOpts := []struct {
|
|
||||||
hclKey string
|
|
||||||
sqlKey string
|
|
||||||
}{
|
|
||||||
{dbConnLimitAttr, "CONNECTION LIMIT"},
|
|
||||||
}
|
|
||||||
boolOpts := []struct {
|
|
||||||
hclKey string
|
|
||||||
sqlKey string
|
|
||||||
}{
|
|
||||||
{dbAllowConnsAttr, "ALLOW_CONNECTIONS"},
|
|
||||||
{dbIsTemplateAttr, "IS_TEMPLATE"},
|
|
||||||
}
|
|
||||||
|
|
||||||
createOpts := make([]string, 0, len(stringOpts)+len(intOpts)+len(boolOpts))
|
// Handle each option individually and stream results into the query
|
||||||
|
// buffer.
|
||||||
|
|
||||||
for _, opt := range stringOpts {
|
switch v, ok := d.GetOk(dbOwnerAttr); {
|
||||||
v, ok := d.GetOk(opt.hclKey)
|
case ok:
|
||||||
var val string
|
fmt.Fprint(b, " OWNER ", pq.QuoteIdentifier(v.(string)))
|
||||||
if !ok {
|
default:
|
||||||
switch {
|
|
||||||
case opt.hclKey == dbOwnerAttr && v.(string) == "":
|
|
||||||
// No owner specified in the config, default to using
|
// No owner specified in the config, default to using
|
||||||
// the connecting username.
|
// the connecting username.
|
||||||
val = c.username
|
fmt.Fprint(b, " OWNER ", pq.QuoteIdentifier(c.username))
|
||||||
case strings.ToUpper(v.(string)) == "DEFAULT" &&
|
|
||||||
(opt.hclKey == dbTemplateAttr ||
|
|
||||||
opt.hclKey == dbEncodingAttr ||
|
|
||||||
opt.hclKey == dbCollationAttr ||
|
|
||||||
opt.hclKey == dbCTypeAttr):
|
|
||||||
|
|
||||||
// Use the defaults from the template database
|
|
||||||
// as opposed to best practices.
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val = v.(string)
|
switch v, ok := d.GetOk(dbTemplateAttr); {
|
||||||
|
case ok:
|
||||||
switch {
|
fmt.Fprint(b, " TEMPLATE ", pq.QuoteIdentifier(v.(string)))
|
||||||
case opt.hclKey == dbOwnerAttr && (val == "" || strings.ToUpper(val) == "DEFAULT"):
|
case v.(string) == "", strings.ToUpper(v.(string)) != "DEFAULT":
|
||||||
// Owner was blank/DEFAULT, default to using the connecting username.
|
fmt.Fprint(b, " TEMPLATE template0")
|
||||||
val = c.username
|
|
||||||
d.Set(dbOwnerAttr, val)
|
|
||||||
case opt.hclKey == dbTablespaceAttr && (val == "" || strings.ToUpper(val) == "DEFAULT"):
|
|
||||||
val = "pg_default"
|
|
||||||
d.Set(dbTablespaceAttr, val)
|
|
||||||
case opt.hclKey == dbTemplateAttr:
|
|
||||||
switch {
|
|
||||||
case val == "":
|
|
||||||
val = "template0"
|
|
||||||
d.Set(dbTemplateAttr, val)
|
|
||||||
case strings.ToUpper(val) == "DEFAULT":
|
|
||||||
val = ""
|
|
||||||
default:
|
|
||||||
d.Set(dbTemplateAttr, val)
|
|
||||||
}
|
|
||||||
case opt.hclKey == dbEncodingAttr:
|
|
||||||
switch {
|
|
||||||
case val == "":
|
|
||||||
val = "UTF8"
|
|
||||||
d.Set(dbEncodingAttr, val)
|
|
||||||
case strings.ToUpper(val) == "DEFAULT":
|
|
||||||
val = ""
|
|
||||||
default:
|
|
||||||
d.Set(dbEncodingAttr, val)
|
|
||||||
}
|
|
||||||
case opt.hclKey == dbCollationAttr:
|
|
||||||
switch {
|
|
||||||
case val == "":
|
|
||||||
val = "C"
|
|
||||||
d.Set(dbCollationAttr, val)
|
|
||||||
case strings.ToUpper(val) == "DEFAULT":
|
|
||||||
val = ""
|
|
||||||
default:
|
|
||||||
d.Set(dbCollationAttr, val)
|
|
||||||
}
|
|
||||||
case opt.hclKey == dbCTypeAttr:
|
|
||||||
switch {
|
|
||||||
case val == "":
|
|
||||||
val = "C"
|
|
||||||
d.Set(dbCTypeAttr, val)
|
|
||||||
case strings.ToUpper(val) == "DEFAULT":
|
|
||||||
val = ""
|
|
||||||
default:
|
|
||||||
d.Set(dbCTypeAttr, val)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if val != "" {
|
switch v, ok := d.GetOk(dbEncodingAttr); {
|
||||||
createOpts = append(createOpts, fmt.Sprintf("%s=%s", opt.sqlKey, pq.QuoteIdentifier(val)))
|
case ok:
|
||||||
}
|
fmt.Fprint(b, " ENCODING ", pq.QuoteIdentifier(v.(string)))
|
||||||
|
case v.(string) == "", strings.ToUpper(v.(string)) != "DEFAULT":
|
||||||
|
fmt.Fprint(b, ` ENCODING "UTF8"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, opt := range intOpts {
|
switch v, ok := d.GetOk(dbCollationAttr); {
|
||||||
val := d.Get(opt.hclKey).(int)
|
case ok:
|
||||||
createOpts = append(createOpts, fmt.Sprintf("%s=%d", opt.sqlKey, val))
|
fmt.Fprint(b, " LC_COLLATE ", pq.QuoteIdentifier(v.(string)))
|
||||||
|
case v.(string) == "", strings.ToUpper(v.(string)) != "DEFAULT":
|
||||||
|
fmt.Fprint(b, ` LC_COLLATE "C"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, opt := range boolOpts {
|
switch v, ok := d.GetOk(dbCTypeAttr); {
|
||||||
val := d.Get(opt.hclKey).(bool)
|
case ok:
|
||||||
|
fmt.Fprint(b, " LC_CTYPE ", pq.QuoteIdentifier(v.(string)))
|
||||||
valStr := "FALSE"
|
case v.(string) == "", strings.ToUpper(v.(string)) != "DEFAULT":
|
||||||
if val {
|
fmt.Fprint(b, ` LC_CTYPE "C"`)
|
||||||
valStr = "TRUE"
|
|
||||||
}
|
|
||||||
createOpts = append(createOpts, fmt.Sprintf("%s=%s", opt.sqlKey, valStr))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbName := d.Get(dbNameAttr).(string)
|
if v, ok := d.GetOk(dbTablespaceAttr); ok {
|
||||||
createStr := strings.Join(createOpts, " ")
|
fmt.Fprint(b, " TABLESPACE ", pq.QuoteIdentifier(v.(string)))
|
||||||
if len(createOpts) > 0 {
|
|
||||||
createStr = " WITH " + createStr
|
|
||||||
}
|
}
|
||||||
query := fmt.Sprintf("CREATE DATABASE %s%s", pq.QuoteIdentifier(dbName), createStr)
|
|
||||||
|
{
|
||||||
|
val := d.Get(dbAllowConnsAttr).(bool)
|
||||||
|
fmt.Fprint(b, " ALLOW_CONNECTIONS ", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
val := d.Get(dbConnLimitAttr).(int)
|
||||||
|
fmt.Fprint(b, " CONNECTION LIMIT ", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
val := d.Get(dbIsTemplateAttr).(bool)
|
||||||
|
fmt.Fprint(b, " IS_TEMPLATE ", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
query := b.String()
|
||||||
_, err = conn.Query(query)
|
_, err = conn.Query(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf(fmt.Sprintf("Error creating database %s: {{err}}", dbName), err)
|
return errwrap.Wrapf(fmt.Sprintf("Error creating database %s: {{err}}", dbName), err)
|
||||||
@ -296,7 +233,7 @@ func resourcePostgreSQLDatabaseRead(d *schema.ResourceData, meta interface{}) er
|
|||||||
err = conn.QueryRow("SELECT d.datname, pg_catalog.pg_get_userbyid(d.datdba) from pg_database d WHERE datname=$1", dbId).Scan(&dbName, &ownerName)
|
err = conn.QueryRow("SELECT d.datname, pg_catalog.pg_get_userbyid(d.datdba) from pg_database d WHERE datname=$1", dbId).Scan(&dbName, &ownerName)
|
||||||
switch {
|
switch {
|
||||||
case err == sql.ErrNoRows:
|
case err == sql.ErrNoRows:
|
||||||
log.Printf("[WARN] PostgreSQL database (%s) not found", d.Id())
|
log.Printf("[WARN] PostgreSQL database (%s) not found", dbId)
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
return nil
|
return nil
|
||||||
case err != nil:
|
case err != nil:
|
||||||
@ -313,7 +250,7 @@ func resourcePostgreSQLDatabaseRead(d *schema.ResourceData, meta interface{}) er
|
|||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
case err == sql.ErrNoRows:
|
case err == sql.ErrNoRows:
|
||||||
log.Printf("[WARN] PostgreSQL database (%s) not found", d.Id())
|
log.Printf("[WARN] PostgreSQL database (%s) not found", dbId)
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
return nil
|
return nil
|
||||||
case err != nil:
|
case err != nil:
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
package postgresql
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func validateConnLimit(v interface{}, key string) (warnings []string, errors []error) {
|
|
||||||
value := v.(int)
|
|
||||||
if value < -1 {
|
|
||||||
errors = append(errors, fmt.Errorf("%d can not be less than -1", key))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user