Flesh out the CREATE DATABASE for PostgreSQL.
This commit is contained in:
parent
2aee081e4b
commit
f3add9e7ef
|
@ -21,13 +21,61 @@ func resourcePostgreSQLDatabase() *schema.Resource {
|
|||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"owner": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"template": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The name of the template from which to create the new database.",
|
||||
},
|
||||
"encoding": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Character set encoding to use in the new database.",
|
||||
},
|
||||
"lc_collate": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Collation order (LC_COLLATE) to use in the new database.",
|
||||
},
|
||||
"lc_ctype": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Character classification (LC_CTYPE) to use in the new database.",
|
||||
},
|
||||
"tablespace_name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The name of the tablespace that will be associated with the new database.",
|
||||
},
|
||||
"connection_limit": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "How many concurrent connections can be made to this database.",
|
||||
ValidateFunc: func(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
|
||||
},
|
||||
},
|
||||
"allow_connections": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: true,
|
||||
Description: "If false then no one can connect to this database.",
|
||||
},
|
||||
"is_template": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "If true, then this database can be cloned by any user with CREATEDB privileges.",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -40,24 +88,85 @@ func resourcePostgreSQLDatabaseCreate(d *schema.ResourceData, meta interface{})
|
|||
}
|
||||
defer conn.Close()
|
||||
|
||||
dbName := d.Get("name").(string)
|
||||
dbOwner := d.Get("owner").(string)
|
||||
connUsername := client.username
|
||||
|
||||
var dbOwnerCfg string
|
||||
if dbOwner != "" {
|
||||
dbOwnerCfg = fmt.Sprintf("WITH OWNER=%s", pq.QuoteIdentifier(dbOwner))
|
||||
} else {
|
||||
dbOwnerCfg = ""
|
||||
const numOptions = 9
|
||||
createOpts := make([]string, 0, numOptions)
|
||||
|
||||
stringOpts := []struct {
|
||||
hclKey string
|
||||
sqlKey string
|
||||
}{
|
||||
{"owner", "OWNER"},
|
||||
{"template", "TEMPLATE"},
|
||||
{"encoding", "ENCODING"},
|
||||
{"lc_collate", "LC_COLLATE"},
|
||||
{"lc_ctype", "LC_CTYPE"},
|
||||
{"tablespace_name", "TABLESPACE"},
|
||||
}
|
||||
for _, opt := range stringOpts {
|
||||
v, ok := d.GetOk(opt.hclKey)
|
||||
var val string
|
||||
if !ok {
|
||||
// Set the owner to the connection username
|
||||
if opt.hclKey == "owner" && v.(string) == "" {
|
||||
val = connUsername
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
val = v.(string)
|
||||
|
||||
// Set the owner to the connection username
|
||||
if opt.hclKey == "owner" && val == "" {
|
||||
val = connUsername
|
||||
}
|
||||
|
||||
if val != "" {
|
||||
createOpts = append(createOpts, fmt.Sprintf("%s=%s", opt.sqlKey, pq.QuoteIdentifier(val)))
|
||||
}
|
||||
}
|
||||
|
||||
//needed in order to set the owner of the db if the connection user is not a superuser
|
||||
err = grantRoleMembership(conn, dbOwner, connUsername)
|
||||
if err != nil {
|
||||
return err
|
||||
intOpts := []struct {
|
||||
hclKey string
|
||||
sqlKey string
|
||||
}{
|
||||
{"connection_limit", "CONNECTION LIMIT"},
|
||||
}
|
||||
for _, opt := range intOpts {
|
||||
v, ok := d.GetOk(opt.hclKey)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
val := v.(int)
|
||||
createOpts = append(createOpts, fmt.Sprintf("%s=%d", opt.sqlKey, val))
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("CREATE DATABASE %s %s", pq.QuoteIdentifier(dbName), dbOwnerCfg)
|
||||
boolOpts := []struct {
|
||||
hclKey string
|
||||
sqlKey string
|
||||
}{
|
||||
{"allow_connections", "ALLOW_CONNECTIONS"},
|
||||
{"is_template", "IS_TEMPLATE"},
|
||||
}
|
||||
for _, opt := range boolOpts {
|
||||
v, ok := d.GetOk(opt.hclKey)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
val := v.(bool)
|
||||
createOpts = append(createOpts, fmt.Sprintf("%s=%t", opt.sqlKey, val))
|
||||
}
|
||||
|
||||
dbName := d.Get("name").(string)
|
||||
createStr := strings.Join(createOpts, " ")
|
||||
if len(createOpts) > 0 {
|
||||
createStr = " WITH " + createStr
|
||||
}
|
||||
query := fmt.Sprintf("CREATE DATABASE %s%s", pq.QuoteIdentifier(dbName), createStr)
|
||||
_, err = conn.Query(query)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf(fmt.Sprintf("Error creating database %s: {{err}}", dbName), err)
|
||||
|
|
|
@ -6,19 +6,19 @@ import (
|
|||
"testing"
|
||||
|
||||
"errors"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccPostgresqlDatabase_Basic(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckPostgresqlDatabaseDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccPostgresqlDatabaseConfig,
|
||||
Config: testAccPostgreSQLDatabaseConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPostgresqlDatabaseExists("postgresql_database.mydb"),
|
||||
resource.TestCheckResourceAttr(
|
||||
|
@ -32,14 +32,13 @@ func TestAccPostgresqlDatabase_Basic(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAccPostgresqlDatabase_DefaultOwner(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckPostgresqlDatabaseDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccPostgresqlDatabaseConfig,
|
||||
Config: testAccPostgreSQLDatabaseConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPostgresqlDatabaseExists("postgresql_database.mydb_default_owner"),
|
||||
resource.TestCheckResourceAttr(
|
||||
|
@ -119,7 +118,7 @@ func checkDatabaseExists(client *Client, dbName string) (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
var testAccPostgresqlDatabaseConfig = `
|
||||
var testAccPostgreSQLDatabaseConfig = `
|
||||
resource "postgresql_role" "myrole" {
|
||||
name = "myrole"
|
||||
login = true
|
||||
|
@ -135,6 +134,19 @@ resource "postgresql_database" "mydb2" {
|
|||
owner = "${postgresql_role.myrole.name}"
|
||||
}
|
||||
|
||||
resource "postgresql_database" "mydb3" {
|
||||
name = "mydb3"
|
||||
owner = "${postgresql_role.myrole.name}"
|
||||
template = "template1"
|
||||
encoding = "SQL_ASCII"
|
||||
lc_collate = "C"
|
||||
lc_ctype = "C"
|
||||
tablespace_name = "pg_default"
|
||||
connection_limit = -1
|
||||
allow_connections = false
|
||||
is_template = false
|
||||
}
|
||||
|
||||
resource "postgresql_database" "mydb_default_owner" {
|
||||
name = "mydb_default_owner"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue