Skip to content

Commit

Permalink
Merge branch 'main' of github.com:hashicorp/terraform into liamcervan…
Browse files Browse the repository at this point in the history
…te/stacks/unknown-removed-component
  • Loading branch information
liamcervante committed Sep 10, 2024
2 parents 3a00455 + b22db51 commit d6372d2
Show file tree
Hide file tree
Showing 10 changed files with 460 additions and 311 deletions.
470 changes: 259 additions & 211 deletions internal/backend/remote-state/kubernetes/backend.go

Large diffs are not rendered by default.

8 changes: 1 addition & 7 deletions internal/backend/remote-state/kubernetes/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ go 1.22.5

require (
github.com/hashicorp/terraform v0.0.0-00010101000000-000000000000
github.com/hashicorp/terraform/internal/legacy v0.0.0-00010101000000-000000000000
github.com/mitchellh/go-homedir v1.1.0
github.com/zclconf/go-cty v1.15.0
k8s.io/api v0.25.5
k8s.io/apimachinery v0.25.5
k8s.io/client-go v0.25.5
Expand Down Expand Up @@ -49,18 +49,14 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/zclconf/go-cty v1.15.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/net v0.23.0 // indirect
Expand Down Expand Up @@ -99,6 +95,4 @@ replace github.com/hashicorp/terraform/internal/backend/remote-state/pg => ../pg

replace github.com/hashicorp/terraform/internal/backend/remote-state/s3 => ../s3

replace github.com/hashicorp/terraform/internal/legacy => ../../../legacy

replace github.com/hashicorp/terraform => ../../../..
6 changes: 0 additions & 6 deletions internal/backend/remote-state/kubernetes/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -261,18 +261,12 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
142 changes: 71 additions & 71 deletions internal/backend/remote-state/pg/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,110 +4,110 @@
package pg

import (
"context"
"database/sql"
"fmt"
"os"
"strconv"

"github.com/hashicorp/terraform/internal/backend"
"github.com/hashicorp/terraform/internal/legacy/helper/schema"
"github.com/lib/pq"
"github.com/zclconf/go-cty/cty"

"github.com/hashicorp/terraform/internal/backend"
"github.com/hashicorp/terraform/internal/backend/backendbase"
"github.com/hashicorp/terraform/internal/configs/configschema"
"github.com/hashicorp/terraform/internal/tfdiags"
)

const (
statesTableName = "states"
statesIndexName = "states_by_name"
)

func defaultBoolFunc(k string, dv bool) schema.SchemaDefaultFunc {
return func() (interface{}, error) {
if v := os.Getenv(k); v != "" {
return strconv.ParseBool(v)
}

return dv, nil
}
}

// New creates a new backend for Postgres remote state.
func New() backend.Backend {
s := &schema.Backend{
Schema: map[string]*schema.Schema{
"conn_str": {
Type: schema.TypeString,
Optional: true,
Description: "Postgres connection string; a `postgres://` URL",
DefaultFunc: schema.EnvDefaultFunc("PG_CONN_STR", nil),
return &Backend{
Base: backendbase.Base{
Schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"conn_str": {
Type: cty.String,
Optional: true,
Description: "Postgres connection string; a `postgres://` URL",
},
"schema_name": {
Type: cty.String,
Optional: true,
Description: "Name of the automatically managed Postgres schema to store state",
},
"skip_schema_creation": {
Type: cty.Bool,
Optional: true,
Description: "If set to `true`, Terraform won't try to create the Postgres schema",
},
"skip_table_creation": {
Type: cty.Bool,
Optional: true,
Description: "If set to `true`, Terraform won't try to create the Postgres table",
},
"skip_index_creation": {
Type: cty.Bool,
Optional: true,
Description: "If set to `true`, Terraform won't try to create the Postgres index",
},
},
},

"schema_name": {
Type: schema.TypeString,
Optional: true,
Description: "Name of the automatically managed Postgres schema to store state",
DefaultFunc: schema.EnvDefaultFunc("PG_SCHEMA_NAME", "terraform_remote_state"),
},

"skip_schema_creation": {
Type: schema.TypeBool,
Optional: true,
Description: "If set to `true`, Terraform won't try to create the Postgres schema",
DefaultFunc: defaultBoolFunc("PG_SKIP_SCHEMA_CREATION", false),
},

"skip_table_creation": {
Type: schema.TypeBool,
Optional: true,
Description: "If set to `true`, Terraform won't try to create the Postgres table",
DefaultFunc: defaultBoolFunc("PG_SKIP_TABLE_CREATION", false),
},

"skip_index_creation": {
Type: schema.TypeBool,
Optional: true,
Description: "If set to `true`, Terraform won't try to create the Postgres index",
DefaultFunc: defaultBoolFunc("PG_SKIP_INDEX_CREATION", false),
SDKLikeDefaults: backendbase.SDKLikeDefaults{
"conn_str": {
EnvVars: []string{"PG_CONN_STR"},
},
"schema_name": {
EnvVars: []string{"PG_SCHEMA_NAME"},
Fallback: "terraform_remote_state",
},
"skip_schema_creation": {
EnvVars: []string{"PG_SKIP_SCHEMA_CREATION"},
Fallback: "false",
},
"skip_table_creation": {
EnvVars: []string{"PG_SKIP_TABLE_CREATION"},
Fallback: "false",
},
"skip_index_creation": {
EnvVars: []string{"PG_SKIP_INDEX_CREATION"},
Fallback: "false",
},
},
},
}

result := &Backend{Backend: s}
result.Backend.ConfigureFunc = result.configure
return result
}

type Backend struct {
*schema.Backend
backendbase.Base

// The fields below are set from configure
db *sql.DB
configData *schema.ResourceData
connStr string
schemaName string
}

func (b *Backend) configure(ctx context.Context) error {
// Grab the resource data
b.configData = schema.FromContextBackendConfig(ctx)
data := b.configData
func (b *Backend) Configure(configVal cty.Value) tfdiags.Diagnostics {
data := backendbase.NewSDKLikeData(configVal)

b.connStr = data.Get("conn_str").(string)
b.schemaName = pq.QuoteIdentifier(data.Get("schema_name").(string))
b.connStr = data.String("conn_str")
b.schemaName = pq.QuoteIdentifier(data.String("schema_name"))

db, err := sql.Open("postgres", b.connStr)
if err != nil {
return err
return backendbase.ErrorAsDiagnostics(err)
}

// Prepare database schema, tables, & indexes.
var query string

if !data.Get("skip_schema_creation").(bool) {
if !data.Bool("skip_schema_creation") {
// list all schemas to see if it exists
var count int
query = `select count(1) from information_schema.schemata where schema_name = $1`
if err := db.QueryRow(query, data.Get("schema_name").(string)).Scan(&count); err != nil {
return err
if err := db.QueryRow(query, data.String("schema_name")).Scan(&count); err != nil {
return backendbase.ErrorAsDiagnostics(err)
}

// skip schema creation if schema already exists
Expand All @@ -117,14 +117,14 @@ func (b *Backend) configure(ctx context.Context) error {
// tries to create the schema
query = `CREATE SCHEMA IF NOT EXISTS %s`
if _, err := db.Exec(fmt.Sprintf(query, b.schemaName)); err != nil {
return err
return backendbase.ErrorAsDiagnostics(err)
}
}
}

if !data.Get("skip_table_creation").(bool) {
if !data.Bool("skip_table_creation") {
if _, err := db.Exec("CREATE SEQUENCE IF NOT EXISTS public.global_states_id_seq AS bigint"); err != nil {
return err
return backendbase.ErrorAsDiagnostics(err)
}

query = `CREATE TABLE IF NOT EXISTS %s.%s (
Expand All @@ -133,14 +133,14 @@ func (b *Backend) configure(ctx context.Context) error {
data text
)`
if _, err := db.Exec(fmt.Sprintf(query, b.schemaName, statesTableName)); err != nil {
return err
return backendbase.ErrorAsDiagnostics(err)
}
}

if !data.Get("skip_index_creation").(bool) {
if !data.Bool("skip_index_creation") {
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
return backendbase.ErrorAsDiagnostics(err)
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/backend/remote-state/pg/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func TestBackendConfig(t *testing.T) {
"conn_str": connStr,
"schema_name": fmt.Sprintf("terraform_%s", t.Name()),
},
ExpectConnectionError: `role "baduser" does not exist`,
ExpectConnectionError: `password authentication failed for user "baduser"`,
},
{
Name: "host-in-env-vars",
Expand Down Expand Up @@ -130,7 +130,7 @@ func TestBackendConfig(t *testing.T) {
Config: map[string]interface{}{
"schema_name": fmt.Sprintf("terraform_%s", t.Name()),
},
ExpectConfigurationError: `error getting default for "skip_schema_creation"`,
ExpectConfigurationError: `invalid value for "skip_schema_creation"`,
},
}

Expand Down
8 changes: 1 addition & 7 deletions internal/backend/remote-state/pg/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ require (
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/hcl/v2 v2.21.0
github.com/hashicorp/terraform v0.0.0-00010101000000-000000000000
github.com/hashicorp/terraform/internal/legacy v0.0.0-00010101000000-000000000000
github.com/lib/pq v1.10.3
github.com/zclconf/go-cty v1.15.0
)

require (
Expand All @@ -20,12 +20,8 @@ require (
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/zclconf/go-cty v1.15.0 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sys v0.20.0 // indirect
Expand All @@ -49,6 +45,4 @@ replace github.com/hashicorp/terraform/internal/backend/remote-state/pg => ../pg

replace github.com/hashicorp/terraform/internal/backend/remote-state/s3 => ../s3

replace github.com/hashicorp/terraform/internal/legacy => ../../../legacy

replace github.com/hashicorp/terraform => ../../../..
6 changes: 0 additions & 6 deletions internal/backend/remote-state/pg/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -196,18 +196,12 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down
1 change: 0 additions & 1 deletion internal/stacks/stackruntime/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3147,7 +3147,6 @@ func TestApply_RemovedBlocks(t *testing.T) {
)

// TODO: Add tests for and implement the following cases:
// - Removed and component blocks that target the same instance.
// - Add a test for a removed block targeting state that has already been
// removed.
// - Add a test for a removed block that forgets instead of destroys.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,24 @@ func (r *RemovedInstance) ModuleTreePlan(ctx context.Context) (*plans.Plan, tfdi
return doOnceWithDiags(ctx, &r.moduleTreePlan, r.main, func(ctx context.Context) (*plans.Plan, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics

component := r.main.Stack(ctx, r.Addr().Stack, PlanPhase).Component(ctx, r.Addr().Item.Component)
if component != nil {
insts, unknown := component.Instances(ctx, PlanPhase)
if !unknown {
if _, exists := insts[r.key]; exists {
// The instance we're planning to remove is also targeted
// by a component block. We won't remove it, and we'll
// report a diagnostic to that effect.
return nil, diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Cannot remove component instance",
Detail: fmt.Sprintf("The component instance %s is targeted by a component block and cannot be removed. The relevant component is defined at %s.", r.Addr(), component.Declaration(ctx).DeclRange.ToHCL()),
Subject: r.DeclRange(ctx),
})
}
}
}

known, unknown, moreDiags := EvalProviderValues(ctx, r.main, r.call.Config(ctx).config.ProviderConfigs, PlanPhase, r)
if moreDiags.HasErrors() {
// We won't actually add the diagnostics here, they should be
Expand Down
Loading

0 comments on commit d6372d2

Please sign in to comment.