From 8547603ff5645edcdcaf2f49fd8a6d18e4cda3b3 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 3 Dec 2019 13:23:07 -0500 Subject: [PATCH 01/19] deprecation warning for destroy provisioner refs Add deprecation warning for references from destroy provisioners or their connections to external resources or values. In order to ensure resource destruction can be completed correctly, destroy nodes must be able to evaluate with only their instance state. We have sufficient information to validate destroy-time provisioners early on during the config loading process. Later on these can be converted to hard errors, and only allow self, count.index, and each.key in destroy provisioners. Limited the provisioner and block evaluation scope later on is tricky, but if the references can never be loaded, then they will never be encountered during evaluation. --- configs/provisioner.go | 55 ++++++++++++++++++- configs/resource.go | 11 ++++ .../warning-files/destroy-provisioners.tf | 40 ++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 configs/testdata/warning-files/destroy-provisioners.tf diff --git a/configs/provisioner.go b/configs/provisioner.go index 47b6567918..fc5136dddf 100644 --- a/configs/provisioner.go +++ b/configs/provisioner.go @@ -50,6 +50,11 @@ func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) { } } + // destroy provisioners can only refer to self + if pv.When == ProvisionerWhenDestroy { + diags = append(diags, onlySelfRefs(config)...) + } + if attr, exists := content.Attributes["on_failure"]; exists { expr, shimDiags := shimTraversalInString(attr.Expr, true) diags = append(diags, shimDiags...) @@ -85,8 +90,11 @@ func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) { } seenConnection = block - //conn, connDiags := decodeConnectionBlock(block) - //diags = append(diags, connDiags...) + // destroy provisioners can only refer to self + if pv.When == ProvisionerWhenDestroy { + diags = append(diags, onlySelfRefs(block.Body)...) + } + pv.Connection = &Connection{ Config: block.Body, DeclRange: block.DefRange, @@ -107,6 +115,49 @@ func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) { return pv, diags } +func onlySelfRefs(body hcl.Body) hcl.Diagnostics { + var diags hcl.Diagnostics + + // Provisioners currently do not use any blocks in their configuration. + // Blocks are likely to remain solely for meta parameters, but in the case + // that blocks are supported for provisioners, we will want to extend this + // to find variables in nested blocks. + attrs, _ := body.JustAttributes() + for _, attr := range attrs { + for _, v := range attr.Expr.Variables() { + valid := false + switch v.RootName() { + case "self": + valid = true + case "count": + // count must use "index" + if len(v) == 2 { + if t, ok := v[1].(hcl.TraverseAttr); ok && t.Name == "index" { + valid = true + } + } + + case "each": + if len(v) == 2 { + if t, ok := v[1].(hcl.TraverseAttr); ok && t.Name == "key" { + valid = true + } + } + } + + if !valid { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: "External references from destroy provisioners are deprecated", + Detail: "Destroy time provisioners and their connections may only reference values stored in the instance state, which include 'self', 'count.index', or 'each.key'.", + Subject: attr.Expr.Range().Ptr(), + }) + } + } + } + return diags +} + // Connection represents a "connection" block when used within either a // "resource" or "provisioner" block in a module or file. type Connection struct { diff --git a/configs/resource.go b/configs/resource.go index 4d5506e293..78f6a240c1 100644 --- a/configs/resource.go +++ b/configs/resource.go @@ -273,6 +273,17 @@ func decodeResourceBlock(block *hcl.Block) (*Resource, hcl.Diagnostics) { } } + // Now we can validate the connection block references if there are any destroy provisioners. + // TODO: should we eliminate standalone connection blocks? + if r.Managed.Connection != nil { + for _, p := range r.Managed.Provisioners { + if p.When == ProvisionerWhenDestroy { + diags = append(diags, onlySelfRefs(r.Managed.Connection.Config)...) + break + } + } + } + return r, diags } diff --git a/configs/testdata/warning-files/destroy-provisioners.tf b/configs/testdata/warning-files/destroy-provisioners.tf new file mode 100644 index 0000000000..ff950bc7fb --- /dev/null +++ b/configs/testdata/warning-files/destroy-provisioners.tf @@ -0,0 +1,40 @@ +locals { + user = "name" +} + +resource "null_resource" "a" { + connection { + host = self.hostname + user = local.user # WARNING: External references from destroy provisioners are deprecated + } + + provisioner "remote-exec" { + when = destroy + index = count.index + key = each.key + + } +} + +resource "null_resource" "b" { + connection { + host = self.hostname + # this is OK since there is no destroy provisioner + user = local.user + } + + provisioner "remote-exec" { + } +} + +resource "null_resource" "b" { + provisioner "remote-exec" { + when = destroy + connection { + host = self.hostname + user = local.user # WARNING: External references from destroy provisioners are deprecated + } + + command = "echo ${local.name}" # WARNING: External references from destroy provisioners are deprecated + } +} From 2b8e876bdb62bfae0d6b93df0b04b265bbb815ba Mon Sep 17 00:00:00 2001 From: Pam Selle <204372+pselle@users.noreply.github.com> Date: Thu, 5 Dec 2019 16:00:19 -0500 Subject: [PATCH 02/19] Don't inspect an empty set, return false --- command/format/diff.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/command/format/diff.go b/command/format/diff.go index 8b1a7edf1e..2f2258de0c 100644 --- a/command/format/diff.go +++ b/command/format/diff.go @@ -1014,8 +1014,9 @@ func (p *blockBodyDiffPrinter) writeActionSymbol(action plans.Action) { } func (p *blockBodyDiffPrinter) pathForcesNewResource(path cty.Path) bool { - if !p.action.IsReplace() { - // "requiredReplace" only applies when the instance is being replaced + if !p.action.IsReplace() || p.requiredReplace.Empty() { + // "requiredReplace" only applies when the instance is being replaced, + // and we should only inspect that set if it is not empty return false } return p.requiredReplace.Has(path) From a5cb36b34c2094c92fc965606be0d53929f74a3d Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 5 Dec 2019 16:06:25 -0500 Subject: [PATCH 03/19] Allow moving instances to new resources If a state mv target happens to be a resource that doesn't exist, allow the creation of the new resource inferring the EachMode from the target address. --- command/state_mv.go | 33 ++++++++++++------- command/state_mv_test.go | 68 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/command/state_mv.go b/command/state_mv.go index 00b48306f0..829ad923bd 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -278,7 +278,9 @@ func (c *StateMvCommand) Run(args []string) int { c.Ui.Output(fmt.Sprintf("%s %q to %q", prefix, addrFrom.String(), args[1])) if !dryRun { fromResourceAddr := addrFrom.ContainingResource() - fromProviderAddr := ssFrom.Resource(fromResourceAddr).ProviderConfig + fromResource := ssFrom.Resource(fromResourceAddr) + fromProviderAddr := fromResource.ProviderConfig + fromEachMode := fromResource.EachMode ssFrom.ForgetResourceInstanceAll(addrFrom) ssFrom.RemoveResourceIfEmpty(fromResourceAddr) @@ -287,22 +289,17 @@ func (c *StateMvCommand) Run(args []string) int { // If we're moving to an address without an index then that // suggests the user's intent is to establish both the // resource and the instance at the same time (since the - // address covers both), but if there's an index in the - // target then the resource must already exist. + // address covers both). If there's an index in the + // target then allow creating the new instance here, + // inferring the mode from how the new address was parsed. if addrTo.Resource.Key != addrs.NoKey { - diags = diags.Append(tfdiags.Sourceless( - tfdiags.Error, - msgInvalidTarget, - fmt.Sprintf("Cannot move to %s: %s does not exist in the current state.", addrTo, addrTo.ContainingResource()), - )) - c.showDiagnostics(diags) - return 1 + fromEachMode = eachModeForInstanceKey(addrTo.Resource.Key) } resourceAddr := addrTo.ContainingResource() stateTo.SyncWrapper().SetResourceMeta( resourceAddr, - states.NoEach, + fromEachMode, fromProviderAddr, // in this case, we bring the provider along as if we were moving the whole resource ) rs = stateTo.Resource(resourceAddr) @@ -358,6 +355,20 @@ func (c *StateMvCommand) Run(args []string) int { return 0 } +func eachModeForInstanceKey(key addrs.InstanceKey) states.EachMode { + switch key.(type) { + case addrs.IntKey: + return states.EachList + case addrs.StringKey: + return states.EachMap + default: + if key == addrs.NoKey { + return states.NoEach + } + panic(fmt.Sprintf("don't know an each mode for instance key %#v", key)) + } +} + // sourceObjectAddrs takes a single source object address and expands it to // potentially multiple objects that need to be handled within it. // diff --git a/command/state_mv_test.go b/command/state_mv_test.go index 504c4fca19..f777d8807e 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -237,6 +237,74 @@ test_instance.foo.0: `) } +func TestStateMv_instanceToNewResource(t *testing.T) { + state := states.BuildState(func(s *states.SyncState) { + s.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "foo", + }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), + &states.ResourceInstanceObjectSrc{ + AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), + Status: states.ObjectReady, + }, + addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + ) + }) + statePath := testStateFile(t, state) + + p := testProvider() + ui := new(cli.MockUi) + c := &StateMvCommand{ + StateMeta{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(p), + Ui: ui, + }, + }, + } + + args := []string{ + "-state", statePath, + "test_instance.foo[0]", + "test_instance.bar[\"new\"]", + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // Test it is correct + testStateOutput(t, statePath, ` +test_instance.bar["new"]: + ID = bar + provider = provider.test + bar = value + foo = value +`) + + // now move the instance to a new resource in a new module + args = []string{ + "-state", statePath, + "test_instance.bar[\"new\"]", + "module.test.test_instance.baz[\"new\"]", + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // Test it is correct + testStateOutput(t, statePath, ` + +module.test: + test_instance.baz["new"]: + ID = bar + provider = provider.test + bar = value + foo = value +`) +} + func TestStateMv_differentResourceTypes(t *testing.T) { state := states.BuildState(func(s *states.SyncState) { s.SetResourceInstanceCurrent( From 3dfeb6770851c7c33d9b8b307decbf0fece91dc9 Mon Sep 17 00:00:00 2001 From: Aaron Heesakkers Date: Fri, 6 Dec 2019 00:00:51 +0100 Subject: [PATCH 04/19] command/internal-plugin: Strip off TF_CLI_ARGS arguments These are not meaningful for the `internal-plugin` subcommand, which is for internal use only. --- command/internal_plugin.go | 17 +++++++++++++++++ command/internal_plugin_test.go | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/command/internal_plugin.go b/command/internal_plugin.go index b26ba1df68..33de8569ac 100644 --- a/command/internal_plugin.go +++ b/command/internal_plugin.go @@ -33,7 +33,24 @@ func BuildPluginCommandString(pluginType, pluginName string) (string, error) { return strings.Join(parts, TFSPACE), nil } +// Internal plugins do not support any CLI args, but we do receive flags that +// main.go:mergeEnvArgs has merged in from EnvCLI. Instead of making main.go +// aware of this exception, we strip all flags from our args. Flags are easily +// identified by the '-' prefix, ensured by the cli package used. +func StripArgFlags(args []string) []string { + argsNoFlags := []string{} + for i := range args { + if !strings.HasPrefix(args[i], "-") { + argsNoFlags = append(argsNoFlags, args[i]) + } + } + return argsNoFlags +} + func (c *InternalPluginCommand) Run(args []string) int { + // strip flags from args, only use subcommands. + args = StripArgFlags(args) + if len(args) != 2 { log.Printf("Wrong number of args; expected: terraform internal-plugin pluginType pluginName") return 1 diff --git a/command/internal_plugin_test.go b/command/internal_plugin_test.go index 83a3f844ee..832ec6b154 100644 --- a/command/internal_plugin_test.go +++ b/command/internal_plugin_test.go @@ -46,3 +46,12 @@ func TestInternalPlugin_BuildPluginCommandString(t *testing.T) { t.Errorf("Expected command to end with %s; got:\n%s\n", expected, actual) } } + +func TestInternalPlugin_StripArgFlags(t *testing.T) { + actual := StripArgFlags([]string{"provisioner", "remote-exec", "-var-file=my_vars.tfvars", "-flag"}) + expected := []string{"provisioner", "remote-exec"} + // Must be same length and order. + if len(actual) != len(expected) || expected[0] != actual[0] || actual[1] != actual[1] { + t.Fatalf("Expected args to be exactly '%s', got '%s'", expected, actual) + } +} From 73958499d1f7ad5d36848bd3c79cdc32a6a4a859 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 5 Dec 2019 15:02:43 -0800 Subject: [PATCH 05/19] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b910b4c73f..56574a6be7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ BUG FIXES: * config: Fixed referencing errors generally involving `for_each` [GH-23475] +* provisioners: The built-in provisioners (`local-exec`, `remote-exec`, `file`, etc) will no longer fail when the `TF_CLI_ARGS` environment variable is set. [GH-17400] ## 0.12.17 (December 02, 2019) From ebc075226ae2d9892df6694b7121a22656ba47f1 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 5 Dec 2019 18:11:54 -0500 Subject: [PATCH 06/19] update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56574a6be7..dcc525edca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,12 @@ ## 0.12.18 (Unreleased) +UPGRADE NOTES: + +* provisioners: Referencing values outside of a resource's own state is being deprecated for destroy provisioners [GH-23559] + BUG FIXES: +* cli: Allow moving indexed resource instances to new addresses that that don't yet exist in state [GH-23582] * config: Fixed referencing errors generally involving `for_each` [GH-23475] * provisioners: The built-in provisioners (`local-exec`, `remote-exec`, `file`, etc) will no longer fail when the `TF_CLI_ARGS` environment variable is set. [GH-17400] From 30bf83cdeb99d47063b0a928f55ebe6ed348ea04 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 5 Dec 2019 11:13:37 -0800 Subject: [PATCH 07/19] helper/logging: Bring the LevelFilter into our own codebase In order to make this work reasonably we can't avoid using some funny heuristics, which are somewhat reasonable to apply within the context of Terraform itself but would not be good to add to the general "logutils". Specifically, this is adding the additional heuristic that lines starting with spaces are continuation lines and so should inherit the log level of the most recent non-continuation line. --- backend/remote-state/azure/sender.go | 2 +- go.mod | 2 - go.sum | 13 +-- helper/logging/indent.go | 23 +++++ helper/logging/indent_test.go | 15 +++ helper/logging/level.go | 144 +++++++++++++++++++++++++++ helper/logging/level_test.go | 93 +++++++++++++++++ helper/logging/logging.go | 17 ++-- helper/resource/testing.go | 7 +- terraform/graph_builder.go | 6 +- terraform/transform.go | 3 +- 11 files changed, 293 insertions(+), 32 deletions(-) create mode 100644 helper/logging/indent.go create mode 100644 helper/logging/indent_test.go create mode 100644 helper/logging/level.go create mode 100644 helper/logging/level_test.go diff --git a/backend/remote-state/azure/sender.go b/backend/remote-state/azure/sender.go index 90a2fb5bd8..d2b432a65a 100644 --- a/backend/remote-state/azure/sender.go +++ b/backend/remote-state/azure/sender.go @@ -21,7 +21,7 @@ func withRequestLogging() autorest.SendDecorator { return func(s autorest.Sender) autorest.Sender { return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) { // only log if logging's enabled - logLevel := logging.LogLevel() + logLevel := logging.CurrentLogLevel() if logLevel == "" { return s.Do(r) } diff --git a/go.mod b/go.mod index aa7d2056aa..e3eb4beadc 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ require ( cloud.google.com/go v0.45.1 github.com/Azure/azure-sdk-for-go v36.2.0+incompatible github.com/Azure/go-autorest/autorest v0.9.2 - github.com/Azure/go-autorest/autorest/adal v0.8.1-0.20191028180845-3492b2aff503 github.com/Unknwon/com v0.0.0-20151008135407-28b053d5a292 // indirect github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af // indirect github.com/agext/levenshtein v1.2.2 @@ -86,7 +85,6 @@ require ( github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba // indirect github.com/lib/pq v1.0.0 github.com/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82 - github.com/marstr/guid v1.1.0 // indirect github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b github.com/mattn/go-colorable v0.1.1 github.com/mattn/go-shellwords v1.0.4 diff --git a/go.sum b/go.sum index 4508c73528..57054a77c3 100644 --- a/go.sum +++ b/go.sum @@ -7,14 +7,9 @@ cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -github.com/Azure/azure-sdk-for-go v21.3.0+incompatible h1:YFvAka2WKAl2xnJkYV1e1b7E2z88AgFszDzWU18ejMY= -github.com/Azure/azure-sdk-for-go v21.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v36.2.0+incompatible h1:09cv2WoH0g6jl6m2iT+R9qcIPZKhXEL0sbmLhxP895s= github.com/Azure/azure-sdk-for-go v36.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-autorest v10.15.4+incompatible h1:q+DRrRdbCnkY7f2WxQBx58TwCGkEdMAK/hkZ10g0Pzk= -github.com/Azure/go-autorest v10.15.4+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v13.3.0+incompatible h1:8Ix0VdeOllBx9jEcZ2Wb1uqWUpE1awmJiaHztwaJCPk= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.2 h1:6AWuh3uWrsZJcNoCHrCF/+g4aKPCU39kaMO6/qrnK/4= github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= @@ -30,6 +25,7 @@ github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSW github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8= github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= @@ -121,8 +117,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dimchansky/utfbom v1.0.0 h1:fGC2kkf4qOoKqZ4q7iIh+Vef4ubC1c38UDsEyZynZPc= -github.com/dimchansky/utfbom v1.0.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31 h1:Dzuw9GtbmllUqEcoHfScT9YpKFUssSiZ5PgZkIGf/YQ= @@ -199,8 +193,6 @@ github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089/go.mod h1:mFrjN1m github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-azure-helpers v0.0.0-20190129193224-166dfd221bb2 h1:VBRx+yPYUZaobnn5ANBcOUf4hhWpTHSQgftG4TcDkhI= -github.com/hashicorp/go-azure-helpers v0.0.0-20190129193224-166dfd221bb2/go.mod h1:lu62V//auUow6k0IykxLK2DCNW8qTmpm8KqhYVWattA= github.com/hashicorp/go-azure-helpers v0.10.0 h1:KhjDnQhCqEMKlt4yH00MCevJQPJ6LkHFdSveXINO6vE= github.com/hashicorp/go-azure-helpers v0.10.0/go.mod h1:YuAtHxm2v74s+IjQwUG88dHBJPd5jL+cXr5BGVzSKhE= github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= @@ -301,8 +293,6 @@ github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82 h1:wnfcqULT+N2seWf6y4yHzmi7GD2kNx4Ute0qArktD48= github.com/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82/go.mod h1:y54tfGmO3NKssKveTEFFzH8C/akrSOy/iW9qEAUDV84= -github.com/marstr/guid v1.1.0 h1:/M4H/1G4avsieL6BbUwCOBzulmoeKVP5ux/3mQNnbyI= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9 h1:SmVbOZFWAlyQshuMfOkiAx1f5oUTsOGG5IXplAEYeeM= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b h1:/1RFh2SLCJ+tEnT73+Fh5R2AO89sQqs8ba7o+hx1G0Y= @@ -442,7 +432,6 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/helper/logging/indent.go b/helper/logging/indent.go new file mode 100644 index 0000000000..e0da0d7c73 --- /dev/null +++ b/helper/logging/indent.go @@ -0,0 +1,23 @@ +package logging + +import ( + "strings" +) + +// Indent adds two spaces to the beginning of each line of the given string, +// with the goal of making the log level filter understand it as a line +// continuation rather than possibly as new log lines. +func Indent(s string) string { + var b strings.Builder + for len(s) > 0 { + end := strings.IndexByte(s, '\n') + if end == -1 { + end = len(s) - 1 + } + var l string + l, s = s[:end+1], s[end+1:] + b.WriteString(" ") + b.WriteString(l) + } + return b.String() +} diff --git a/helper/logging/indent_test.go b/helper/logging/indent_test.go new file mode 100644 index 0000000000..46b12a42ca --- /dev/null +++ b/helper/logging/indent_test.go @@ -0,0 +1,15 @@ +package logging + +import ( + "testing" +) + +func TestIndent(t *testing.T) { + s := "hello\n world\ngoodbye\n moon" + got := Indent(s) + want := " hello\n world\n goodbye\n moon" + + if got != want { + t.Errorf("wrong result\ngot:\n%s\n\nwant:\n%s", got, want) + } +} diff --git a/helper/logging/level.go b/helper/logging/level.go new file mode 100644 index 0000000000..2c173a626a --- /dev/null +++ b/helper/logging/level.go @@ -0,0 +1,144 @@ +package logging + +import ( + "bytes" + "io" + "sync" +) + +// LogLevel is a special string, conventionally written all in uppercase, that +// can be used to mark a log line for filtering and to specify filtering +// levels in the LevelFilter type. +type LogLevel string + +// LevelFilter is an io.Writer that can be used with a logger that +// will attempt to filter out log messages that aren't at least a certain +// level. +// +// This filtering is HEURISTIC-BASED, and so will not be 100% reliable. The +// assumptions it makes are: +// +// - Individual log messages are never split across multiple calls to the +// Write method. +// +// - Messages that carry levels are marked by a sequence starting with "[", +// then the level name string, and then "]". Any message without a sequence +// like this is an un-levelled message, and is not subject to filtering. +// +// - Each \n-delimited line in a write is a separate log message, unless a +// line starts with at least one space in which case it is interpreted +// as a continuation of the previous line. +// +// Because logging is a cross-cutting concern and not fully under the control +// of Terraform itself, there will certainly be cases where the above +// heuristics will fail. For example, it is likely that LevelFilter will +// occasionally misinterpret a continuation line as a new message because the +// code generating it doesn't know about our indentation convention. +// +// Our goal here is just to make a best effort to reduce the log volume, +// accepting that the results will not be 100% correct. +// +// Logging calls within Terraform Core should follow the above conventions so +// that the log output is broadly correct, however. +// +// Once the filter is in use somewhere, it is not safe to modify +// the structure. +type LevelFilter struct { + // Levels is the list of log levels, in increasing order of + // severity. Example might be: {"DEBUG", "WARN", "ERROR"}. + Levels []LogLevel + + // MinLevel is the minimum level allowed through + MinLevel LogLevel + + // The underlying io.Writer where log messages that pass the filter + // will be set. + Writer io.Writer + + badLevels map[LogLevel]struct{} + once sync.Once +} + +// Check will check a given line if it would be included in the level +// filter. +func (f *LevelFilter) Check(line []byte) bool { + f.once.Do(f.init) + + // Check for a log level + var level LogLevel + x := bytes.IndexByte(line, '[') + if x >= 0 { + y := bytes.IndexByte(line[x:], ']') + if y >= 0 { + level = LogLevel(line[x+1 : x+y]) + } + } + + //return level == "" + + _, ok := f.badLevels[level] + return !ok +} + +// Write is a specialized implementation of io.Writer suitable for being +// the output of a logger from the "log" package. +// +// This Writer implementation assumes that it will only recieve byte slices +// containing one or more entire lines of log output, each one terminated by +// a newline. This is compatible with the behavior of the "log" package +// directly, and is also tolerant of intermediaries that might buffer multiple +// separate writes together, as long as no individual log line is ever +// split into multiple slices. +// +// Behavior is undefined if any log line is split across multiple writes or +// written without a trailing '\n' delimiter. +func (f *LevelFilter) Write(p []byte) (n int, err error) { + show := true + for len(p) > 0 { + // Split at the first \n, inclusive + idx := bytes.IndexByte(p, '\n') + if idx == -1 { + // Invalid, undelimited write + break + } + var l []byte + l, p = p[:idx+1], p[idx+1:] + // Lines starting with whitespace are continuations, so they inherit + // the result of the check of the previous line. + if !(l[0] == ' ' || l[0] == '\t' || l[0] == '\n') { + show = f.Check(l) + } + if show { + _, err = f.Writer.Write(l) + if err != nil { + // Technically it's not correct to say we've written the whole + // buffer, but for our purposes here it's good enough as we're + // only implementing io.Writer enough to satisfy logging + // use-cases. + return len(p), err + } + } + } + + // We always behave as if we wrote the whole of the buffer, even if + // we actually skipped some lines. We're only implementiong io.Writer + // enough to satisfy logging use-cases. + return len(p), nil +} + +// SetMinLevel is used to update the minimum log level +func (f *LevelFilter) SetMinLevel(min LogLevel) { + f.MinLevel = min + f.init() +} + +func (f *LevelFilter) init() { + badLevels := make(map[LogLevel]struct{}) + for _, level := range f.Levels { + if level == f.MinLevel { + break + } + badLevels[level] = struct{}{} + } + f.badLevels = badLevels +} diff --git a/helper/logging/level_test.go b/helper/logging/level_test.go new file mode 100644 index 0000000000..12cade3140 --- /dev/null +++ b/helper/logging/level_test.go @@ -0,0 +1,93 @@ +package logging + +import ( + "bytes" + "io" + "log" + "testing" +) + +func TestLevelFilter_impl(t *testing.T) { + var _ io.Writer = new(LevelFilter) +} + +func TestLevelFilter(t *testing.T) { + buf := new(bytes.Buffer) + filter := &LevelFilter{ + Levels: []LogLevel{"DEBUG", "WARN", "ERROR"}, + MinLevel: "WARN", + Writer: buf, + } + + logger := log.New(filter, "", 0) + logger.Print("[WARN] foo") + logger.Println("[ERROR] bar\n[DEBUG] buzz") + logger.Println("[DEBUG] baz\n continuation\n[WARN] buzz\n more\n[DEBUG] fizz") + + result := buf.String() + expected := "[WARN] foo\n[ERROR] bar\n[WARN] buzz\n more\n" + if result != expected { + t.Fatalf("wrong result\ngot:\n%s\nwant:\n%s", result, expected) + } +} + +func TestLevelFilterCheck(t *testing.T) { + filter := &LevelFilter{ + Levels: []LogLevel{"DEBUG", "WARN", "ERROR"}, + MinLevel: "WARN", + Writer: nil, + } + + testCases := []struct { + line string + check bool + }{ + {"[WARN] foo\n", true}, + {"[ERROR] bar\n", true}, + {"[DEBUG] baz\n", false}, + {"[WARN] buzz\n", true}, + } + + for _, testCase := range testCases { + result := filter.Check([]byte(testCase.line)) + if result != testCase.check { + t.Errorf("Fail: %s", testCase.line) + } + } +} + +func TestLevelFilter_SetMinLevel(t *testing.T) { + filter := &LevelFilter{ + Levels: []LogLevel{"DEBUG", "WARN", "ERROR"}, + MinLevel: "ERROR", + Writer: nil, + } + + testCases := []struct { + line string + checkBefore bool + checkAfter bool + }{ + {"[WARN] foo\n", false, true}, + {"[ERROR] bar\n", true, true}, + {"[DEBUG] baz\n", false, false}, + {"[WARN] buzz\n", false, true}, + } + + for _, testCase := range testCases { + result := filter.Check([]byte(testCase.line)) + if result != testCase.checkBefore { + t.Errorf("Fail: %s", testCase.line) + } + } + + // Update the minimum level to WARN + filter.SetMinLevel("WARN") + + for _, testCase := range testCases { + result := filter.Check([]byte(testCase.line)) + if result != testCase.checkAfter { + t.Errorf("Fail: %s", testCase.line) + } + } +} diff --git a/helper/logging/logging.go b/helper/logging/logging.go index 6bd92f7778..e2913fa2be 100644 --- a/helper/logging/logging.go +++ b/helper/logging/logging.go @@ -7,8 +7,6 @@ import ( "os" "strings" "syscall" - - "github.com/hashicorp/logutils" ) // These are the environmental variables that determine if we log, and if @@ -18,13 +16,14 @@ const ( EnvLogFile = "TF_LOG_PATH" // Set to a file ) -var ValidLevels = []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERROR"} +// ValidLevels are the log level names that Terraform recognizes. +var ValidLevels = []LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERROR"} // LogOutput determines where we should send logs (if anywhere) and the log level. func LogOutput() (logOutput io.Writer, err error) { logOutput = ioutil.Discard - logLevel := LogLevel() + logLevel := CurrentLogLevel() if logLevel == "" { return } @@ -39,9 +38,9 @@ func LogOutput() (logOutput io.Writer, err error) { } // This was the default since the beginning - logOutput = &logutils.LevelFilter{ + logOutput = &LevelFilter{ Levels: ValidLevels, - MinLevel: logutils.LogLevel(logLevel), + MinLevel: LogLevel(logLevel), Writer: logOutput, } @@ -64,8 +63,8 @@ func SetOutput() { log.SetOutput(out) } -// LogLevel returns the current log level string based the environment vars -func LogLevel() string { +// CurrentLogLevel returns the current log level string based the environment vars +func CurrentLogLevel() string { envLevel := os.Getenv(EnvLog) if envLevel == "" { return "" @@ -85,7 +84,7 @@ func LogLevel() string { // IsDebugOrHigher returns whether or not the current log level is debug or trace func IsDebugOrHigher() bool { - level := string(LogLevel()) + level := string(CurrentLogLevel()) return level == "DEBUG" || level == "TRACE" } diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 26ea72a8df..0e5af09334 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -18,7 +18,6 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/hashicorp/errwrap" "github.com/hashicorp/go-multierror" - "github.com/hashicorp/logutils" "github.com/mitchellh/colorstring" "github.com/hashicorp/terraform/addrs" @@ -396,7 +395,7 @@ const EnvLogPathMask = "TF_LOG_PATH_MASK" func LogOutput(t TestT) (logOutput io.Writer, err error) { logOutput = ioutil.Discard - logLevel := logging.LogLevel() + logLevel := logging.CurrentLogLevel() if logLevel == "" { return } @@ -424,9 +423,9 @@ func LogOutput(t TestT) (logOutput io.Writer, err error) { } // This was the default since the beginning - logOutput = &logutils.LevelFilter{ + logOutput = &logging.LevelFilter{ Levels: logging.ValidLevels, - MinLevel: logutils.LogLevel(logLevel), + MinLevel: logging.LogLevel(logLevel), Writer: logOutput, } diff --git a/terraform/graph_builder.go b/terraform/graph_builder.go index 66b21f300d..71b71b7528 100644 --- a/terraform/graph_builder.go +++ b/terraform/graph_builder.go @@ -5,9 +5,9 @@ import ( "log" "strings" - "github.com/hashicorp/terraform/tfdiags" - "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/helper/logging" + "github.com/hashicorp/terraform/tfdiags" ) // GraphBuilder is an interface that can be implemented and used with @@ -56,7 +56,7 @@ func (b *BasicGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Di debugOp.End(errMsg) if thisStepStr := g.StringWithNodeTypes(); thisStepStr != lastStepStr { - log.Printf("[TRACE] Completed graph transform %T with new graph:\n%s------", step, thisStepStr) + log.Printf("[TRACE] Completed graph transform %T with new graph:\n%s ------", step, logging.Indent(thisStepStr)) lastStepStr = thisStepStr } else { log.Printf("[TRACE] Completed graph transform %T (no changes)", step) diff --git a/terraform/transform.go b/terraform/transform.go index fd3f5c7daa..d587c89e49 100644 --- a/terraform/transform.go +++ b/terraform/transform.go @@ -4,6 +4,7 @@ import ( "log" "github.com/hashicorp/terraform/dag" + "github.com/hashicorp/terraform/helper/logging" ) // GraphTransformer is the interface that transformers implement. This @@ -45,7 +46,7 @@ func (t *graphTransformerMulti) Transform(g *Graph) error { return err } if thisStepStr := g.StringWithNodeTypes(); thisStepStr != lastStepStr { - log.Printf("[TRACE] (graphTransformerMulti) Completed graph transform %T with new graph:\n%s------", t, thisStepStr) + log.Printf("[TRACE] (graphTransformerMulti) Completed graph transform %T with new graph:\n%s ------", t, logging.Indent(thisStepStr)) lastStepStr = thisStepStr } else { log.Printf("[TRACE] (graphTransformerMulti) Completed graph transform %T (no changes)", t) From faffb3a7848f86dd7ef041a244140918584e4e5a Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 5 Dec 2019 11:49:11 -0800 Subject: [PATCH 08/19] helper/logging: Warn about levels other than TRACE The filtering for other log levels is unreliable and glitchy because it's trying to infer information from the log stream that isn't reliably represented. Although the previous commit has improved the situation somewhat, it is still a tricky and unreliable heuristic, so worth a warning to anyone who is reading such a log that if they see something confusing it could be a result of the heuristic not working fully. --- helper/logging/logging.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/helper/logging/logging.go b/helper/logging/logging.go index e2913fa2be..f5a0ba47fe 100644 --- a/helper/logging/logging.go +++ b/helper/logging/logging.go @@ -78,6 +78,9 @@ func CurrentLogLevel() string { log.Printf("[WARN] Invalid log level: %q. Defaulting to level: TRACE. Valid levels are: %+v", envLevel, ValidLevels) } + if logLevel != "TRACE" { + log.Printf("[WARN] Log levels other than TRACE are currently unreliable, and are supported only for backward compatibility.\n Use TF_LOG=TRACE to see Terraform's internal logs.\n ----") + } return logLevel } From 97d64581c613dd899f59d6753e92033e7cf09b40 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 5 Dec 2019 12:19:22 -0800 Subject: [PATCH 09/19] helper/logging: Loosen the filtering heuristic even more Now we'll consider any message that doesn't start with a digit as a continuation. This is _definitely_ in loose, best-effort territory now since a continuation line could very well start with a digit, but ultimately this is still better than the totally broken behavior that preceded it. Just to make sure that none of these heuristics interfere with producing complete, accurate logs for TRACE, we'll skip the LevelFilter altogether in that case. --- helper/logging/level.go | 29 ++++++++++++++++++++++------- helper/logging/level_test.go | 8 ++++---- helper/logging/logging.go | 11 +++++++++-- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/helper/logging/level.go b/helper/logging/level.go index 2c173a626a..0dc4dfe8d5 100644 --- a/helper/logging/level.go +++ b/helper/logging/level.go @@ -29,6 +29,14 @@ type LogLevel string // line starts with at least one space in which case it is interpreted // as a continuation of the previous line. // +// - If a log line starts with a non-whitespace character that isn't a digit +// then it's recognized as a degenerate continuation, because "real" log +// lines should start with a date/time and thus always have a leading +// digit. (This also cleans up after some situations where the assumptuion +// that messages arrive atomically aren't met, which is sadly sometimes +// true for longer messages that trip over some buffering behavior in +// panicwrap.) +// // Because logging is a cross-cutting concern and not fully under the control // of Terraform itself, there will certainly be cases where the above // heuristics will fail. For example, it is likely that LevelFilter will @@ -56,6 +64,7 @@ type LevelFilter struct { Writer io.Writer badLevels map[LogLevel]struct{} + show bool once sync.Once } @@ -93,22 +102,27 @@ func (f *LevelFilter) Check(line []byte) bool { // Behavior is undefined if any log line is split across multiple writes or // written without a trailing '\n' delimiter. func (f *LevelFilter) Write(p []byte) (n int, err error) { - show := true for len(p) > 0 { // Split at the first \n, inclusive idx := bytes.IndexByte(p, '\n') if idx == -1 { - // Invalid, undelimited write + // Invalid, undelimited write. We'll tolerate it assuming that + // our assumptions are being violated, but the results may be + // non-ideal. + idx = len(p) - 1 break } var l []byte l, p = p[:idx+1], p[idx+1:] - // Lines starting with whitespace are continuations, so they inherit - // the result of the check of the previous line. - if !(l[0] == ' ' || l[0] == '\t' || l[0] == '\n') { - show = f.Check(l) + // Lines starting with characters other than decimal digits (including + // whitespace) are assumed to be continuations lines. This is an + // imprecise heuristic, but experimentally it seems to generate + // "good enough" results from Terraform Core's own logging. Its mileage + // may vary with output from other systems. + if l[0] >= '0' && l[0] <= '9' { + f.show = f.Check(l) } - if show { + if f.show { _, err = f.Writer.Write(l) if err != nil { // Technically it's not correct to say we've written the whole @@ -141,4 +155,5 @@ func (f *LevelFilter) init() { badLevels[level] = struct{}{} } f.badLevels = badLevels + f.show = true } diff --git a/helper/logging/level_test.go b/helper/logging/level_test.go index 12cade3140..baa94748e4 100644 --- a/helper/logging/level_test.go +++ b/helper/logging/level_test.go @@ -20,12 +20,12 @@ func TestLevelFilter(t *testing.T) { } logger := log.New(filter, "", 0) - logger.Print("[WARN] foo") - logger.Println("[ERROR] bar\n[DEBUG] buzz") - logger.Println("[DEBUG] baz\n continuation\n[WARN] buzz\n more\n[DEBUG] fizz") + logger.Print("2019/01/01 00:00:00 [WARN] foo") + logger.Println("2019/01/01 00:00:00 [ERROR] bar\n2019/01/01 00:00:00 [DEBUG] buzz") + logger.Println("2019/01/01 00:00:00 [DEBUG] baz\n continuation\n2019/01/01 00:00:00 [WARN] buzz\n more\n2019/01/01 00:00:00 [DEBUG] fizz") result := buf.String() - expected := "[WARN] foo\n[ERROR] bar\n[WARN] buzz\n more\n" + expected := "2019/01/01 00:00:00 [WARN] foo\n2019/01/01 00:00:00 [ERROR] bar\n2019/01/01 00:00:00 [WARN] buzz\n more\n" if result != expected { t.Fatalf("wrong result\ngot:\n%s\nwant:\n%s", result, expected) } diff --git a/helper/logging/logging.go b/helper/logging/logging.go index f5a0ba47fe..75627cf02e 100644 --- a/helper/logging/logging.go +++ b/helper/logging/logging.go @@ -37,14 +37,21 @@ func LogOutput() (logOutput io.Writer, err error) { } } - // This was the default since the beginning + if logLevel == "TRACE" { + // Just pass through logs directly then, without any level filtering at all. + return logOutput, nil + } + + // Otherwise we'll use our level filter, which is a heuristic-based + // best effort thing that is not totally reliable but helps to reduce + // the volume of logs in some cases. logOutput = &LevelFilter{ Levels: ValidLevels, MinLevel: LogLevel(logLevel), Writer: logOutput, } - return + return logOutput, nil } // SetOutput checks for a log destination with LogOutput, and calls From 28850a3f1dd9c49019c11d129c9ea0eca50849bc Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 5 Dec 2019 15:27:29 -0800 Subject: [PATCH 10/19] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc525edca..7d6fcf0e0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,15 @@ UPGRADE NOTES: -* provisioners: Referencing values outside of a resource's own state is being deprecated for destroy provisioners [GH-23559] +* Inside `provisioner` blocks that have `when = destroy` set, and inside any `connection` blocks that are used by such provisioner blocks, it is now deprecated to refer to any objects other than `self`, `count`, and `each`. + + Terraform has historically allowed this but doing so tends to cause downstream problems with dependency cycles or incorrect destroy ordering because it causes the destroy phase of one resource to depend on the existing state of another. Although this is currently only a warning, we strongly suggest seeking alternative approaches for existing configurations that are hitting this warning in order to avoid the risk of later problems should you need to replace or destroy the related resources. + + This deprecation warning will be promoted to an error in a future release. + +ENHANCEMENTS: + +* provisioners: Warn about the deprecation of non-self references in destroy-time provisioners, both to allow preparation for this later becoming an error and also as an extra hint for the "Cycle" errors that commonly arise when such references are used. [GH-23559] BUG FIXES: From 161e6d6dbfdf3bc0d347bb309dc012481140f306 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Thu, 5 Dec 2019 15:29:14 -0800 Subject: [PATCH 11/19] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d6fcf0e0e..5f62ef78c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ ENHANCEMENTS: BUG FIXES: * cli: Allow moving indexed resource instances to new addresses that that don't yet exist in state [GH-23582] +* cli: Improved heuristics for log level filtering with the `TF_LOG` environment variable, although it is still not 100% reliable for levels other than `TRACE` due to limitations of Terraform's internal logging infrastructure. Because of that, levels other than `TRACE` will now cause the logs to begin with a warning about potential filtering inaccuracy. [GH-23577] * config: Fixed referencing errors generally involving `for_each` [GH-23475] * provisioners: The built-in provisioners (`local-exec`, `remote-exec`, `file`, etc) will no longer fail when the `TF_CLI_ARGS` environment variable is set. [GH-17400] From c355fbd67c3c60d757120ef795c8e5f52609d5ec Mon Sep 17 00:00:00 2001 From: cgriggs01 Date: Thu, 5 Dec 2019 16:29:01 -0800 Subject: [PATCH 12/19] add stackpath links --- website/docs/providers/index.html.markdown | 1 + website/docs/providers/type/cloud-index.html.markdown | 1 + 2 files changed, 2 insertions(+) diff --git a/website/docs/providers/index.html.markdown b/website/docs/providers/index.html.markdown index 1b46aac501..22df0d3154 100644 --- a/website/docs/providers/index.html.markdown +++ b/website/docs/providers/index.html.markdown @@ -125,6 +125,7 @@ down to see all providers. - [Skytap](/docs/providers/skytap/index.html) - [SoftLayer](/docs/providers/softlayer/index.html) - [Spotinst](/docs/providers/spotinst/index.html) +- [StackPath](/docs/providers/stackpath/index.html) - [StatusCake](/docs/providers/statuscake/index.html) - [TelefonicaOpenCloud](/docs/providers/telefonicaopencloud/index.html) - [Template](/docs/providers/template/index.html) diff --git a/website/docs/providers/type/cloud-index.html.markdown b/website/docs/providers/type/cloud-index.html.markdown index 01cc7faebd..62651972b8 100644 --- a/website/docs/providers/type/cloud-index.html.markdown +++ b/website/docs/providers/type/cloud-index.html.markdown @@ -48,6 +48,7 @@ vendor in close collaboration with HashiCorp, and are tested by HashiCorp. - [Skytap](/docs/providers/skytap/index.html) - [Selectel](/docs/providers/selectel/index.html) - [SoftLayer](/docs/providers/softlayer/index.html) +- [StackPath](/docs/providers/stackpath/index.html) - [TelefonicaOpenCloud](/docs/providers/telefonicaopencloud/index.html) - [TencentCloud](/docs/providers/tencentcloud/index.html) - [Triton](/docs/providers/triton/index.html) From e3416124ccdd8d78e90e25b49ff396a15777baf4 Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Fri, 6 Dec 2019 08:00:18 -0500 Subject: [PATCH 13/19] addrs: replace "Type string" with "Type Provider" in ProviderConfig * huge change to weave new addrs.Provider into addrs.ProviderConfig * terraform: do not include an empty string in the returned Providers / Provisioners - Fixed a minor bug where results included an extra empty string --- addrs/provider.go | 4 +- addrs/provider_config.go | 22 ++++----- addrs/provider_config_test.go | 18 +++---- addrs/resource.go | 3 +- backend/local/backend_plan.go | 2 +- backend/local/backend_plan_test.go | 10 ++-- backend/testing.go | 2 +- command/apply_destroy_test.go | 8 ++-- command/apply_test.go | 8 ++-- command/command_test.go | 2 +- command/format/diff_test.go | 2 +- command/format/state_test.go | 14 +++--- command/graph_test.go | 2 +- command/jsonconfig/config.go | 2 +- command/jsonplan/plan.go | 2 +- command/jsonplan/values.go | 2 +- command/jsonplan/values_test.go | 2 +- command/jsonstate/state.go | 2 +- command/jsonstate/state_test.go | 6 +-- command/plan_test.go | 4 +- command/show_test.go | 2 +- command/state_mv_test.go | 46 +++++++++--------- command/state_rm_test.go | 24 +++++----- command/state_show_test.go | 6 +-- command/taint_test.go | 12 ++--- command/untaint_test.go | 12 ++--- command/workspace_command_test.go | 2 +- configs/config.go | 4 +- configs/provider.go | 2 +- configs/resource.go | 4 +- helper/resource/state_shim.go | 2 +- helper/resource/state_shim_test.go | 16 +++---- helper/resource/testing.go | 2 +- helper/resource/testing_import_state.go | 2 +- plans/plan_test.go | 10 ++-- plans/planfile/tfplan_test.go | 6 +-- providers/addressed_types.go | 4 +- providers/addressed_types_test.go | 20 ++++---- repl/session_test.go | 4 +- states/state_test.go | 8 ++-- terraform/context_apply_test.go | 52 ++++++++++----------- terraform/context_components.go | 5 +- terraform/context_import_test.go | 6 +-- terraform/context_input.go | 2 +- terraform/context_input_test.go | 2 +- terraform/context_plan_test.go | 2 +- terraform/context_refresh_test.go | 10 ++-- terraform/eval_context_builtin.go | 2 +- terraform/eval_context_builtin_test.go | 6 +-- terraform/eval_diff.go | 4 +- terraform/eval_provider.go | 2 +- terraform/eval_provider_test.go | 8 ++-- terraform/eval_state.go | 2 +- terraform/evaltree_provider.go | 2 +- terraform/evaluate.go | 2 +- terraform/evaluate_valid.go | 2 +- terraform/graph_builder_apply_test.go | 4 +- terraform/node_data_refresh_test.go | 4 +- terraform/node_provider_eval.go | 2 +- terraform/node_resource_plan_destroy.go | 2 +- terraform/transform_attach_schema.go | 4 +- terraform/transform_diff_test.go | 2 +- terraform/transform_import_state.go | 2 +- terraform/transform_orphan_count_test.go | 4 +- terraform/transform_orphan_resource_test.go | 16 +++---- terraform/transform_provider.go | 4 +- terraform/transform_provisioner_test.go | 4 +- 67 files changed, 232 insertions(+), 230 deletions(-) diff --git a/addrs/provider.go b/addrs/provider.go index 04fb731bd4..b73cfb5a7f 100644 --- a/addrs/provider.go +++ b/addrs/provider.go @@ -1,6 +1,8 @@ package addrs -import svchost "github.com/hashicorp/terraform-svchost" +import ( + svchost "github.com/hashicorp/terraform-svchost" +) // Provider encapsulates a single provider type. In the future this will be // extended to include additional fields including Namespace and SourceHost diff --git a/addrs/provider_config.go b/addrs/provider_config.go index aaef1d3a4b..6413ed9cfb 100644 --- a/addrs/provider_config.go +++ b/addrs/provider_config.go @@ -11,7 +11,7 @@ import ( // ProviderConfig is the address of a provider configuration. type ProviderConfig struct { - Type string + Type Provider // If not empty, Alias identifies which non-default (aliased) provider // configuration this address refers to. @@ -22,7 +22,7 @@ type ProviderConfig struct { // configuration for the provider with the given type name. func NewDefaultProviderConfig(typeName string) ProviderConfig { return ProviderConfig{ - Type: typeName, + Type: NewLegacyProvider(typeName), } } @@ -41,7 +41,7 @@ func NewDefaultProviderConfig(typeName string) ProviderConfig { func ParseProviderConfigCompact(traversal hcl.Traversal) (ProviderConfig, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics ret := ProviderConfig{ - Type: traversal.RootName(), + Type: NewLegacyProvider(traversal.RootName()), } if len(traversal) < 2 { @@ -114,25 +114,25 @@ func (pc ProviderConfig) Absolute(module ModuleInstance) AbsProviderConfig { } func (pc ProviderConfig) String() string { - if pc.Type == "" { + if pc.Type.LegacyString() == "" { // Should never happen; always indicates a bug return "provider." } if pc.Alias != "" { - return fmt.Sprintf("provider.%s.%s", pc.Type, pc.Alias) + return fmt.Sprintf("provider.%s.%s", pc.Type.LegacyString(), pc.Alias) } - return "provider." + pc.Type + return "provider." + pc.Type.LegacyString() } // StringCompact is an alternative to String that returns the form that can // be parsed by ParseProviderConfigCompact, without the "provider." prefix. func (pc ProviderConfig) StringCompact() string { if pc.Alias != "" { - return fmt.Sprintf("%s.%s", pc.Type, pc.Alias) + return fmt.Sprintf("%s.%s", pc.Type.LegacyString(), pc.Alias) } - return pc.Type + return pc.Type.LegacyString() } // AbsProviderConfig is the absolute address of a provider configuration @@ -181,7 +181,7 @@ func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags } if tt, ok := remain[1].(hcl.TraverseAttr); ok { - ret.ProviderConfig.Type = tt.Name + ret.ProviderConfig.Type = NewLegacyProvider(tt.Name) } else { diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, @@ -244,7 +244,7 @@ func (m ModuleInstance) ProviderConfigDefault(name string) AbsProviderConfig { return AbsProviderConfig{ Module: m, ProviderConfig: ProviderConfig{ - Type: name, + Type: NewLegacyProvider(name), }, } } @@ -255,7 +255,7 @@ func (m ModuleInstance) ProviderConfigAliased(name, alias string) AbsProviderCon return AbsProviderConfig{ Module: m, ProviderConfig: ProviderConfig{ - Type: name, + Type: NewLegacyProvider(name), Alias: alias, }, } diff --git a/addrs/provider_config_test.go b/addrs/provider_config_test.go index 1d92a83489..756fa0bb16 100644 --- a/addrs/provider_config_test.go +++ b/addrs/provider_config_test.go @@ -18,14 +18,14 @@ func TestParseProviderConfigCompact(t *testing.T) { { `aws`, ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), }, ``, }, { `aws.foo`, ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), Alias: "foo", }, ``, @@ -82,7 +82,7 @@ func TestParseAbsProviderConfig(t *testing.T) { AbsProviderConfig{ Module: RootModuleInstance, ProviderConfig: ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), }, }, ``, @@ -92,7 +92,7 @@ func TestParseAbsProviderConfig(t *testing.T) { AbsProviderConfig{ Module: RootModuleInstance, ProviderConfig: ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), Alias: "foo", }, }, @@ -107,7 +107,7 @@ func TestParseAbsProviderConfig(t *testing.T) { }, }, ProviderConfig: ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), }, }, ``, @@ -121,7 +121,7 @@ func TestParseAbsProviderConfig(t *testing.T) { }, }, ProviderConfig: ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), Alias: "foo", }, }, @@ -137,7 +137,7 @@ func TestParseAbsProviderConfig(t *testing.T) { }, }, ProviderConfig: ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), }, }, ``, @@ -152,7 +152,7 @@ func TestParseAbsProviderConfig(t *testing.T) { }, }, ProviderConfig: ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), }, }, ``, @@ -170,7 +170,7 @@ func TestParseAbsProviderConfig(t *testing.T) { }, }, ProviderConfig: ProviderConfig{ - Type: "aws", + Type: NewLegacyProvider("aws"), }, }, ``, diff --git a/addrs/resource.go b/addrs/resource.go index b075a6d1d2..bb4831ea6c 100644 --- a/addrs/resource.go +++ b/addrs/resource.go @@ -65,8 +65,9 @@ func (r Resource) DefaultProviderConfig() ProviderConfig { if under := strings.Index(typeName, "_"); under != -1 { typeName = typeName[:under] } + return ProviderConfig{ - Type: typeName, + Type: NewLegacyProvider(typeName), } } diff --git a/backend/local/backend_plan.go b/backend/local/backend_plan.go index ed51acc986..089453f1dc 100644 --- a/backend/local/backend_plan.go +++ b/backend/local/backend_plan.go @@ -262,7 +262,7 @@ func RenderPlan(plan *plans.Plan, state *states.State, schemas *terraform.Schema if rcs.Action == plans.NoOp { continue } - providerSchema := schemas.ProviderSchema(rcs.ProviderAddr.ProviderConfig.Type) + providerSchema := schemas.ProviderSchema(rcs.ProviderAddr.ProviderConfig.Type.LegacyString()) if providerSchema == nil { // Should never happen ui.Output(fmt.Sprintf("(schema missing for %s)\n", rcs.ProviderAddr)) diff --git a/backend/local/backend_plan_test.go b/backend/local/backend_plan_test.go index 1aa4183a90..898a735fe4 100644 --- a/backend/local/backend_plan_test.go +++ b/backend/local/backend_plan_test.go @@ -216,7 +216,7 @@ func TestLocal_planDeposedOnly(t *testing.T) { }`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) })) @@ -659,7 +659,7 @@ func testPlanState() *states.State { }`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state @@ -685,7 +685,7 @@ func testPlanState_withDataSource() *states.State { }`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) rootModule.SetResourceInstanceCurrent( @@ -701,7 +701,7 @@ func testPlanState_withDataSource() *states.State { }`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state @@ -727,7 +727,7 @@ func testPlanState_tainted() *states.State { }`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state diff --git a/backend/testing.go b/backend/testing.go index 1fc081db54..c79a138211 100644 --- a/backend/testing.go +++ b/backend/testing.go @@ -151,7 +151,7 @@ func TestBackendStates(t *testing.T, b Backend) { SchemaVersion: 0, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) diff --git a/command/apply_destroy_test.go b/command/apply_destroy_test.go index 3cdf998f71..c77f627507 100644 --- a/command/apply_destroy_test.go +++ b/command/apply_destroy_test.go @@ -29,7 +29,7 @@ func TestApply_destroy(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, originalState) @@ -122,7 +122,7 @@ func TestApply_destroyLockedState(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, originalState) @@ -194,7 +194,7 @@ func TestApply_destroyTargeted(t *testing.T) { AttrsJSON: []byte(`{"id":"i-ab123"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -206,7 +206,7 @@ func TestApply_destroyTargeted(t *testing.T) { AttrsJSON: []byte(`{"id":"i-abc123"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, originalState) diff --git a/command/apply_test.go b/command/apply_test.go index c15718104e..7a31d71300 100644 --- a/command/apply_test.go +++ b/command/apply_test.go @@ -833,7 +833,7 @@ func TestApply_refresh(t *testing.T) { AttrsJSON: []byte(`{"ami":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, originalState) @@ -987,7 +987,7 @@ func TestApply_state(t *testing.T) { AttrsJSON: []byte(`{"ami":"foo"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, originalState) @@ -1351,7 +1351,7 @@ func TestApply_backup(t *testing.T) { AttrsJSON: []byte("{\n \"id\": \"bar\"\n }"), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, originalState) @@ -1652,7 +1652,7 @@ func applyFixturePlanFile(t *testing.T) string { Type: "test_instance", Name: "foo", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + ProviderAddr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: plans.Create, Before: priorValRaw, diff --git a/command/command_test.go b/command/command_test.go index b6c16ea521..9f0fa4381a 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -266,7 +266,7 @@ func testState() *states.State { DependsOn: []addrs.Referenceable{}, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) // DeepCopy is used here to ensure our synthetic state matches exactly diff --git a/command/format/diff_test.go b/command/format/diff_test.go index 96d414cb6b..e1b1d414ad 100644 --- a/command/format/diff_test.go +++ b/command/format/diff_test.go @@ -3157,7 +3157,7 @@ func runTestCases(t *testing.T, testCases map[string]testCase) { Type: "test_instance", Name: "example", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + ProviderAddr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: tc.Action, Before: before, diff --git a/command/format/state_test.go b/command/format/state_test.go index 2b00da9b84..8f64ba9437 100644 --- a/command/format/state_test.go +++ b/command/format/state_test.go @@ -244,7 +244,7 @@ func basicState(t *testing.T) *states.State { AttrsJSON: []byte(`{"woozles":"confuzles"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) rootModule.SetResourceInstanceCurrent( @@ -259,7 +259,7 @@ func basicState(t *testing.T) *states.State { AttrsJSON: []byte(`{"compute":"sure"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state @@ -294,7 +294,7 @@ func stateWithMoreOutputs(t *testing.T) *states.State { AttrsJSON: []byte(`{"woozles":"confuzles"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state @@ -320,7 +320,7 @@ func nestedState(t *testing.T) *states.State { AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state @@ -342,7 +342,7 @@ func deposedState(t *testing.T) *states.State { AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state @@ -370,7 +370,7 @@ func onlyDeposedState(t *testing.T) *states.State { AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) rootModule.SetResourceInstanceDeposed( @@ -386,7 +386,7 @@ func onlyDeposedState(t *testing.T) *states.State { AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) return state diff --git a/command/graph_test.go b/command/graph_test.go index b8712e6036..13c3bd09f8 100644 --- a/command/graph_test.go +++ b/command/graph_test.go @@ -125,7 +125,7 @@ func TestGraph_plan(t *testing.T) { Before: plans.DynamicValue(`{}`), After: plans.DynamicValue(`null`), }, - ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + ProviderAddr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), }) emptyConfig, err := plans.NewDynamicValue(cty.EmptyObjectVal, cty.EmptyObject) if err != nil { diff --git a/command/jsonconfig/config.go b/command/jsonconfig/config.go index 0b27c7af4b..4887ed5871 100644 --- a/command/jsonconfig/config.go +++ b/command/jsonconfig/config.go @@ -302,7 +302,7 @@ func marshalResources(resources map[string]*configs.Resource, schemas *terraform } schema, schemaVer := schemas.ResourceTypeConfig( - v.ProviderConfigAddr().Type, + v.ProviderConfigAddr().Type.LegacyString(), v.Mode, v.Type, ) diff --git a/command/jsonplan/plan.go b/command/jsonplan/plan.go index f1563abef3..2659f6deb4 100644 --- a/command/jsonplan/plan.go +++ b/command/jsonplan/plan.go @@ -178,7 +178,7 @@ func (p *plan) marshalResourceChanges(changes *plans.Changes, schemas *terraform } schema, _ := schemas.ResourceTypeConfig( - rc.ProviderAddr.ProviderConfig.Type, + rc.ProviderAddr.ProviderConfig.Type.LegacyString(), addr.Resource.Resource.Mode, addr.Resource.Resource.Type, ) diff --git a/command/jsonplan/values.go b/command/jsonplan/values.go index caa8babf4f..3a3b8f52ec 100644 --- a/command/jsonplan/values.go +++ b/command/jsonplan/values.go @@ -181,7 +181,7 @@ func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstanc } schema, schemaVer := schemas.ResourceTypeConfig( - r.ProviderAddr.ProviderConfig.Type, + r.ProviderAddr.ProviderConfig.Type.LegacyString(), r.Addr.Resource.Resource.Mode, resource.Type, ) diff --git a/command/jsonplan/values_test.go b/command/jsonplan/values_test.go index 8395ee0aaf..3716e1b4f5 100644 --- a/command/jsonplan/values_test.go +++ b/command/jsonplan/values_test.go @@ -258,7 +258,7 @@ func TestMarshalPlanResources(t *testing.T) { Type: "test_thing", Name: "example", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + ProviderAddr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: test.Action, Before: before, diff --git a/command/jsonstate/state.go b/command/jsonstate/state.go index 2fac8fbba6..99b5bdcc8e 100644 --- a/command/jsonstate/state.go +++ b/command/jsonstate/state.go @@ -274,7 +274,7 @@ func marshalResources(resources map[string]*states.Resource, schemas *terraform. } schema, _ := schemas.ResourceTypeConfig( - r.ProviderConfig.ProviderConfig.Type, + r.ProviderConfig.ProviderConfig.Type.LegacyString(), r.Addr.Mode, r.Addr.Type, ) diff --git a/command/jsonstate/state_test.go b/command/jsonstate/state_test.go index e40c123c66..aee5abe127 100644 --- a/command/jsonstate/state_test.go +++ b/command/jsonstate/state_test.go @@ -202,7 +202,7 @@ func TestMarshalResources(t *testing.T) { }, }, ProviderConfig: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), }, }, @@ -245,7 +245,7 @@ func TestMarshalResources(t *testing.T) { }, }, ProviderConfig: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), }, }, @@ -293,7 +293,7 @@ func TestMarshalResources(t *testing.T) { }, }, ProviderConfig: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), }, }, diff --git a/command/plan_test.go b/command/plan_test.go index 6885810d5c..fdac20f01c 100644 --- a/command/plan_test.go +++ b/command/plan_test.go @@ -124,7 +124,7 @@ func TestPlan_destroy(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) outPath := testTempFile(t) @@ -240,7 +240,7 @@ func TestPlan_outPathNoChange(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","ami":"bar","network_interface":[{"description":"Main network interface","device_index":"0"}]}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, originalState) diff --git a/command/show_test.go b/command/show_test.go index 30da8c5724..9aee9b3142 100644 --- a/command/show_test.go +++ b/command/show_test.go @@ -400,7 +400,7 @@ func showFixturePlanFile(t *testing.T) string { Type: "test_instance", Name: "foo", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + ProviderAddr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: plans.Create, Before: priorValRaw, diff --git a/command/state_mv_test.go b/command/state_mv_test.go index f777d8807e..406afa412c 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -27,7 +27,7 @@ func TestStateMv(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -39,7 +39,7 @@ func TestStateMv(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -87,7 +87,7 @@ func TestStateMv_resourceToInstance(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -99,7 +99,7 @@ func TestStateMv_resourceToInstance(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceMeta( addrs.Resource{ @@ -108,7 +108,7 @@ func TestStateMv_resourceToInstance(t *testing.T) { Name: "bar", }.Absolute(addrs.RootModuleInstance), states.EachList, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -167,7 +167,7 @@ func TestStateMv_instanceToResource(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -179,7 +179,7 @@ func TestStateMv_instanceToResource(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -317,7 +317,7 @@ func TestStateMv_differentResourceTypes(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -367,7 +367,7 @@ func TestStateMv_explicitWithBackend(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -379,7 +379,7 @@ func TestStateMv_explicitWithBackend(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -436,7 +436,7 @@ func TestStateMv_backupExplicit(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -448,7 +448,7 @@ func TestStateMv_backupExplicit(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -494,7 +494,7 @@ func TestStateMv_stateOutNew(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -545,7 +545,7 @@ func TestStateMv_stateOutExisting(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, stateSrc) @@ -561,7 +561,7 @@ func TestStateMv_stateOutExisting(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) stateOutPath := testStateFile(t, stateDst) @@ -638,7 +638,7 @@ func TestStateMv_stateOutNew_count(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -650,7 +650,7 @@ func TestStateMv_stateOutNew_count(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -662,7 +662,7 @@ func TestStateMv_stateOutNew_count(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -717,7 +717,7 @@ func TestStateMv_stateOutNew_largeCount(t *testing.T) { AttrsJSON: []byte(fmt.Sprintf(`{"id":"foo%d","foo":"value","bar":"value"}`, i)), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) } s.SetResourceInstanceCurrent( @@ -730,7 +730,7 @@ func TestStateMv_stateOutNew_largeCount(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -781,7 +781,7 @@ func TestStateMv_stateOutNew_nestedModule(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -793,7 +793,7 @@ func TestStateMv_stateOutNew_nestedModule(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) @@ -845,7 +845,7 @@ func TestStateMv_toNewModule(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) diff --git a/command/state_rm_test.go b/command/state_rm_test.go index a35c247bb3..ed985ff068 100644 --- a/command/state_rm_test.go +++ b/command/state_rm_test.go @@ -25,7 +25,7 @@ func TestStateRm(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -37,7 +37,7 @@ func TestStateRm(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -84,7 +84,7 @@ func TestStateRmNotChildModule(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) // This second instance has the same local address as the first but // is in a child module. Older versions of Terraform would incorrectly @@ -99,7 +99,7 @@ func TestStateRmNotChildModule(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -167,7 +167,7 @@ func TestStateRmNoArgs(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -179,7 +179,7 @@ func TestStateRmNoArgs(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -220,7 +220,7 @@ func TestStateRmNonExist(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -232,7 +232,7 @@ func TestStateRmNonExist(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -274,7 +274,7 @@ func TestStateRm_backupExplicit(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -286,7 +286,7 @@ func TestStateRm_backupExplicit(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -384,7 +384,7 @@ func TestStateRm_backendState(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -396,7 +396,7 @@ func TestStateRm_backendState(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) diff --git a/command/state_show_test.go b/command/state_show_test.go index e1c574e9aa..17f0365419 100644 --- a/command/state_show_test.go +++ b/command/state_show_test.go @@ -24,7 +24,7 @@ func TestStateShow(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -79,7 +79,7 @@ func TestStateShow_multi(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -91,7 +91,7 @@ func TestStateShow_multi(t *testing.T) { AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(submod), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(submod), ) }) statePath := testStateFile(t, state) diff --git a/command/taint_test.go b/command/taint_test.go index bcdb76a9c3..b38317d434 100644 --- a/command/taint_test.go +++ b/command/taint_test.go @@ -24,7 +24,7 @@ func TestTaint(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -59,7 +59,7 @@ func TestTaint_lockedState(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -245,7 +245,7 @@ func TestTaint_missing(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -278,7 +278,7 @@ func TestTaint_missingAllow(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -354,7 +354,7 @@ func TestTaint_module(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -366,7 +366,7 @@ func TestTaint_module(t *testing.T) { AttrsJSON: []byte(`{"id":"blah"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) diff --git a/command/untaint_test.go b/command/untaint_test.go index c5f7275f1b..b568c94570 100644 --- a/command/untaint_test.go +++ b/command/untaint_test.go @@ -23,7 +23,7 @@ func TestUntaint(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectTainted, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -63,7 +63,7 @@ func TestUntaint_lockedState(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectTainted, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -271,7 +271,7 @@ func TestUntaint_missing(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectTainted, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -304,7 +304,7 @@ func TestUntaint_missingAllow(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectTainted, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) @@ -389,7 +389,7 @@ func TestUntaint_module(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectTainted, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( addrs.Resource{ @@ -401,7 +401,7 @@ func TestUntaint_module(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectTainted, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) diff --git a/command/workspace_command_test.go b/command/workspace_command_test.go index ea645e0062..2069486c03 100644 --- a/command/workspace_command_test.go +++ b/command/workspace_command_test.go @@ -241,7 +241,7 @@ func TestWorkspace_createWithState(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) diff --git a/configs/config.go b/configs/config.go index cc10fb9c4c..cde0014c90 100644 --- a/configs/config.go +++ b/configs/config.go @@ -191,11 +191,11 @@ func (c *Config) gatherProviderTypes(m map[string]struct{}) { } for _, rc := range c.Module.ManagedResources { providerAddr := rc.ProviderConfigAddr() - m[providerAddr.Type] = struct{}{} + m[providerAddr.Type.LegacyString()] = struct{}{} } for _, rc := range c.Module.DataResources { providerAddr := rc.ProviderConfigAddr() - m[providerAddr.Type] = struct{}{} + m[providerAddr.Type.LegacyString()] = struct{}{} } // Must also visit our child modules, recursively. diff --git a/configs/provider.go b/configs/provider.go index 17754a669d..169f897bfb 100644 --- a/configs/provider.go +++ b/configs/provider.go @@ -95,7 +95,7 @@ func decodeProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) { // to its containing module. func (p *Provider) Addr() addrs.ProviderConfig { return addrs.ProviderConfig{ - Type: p.Name, + Type: addrs.NewLegacyProvider(p.Name), Alias: p.Alias, } } diff --git a/configs/resource.go b/configs/resource.go index 78f6a240c1..7ca73ff1ac 100644 --- a/configs/resource.go +++ b/configs/resource.go @@ -70,7 +70,7 @@ func (r *Resource) ProviderConfigAddr() addrs.ProviderConfig { } return addrs.ProviderConfig{ - Type: r.ProviderConfigRef.Name, + Type: addrs.NewLegacyProvider(r.ProviderConfigRef.Name), Alias: r.ProviderConfigRef.Alias, } } @@ -447,7 +447,7 @@ func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConf // location information and keeping just the addressing information. func (r *ProviderConfigRef) Addr() addrs.ProviderConfig { return addrs.ProviderConfig{ - Type: r.Name, + Type: addrs.NewLegacyProvider(r.Name), Alias: r.Alias, } } diff --git a/helper/resource/state_shim.go b/helper/resource/state_shim.go index afd60b318a..257109d3b6 100644 --- a/helper/resource/state_shim.go +++ b/helper/resource/state_shim.go @@ -50,7 +50,7 @@ func shimNewState(newState *states.State, providers map[string]terraform.Resourc resType := res.Addr.Type providerType := res.ProviderConfig.ProviderConfig.Type - resource := getResource(providers, providerType, res.Addr) + resource := getResource(providers, providerType.LegacyString(), res.Addr) for key, i := range res.Instances { resState := &terraform.ResourceState{ diff --git a/helper/resource/state_shim_test.go b/helper/resource/state_shim_test.go index a9c101a45c..af85b3906d 100644 --- a/helper/resource/state_shim_test.go +++ b/helper/resource/state_shim_test.go @@ -42,7 +42,7 @@ func TestStateShim(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) rootModule.SetResourceInstanceCurrent( @@ -57,7 +57,7 @@ func TestStateShim(t *testing.T) { DependsOn: []addrs.Referenceable{}, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) @@ -75,7 +75,7 @@ func TestStateShim(t *testing.T) { DependsOn: []addrs.Referenceable{}, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(childInstance), ) childModule.SetResourceInstanceCurrent( @@ -98,7 +98,7 @@ func TestStateShim(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(childInstance), ) @@ -123,7 +123,7 @@ func TestStateShim(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(childInstance), ) @@ -139,7 +139,7 @@ func TestStateShim(t *testing.T) { DependsOn: []addrs.Referenceable{}, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(childInstance), ) childModule.SetResourceInstanceCurrent( @@ -154,7 +154,7 @@ func TestStateShim(t *testing.T) { DependsOn: []addrs.Referenceable{}, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(childInstance), ) @@ -170,7 +170,7 @@ func TestStateShim(t *testing.T) { DependsOn: []addrs.Referenceable{}, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(childInstance), ) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 0e5af09334..1119144b4d 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -727,7 +727,7 @@ func testIDOnlyRefresh(c TestCase, opts terraform.ContextOpts, step TestStep, r AttrsFlat: r.Primary.Attributes, Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "placeholder"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("placeholder")}.Absolute(addrs.RootModuleInstance), ) // Create the config module. We use the full config because Refresh diff --git a/helper/resource/testing_import_state.go b/helper/resource/testing_import_state.go index 1f3796176f..9a3ef1be02 100644 --- a/helper/resource/testing_import_state.go +++ b/helper/resource/testing_import_state.go @@ -137,7 +137,7 @@ func testStepImportState( // this shouldn't happen in any reasonable case. var rsrcSchema *schema.Resource if providerAddr, diags := addrs.ParseAbsProviderConfigStr(r.Provider); !diags.HasErrors() { - providerType := providerAddr.ProviderConfig.Type + providerType := providerAddr.ProviderConfig.Type.LegacyString() if provider, ok := step.providers[providerType]; ok { if provider, ok := provider.(*schema.Provider); ok { rsrcSchema = provider.ResourcesMap[r.Type] diff --git a/plans/plan_test.go b/plans/plan_test.go index f68357072f..0fa2361dff 100644 --- a/plans/plan_test.go +++ b/plans/plan_test.go @@ -21,7 +21,7 @@ func TestProviderAddrs(t *testing.T) { Name: "woot", }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), ProviderAddr: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), }, { @@ -32,7 +32,7 @@ func TestProviderAddrs(t *testing.T) { }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), DeposedKey: "foodface", ProviderAddr: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), }, { @@ -42,7 +42,7 @@ func TestProviderAddrs(t *testing.T) { Name: "what", }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), ProviderAddr: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey)), }, }, @@ -52,10 +52,10 @@ func TestProviderAddrs(t *testing.T) { got := plan.ProviderAddrs() want := []addrs.AbsProviderConfig{ addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey)), addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), } diff --git a/plans/planfile/tfplan_test.go b/plans/planfile/tfplan_test.go index 2b49553acd..931e223409 100644 --- a/plans/planfile/tfplan_test.go +++ b/plans/planfile/tfplan_test.go @@ -57,7 +57,7 @@ func TestTFPlanRoundTrip(t *testing.T) { Name: "woot", }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), ProviderAddr: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: plans.DeleteThenCreate, @@ -77,7 +77,7 @@ func TestTFPlanRoundTrip(t *testing.T) { }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), DeposedKey: "foodface", ProviderAddr: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: plans.Delete, @@ -195,7 +195,7 @@ func TestTFPlanRoundTripDestroy(t *testing.T) { Name: "woot", }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), ProviderAddr: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: plans.Delete, diff --git a/providers/addressed_types.go b/providers/addressed_types.go index 7ed523f158..46bb80b602 100644 --- a/providers/addressed_types.go +++ b/providers/addressed_types.go @@ -14,7 +14,7 @@ func AddressedTypes(providerAddrs []addrs.ProviderConfig) []string { } m := map[string]struct{}{} for _, addr := range providerAddrs { - m[addr.Type] = struct{}{} + m[addr.Type.LegacyString()] = struct{}{} } names := make([]string, 0, len(m)) @@ -34,7 +34,7 @@ func AddressedTypesAbs(providerAddrs []addrs.AbsProviderConfig) []string { } m := map[string]struct{}{} for _, addr := range providerAddrs { - m[addr.ProviderConfig.Type] = struct{}{} + m[addr.ProviderConfig.Type.LegacyString()] = struct{}{} } names := make([]string, 0, len(m)) diff --git a/providers/addressed_types_test.go b/providers/addressed_types_test.go index 80915e3e68..407b83510b 100644 --- a/providers/addressed_types_test.go +++ b/providers/addressed_types_test.go @@ -10,11 +10,11 @@ import ( func TestAddressedTypes(t *testing.T) { providerAddrs := []addrs.ProviderConfig{ - {Type: "aws"}, - {Type: "aws", Alias: "foo"}, - {Type: "azure"}, - {Type: "null"}, - {Type: "null"}, + {Type: addrs.NewLegacyProvider("aws")}, + {Type: addrs.NewLegacyProvider("aws"), Alias: "foo"}, + {Type: addrs.NewLegacyProvider("azure")}, + {Type: addrs.NewLegacyProvider("null")}, + {Type: addrs.NewLegacyProvider("null")}, } got := AddressedTypes(providerAddrs) @@ -30,11 +30,11 @@ func TestAddressedTypes(t *testing.T) { func TestAddressedTypesAbs(t *testing.T) { providerAddrs := []addrs.AbsProviderConfig{ - addrs.ProviderConfig{Type: "aws"}.Absolute(addrs.RootModuleInstance), - addrs.ProviderConfig{Type: "aws", Alias: "foo"}.Absolute(addrs.RootModuleInstance), - addrs.ProviderConfig{Type: "azure"}.Absolute(addrs.RootModuleInstance), - addrs.ProviderConfig{Type: "null"}.Absolute(addrs.RootModuleInstance), - addrs.ProviderConfig{Type: "null"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("aws")}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("aws"), Alias: "foo"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("azure")}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("null")}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("null")}.Absolute(addrs.RootModuleInstance), } got := AddressedTypesAbs(providerAddrs) diff --git a/repl/session_test.go b/repl/session_test.go index 0d2f37326d..3ee9bf17a8 100644 --- a/repl/session_test.go +++ b/repl/session_test.go @@ -46,7 +46,7 @@ func TestSession_basicState(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( @@ -60,7 +60,7 @@ func TestSession_basicState(t *testing.T) { AttrsJSON: []byte(`{"id":"bar"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) }) diff --git a/states/state_test.go b/states/state_test.go index 22a43859f1..7b33f034ff 100644 --- a/states/state_test.go +++ b/states/state_test.go @@ -36,7 +36,7 @@ func TestState(t *testing.T) { AttrsJSON: []byte(`{"woozles":"confuzles"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) @@ -79,7 +79,7 @@ func TestState(t *testing.T) { }, }, ProviderConfig: addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), }, }, @@ -141,7 +141,7 @@ func TestStateDeepCopy(t *testing.T) { Dependencies: []addrs.AbsResource{}, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) rootModule.SetResourceInstanceCurrent( @@ -167,7 +167,7 @@ func TestStateDeepCopy(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index 7fc9f36821..6c20625725 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -1371,7 +1371,7 @@ func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) { Dependencies: []addrs.AbsResource{}, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -1395,7 +1395,7 @@ func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -1498,7 +1498,7 @@ func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) { Dependencies: []addrs.AbsResource{}, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) child.SetResourceInstanceCurrent( @@ -1522,7 +1522,7 @@ func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -2145,7 +2145,7 @@ func TestContext2Apply_provisionerDestroyForEach(t *testing.T) { }, ProviderConfig: addrs.AbsProviderConfig{ Module: addrs.ModuleInstance(nil), - ProviderConfig: addrs.ProviderConfig{Type: "aws", Alias: ""}, + ProviderConfig: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("aws"), Alias: ""}, }, }, }, @@ -2966,7 +2966,7 @@ func TestContext2Apply_orphanResource(t *testing.T) { // with the single instance associated with test_thing.one. want := states.BuildState(func(s *states.SyncState) { providerAddr := addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance) zeroAddr := addrs.Resource{ Mode: addrs.ManagedResourceMode, @@ -7386,7 +7386,7 @@ func TestContext2Apply_errorDestroy(t *testing.T) { AttrsJSON: []byte(`{"id":"baz"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) }), @@ -7525,7 +7525,7 @@ func TestContext2Apply_errorUpdateNullNew(t *testing.T) { AttrsJSON: []byte(`{"value":"old"}`), }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) }), @@ -9188,7 +9188,7 @@ func TestContext2Apply_createBefore_depends(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","require_new":"ami-old"}`), }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -9213,7 +9213,7 @@ func TestContext2Apply_createBefore_depends(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -9319,7 +9319,7 @@ func TestContext2Apply_singleDestroy(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","require_new":"ami-old"}`), }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -9344,7 +9344,7 @@ func TestContext2Apply_singleDestroy(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -10262,7 +10262,7 @@ func TestContext2Apply_destroyWithProviders(t *testing.T) { // correct the state s.Modules["module.mod.module.removed"].Resources["aws_instance.child"].ProviderConfig = addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), Alias: "bar", }.Absolute(addrs.RootModuleInstance) @@ -10687,7 +10687,7 @@ func TestContext2Apply_issue19908(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) }), @@ -10814,7 +10814,7 @@ func TestContext2Apply_moduleReplaceCycle(t *testing.T) { AttrsJSON: []byte(`{"id":"a","require_new":"old"}`), }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -10830,7 +10830,7 @@ func TestContext2Apply_moduleReplaceCycle(t *testing.T) { AttrsJSON: []byte(`{"id":"b","require_new":"old"}`), }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -10872,7 +10872,7 @@ func TestContext2Apply_moduleReplaceCycle(t *testing.T) { Name: "a", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("a", addrs.NoKey)), ProviderAddr: addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: aAction, @@ -10887,7 +10887,7 @@ func TestContext2Apply_moduleReplaceCycle(t *testing.T) { Name: "b", }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance.Child("b", addrs.NoKey)), ProviderAddr: addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: plans.DeleteThenCreate, @@ -10937,7 +10937,7 @@ func TestContext2Apply_destroyDataCycle(t *testing.T) { AttrsJSON: []byte(`{"id":"a"}`), }, addrs.ProviderConfig{ - Type: "null", + Type: addrs.NewLegacyProvider("null"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -10951,7 +10951,7 @@ func TestContext2Apply_destroyDataCycle(t *testing.T) { AttrsJSON: []byte(`{"id":"data"}`), }, addrs.ProviderConfig{ - Type: "null", + Type: addrs.NewLegacyProvider("null"), }.Absolute(addrs.RootModuleInstance), ) @@ -11025,7 +11025,7 @@ func TestContext2Apply_taintedDestroyFailure(t *testing.T) { AttrsJSON: []byte(`{"id":"a","foo":"a"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -11039,7 +11039,7 @@ func TestContext2Apply_taintedDestroyFailure(t *testing.T) { AttrsJSON: []byte(`{"id":"b","foo":"b"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -11053,7 +11053,7 @@ func TestContext2Apply_taintedDestroyFailure(t *testing.T) { AttrsJSON: []byte(`{"id":"c","foo":"old"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) @@ -11168,7 +11168,7 @@ func TestContext2Apply_cbdCycle(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -11192,7 +11192,7 @@ func TestContext2Apply_cbdCycle(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -11206,7 +11206,7 @@ func TestContext2Apply_cbdCycle(t *testing.T) { AttrsJSON: []byte(`{"id":"c","require_new":"old"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) diff --git a/terraform/context_components.go b/terraform/context_components.go index e824848f0b..74ab501379 100644 --- a/terraform/context_components.go +++ b/terraform/context_components.go @@ -33,16 +33,15 @@ type basicComponentFactory struct { } func (c *basicComponentFactory) ResourceProviders() []string { - result := make([]string, len(c.providers)) + var result []string for k := range c.providers { result = append(result, k.LegacyString()) } - return result } func (c *basicComponentFactory) ResourceProvisioners() []string { - result := make([]string, len(c.provisioners)) + var result []string for k := range c.provisioners { result = append(result, k) } diff --git a/terraform/context_import_test.go b/terraform/context_import_test.go index 56d60f1b97..1d94264d4b 100644 --- a/terraform/context_import_test.go +++ b/terraform/context_import_test.go @@ -115,7 +115,7 @@ func TestContextImport_collision(t *testing.T) { }, Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "aws"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("aws")}.Absolute(addrs.RootModuleInstance), ) }), }) @@ -601,7 +601,7 @@ func TestContextImport_moduleDiff(t *testing.T) { }, Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "aws"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("aws")}.Absolute(addrs.RootModuleInstance), ) }), }) @@ -659,7 +659,7 @@ func TestContextImport_moduleExisting(t *testing.T) { }, Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "aws"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("aws")}.Absolute(addrs.RootModuleInstance), ) }), }) diff --git a/terraform/context_input.go b/terraform/context_input.go index d24adcb7c2..acc42ae9b8 100644 --- a/terraform/context_input.go +++ b/terraform/context_input.go @@ -96,7 +96,7 @@ func (c *Context) Input(mode InputMode) tfdiags.Diagnostics { UIInput: c.uiInput, } - schema := c.schemas.ProviderConfig(pa.Type) + schema := c.schemas.ProviderConfig(pa.Type.LegacyString()) if schema == nil { // Could either be an incorrect config or just an incomplete // mock in tests. We'll let a later pass decide, and just diff --git a/terraform/context_input_test.go b/terraform/context_input_test.go index 5782184e90..a43b8567ed 100644 --- a/terraform/context_input_test.go +++ b/terraform/context_input_test.go @@ -478,7 +478,7 @@ func TestContext2Input_dataSourceRequiresRefresh(t *testing.T) { }, Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "null"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("null")}.Absolute(addrs.RootModuleInstance), ) }) diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index b069c3ec62..1710363053 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -4976,7 +4976,7 @@ func TestContext2Plan_ignoreChangesInMap(t *testing.T) { AttrsJSON: []byte(`{"tags":{"ignored":"from state","other":"from state"}}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) }) diff --git a/terraform/context_refresh_test.go b/terraform/context_refresh_test.go index 65e091e6c3..77c2e9c11c 100644 --- a/terraform/context_refresh_test.go +++ b/terraform/context_refresh_test.go @@ -104,7 +104,7 @@ func TestContext2Refresh_dynamicAttr(t *testing.T) { AttrsJSON: []byte(`{"dynamic":{"type":"string","value":"hello"}}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) }) @@ -1739,7 +1739,7 @@ func TestContext2Refresh_schemaUpgradeFlatmap(t *testing.T) { "id": "foo", }, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) @@ -1822,7 +1822,7 @@ func TestContext2Refresh_schemaUpgradeJSON(t *testing.T) { SchemaVersion: 3, AttrsJSON: []byte(`{"id":"foo"}`), }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) @@ -1991,7 +1991,7 @@ func TestRefresh_updateDependencies(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -2005,7 +2005,7 @@ func TestRefresh_updateDependencies(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"foo"}`), }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) diff --git a/terraform/eval_context_builtin.go b/terraform/eval_context_builtin.go index f6531848ff..f7e9973fee 100644 --- a/terraform/eval_context_builtin.go +++ b/terraform/eval_context_builtin.go @@ -142,7 +142,7 @@ func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers. func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *ProviderSchema { ctx.once.Do(ctx.init) - return ctx.Schemas.ProviderSchema(addr.ProviderConfig.Type) + return ctx.Schemas.ProviderSchema(addr.ProviderConfig.Type.LegacyString()) } func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.ProviderConfig) error { diff --git a/terraform/eval_context_builtin_test.go b/terraform/eval_context_builtin_test.go index 1907d136e3..81c5ffe9cd 100644 --- a/terraform/eval_context_builtin_test.go +++ b/terraform/eval_context_builtin_test.go @@ -24,7 +24,7 @@ func TestBuiltinEvalContextProviderInput(t *testing.T) { ctx2.ProviderInputConfig = cache ctx2.ProviderLock = &lock - providerAddr := addrs.ProviderConfig{Type: "foo"} + providerAddr := addrs.ProviderConfig{Type: addrs.NewLegacyProvider("foo")} expected1 := map[string]cty.Value{"value": cty.StringVal("foo")} ctx1.SetProviderInput(providerAddr, expected1) @@ -57,8 +57,8 @@ func TestBuildingEvalContextInitProvider(t *testing.T) { }, } - providerAddrDefault := addrs.ProviderConfig{Type: "test"} - providerAddrAlias := addrs.ProviderConfig{Type: "test", Alias: "foo"} + providerAddrDefault := addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")} + providerAddrAlias := addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test"), Alias: "foo"} _, err := ctx.InitProvider("test", providerAddrDefault) if err != nil { diff --git a/terraform/eval_diff.go b/terraform/eval_diff.go index b675253e7b..cc9046c20b 100644 --- a/terraform/eval_diff.go +++ b/terraform/eval_diff.go @@ -120,7 +120,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) { if providerSchema == nil { return nil, fmt.Errorf("provider schema is unavailable for %s", n.Addr) } - if n.ProviderAddr.ProviderConfig.Type == "" { + if n.ProviderAddr.ProviderConfig.Type.LegacyString() == "" { panic(fmt.Sprintf("EvalDiff for %s does not have ProviderAddr set", n.Addr.Absolute(ctx.Path()))) } @@ -603,7 +603,7 @@ func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) { absAddr := n.Addr.Absolute(ctx.Path()) state := *n.State - if n.ProviderAddr.ProviderConfig.Type == "" { + if n.ProviderAddr.ProviderConfig.Type.LegacyString() == "" { if n.DeposedKey == "" { panic(fmt.Sprintf("EvalDiffDestroy for %s does not have ProviderAddr set", absAddr)) } else { diff --git a/terraform/eval_provider.go b/terraform/eval_provider.go index 1b12b3cc85..2ff3745d12 100644 --- a/terraform/eval_provider.go +++ b/terraform/eval_provider.go @@ -125,7 +125,7 @@ type EvalGetProvider struct { } func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { - if n.Addr.ProviderConfig.Type == "" { + if n.Addr.ProviderConfig.Type.LegacyString() == "" { // Should never happen panic("EvalGetProvider used with uninitialized provider configuration address") } diff --git a/terraform/eval_provider_test.go b/terraform/eval_provider_test.go index f71688d37d..5d9a2f61ce 100644 --- a/terraform/eval_provider_test.go +++ b/terraform/eval_provider_test.go @@ -17,7 +17,7 @@ func TestBuildProviderConfig(t *testing.T) { "set_in_config": cty.StringVal("config"), }) providerAddr := addrs.ProviderConfig{ - Type: "foo", + Type: addrs.NewLegacyProvider("foo"), } ctx := &MockEvalContext{ @@ -68,7 +68,7 @@ func TestEvalConfigProvider(t *testing.T) { provider := mockProviderWithConfigSchema(simpleTestSchema()) rp := providers.Interface(provider) n := &EvalConfigProvider{ - Addr: addrs.ProviderConfig{Type: "foo"}, + Addr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("foo")}, Config: config, Provider: &rp, } @@ -98,7 +98,7 @@ func TestEvalInitProvider_impl(t *testing.T) { func TestEvalInitProvider(t *testing.T) { n := &EvalInitProvider{ - Addr: addrs.ProviderConfig{Type: "foo"}, + Addr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("foo")}, } provider := &MockProvider{} ctx := &MockEvalContext{InitProviderProvider: provider} @@ -116,7 +116,7 @@ func TestEvalInitProvider(t *testing.T) { func TestEvalCloseProvider(t *testing.T) { n := &EvalCloseProvider{ - Addr: addrs.ProviderConfig{Type: "foo"}, + Addr: addrs.ProviderConfig{Type: addrs.NewLegacyProvider("foo")}, } provider := &MockProvider{} ctx := &MockEvalContext{CloseProviderProvider: provider} diff --git a/terraform/eval_state.go b/terraform/eval_state.go index 0be8775441..fddc62bf23 100644 --- a/terraform/eval_state.go +++ b/terraform/eval_state.go @@ -217,7 +217,7 @@ func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) { absAddr := n.Addr.Absolute(ctx.Path()) state := ctx.State() - if n.ProviderAddr.ProviderConfig.Type == "" { + if n.ProviderAddr.ProviderConfig.Type.LegacyString() == "" { return nil, fmt.Errorf("failed to write state for %s, missing provider type", absAddr) } obj := *n.State diff --git a/terraform/evaltree_provider.go b/terraform/evaltree_provider.go index 6b4df67aaf..f163a727cd 100644 --- a/terraform/evaltree_provider.go +++ b/terraform/evaltree_provider.go @@ -16,7 +16,7 @@ func ProviderEvalTree(n *NodeApplyableProvider, config *configs.Provider) EvalNo seq := make([]EvalNode, 0, 5) seq = append(seq, &EvalInitProvider{ - TypeName: relAddr.Type, + TypeName: relAddr.Type.LegacyString(), Addr: addr.ProviderConfig, }) diff --git a/terraform/evaluate.go b/terraform/evaluate.go index de1fd9a058..ae171ed011 100644 --- a/terraform/evaluate.go +++ b/terraform/evaluate.go @@ -779,7 +779,7 @@ func (d *evaluationStateData) getResourceInstancesAll(addr addrs.Resource, rng t } func (d *evaluationStateData) getResourceSchema(addr addrs.Resource, providerAddr addrs.AbsProviderConfig) *configschema.Block { - providerType := providerAddr.ProviderConfig.Type + providerType := providerAddr.ProviderConfig.Type.LegacyString() schemas := d.Evaluator.Schemas schema, _ := schemas.ResourceTypeConfig(providerType, addr.Mode, addr.Type) return schema diff --git a/terraform/evaluate_valid.go b/terraform/evaluate_valid.go index 9e55b2f996..01f5ca1dba 100644 --- a/terraform/evaluate_valid.go +++ b/terraform/evaluate_valid.go @@ -215,7 +215,7 @@ func (d *evaluationStateData) staticValidateResourceReference(modCfg *configs.Co // Normally accessing this directly is wrong because it doesn't take into // account provider inheritance, etc but it's okay here because we're only // paying attention to the type anyway. - providerType := cfg.ProviderConfigAddr().Type + providerType := cfg.ProviderConfigAddr().Type.LegacyString() schema, _ := d.Evaluator.Schemas.ResourceTypeConfig(providerType, addr.Mode, addr.Type) if schema == nil { diff --git a/terraform/graph_builder_apply_test.go b/terraform/graph_builder_apply_test.go index 92908e583f..af1aa97791 100644 --- a/terraform/graph_builder_apply_test.go +++ b/terraform/graph_builder_apply_test.go @@ -545,7 +545,7 @@ func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) { AttrsJSON: []byte(`{"id":"a_id"}`), }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) root.SetResourceInstanceCurrent( @@ -569,7 +569,7 @@ func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) { }, }, addrs.ProviderConfig{ - Type: "test", + Type: addrs.NewLegacyProvider("test"), }.Absolute(addrs.RootModuleInstance), ) diff --git a/terraform/node_data_refresh_test.go b/terraform/node_data_refresh_test.go index 6b6059fa2b..d4ad1b55af 100644 --- a/terraform/node_data_refresh_test.go +++ b/terraform/node_data_refresh_test.go @@ -130,7 +130,7 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleIn(t *testing.T) { Config: m.Module.DataResources["data.aws_instance.foo"], ResolvedProvider: addrs.AbsProviderConfig{ ProviderConfig: addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }, }, }, @@ -174,7 +174,7 @@ root - terraform.graphNodeRoot t.Fatal("failed to find a destroyableDataResource") } - if destroyableDataResource.ResolvedProvider.ProviderConfig.Type == "" { + if destroyableDataResource.ResolvedProvider.ProviderConfig.Type.LegacyString() == "" { t.Fatal("NodeDestroyableDataResourceInstance missing provider config") } } diff --git a/terraform/node_provider_eval.go b/terraform/node_provider_eval.go index 580e60cb7e..1e4daabb98 100644 --- a/terraform/node_provider_eval.go +++ b/terraform/node_provider_eval.go @@ -14,7 +14,7 @@ func (n *NodeEvalableProvider) EvalTree() EvalNode { relAddr := addr.ProviderConfig return &EvalInitProvider{ - TypeName: relAddr.Type, + TypeName: relAddr.Type.LegacyString(), Addr: addr.ProviderConfig, } } diff --git a/terraform/node_resource_plan_destroy.go b/terraform/node_resource_plan_destroy.go index 38746f0d35..decc372a5c 100644 --- a/terraform/node_resource_plan_destroy.go +++ b/terraform/node_resource_plan_destroy.go @@ -47,7 +47,7 @@ func (n *NodePlanDestroyableResourceInstance) EvalTree() EvalNode { var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject - if n.ResolvedProvider.ProviderConfig.Type == "" { + if n.ResolvedProvider.ProviderConfig.Type.String() == "" { // Should never happen; indicates that the graph was not constructed // correctly since we didn't get our provider attached. panic(fmt.Sprintf("%T %q was not assigned a resolved provider", n, dag.VertexName(n))) diff --git a/terraform/transform_attach_schema.go b/terraform/transform_attach_schema.go index c7695dd4ee..2e4c355185 100644 --- a/terraform/transform_attach_schema.go +++ b/terraform/transform_attach_schema.go @@ -59,7 +59,7 @@ func (t *AttachSchemaTransformer) Transform(g *Graph) error { mode := addr.Resource.Mode typeName := addr.Resource.Type providerAddr, _ := tv.ProvidedBy() - providerType := providerAddr.ProviderConfig.Type + providerType := providerAddr.ProviderConfig.Type.LegacyString() schema, version := t.Schemas.ResourceTypeConfig(providerType, mode, typeName) if schema == nil { @@ -72,7 +72,7 @@ func (t *AttachSchemaTransformer) Transform(g *Graph) error { if tv, ok := v.(GraphNodeAttachProviderConfigSchema); ok { providerAddr := tv.ProviderAddr() - schema := t.Schemas.ProviderConfig(providerAddr.ProviderConfig.Type) + schema := t.Schemas.ProviderConfig(providerAddr.ProviderConfig.Type.LegacyString()) if schema == nil { log.Printf("[ERROR] AttachSchemaTransformer: No provider config schema available for %s", providerAddr) continue diff --git a/terraform/transform_diff_test.go b/terraform/transform_diff_test.go index a83a5d75f5..1aced02fbe 100644 --- a/terraform/transform_diff_test.go +++ b/terraform/transform_diff_test.go @@ -44,7 +44,7 @@ func TestDiffTransformer(t *testing.T) { Name: "foo", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), ProviderAddr: addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ Action: plans.Update, diff --git a/terraform/transform_import_state.go b/terraform/transform_import_state.go index ab0ecae0a9..7bda3121f6 100644 --- a/terraform/transform_import_state.go +++ b/terraform/transform_import_state.go @@ -20,7 +20,7 @@ func (t *ImportStateTransformer) Transform(g *Graph) error { // This will be populated if the targets come from the cli, but tests // may not specify implied provider addresses. providerAddr := target.ProviderAddr - if providerAddr.ProviderConfig.Type == "" { + if providerAddr.ProviderConfig.Type.Type == "" { providerAddr = target.Addr.Resource.Resource.DefaultProviderConfig().Absolute(target.Addr.Module) } diff --git a/terraform/transform_orphan_count_test.go b/terraform/transform_orphan_count_test.go index 4853ce831b..94acecfbb9 100644 --- a/terraform/transform_orphan_count_test.go +++ b/terraform/transform_orphan_count_test.go @@ -353,7 +353,7 @@ func TestOrphanResourceCountTransformer_ForEachEdgesAdded(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -371,7 +371,7 @@ func TestOrphanResourceCountTransformer_ForEachEdgesAdded(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) }) diff --git a/terraform/transform_orphan_resource_test.go b/terraform/transform_orphan_resource_test.go index fed351cc1f..1eae68d786 100644 --- a/terraform/transform_orphan_resource_test.go +++ b/terraform/transform_orphan_resource_test.go @@ -27,7 +27,7 @@ func TestOrphanResourceInstanceTransformer(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) @@ -45,7 +45,7 @@ func TestOrphanResourceInstanceTransformer(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) }) @@ -93,7 +93,7 @@ func TestOrphanResourceInstanceTransformer_countGood(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( @@ -109,7 +109,7 @@ func TestOrphanResourceInstanceTransformer_countGood(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) }) @@ -156,7 +156,7 @@ func TestOrphanResourceInstanceTransformer_countBad(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( @@ -172,7 +172,7 @@ func TestOrphanResourceInstanceTransformer_countBad(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) }) @@ -219,7 +219,7 @@ func TestOrphanResourceInstanceTransformer_modules(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( @@ -235,7 +235,7 @@ func TestOrphanResourceInstanceTransformer_modules(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) }) diff --git a/terraform/transform_provider.go b/terraform/transform_provider.go index bc86d295fb..8b8dff86fa 100644 --- a/terraform/transform_provider.go +++ b/terraform/transform_provider.go @@ -295,7 +295,7 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error { // We're going to create an implicit _default_ configuration for the // referenced provider type in the _root_ module, ignoring all other // aspects of the resource's declared provider address. - defaultAddr := addrs.RootModuleInstance.ProviderConfigDefault(p.ProviderConfig.Type) + defaultAddr := addrs.RootModuleInstance.ProviderConfigDefault(p.ProviderConfig.Type.LegacyString()) key := defaultAddr.String() provider := m[key] @@ -705,7 +705,7 @@ func (t *ProviderConfigTransformer) attachProviderConfigs(g *Graph) error { // Go through the provider configs to find the matching config for _, p := range mc.Module.ProviderConfigs { - if p.Name == addr.ProviderConfig.Type && p.Alias == addr.ProviderConfig.Alias { + if p.Name == addr.ProviderConfig.Type.LegacyString() && p.Alias == addr.ProviderConfig.Alias { log.Printf("[TRACE] ProviderConfigTransformer: attaching to %q provider configuration from %s", dag.VertexName(v), p.DeclRange) apn.AttachProvider(p) break diff --git a/terraform/transform_provisioner_test.go b/terraform/transform_provisioner_test.go index eecd677888..e96ce22518 100644 --- a/terraform/transform_provisioner_test.go +++ b/terraform/transform_provisioner_test.go @@ -71,7 +71,7 @@ func TestMissingProvisionerTransformer_module(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) s.SetResourceInstanceCurrent( @@ -87,7 +87,7 @@ func TestMissingProvisionerTransformer_module(t *testing.T) { Status: states.ObjectReady, }, addrs.ProviderConfig{ - Type: "aws", + Type: addrs.NewLegacyProvider("aws"), }.Absolute(addrs.RootModuleInstance), ) }) From 2fdf984cce1199f0f39870ef78e7f2e5c69d2a9c Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 6 Dec 2019 09:45:19 -0500 Subject: [PATCH 14/19] update destroy provisioner warning text Make it a little more user-oriented --- configs/provisioner.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/configs/provisioner.go b/configs/provisioner.go index fc5136dddf..bbc6de993a 100644 --- a/configs/provisioner.go +++ b/configs/provisioner.go @@ -149,8 +149,11 @@ func onlySelfRefs(body hcl.Body) hcl.Diagnostics { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagWarning, Summary: "External references from destroy provisioners are deprecated", - Detail: "Destroy time provisioners and their connections may only reference values stored in the instance state, which include 'self', 'count.index', or 'each.key'.", - Subject: attr.Expr.Range().Ptr(), + Detail: "Destroy-time provisioners and their connection configurations may only " + + "reference attributes of the related resource, via 'self', 'count.index', " + + "or 'each.key'.\n\nReferences to other resources during the destroy phase " + + "can cause dependency cycles and interact poorly with create_before_destroy.", + Subject: attr.Expr.Range().Ptr(), }) } } From b715ef2590fe0ad2fda2622f67f52a9c13231e7b Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 6 Dec 2019 09:46:03 -0500 Subject: [PATCH 15/19] don't print just warnings when loading backend cfg Any warnings will be caught again when the entire config is loaded, and duplicated in the output. --- command/meta_config.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/command/meta_config.go b/command/meta_config.go index ec7b3ec16a..2bb104a11a 100644 --- a/command/meta_config.go +++ b/command/meta_config.go @@ -173,10 +173,13 @@ func (m *Meta) dirIsConfigPath(dir string) bool { // directory even if loadBackendConfig succeeded.) func (m *Meta) loadBackendConfig(rootDir string) (*configs.Backend, tfdiags.Diagnostics) { mod, diags := m.loadSingleModule(rootDir) + + // Only return error diagnostics at this point. Any warnings will be caught + // again later and duplicated in the output. if diags.HasErrors() { return nil, diags } - return mod.Backend, diags + return mod.Backend, nil } // loadValuesFile loads a file that defines a single map of key/value pairs. From 96d1e57191689c1c7dfddda4e158583e3c05b978 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 6 Dec 2019 10:52:02 -0500 Subject: [PATCH 16/19] fix type in state mv test --- command/state_mv_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/state_mv_test.go b/command/state_mv_test.go index 406afa412c..25addaefd5 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -249,7 +249,7 @@ func TestStateMv_instanceToNewResource(t *testing.T) { AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), Status: states.ObjectReady, }, - addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), ) }) statePath := testStateFile(t, state) From 42a2bb4da3e3bd4d67356e03aa4cb5c6aee5c2b4 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 6 Dec 2019 10:56:47 -0500 Subject: [PATCH 17/19] expand test tempdir symlinks to fix tests on macos --- command/command_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/command/command_test.go b/command/command_test.go index 9f0fa4381a..4f5acfe381 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -100,6 +100,12 @@ func tempDir(t *testing.T) string { if err != nil { t.Fatalf("err: %s", err) } + + dir, err = filepath.EvalSymlinks(dir) + if err != nil { + t.Fatal(err) + } + if err := os.RemoveAll(dir); err != nil { t.Fatalf("err: %s", err) } @@ -486,6 +492,11 @@ func testTempDir(t *testing.T) string { t.Fatalf("err: %s", err) } + d, err = filepath.EvalSymlinks(d) + if err != nil { + t.Fatal(err) + } + return d } From 9c4d3cc1b1b6c8be8ce87aa4c419b67852ef3417 Mon Sep 17 00:00:00 2001 From: Pam Selle <204372+pselle@users.noreply.github.com> Date: Fri, 6 Dec 2019 11:53:43 -0500 Subject: [PATCH 18/19] Add a test --- command/show_test.go | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/command/show_test.go b/command/show_test.go index 30da8c5724..ba70ade401 100644 --- a/command/show_test.go +++ b/command/show_test.go @@ -101,8 +101,34 @@ func TestShow_plan(t *testing.T) { } } +func TestShow_planWithChanges(t *testing.T) { + planPathWithChanges := showFixturePlanFile(t, plans.DeleteThenCreate) + + ui := cli.NewMockUi() + c := &ShowCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(showFixtureProvider()), + Ui: ui, + }, + } + + args := []string{ + planPathWithChanges, + } + + if code := c.Run(args); code != 0 { + t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) + } + + want := `test_instance.foo must be replaced` + got := ui.OutputWriter.String() + if !strings.Contains(got, want) { + t.Errorf("missing expected output\nwant: %s\ngot:\n%s", want, got) + } +} + func TestShow_plan_json(t *testing.T) { - planPath := showFixturePlanFile(t) + planPath := showFixturePlanFile(t, plans.Create) ui := new(cli.MockUi) c := &ShowCommand{ @@ -377,9 +403,10 @@ func showFixtureProvider() *terraform.MockProvider { } // showFixturePlanFile creates a plan file at a temporary location containing a -// single change to create the test_instance.foo that is included in the "show" +// single change to create or update the test_instance.foo that is included in the "show" // test fixture, returning the location of that plan file. -func showFixturePlanFile(t *testing.T) string { +// `action` is the planned change you would like to elicit +func showFixturePlanFile(t *testing.T, action plans.Action) string { _, snap := testModuleWithSnapshot(t, "show") plannedVal := cty.ObjectVal(map[string]cty.Value{ "id": cty.UnknownVal(cty.String), @@ -402,7 +429,7 @@ func showFixturePlanFile(t *testing.T) string { }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), ChangeSrc: plans.ChangeSrc{ - Action: plans.Create, + Action: action, Before: priorValRaw, After: plannedValRaw, }, From 9ef44b72b36378ae0661eeffd9a46c03549401fa Mon Sep 17 00:00:00 2001 From: Pam Selle Date: Fri, 6 Dec 2019 12:10:33 -0500 Subject: [PATCH 19/19] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f62ef78c2..921fb23074 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ BUG FIXES: * cli: Allow moving indexed resource instances to new addresses that that don't yet exist in state [GH-23582] * cli: Improved heuristics for log level filtering with the `TF_LOG` environment variable, although it is still not 100% reliable for levels other than `TRACE` due to limitations of Terraform's internal logging infrastructure. Because of that, levels other than `TRACE` will now cause the logs to begin with a warning about potential filtering inaccuracy. [GH-23577] +* command/show: Fix panic on show plan [GH-23581] * config: Fixed referencing errors generally involving `for_each` [GH-23475] * provisioners: The built-in provisioners (`local-exec`, `remote-exec`, `file`, etc) will no longer fail when the `TF_CLI_ARGS` environment variable is set. [GH-17400]