Merge pull request #26557 from remilapeyre/skip-ddl-commands
Add skip_table_creation and skip_index_creation options to the pg backend
This commit is contained in:
commit
657dd33008
|
@ -19,25 +19,37 @@ const (
|
||||||
func New() backend.Backend {
|
func New() backend.Backend {
|
||||||
s := &schema.Backend{
|
s := &schema.Backend{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"conn_str": &schema.Schema{
|
"conn_str": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Postgres connection string; a `postgres://` URL",
|
Description: "Postgres connection string; a `postgres://` URL",
|
||||||
},
|
},
|
||||||
|
|
||||||
"schema_name": &schema.Schema{
|
"schema_name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Description: "Name of the automatically managed Postgres schema to store state",
|
Description: "Name of the automatically managed Postgres schema to store state",
|
||||||
Default: "terraform_remote_state",
|
Default: "terraform_remote_state",
|
||||||
},
|
},
|
||||||
|
|
||||||
"skip_schema_creation": &schema.Schema{
|
"skip_schema_creation": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Description: "If set to `true`, Terraform won't try to create the Postgres schema",
|
Description: "If set to `true`, Terraform won't try to create the Postgres schema",
|
||||||
Default: false,
|
Default: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"skip_table_creation": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Description: "If set to `true`, Terraform won't try to create the Postgres table",
|
||||||
|
},
|
||||||
|
|
||||||
|
"skip_index_creation": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Description: "If set to `true`, Terraform won't try to create the Postgres index",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,17 +103,23 @@ func (b *Backend) configure(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
query = `CREATE TABLE IF NOT EXISTS %s.%s (
|
|
||||||
id SERIAL PRIMARY KEY,
|
if !data.Get("skip_table_creation").(bool) {
|
||||||
name TEXT,
|
query = `CREATE TABLE IF NOT EXISTS %s.%s (
|
||||||
data TEXT
|
id SERIAL PRIMARY KEY,
|
||||||
)`
|
name TEXT,
|
||||||
if _, err := db.Exec(fmt.Sprintf(query, b.schemaName, statesTableName)); err != nil {
|
data TEXT
|
||||||
return err
|
)`
|
||||||
|
if _, err := db.Exec(fmt.Sprintf(query, b.schemaName, statesTableName)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
query = `CREATE UNIQUE INDEX IF NOT EXISTS %s ON %s.%s (name)`
|
|
||||||
if _, err := db.Exec(fmt.Sprintf(query, statesIndexName, b.schemaName, statesTableName)); err != nil {
|
if !data.Get("skip_index_creation").(bool) {
|
||||||
return err
|
query = `CREATE UNIQUE INDEX IF NOT EXISTS %s ON %s.%s (name)`
|
||||||
|
if _, err := db.Exec(fmt.Sprintf(query, statesIndexName, b.schemaName, statesTableName)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign db after its schema is prepared.
|
// Assign db after its schema is prepared.
|
||||||
|
|
|
@ -79,49 +79,131 @@ func TestBackendConfig(t *testing.T) {
|
||||||
backend.TestBackendStates(t, b)
|
backend.TestBackendStates(t, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackendConfigSkipSchema(t *testing.T) {
|
func TestBackendConfigSkipOptions(t *testing.T) {
|
||||||
testACC(t)
|
testACC(t)
|
||||||
connStr := getDatabaseUrl()
|
connStr := getDatabaseUrl()
|
||||||
schemaName := fmt.Sprintf("terraform_%s", t.Name())
|
|
||||||
config := backend.TestWrapConfig(map[string]interface{}{
|
testCases := []struct {
|
||||||
"conn_str": connStr,
|
Name string
|
||||||
"schema_name": schemaName,
|
SkipSchemaCreation bool
|
||||||
"skip_schema_creation": true,
|
SkipTableCreation bool
|
||||||
})
|
SkipIndexCreation bool
|
||||||
schemaName = pq.QuoteIdentifier(schemaName)
|
Setup func(t *testing.T, db *sql.DB, schemaName string)
|
||||||
db, err := sql.Open("postgres", connStr)
|
}{
|
||||||
if err != nil {
|
{
|
||||||
t.Fatal(err)
|
Name: "skip_schema_creation",
|
||||||
|
SkipSchemaCreation: true,
|
||||||
|
Setup: func(t *testing.T, db *sql.DB, schemaName string) {
|
||||||
|
// create the schema as a prerequisites
|
||||||
|
_, err := db.Query(fmt.Sprintf(`CREATE SCHEMA IF NOT EXISTS %s`, schemaName))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "skip_table_creation",
|
||||||
|
SkipTableCreation: true,
|
||||||
|
Setup: func(t *testing.T, db *sql.DB, schemaName string) {
|
||||||
|
// since the table needs to be already created the schema must be too
|
||||||
|
_, err := db.Query(fmt.Sprintf(`CREATE SCHEMA %s`, schemaName))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = db.Query(fmt.Sprintf(`CREATE TABLE %s.%s (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
data TEXT
|
||||||
|
)`, schemaName, statesTableName))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "skip_index_creation",
|
||||||
|
SkipIndexCreation: true,
|
||||||
|
Setup: func(t *testing.T, db *sql.DB, schemaName string) {
|
||||||
|
// Everything need to exists for the index to be created
|
||||||
|
_, err := db.Query(fmt.Sprintf(`CREATE SCHEMA %s`, schemaName))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = db.Query(fmt.Sprintf(`CREATE TABLE %s.%s (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
data TEXT
|
||||||
|
)`, schemaName, statesTableName))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = db.Exec(fmt.Sprintf(`CREATE UNIQUE INDEX IF NOT EXISTS %s ON %s.%s (name)`, statesIndexName, schemaName, statesTableName))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the schema as a prerequisites
|
for _, tc := range testCases {
|
||||||
db.Query(fmt.Sprintf("CREATE SCHEMA IF NOT EXISTS %s", schemaName))
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
defer db.Query(fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", schemaName))
|
schemaName := tc.Name
|
||||||
|
|
||||||
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
config := backend.TestWrapConfig(map[string]interface{}{
|
||||||
|
"conn_str": connStr,
|
||||||
|
"schema_name": schemaName,
|
||||||
|
"skip_schema_creation": tc.SkipSchemaCreation,
|
||||||
|
"skip_table_creation": tc.SkipTableCreation,
|
||||||
|
"skip_index_creation": tc.SkipIndexCreation,
|
||||||
|
})
|
||||||
|
schemaName = pq.QuoteIdentifier(schemaName)
|
||||||
|
db, err := sql.Open("postgres", connStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
if b == nil {
|
tc.Setup(t, db, schemaName)
|
||||||
t.Fatal("Backend could not be configured")
|
defer db.Query(fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", schemaName))
|
||||||
|
|
||||||
|
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||||
|
|
||||||
|
if b == nil {
|
||||||
|
t.Fatal("Backend could not be configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure everything has been created
|
||||||
|
|
||||||
|
// This tests that both the schema and the table have been created
|
||||||
|
_, err = b.db.Query(fmt.Sprintf("SELECT name, data FROM %s.%s LIMIT 1", schemaName, statesTableName))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// Make sure that the index exists
|
||||||
|
query := `select count(*) from pg_indexes where schemaname=$1 and tablename=$2 and indexname=$3;`
|
||||||
|
var count int
|
||||||
|
if err := b.db.QueryRow(query, tc.Name, statesTableName, statesIndexName).Scan(&count); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if count != 1 {
|
||||||
|
t.Fatalf("The index has not been created (%d)", count)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = b.StateMgr(backend.DefaultStateName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := b.StateMgr(backend.DefaultStateName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c := s.(*remote.State).Client.(*RemoteClient)
|
||||||
|
if c.Name != backend.DefaultStateName {
|
||||||
|
t.Fatal("RemoteClient name is not configured")
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = b.db.Query(fmt.Sprintf("SELECT name, data FROM %s.%s LIMIT 1", schemaName, statesTableName))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = b.StateMgr(backend.DefaultStateName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := b.StateMgr(backend.DefaultStateName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
c := s.(*remote.State).Client.(*RemoteClient)
|
|
||||||
if c.Name != backend.DefaultStateName {
|
|
||||||
t.Fatal("RemoteClient name is not configured")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackendStates(t *testing.T) {
|
func TestBackendStates(t *testing.T) {
|
||||||
|
|
|
@ -72,6 +72,8 @@ The following configuration options or environment variables are supported:
|
||||||
* `conn_str` - (Required) Postgres connection string; a `postgres://` URL
|
* `conn_str` - (Required) Postgres connection string; a `postgres://` URL
|
||||||
* `schema_name` - Name of the automatically-managed Postgres schema, default `terraform_remote_state`.
|
* `schema_name` - Name of the automatically-managed Postgres schema, default `terraform_remote_state`.
|
||||||
* `skip_schema_creation` - If set to `true`, the Postgres schema must already exist. Terraform won't try to create the schema. Useful when the Postgres user does not have "create schema" permission on the database.
|
* `skip_schema_creation` - If set to `true`, the Postgres schema must already exist. Terraform won't try to create the schema. Useful when the Postgres user does not have "create schema" permission on the database.
|
||||||
|
* `skip_table_creation` - If set to `true`, the Postgres table must already exist. Terraform won't try to create the table. Useful when the Postgres user does not have "create table" permission on the database.
|
||||||
|
* `skip_index_creation` - If set to `true`, the Postgres index must already exist. Terraform won't try to create the index. Useful when the Postgres user does not have "create index" permission on the database.
|
||||||
|
|
||||||
## Technical Design
|
## Technical Design
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue