mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
backend/pg: Accept connection string in PGDATABASE environment variable
This commit is contained in:
parent
dfbb9c2e10
commit
1f603b1a7f
@ -23,6 +23,7 @@ func New() backend.Backend {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Postgres connection string; a `postgres://` URL",
|
Description: "Postgres connection string; a `postgres://` URL",
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("PGDATABASE", nil),
|
||||||
},
|
},
|
||||||
|
|
||||||
"schema_name": {
|
"schema_name": {
|
||||||
|
@ -7,13 +7,15 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/hcl/v2/hcldec"
|
||||||
"github.com/hashicorp/terraform/internal/backend"
|
"github.com/hashicorp/terraform/internal/backend"
|
||||||
"github.com/hashicorp/terraform/internal/states/remote"
|
"github.com/hashicorp/terraform/internal/states/remote"
|
||||||
"github.com/hashicorp/terraform/internal/states/statemgr"
|
"github.com/hashicorp/terraform/internal/states/statemgr"
|
||||||
|
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
_ "github.com/lib/pq"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Function to skip a test unless in ACCeptance test mode.
|
// Function to skip a test unless in ACCeptance test mode.
|
||||||
@ -38,46 +40,110 @@ func TestBackend_impl(t *testing.T) {
|
|||||||
func TestBackendConfig(t *testing.T) {
|
func TestBackendConfig(t *testing.T) {
|
||||||
testACC(t)
|
testACC(t)
|
||||||
connStr := getDatabaseUrl()
|
connStr := getDatabaseUrl()
|
||||||
schemaName := pq.QuoteIdentifier(fmt.Sprintf("terraform_%s", t.Name()))
|
|
||||||
|
|
||||||
config := backend.TestWrapConfig(map[string]interface{}{
|
testCases := []struct {
|
||||||
"conn_str": connStr,
|
Name string
|
||||||
"schema_name": schemaName,
|
EnvVars map[string]string
|
||||||
})
|
Config map[string]interface{}
|
||||||
schemaName = pq.QuoteIdentifier(schemaName)
|
ExpectError string
|
||||||
|
}{
|
||||||
dbCleaner, err := sql.Open("postgres", connStr)
|
{
|
||||||
if err != nil {
|
Name: "valid-config",
|
||||||
t.Fatal(err)
|
Config: map[string]interface{}{
|
||||||
}
|
"conn_str": connStr,
|
||||||
defer dbCleaner.Query(fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", schemaName))
|
"schema_name": fmt.Sprintf("terraform_%s", t.Name()),
|
||||||
|
},
|
||||||
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
},
|
||||||
|
{
|
||||||
if b == nil {
|
Name: "missing-conn-str",
|
||||||
t.Fatal("Backend could not be configured")
|
Config: map[string]interface{}{
|
||||||
|
"schema_name": fmt.Sprintf("terraform_%s", t.Name()),
|
||||||
|
},
|
||||||
|
ExpectError: `The attribute "conn_str" is required, but no definition was found.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "conn-str-env-var",
|
||||||
|
EnvVars: map[string]string{
|
||||||
|
"PGDATABASE": connStr,
|
||||||
|
},
|
||||||
|
Config: map[string]interface{}{
|
||||||
|
"schema_name": fmt.Sprintf("terraform_%s", t.Name()),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = b.db.Query(fmt.Sprintf("SELECT name, data FROM %s.%s LIMIT 1", schemaName, statesTableName))
|
for _, tc := range testCases {
|
||||||
if err != nil {
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
t.Fatal(err)
|
for k, v := range tc.EnvVars {
|
||||||
|
t.Setenv(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := backend.TestWrapConfig(tc.Config)
|
||||||
|
schemaName := pq.QuoteIdentifier(tc.Config["schema_name"].(string))
|
||||||
|
|
||||||
|
dbCleaner, err := sql.Open("postgres", connStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer dbCleaner.Query(fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", schemaName))
|
||||||
|
|
||||||
|
var diags tfdiags.Diagnostics
|
||||||
|
b := New().(*Backend)
|
||||||
|
schema := b.ConfigSchema()
|
||||||
|
spec := schema.DecoderSpec()
|
||||||
|
obj, decDiags := hcldec.Decode(config, spec, nil)
|
||||||
|
diags = diags.Append(decDiags)
|
||||||
|
|
||||||
|
newObj, valDiags := b.PrepareConfig(obj)
|
||||||
|
diags = diags.Append(valDiags.InConfigBody(config, ""))
|
||||||
|
|
||||||
|
if tc.ExpectError != "" {
|
||||||
|
if !diags.HasErrors() {
|
||||||
|
t.Fatal("error expected but got none")
|
||||||
|
}
|
||||||
|
if !strings.Contains(diags.ErrWithWarnings().Error(), tc.ExpectError) {
|
||||||
|
t.Fatalf("failed to find %q in %s", tc.ExpectError, diags.ErrWithWarnings())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if diags.HasErrors() {
|
||||||
|
t.Fatal(diags.ErrWithWarnings())
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = newObj
|
||||||
|
|
||||||
|
confDiags := b.Configure(obj)
|
||||||
|
if len(confDiags) != 0 {
|
||||||
|
confDiags = confDiags.InConfigBody(config, "")
|
||||||
|
t.Fatal(confDiags.ErrWithWarnings())
|
||||||
|
}
|
||||||
|
|
||||||
|
if b == nil {
|
||||||
|
t.Fatal("Backend could not be 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.TestBackendStates(t, b)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_, 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")
|
|
||||||
}
|
|
||||||
|
|
||||||
backend.TestBackendStates(t, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackendConfigSkipOptions(t *testing.T) {
|
func TestBackendConfigSkipOptions(t *testing.T) {
|
||||||
@ -243,7 +309,7 @@ func TestBackendStates(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer dbCleaner.Query("DROP SCHEMA IF EXISTS %s CASCADE", pq.QuoteIdentifier(schemaName))
|
defer dbCleaner.Query(fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", pq.QuoteIdentifier(schemaName)))
|
||||||
|
|
||||||
config := backend.TestWrapConfig(map[string]interface{}{
|
config := backend.TestWrapConfig(map[string]interface{}{
|
||||||
"conn_str": connStr,
|
"conn_str": connStr,
|
||||||
|
@ -68,7 +68,7 @@ data "terraform_remote_state" "network" {
|
|||||||
|
|
||||||
The following configuration options or environment variables are supported:
|
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. `conn_str` can also be set using the `PGDATABASE` environment variable.
|
||||||
- `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, this is useful when it has already been created by a database administrator.
|
- `skip_schema_creation` - If set to `true`, the Postgres schema must already exist. Terraform won't try to create the schema, this is useful when it has already been created by a database administrator.
|
||||||
- `skip_table_creation` - If set to `true`, the Postgres table must already exist. Terraform won't try to create the table, this is useful when it has already been created by a database administrator.
|
- `skip_table_creation` - If set to `true`, the Postgres table must already exist. Terraform won't try to create the table, this is useful when it has already been created by a database administrator.
|
||||||
|
Loading…
Reference in New Issue
Block a user