mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Implement Provider for_each (#2105)
Signed-off-by: ollevche <ollevche@gmail.com> Signed-off-by: Christian Mesh <christianmesh1@gmail.com> Signed-off-by: Ronny Orot <ronny.orot@gmail.com> Signed-off-by: Martin Atkins <mart@degeneration.co.uk> Co-authored-by: ollevche <ollevche@gmail.com> Co-authored-by: Ronny Orot <ronny.orot@gmail.com> Co-authored-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
parent
3d4bf29c56
commit
fd775f0fe3
@ -30,7 +30,7 @@ linters-settings:
|
||||
require-specific: true
|
||||
|
||||
cyclop:
|
||||
max-complexity: 15
|
||||
max-complexity: 20
|
||||
|
||||
gocognit:
|
||||
min-complexity: 50
|
||||
@ -38,6 +38,14 @@ linters-settings:
|
||||
goconst:
|
||||
ignore-tests: true # Is documented to be the default behaviour, but that doesn't seem to be the case
|
||||
|
||||
gocritic:
|
||||
settings:
|
||||
ifElseChain:
|
||||
minThreshold: 4
|
||||
|
||||
nestif:
|
||||
min-complexity: 6
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
- path: (.+)_test.go
|
||||
|
@ -17,6 +17,7 @@ ENHANCEMENTS:
|
||||
* Added a help target to the Makefile. ([#1925](https://github.com/opentofu/opentofu/pull/1925))
|
||||
* Added a simplified Build Process with a Makefile Target ([#1926](https://github.com/opentofu/opentofu/issues/1926))
|
||||
* Ensures that the Makefile adheres to POSIX standards ([#1811](https://github.com/opentofu/opentofu/pull/1928))
|
||||
* Added for-each support to providers ([#300](https://github.com/opentofu/opentofu/issues/300))
|
||||
* Added consolidate warnings and errors flags ([#1894](https://github.com/opentofu/opentofu/pull/1894))
|
||||
|
||||
BUG FIXES:
|
||||
|
@ -113,8 +113,26 @@ var _ ProviderConfig = AbsProviderConfig{}
|
||||
// This type of address is typically not used prominently in the UI, except in
|
||||
// error messages that refer to provider configurations.
|
||||
func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags.Diagnostics) {
|
||||
pc, key, diags := ParseAbsProviderConfigInstance(traversal)
|
||||
if key != NoKey {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration address",
|
||||
Detail: "A provider address must not include an instance key.",
|
||||
Subject: traversal.SourceRange().Ptr(),
|
||||
})
|
||||
}
|
||||
return pc, diags
|
||||
}
|
||||
|
||||
// ParseAbsProviderConfigInstance behaves identically to ParseAbsProviderConfig, but additionally
|
||||
// allows an instance key after the alias.
|
||||
//
|
||||
//nolint:mnd // traversals with specific indices
|
||||
func ParseAbsProviderConfigInstance(traversal hcl.Traversal) (AbsProviderConfig, InstanceKey, tfdiags.Diagnostics) {
|
||||
modInst, remain, diags := parseModuleInstancePrefix(traversal)
|
||||
var ret AbsProviderConfig
|
||||
var key InstanceKey
|
||||
|
||||
// Providers cannot resolve within module instances, so verify that there
|
||||
// are no instance keys in the module path before converting to a Module.
|
||||
@ -123,10 +141,10 @@ func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration address",
|
||||
Detail: "Provider address cannot contain module indexes",
|
||||
Detail: "A provider configuration must not appear in a module instance that uses count or for_each.",
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
return ret, key, diags
|
||||
}
|
||||
}
|
||||
ret.Module = modInst.Module()
|
||||
@ -138,16 +156,16 @@ func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags
|
||||
Detail: "Provider address must begin with \"provider.\", followed by a provider type name.",
|
||||
Subject: remain.SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
return ret, key, diags
|
||||
}
|
||||
if len(remain) > 3 {
|
||||
if len(remain) > 4 {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration address",
|
||||
Detail: "Extraneous operators after provider configuration alias.",
|
||||
Subject: hcl.Traversal(remain[3:]).SourceRange().Ptr(),
|
||||
Detail: "Extraneous operators after provider configuration reference.",
|
||||
Subject: remain[4:].SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
return ret, key, diags
|
||||
}
|
||||
|
||||
if tt, ok := remain[1].(hcl.TraverseIndex); ok {
|
||||
@ -158,13 +176,13 @@ func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags
|
||||
Detail: "The prefix \"provider.\" must be followed by a provider type name.",
|
||||
Subject: remain[1].SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
return ret, key, diags
|
||||
}
|
||||
p, sourceDiags := ParseProviderSourceString(tt.Key.AsString())
|
||||
ret.Provider = p
|
||||
if sourceDiags.HasErrors() {
|
||||
diags = diags.Append(sourceDiags)
|
||||
return ret, diags
|
||||
return ret, key, diags
|
||||
}
|
||||
} else {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
@ -173,10 +191,10 @@ func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags
|
||||
Detail: "The prefix \"provider.\" must be followed by a provider type name.",
|
||||
Subject: remain[1].SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
return ret, key, diags
|
||||
}
|
||||
|
||||
if len(remain) == 3 {
|
||||
if len(remain) > 2 {
|
||||
if tt, ok := remain[2].(hcl.TraverseAttr); ok {
|
||||
ret.Alias = tt.Name
|
||||
} else {
|
||||
@ -186,11 +204,34 @@ func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags
|
||||
Detail: "Provider type name must be followed by a configuration alias name.",
|
||||
Subject: remain[2].SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
return ret, key, diags
|
||||
}
|
||||
}
|
||||
|
||||
return ret, diags
|
||||
if len(remain) > 3 {
|
||||
if tt, ok := remain[3].(hcl.TraverseIndex); ok {
|
||||
var keyErr error
|
||||
key, keyErr = ParseInstanceKey(tt.Key)
|
||||
if keyErr != nil {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration address",
|
||||
Detail: fmt.Sprintf("Invalid provider instance key: %s.", keyErr.Error()),
|
||||
Subject: remain[3].SourceRange().Ptr(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration address",
|
||||
Detail: "A provider configuration alias can be followed only by an instance key in brackets.",
|
||||
Subject: remain[3].SourceRange().Ptr(),
|
||||
})
|
||||
return ret, key, diags
|
||||
}
|
||||
}
|
||||
|
||||
return ret, key, diags
|
||||
}
|
||||
|
||||
// ParseAbsProviderConfigStr is a helper wrapper around ParseAbsProviderConfig
|
||||
@ -219,6 +260,17 @@ func ParseAbsProviderConfigStr(str string) (AbsProviderConfig, tfdiags.Diagnosti
|
||||
diags = diags.Append(addrDiags)
|
||||
return addr, diags
|
||||
}
|
||||
func ParseAbsProviderConfigInstanceStr(str string) (AbsProviderConfig, InstanceKey, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
|
||||
diags = diags.Append(parseDiags)
|
||||
if parseDiags.HasErrors() {
|
||||
return AbsProviderConfig{}, nil, diags
|
||||
}
|
||||
addr, key, addrDiags := ParseAbsProviderConfigInstance(traversal)
|
||||
diags = diags.Append(addrDiags)
|
||||
return addr, key, diags
|
||||
}
|
||||
|
||||
func ParseLegacyAbsProviderConfigStr(str string) (AbsProviderConfig, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
@ -413,3 +465,10 @@ func (pc AbsProviderConfig) String() string {
|
||||
|
||||
return strings.Join(parts, ".")
|
||||
}
|
||||
|
||||
func (pc AbsProviderConfig) InstanceString(key InstanceKey) string {
|
||||
if key == NoKey {
|
||||
return pc.String()
|
||||
}
|
||||
return pc.String() + key.String()
|
||||
}
|
||||
|
@ -15,10 +15,11 @@ import (
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
)
|
||||
|
||||
func TestParseAbsProviderConfig(t *testing.T) {
|
||||
func TestParseAbsProviderConfigInstances(t *testing.T) {
|
||||
tests := []struct {
|
||||
Input string
|
||||
Want AbsProviderConfig
|
||||
WantKey InstanceKey
|
||||
WantDiag string
|
||||
}{
|
||||
{
|
||||
@ -31,6 +32,7 @@ func TestParseAbsProviderConfig(t *testing.T) {
|
||||
Hostname: "registry.opentofu.org",
|
||||
},
|
||||
},
|
||||
NoKey,
|
||||
``,
|
||||
},
|
||||
{
|
||||
@ -44,6 +46,7 @@ func TestParseAbsProviderConfig(t *testing.T) {
|
||||
},
|
||||
Alias: "foo",
|
||||
},
|
||||
NoKey,
|
||||
``,
|
||||
},
|
||||
{
|
||||
@ -56,6 +59,7 @@ func TestParseAbsProviderConfig(t *testing.T) {
|
||||
Hostname: "registry.opentofu.org",
|
||||
},
|
||||
},
|
||||
NoKey,
|
||||
``,
|
||||
},
|
||||
{
|
||||
@ -69,56 +73,81 @@ func TestParseAbsProviderConfig(t *testing.T) {
|
||||
},
|
||||
Alias: "foo",
|
||||
},
|
||||
NoKey,
|
||||
``,
|
||||
},
|
||||
{
|
||||
`module.baz.provider["registry.opentofu.org/hashicorp/aws"].foo["keystr"]`,
|
||||
AbsProviderConfig{
|
||||
Module: Module{"baz"},
|
||||
Provider: Provider{
|
||||
Type: "aws",
|
||||
Namespace: "hashicorp",
|
||||
Hostname: "registry.opentofu.org",
|
||||
},
|
||||
Alias: "foo",
|
||||
},
|
||||
StringKey("keystr"),
|
||||
``,
|
||||
},
|
||||
{
|
||||
`module.baz["foo"].provider["registry.opentofu.org/hashicorp/aws"]`,
|
||||
AbsProviderConfig{},
|
||||
`Provider address cannot contain module indexes`,
|
||||
NoKey,
|
||||
`A provider configuration must not appear in a module instance that uses count or for_each.`,
|
||||
},
|
||||
{
|
||||
`module.baz[1].provider["registry.opentofu.org/hashicorp/aws"]`,
|
||||
AbsProviderConfig{},
|
||||
`Provider address cannot contain module indexes`,
|
||||
NoKey,
|
||||
`A provider configuration must not appear in a module instance that uses count or for_each.`,
|
||||
},
|
||||
{
|
||||
`module.baz[1].module.bar.provider["registry.opentofu.org/hashicorp/aws"]`,
|
||||
AbsProviderConfig{},
|
||||
`Provider address cannot contain module indexes`,
|
||||
NoKey,
|
||||
`A provider configuration must not appear in a module instance that uses count or for_each.`,
|
||||
},
|
||||
{
|
||||
`aws`,
|
||||
AbsProviderConfig{},
|
||||
NoKey,
|
||||
`Provider address must begin with "provider.", followed by a provider type name.`,
|
||||
},
|
||||
{
|
||||
`aws.foo`,
|
||||
AbsProviderConfig{},
|
||||
NoKey,
|
||||
`Provider address must begin with "provider.", followed by a provider type name.`,
|
||||
},
|
||||
{
|
||||
`provider`,
|
||||
AbsProviderConfig{},
|
||||
NoKey,
|
||||
`Provider address must begin with "provider.", followed by a provider type name.`,
|
||||
},
|
||||
{
|
||||
`provider.aws.foo.bar`,
|
||||
`provider.aws.foo["bar"].baz`,
|
||||
AbsProviderConfig{},
|
||||
`Extraneous operators after provider configuration alias.`,
|
||||
NoKey,
|
||||
`Extraneous operators after provider configuration reference.`,
|
||||
},
|
||||
{
|
||||
`provider["aws"]["foo"]`,
|
||||
AbsProviderConfig{},
|
||||
NoKey,
|
||||
`Provider type name must be followed by a configuration alias name.`,
|
||||
},
|
||||
{
|
||||
`module.foo`,
|
||||
AbsProviderConfig{},
|
||||
NoKey,
|
||||
`Provider address must begin with "provider.", followed by a provider type name.`,
|
||||
},
|
||||
{
|
||||
`provider[0]`,
|
||||
AbsProviderConfig{},
|
||||
NoKey,
|
||||
`The prefix "provider." must be followed by a provider type name.`,
|
||||
},
|
||||
}
|
||||
@ -134,7 +163,7 @@ func TestParseAbsProviderConfig(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
got, diags := ParseAbsProviderConfig(traversal)
|
||||
got, key, diags := ParseAbsProviderConfigInstance(traversal)
|
||||
|
||||
if test.WantDiag != "" {
|
||||
if len(diags) != 1 {
|
||||
@ -154,6 +183,10 @@ func TestParseAbsProviderConfig(t *testing.T) {
|
||||
for _, problem := range deep.Equal(got, test.Want) {
|
||||
t.Error(problem)
|
||||
}
|
||||
|
||||
if test.WantKey != key {
|
||||
t.Errorf("Wanted key %s, got key %s", test.WantKey, key)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -369,6 +369,7 @@ func TestLocal_planDeposedOnly(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
}))
|
||||
outDir := t.TempDir()
|
||||
@ -765,6 +766,7 @@ func testPlanState() *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
@ -792,6 +794,7 @@ func testPlanState_withDataSource() *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
rootModule.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -809,6 +812,7 @@ func testPlanState_withDataSource() *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
@ -836,6 +840,7 @@ func testPlanState_tainted() *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
|
@ -300,6 +300,7 @@ func testRefreshState() *states.State {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
|
@ -159,6 +159,7 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// write a distinct known state to bar
|
||||
|
@ -44,6 +44,7 @@ func TestApply_destroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -149,6 +150,7 @@ func TestApply_destroyApproveNo(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -217,6 +219,7 @@ func TestApply_destroyApproveYes(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -287,6 +290,7 @@ func TestApply_destroyLockedState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -415,6 +419,7 @@ func TestApply_targetedDestroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
},
|
||||
},
|
||||
@ -456,6 +461,7 @@ func TestApply_targetedDestroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
},
|
||||
},
|
||||
@ -483,6 +489,7 @@ func TestApply_targetedDestroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -499,6 +506,7 @@ func TestApply_targetedDestroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1000,6 +1000,7 @@ func TestApply_refresh(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -1067,6 +1068,7 @@ func TestApply_refreshFalse(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -1204,6 +1206,7 @@ func TestApply_state(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -1601,6 +1604,7 @@ func TestApply_backup(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -2128,6 +2132,7 @@ func TestApply_replace(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
|
@ -311,6 +311,7 @@ func testState() *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
// DeepCopy is used here to ensure our synthetic state matches exactly
|
||||
// with a state that will have been copied during the command
|
||||
|
@ -271,6 +271,7 @@ func basicState(t *testing.T) *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
rootModule.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -287,6 +288,7 @@ func basicState(t *testing.T) *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
@ -323,6 +325,7 @@ func stateWithMoreOutputs(t *testing.T) *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
@ -350,6 +353,7 @@ func nestedState(t *testing.T) *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
@ -373,6 +377,7 @@ func deposedState(t *testing.T) *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
@ -402,6 +407,7 @@ func onlyDeposedState(t *testing.T) *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
rootModule.SetResourceInstanceDeposed(
|
||||
addrs.Resource{
|
||||
@ -419,6 +425,7 @@ func onlyDeposedState(t *testing.T) *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return state
|
||||
}
|
||||
|
@ -631,6 +631,7 @@ func TestMarshalModules_basic(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -646,6 +647,7 @@ func TestMarshalModules_basic(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: childModule.Module(),
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -661,6 +663,7 @@ func TestMarshalModules_basic(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: subModule.Module(),
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
moduleMap := make(map[string][]addrs.ModuleInstance)
|
||||
@ -700,6 +703,7 @@ func TestMarshalModules_nested(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -715,6 +719,7 @@ func TestMarshalModules_nested(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: childModule.Module(),
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -730,6 +735,7 @@ func TestMarshalModules_nested(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: subModule.Module(),
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
moduleMap := make(map[string][]addrs.ModuleInstance)
|
||||
@ -772,6 +778,7 @@ func TestMarshalModules_parent_no_resources(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -787,6 +794,7 @@ func TestMarshalModules_parent_no_resources(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: subModule.Module(),
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
got, err := marshalRootModule(testState, testSchemas())
|
||||
|
@ -153,6 +153,7 @@ func TestPlan_destroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
outPath := testTempFile(t)
|
||||
@ -316,6 +317,7 @@ func TestPlan_outPathNoChange(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
@ -417,6 +419,7 @@ func TestPlan_outBackend(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1507,6 +1510,7 @@ func TestPlan_replace(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, originalState)
|
||||
|
@ -148,6 +148,7 @@ func TestShow_argsWithStateAliasedProvider(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
addrs.RootModuleInstance.ProviderConfigAliased(addrs.NewDefaultProvider("test"), "alias"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -35,6 +35,7 @@ func TestStateMv(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -51,6 +52,7 @@ func TestStateMv(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -171,6 +173,7 @@ func TestStateMv_backupAndBackupOutOptionsWithNonLocalBackend(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -418,6 +421,7 @@ func TestStateMv_resourceToInstance(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -434,6 +438,7 @@ func TestStateMv_resourceToInstance(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceProvider(
|
||||
addrs.Resource{
|
||||
@ -509,6 +514,7 @@ func TestStateMv_resourceToInstanceErr(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceProvider(
|
||||
addrs.Resource{
|
||||
@ -578,6 +584,7 @@ func TestStateMv_resourceToInstanceErrInAutomation(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceProvider(
|
||||
addrs.Resource{
|
||||
@ -648,6 +655,7 @@ func TestStateMv_instanceToResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -663,6 +671,7 @@ func TestStateMv_instanceToResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -738,6 +747,7 @@ func TestStateMv_instanceToNewResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -811,6 +821,7 @@ func TestStateMv_differentResourceTypes(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -873,6 +884,7 @@ func TestStateMv_explicitWithBackend(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -888,6 +900,7 @@ func TestStateMv_explicitWithBackend(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -951,6 +964,7 @@ func TestStateMv_backupExplicit(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -967,6 +981,7 @@ func TestStateMv_backupExplicit(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -1018,6 +1033,7 @@ func TestStateMv_stateOutNew(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -1074,6 +1090,7 @@ func TestStateMv_stateOutExisting(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, stateSrc)
|
||||
@ -1093,6 +1110,7 @@ func TestStateMv_stateOutExisting(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
stateOutPath := testStateFile(t, stateDst)
|
||||
@ -1176,6 +1194,7 @@ func TestStateMv_stateOutNew_count(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -1191,6 +1210,7 @@ func TestStateMv_stateOutNew_count(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -1206,6 +1226,7 @@ func TestStateMv_stateOutNew_count(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -1266,6 +1287,7 @@ func TestStateMv_stateOutNew_largeCount(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
}
|
||||
s.SetResourceInstanceCurrent(
|
||||
@ -1282,6 +1304,7 @@ func TestStateMv_stateOutNew_largeCount(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -1338,6 +1361,7 @@ func TestStateMv_stateOutNew_nestedModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -1353,6 +1377,7 @@ func TestStateMv_stateOutNew_nestedModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1410,6 +1435,7 @@ func TestStateMv_toNewModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1484,6 +1510,7 @@ func TestStateMv_withinBackend(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -1500,6 +1527,7 @@ func TestStateMv_withinBackend(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1559,6 +1587,7 @@ func TestStateMv_fromBackendToLocal(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
state.Module(addrs.RootModuleInstance).SetResourceInstanceCurrent(
|
||||
mustResourceAddr("test_instance.baz").Resource.Instance(addrs.NoKey),
|
||||
@ -1570,6 +1599,7 @@ func TestStateMv_fromBackendToLocal(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// the local backend state file is "foo"
|
||||
@ -1635,6 +1665,7 @@ func TestStateMv_onlyResourceInModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1730,6 +1761,7 @@ func TestStateMv_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -1746,6 +1778,7 @@ func TestStateMv_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
|
@ -33,6 +33,7 @@ func TestStateReplaceProvider(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -48,6 +49,7 @@ func TestStateReplaceProvider(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -63,6 +65,7 @@ func TestStateReplaceProvider(t *testing.T) {
|
||||
Provider: addrs.NewLegacyProvider("azurerm"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -320,6 +323,7 @@ func TestStateReplaceProvider_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -335,6 +339,7 @@ func TestStateReplaceProvider_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -350,6 +355,7 @@ func TestStateReplaceProvider_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewLegacyProvider("azurerm"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -33,6 +33,7 @@ func TestStateRm(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -48,6 +49,7 @@ func TestStateRm(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -100,6 +102,7 @@ func TestStateRmNotChildModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
// This second instance has the same local address as the first but
|
||||
// is in a child module. Older versions of Terraform would incorrectly
|
||||
@ -118,6 +121,7 @@ func TestStateRmNotChildModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -191,6 +195,7 @@ func TestStateRmNoArgs(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -206,6 +211,7 @@ func TestStateRmNoArgs(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -252,6 +258,7 @@ func TestStateRmNonExist(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -267,6 +274,7 @@ func TestStateRmNonExist(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -309,6 +317,7 @@ func TestStateRm_backupExplicit(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -324,6 +333,7 @@ func TestStateRm_backupExplicit(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -428,6 +438,7 @@ func TestStateRm_backendState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -443,6 +454,7 @@ func TestStateRm_backendState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -509,6 +521,7 @@ func TestStateRm_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -524,6 +537,7 @@ func TestStateRm_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
|
@ -172,6 +172,7 @@ func (c *StateShowCommand) Run(args []string) int {
|
||||
addr.Resource,
|
||||
is.Current,
|
||||
absPc,
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
root, outputs, err := jsonstate.MarshalForRenderer(statefile.New(singleInstance, "", 0), schemas)
|
||||
|
@ -34,6 +34,7 @@ func TestStateShow(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -96,6 +97,7 @@ func TestStateShow_multi(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -111,6 +113,7 @@ func TestStateShow_multi(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: submod.Module(),
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -222,6 +225,7 @@ func TestStateShow_configured_provider(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test-beta"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -364,6 +368,7 @@ func stateWithSensitiveValueForStateShow() *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -186,7 +186,7 @@ func (c *TaintCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
obj.Status = states.ObjectTainted
|
||||
ss.SetResourceInstanceCurrent(addr, obj, rs.ProviderConfig)
|
||||
ss.SetResourceInstanceCurrent(addr, obj, rs.ProviderConfig, is.ProviderKey)
|
||||
|
||||
if err := stateMgr.WriteState(state); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
|
@ -33,6 +33,7 @@ func TestTaint(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -73,6 +74,7 @@ func TestTaint_lockedState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -125,6 +127,7 @@ func TestTaint_backup(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -169,6 +172,7 @@ func TestTaint_backupDisable(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -236,6 +240,7 @@ func TestTaint_defaultState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -278,6 +283,7 @@ func TestTaint_defaultWorkspaceState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testWorkspace := "development"
|
||||
@ -317,6 +323,7 @@ func TestTaint_missing(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -355,6 +362,7 @@ func TestTaint_missingAllow(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -411,6 +419,7 @@ func TestTaint_stateOut(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -452,6 +461,7 @@ func TestTaint_module(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -467,6 +477,7 @@ func TestTaint_module(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -513,6 +524,7 @@ func TestTaint_checkRequiredVersion(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
path := testStateFile(t, state)
|
||||
|
@ -187,7 +187,7 @@ func (c *UntaintCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
obj.Status = states.ObjectReady
|
||||
ss.SetResourceInstanceCurrent(addr, obj, rs.ProviderConfig)
|
||||
ss.SetResourceInstanceCurrent(addr, obj, rs.ProviderConfig, is.ProviderKey)
|
||||
|
||||
if err := stateMgr.WriteState(state); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
|
@ -32,6 +32,7 @@ func TestUntaint(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -77,6 +78,7 @@ func TestUntaint_lockedState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -129,6 +131,7 @@ func TestUntaint_backup(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -184,6 +187,7 @@ func TestUntaint_backupDisable(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -255,6 +259,7 @@ func TestUntaint_defaultState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -302,6 +307,7 @@ func TestUntaint_defaultWorkspaceState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testWorkspace := "development"
|
||||
@ -345,6 +351,7 @@ func TestUntaint_missing(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -383,6 +390,7 @@ func TestUntaint_missingAllow(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
@ -439,6 +447,7 @@ func TestUntaint_stateOut(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
testStateFileDefault(t, state)
|
||||
@ -488,6 +497,7 @@ func TestUntaint_module(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -503,6 +513,7 @@ func TestUntaint_module(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
statePath := testStateFile(t, state)
|
||||
|
@ -309,6 +309,7 @@ func TestOperation_planNoChanges(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
addrs.RootModuleInstance.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
PriorState: states.NewState(),
|
||||
|
@ -233,6 +233,7 @@ func testState() *states.State {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
// DeepCopy is used here to ensure our synthetic state matches exactly
|
||||
// with a state that will have been copied during the command
|
||||
|
@ -665,7 +665,7 @@ Plan: 1 to add, 0 to change, 0 to destroy.
|
||||
Namespace: "hashicorp",
|
||||
Type: "test",
|
||||
},
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
Config: &configs.Config{},
|
||||
Providers: map[addrs.Provider]providers.ProviderSchema{
|
||||
@ -812,7 +812,7 @@ this time it is very bad
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -825,7 +825,7 @@ this time it is very bad
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceDeposed(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -839,7 +839,7 @@ this time it is very bad
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stdout: `
|
||||
Warning: first warning
|
||||
@ -880,7 +880,7 @@ up manually:
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -893,7 +893,7 @@ up manually:
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceDeposed(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -907,7 +907,7 @@ up manually:
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stdout: `
|
||||
Warning: first warning
|
||||
@ -954,7 +954,7 @@ up manually:
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -978,7 +978,7 @@ up manually:
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stdout: `
|
||||
Warning: first warning
|
||||
@ -1096,7 +1096,7 @@ OpenTofu was in the process of creating the following resources for
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -1110,7 +1110,7 @@ OpenTofu was in the process of creating the following resources for
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
},
|
||||
created: nil,
|
||||
@ -1146,7 +1146,7 @@ test:
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -1160,7 +1160,7 @@ test:
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
},
|
||||
created: nil,
|
||||
@ -1196,7 +1196,7 @@ OpenTofu has already created the following resources for "setup_block" from
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -1210,7 +1210,7 @@ OpenTofu has already created the following resources for "setup_block" from
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
nil: states.BuildState(func(state *states.SyncState) {
|
||||
state.SetResourceInstanceCurrent(
|
||||
@ -1225,7 +1225,7 @@ OpenTofu has already created the following resources for "setup_block" from
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -1239,7 +1239,7 @@ OpenTofu has already created the following resources for "setup_block" from
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
},
|
||||
created: []*plans.ResourceInstanceChangeSrc{
|
||||
@ -2021,7 +2021,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
want: []map[string]interface{}{
|
||||
{
|
||||
@ -2060,7 +2060,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -2073,7 +2073,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceDeposed(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -2087,7 +2087,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
want: []map[string]interface{}{
|
||||
{
|
||||
@ -2157,7 +2157,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -2170,7 +2170,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceDeposed(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -2184,7 +2184,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
want: []map[string]interface{}{
|
||||
{
|
||||
@ -2266,7 +2266,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -2290,7 +2290,7 @@ func TestTestJSON_DestroySummary(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}), want: []map[string]interface{}{
|
||||
{
|
||||
"@level": "error",
|
||||
@ -2864,7 +2864,7 @@ func TestTestJSON_Run(t *testing.T) {
|
||||
Namespace: "hashicorp",
|
||||
Type: "test",
|
||||
},
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
Config: &configs.Config{
|
||||
Module: &configs.Module{},
|
||||
@ -3021,7 +3021,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -3035,7 +3035,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
},
|
||||
changes: nil,
|
||||
@ -3074,7 +3074,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -3088,7 +3088,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
},
|
||||
changes: nil,
|
||||
@ -3129,7 +3129,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -3143,7 +3143,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
nil: states.BuildState(func(state *states.SyncState) {
|
||||
state.SetResourceInstanceCurrent(
|
||||
@ -3158,7 +3158,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.AbsResourceInstance{
|
||||
@ -3172,7 +3172,7 @@ func TestTestJSON_FatalInterruptSummary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
&states.ResourceInstanceObjectSrc{},
|
||||
addrs.AbsProviderConfig{})
|
||||
addrs.AbsProviderConfig{}, addrs.NoKey)
|
||||
}),
|
||||
},
|
||||
changes: []*plans.ResourceInstanceChangeSrc{
|
||||
@ -3279,7 +3279,7 @@ func TestSaveErroredStateFile(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -3292,7 +3292,7 @@ func TestSaveErroredStateFile(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceDeposed(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -3306,7 +3306,7 @@ func TestSaveErroredStateFile(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stderr: `
|
||||
Writing state to file: errored_test.tfstate
|
||||
@ -3328,7 +3328,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -3352,7 +3352,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stderr: `
|
||||
Writing state to file: errored_test.tfstate
|
||||
@ -3384,7 +3384,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stderr: "",
|
||||
want: []map[string]interface{}{
|
||||
@ -3410,7 +3410,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -3423,7 +3423,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceDeposed(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -3437,7 +3437,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stderr: "",
|
||||
want: []map[string]interface{}{
|
||||
@ -3463,7 +3463,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
state.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
@ -3487,7 +3487,7 @@ Writing state to file: errored_test.tfstate
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
stderr: "",
|
||||
want: []map[string]interface{}{
|
||||
|
@ -251,6 +251,7 @@ func TestWorkspace_createWithState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -250,6 +250,11 @@ func NewModule(primaryFiles, overrideFiles []*File, call StaticModuleCall, sourc
|
||||
diags = append(diags, mDiags...)
|
||||
}
|
||||
|
||||
for _, pc := range mod.ProviderConfigs {
|
||||
pDiags := pc.decodeStaticFields(mod.StaticEvaluator)
|
||||
diags = append(diags, pDiags...)
|
||||
}
|
||||
|
||||
diags = append(diags, checkModuleExperiments(mod)...)
|
||||
|
||||
// Generate the FQN -> LocalProviderName map
|
||||
|
@ -95,7 +95,7 @@ func TestParserLoadConfigDirSuccess(t *testing.T) {
|
||||
|
||||
for _, info := range files {
|
||||
name := info.Name()
|
||||
t.Run(fmt.Sprintf("%s as module", name), func(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
src, err := os.ReadFile(filepath.Join("testdata/valid-files", name))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -11,8 +11,11 @@ import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/gohcl"
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/instances"
|
||||
"github.com/opentofu/opentofu/internal/lang/evalchecks"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
@ -42,6 +45,9 @@ type Provider struct {
|
||||
// testing framework to instantiate test provider wrapper.
|
||||
IsMocked bool
|
||||
MockResources []*MockResource
|
||||
|
||||
ForEach hcl.Expression
|
||||
Instances map[addrs.InstanceKey]instances.RepetitionData
|
||||
}
|
||||
|
||||
func decodeProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) {
|
||||
@ -95,8 +101,21 @@ func decodeProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) {
|
||||
diags = append(diags, versionDiags...)
|
||||
}
|
||||
|
||||
if attr, exists := content.Attributes["for_each"]; exists {
|
||||
provider.ForEach = attr.Expr
|
||||
}
|
||||
|
||||
if len(provider.Alias) == 0 && provider.ForEach != nil {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: `Alias required when using "for_each"`,
|
||||
Detail: `The for_each argument is allowed only for provider configurations with an alias.`,
|
||||
Subject: provider.ForEach.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
// Reserved attribute names
|
||||
for _, name := range []string{"count", "depends_on", "for_each", "source"} {
|
||||
for _, name := range []string{"count", "depends_on", "source"} {
|
||||
if attr, exists := content.Attributes[name]; exists {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
@ -145,6 +164,38 @@ func decodeProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) {
|
||||
return provider, diags
|
||||
}
|
||||
|
||||
func (p *Provider) decodeStaticFields(eval *StaticEvaluator) hcl.Diagnostics {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
if p.ForEach != nil {
|
||||
forEachRefsFunc := func(refs []*addrs.Reference) (*hcl.EvalContext, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
evalContext, evalDiags := eval.EvalContext(StaticIdentifier{
|
||||
Module: eval.call.addr,
|
||||
Subject: fmt.Sprintf("provider.%s.%s.for_each", p.Name, p.Alias),
|
||||
DeclRange: p.ForEach.Range(),
|
||||
}, refs)
|
||||
return evalContext, diags.Append(evalDiags)
|
||||
}
|
||||
|
||||
forVal, evalDiags := evalchecks.EvaluateForEachExpression(p.ForEach, forEachRefsFunc)
|
||||
diags = append(diags, evalDiags.ToHCL()...)
|
||||
if evalDiags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
p.Instances = make(map[addrs.InstanceKey]instances.RepetitionData)
|
||||
for k, v := range forVal {
|
||||
p.Instances[addrs.StringKey(k)] = instances.RepetitionData{
|
||||
EachKey: cty.StringVal(k),
|
||||
EachValue: v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
// Addr returns the address of the receiving provider configuration, relative
|
||||
// to its containing module.
|
||||
func (p *Provider) Addr() addrs.LocalProviderConfig {
|
||||
@ -247,11 +298,13 @@ var providerBlockSchema = &hcl.BodySchema{
|
||||
{
|
||||
Name: "version",
|
||||
},
|
||||
{
|
||||
Name: "for_each",
|
||||
},
|
||||
|
||||
// Attribute names reserved for future expansion.
|
||||
{Name: "count"},
|
||||
{Name: "depends_on"},
|
||||
{Name: "for_each"},
|
||||
{Name: "source"},
|
||||
},
|
||||
Blocks: []hcl.BlockHeaderSchema{
|
||||
|
@ -30,10 +30,9 @@ func TestProviderReservedNames(t *testing.T) {
|
||||
`config.tf:4,13-20: Version constraints inside provider configuration blocks are deprecated; OpenTofu 0.13 and earlier allowed provider version constraints inside the provider configuration block, but that is now deprecated and will be removed in a future version of OpenTofu. To silence this warning, move the provider version constraint into the required_providers block.`,
|
||||
`config.tf:10,3-8: Reserved argument name in provider block; The provider argument name "count" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:11,3-13: Reserved argument name in provider block; The provider argument name "depends_on" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:12,3-11: Reserved argument name in provider block; The provider argument name "for_each" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:14,3-12: Reserved block type name in provider block; The block type name "lifecycle" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:15,3-9: Reserved block type name in provider block; The block type name "locals" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:13,3-9: Reserved argument name in provider block; The provider argument name "source" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:12,3-9: Reserved argument name in provider block; The provider argument name "source" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:13,3-12: Reserved block type name in provider block; The block type name "lifecycle" is reserved for use by OpenTofu in a future version.`,
|
||||
`config.tf:14,3-9: Reserved block type name in provider block; The block type name "locals" is reserved for use by OpenTofu in a future version.`,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -322,6 +322,8 @@ func validateProviderConfigs(parentCall *ModuleCall, cfg *Config, noProviderConf
|
||||
// of the configuration block declaration.
|
||||
configured := map[string]hcl.Range{}
|
||||
|
||||
instanced := map[string]bool{}
|
||||
|
||||
// the set of configuration_aliases defined in the required_providers
|
||||
// block, with the fully qualified provider type.
|
||||
configAliases := map[string]addrs.AbsProviderConfig{}
|
||||
@ -339,6 +341,8 @@ func validateProviderConfigs(parentCall *ModuleCall, cfg *Config, noProviderConf
|
||||
} else {
|
||||
emptyConfigs[name] = pc.DeclRange
|
||||
}
|
||||
|
||||
instanced[name] = len(pc.Instances) != 0
|
||||
}
|
||||
|
||||
if mod.ProviderRequirements != nil {
|
||||
@ -470,6 +474,37 @@ func validateProviderConfigs(parentCall *ModuleCall, cfg *Config, noProviderConf
|
||||
}
|
||||
}
|
||||
|
||||
// Validate provider expansion is properly configured
|
||||
for _, modCall := range mod.ModuleCalls {
|
||||
for _, passed := range modCall.Providers {
|
||||
if passed.InChild.KeyExpression != nil {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid module provider configuration",
|
||||
Detail: "Instance keys are not allowed on the left side of a provider configuration assignment.",
|
||||
Subject: passed.InChild.KeyExpression.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
isInstanced := instanced[providerName(passed.InParent.Name, passed.InParent.Alias)]
|
||||
diags = diags.Extend(passed.InParent.InstanceValidation("module", isInstanced))
|
||||
}
|
||||
}
|
||||
// Validate that resources using provider keys are properly configured
|
||||
checkProviderKeys := func(resourceConfigs map[string]*Resource) {
|
||||
for _, r := range resourceConfigs {
|
||||
// We're looking for resources with a specific provider reference
|
||||
if r.ProviderConfigRef == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
isInstanced := instanced[providerName(r.ProviderConfigRef.Name, r.ProviderConfigRef.Alias)]
|
||||
diags = diags.Extend(r.ProviderConfigRef.InstanceValidation("resource", isInstanced))
|
||||
}
|
||||
}
|
||||
checkProviderKeys(mod.ManagedResources)
|
||||
checkProviderKeys(mod.DataResources)
|
||||
|
||||
// Verify that any module calls only refer to named providers, and that
|
||||
// those providers will have a configuration at runtime. This way we can
|
||||
// direct users where to add the missing configuration, because the runtime
|
||||
|
@ -659,11 +659,31 @@ type ProviderConfigRef struct {
|
||||
// export this so providers don't need to be re-resolved.
|
||||
// This same field is also added to the Provider struct.
|
||||
providerType addrs.Provider
|
||||
|
||||
KeyExpression hcl.Expression
|
||||
}
|
||||
|
||||
func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConfigRef, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
var keyExpr hcl.Expression
|
||||
|
||||
const (
|
||||
// name.alias[const_key]
|
||||
nameIndex = 0
|
||||
aliasIndex = 1
|
||||
keyIndex = 2
|
||||
)
|
||||
var maxTraversalLength = keyIndex + 1
|
||||
|
||||
// name.alias[expr_key]
|
||||
if iex, ok := expr.(*hclsyntax.IndexExpr); ok {
|
||||
maxTraversalLength = aliasIndex + 1 // expr key found, no const key allowed
|
||||
|
||||
keyExpr = iex.Key
|
||||
expr = iex.Collection
|
||||
}
|
||||
|
||||
var shimDiags hcl.Diagnostics
|
||||
expr, shimDiags = shimTraversalInString(expr, false)
|
||||
diags = append(diags, shimDiags...)
|
||||
@ -677,7 +697,7 @@ func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConf
|
||||
diags = append(diags, travDiags...)
|
||||
}
|
||||
|
||||
if len(traversal) < 1 || len(traversal) > 2 {
|
||||
if len(traversal) == 0 || len(traversal) > maxTraversalLength {
|
||||
// A provider reference was given as a string literal in the legacy
|
||||
// configuration language and there are lots of examples out there
|
||||
// showing that usage, so we'll sniff for that situation here and
|
||||
@ -696,7 +716,7 @@ func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConf
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration reference",
|
||||
Detail: fmt.Sprintf("The %s argument requires a provider type name, optionally followed by a period and then a configuration alias.", argName),
|
||||
Detail: fmt.Sprintf("The %s argument requires a provider type name, optionally followed by a period and then a configuration alias and optional instance key.", argName),
|
||||
Subject: expr.Range().Ptr(),
|
||||
})
|
||||
return nil, diags
|
||||
@ -704,25 +724,26 @@ func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConf
|
||||
|
||||
// verify that the provider local name is normalized
|
||||
name := traversal.RootName()
|
||||
nameDiags := checkProviderNameNormalized(name, traversal[0].SourceRange())
|
||||
nameDiags := checkProviderNameNormalized(name, traversal[nameIndex].SourceRange())
|
||||
diags = append(diags, nameDiags...)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
ret := &ProviderConfigRef{
|
||||
Name: name,
|
||||
NameRange: traversal[0].SourceRange(),
|
||||
Name: name,
|
||||
NameRange: traversal[nameIndex].SourceRange(),
|
||||
KeyExpression: keyExpr,
|
||||
}
|
||||
|
||||
if len(traversal) > 1 {
|
||||
aliasStep, ok := traversal[1].(hcl.TraverseAttr)
|
||||
if len(traversal) > aliasIndex {
|
||||
aliasStep, ok := traversal[aliasIndex].(hcl.TraverseAttr)
|
||||
if !ok {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration reference",
|
||||
Detail: "Provider name must either stand alone or be followed by a period and then a configuration alias.",
|
||||
Subject: traversal[1].SourceRange().Ptr(),
|
||||
Subject: traversal[aliasIndex].SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
}
|
||||
@ -731,6 +752,30 @@ func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConf
|
||||
ret.AliasRange = aliasStep.SourceRange().Ptr()
|
||||
}
|
||||
|
||||
if len(traversal) > keyIndex {
|
||||
indexStep, ok := traversal[keyIndex].(hcl.TraverseIndex)
|
||||
if !ok {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration reference",
|
||||
Detail: "Provider name must either stand alone or be followed by a period and then a configuration alias.",
|
||||
Subject: traversal[keyIndex].SourceRange().Ptr(),
|
||||
})
|
||||
return ret, diags
|
||||
}
|
||||
|
||||
ret.KeyExpression = hcl.StaticExpr(indexStep.Key, traversal.SourceRange())
|
||||
}
|
||||
|
||||
if len(ret.Alias) == 0 && ret.KeyExpression != nil {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider configuration reference",
|
||||
Detail: "Provider assignment requires an alias when specifying an instance key, in the form of provider.name[instance_key]",
|
||||
Subject: traversal.SourceRange().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
return ret, diags
|
||||
}
|
||||
|
||||
@ -756,6 +801,39 @@ func (r *ProviderConfigRef) String() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
func (r *ProviderConfigRef) InstanceValidation(blockType string, isInstanced bool) hcl.Diagnostics {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
summary := fmt.Sprintf("Invalid %s provider configuration", blockType)
|
||||
|
||||
if r.KeyExpression != nil {
|
||||
if r.Alias == "" {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: summary,
|
||||
Detail: "An instance key can be specified only for a provider configuration which has an alias and uses for_each.",
|
||||
Subject: r.KeyExpression.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
if !isInstanced {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: summary,
|
||||
Detail: "An instance key can be specified only for a provider configuration that uses for_each.",
|
||||
Subject: r.KeyExpression.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
} else if isInstanced {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: summary,
|
||||
Detail: "A reference to a provider configuration which uses for_each requires an instance key. Passing a collection of provider instances into a child module is not allowed.",
|
||||
Subject: r.NameRange.Ptr(),
|
||||
})
|
||||
}
|
||||
return diags
|
||||
}
|
||||
|
||||
var commonResourceAttributes = []hcl.AttributeSchema{
|
||||
{
|
||||
Name: "count",
|
||||
|
@ -16,8 +16,6 @@ import (
|
||||
)
|
||||
|
||||
// This exercises most of the logic in StaticEvaluator and staticScopeData
|
||||
//
|
||||
//nolint:cyclop // it's a test
|
||||
func TestStaticEvaluator_Evaluate(t *testing.T) {
|
||||
// Synthetic file for building test components
|
||||
testData := `
|
||||
|
@ -7,9 +7,8 @@ provider "test" {
|
||||
arbitrary = true
|
||||
|
||||
# These are all reserved and should generate errors.
|
||||
count = 3
|
||||
count = 3
|
||||
depends_on = ["foo.bar"]
|
||||
for_each = ["a", "b"]
|
||||
source = "foo.example.com/baz/bar"
|
||||
lifecycle {}
|
||||
locals {}
|
||||
|
@ -11,3 +11,8 @@ provider "bar" {
|
||||
|
||||
alias = "bar"
|
||||
}
|
||||
|
||||
provider "baz" {
|
||||
alias = "foo"
|
||||
for_each = {"a": "first", "b": "second"}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
emptyResults,
|
||||
@ -78,6 +79,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -105,6 +107,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -133,6 +136,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -161,6 +165,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -189,6 +194,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -217,6 +223,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("module.boo.module.hoo.foo.from"),
|
||||
@ -225,6 +232,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -258,6 +266,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -287,6 +296,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -316,6 +326,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -344,6 +355,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("module.boo.foo.to[0]"),
|
||||
@ -352,6 +364,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -386,6 +399,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("foo.to"),
|
||||
@ -394,6 +408,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -428,6 +443,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("foo.to[0]"),
|
||||
@ -436,6 +452,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -470,6 +487,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -499,6 +517,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("foo.from"),
|
||||
@ -507,6 +526,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -542,6 +562,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("bar.from"),
|
||||
@ -550,6 +571,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
@ -584,6 +606,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("foo.from"),
|
||||
@ -592,6 +615,7 @@ func TestApplyMoves(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
MoveResults{
|
||||
|
@ -99,41 +99,49 @@ func TestImpliedMoveStatements(t *testing.T) {
|
||||
resourceAddr("formerly_count").Instance(addrs.IntKey(0)),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("formerly_count").Instance(addrs.IntKey(1)),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("now_count").Instance(addrs.NoKey),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("formerly_count_explicit").Instance(addrs.IntKey(0)),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("formerly_count_explicit").Instance(addrs.IntKey(1)),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("now_count_explicit").Instance(addrs.NoKey),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("now_for_each_formerly_count").Instance(addrs.IntKey(0)),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("now_for_each_formerly_no_count").Instance(addrs.NoKey),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// This "ambiguous" resource is representing a rare but possible
|
||||
@ -147,11 +155,13 @@ func TestImpliedMoveStatements(t *testing.T) {
|
||||
resourceAddr("ambiguous").Instance(addrs.NoKey),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
resourceAddr("ambiguous").Instance(addrs.IntKey(0)),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// Add two resource nested in a module to ensure we find these
|
||||
@ -160,11 +170,13 @@ func TestImpliedMoveStatements(t *testing.T) {
|
||||
nestedResourceAddr("child", "formerly_count").Instance(addrs.IntKey(0)),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
nestedResourceAddr("child", "now_count").Instance(addrs.NoKey),
|
||||
instObjState(),
|
||||
providerAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -45,6 +45,7 @@ func TestSession_basicState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -60,6 +61,7 @@ func TestSession_basicState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -89,7 +89,7 @@ func (ms *Module) RemoveResource(addr addrs.Resource) {
|
||||
//
|
||||
// The provider address is a resource-wide setting and is updated for all other
|
||||
// instances of the same resource as a side-effect of this call.
|
||||
func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) {
|
||||
func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig, providerKey addrs.InstanceKey) {
|
||||
rs := ms.Resource(addr.Resource)
|
||||
// if the resource is nil and the object is nil, don't do anything!
|
||||
// you'll probably just cause issues
|
||||
@ -139,6 +139,7 @@ func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *R
|
||||
}
|
||||
// Update the resource's ProviderConfig, in case the provider has updated
|
||||
rs.ProviderConfig = provider
|
||||
is.ProviderKey = providerKey
|
||||
is.Current = obj
|
||||
}
|
||||
|
||||
@ -158,11 +159,12 @@ func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *R
|
||||
// is overwritten. Set obj to nil to remove the deposed object altogether. If
|
||||
// the instance is left with no objects after this operation then it will
|
||||
// be removed from its containing resource altogether.
|
||||
func (ms *Module) SetResourceInstanceDeposed(addr addrs.ResourceInstance, key DeposedKey, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) {
|
||||
func (ms *Module) SetResourceInstanceDeposed(addr addrs.ResourceInstance, key DeposedKey, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig, providerKey addrs.InstanceKey) {
|
||||
ms.SetResourceProvider(addr.Resource, provider)
|
||||
|
||||
rs := ms.Resource(addr.Resource)
|
||||
is := rs.EnsureInstance(addr.Key)
|
||||
is.ProviderKey = providerKey
|
||||
if obj != nil {
|
||||
is.Deposed[key] = obj
|
||||
} else {
|
||||
|
@ -99,6 +99,7 @@ func TestStatePersist(t *testing.T) {
|
||||
addrs.AbsProviderConfig{
|
||||
Provider: tfaddr.Provider{Namespace: "local"},
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
return s, func() {}
|
||||
},
|
||||
|
@ -70,6 +70,11 @@ type ResourceInstance struct {
|
||||
// replaced and are pending destruction due to the create_before_destroy
|
||||
// lifecycle mode.
|
||||
Deposed map[DeposedKey]*ResourceInstanceObjectSrc
|
||||
|
||||
// ProviderKey, in combination with Resource.ProviderConfig, represents
|
||||
// the resource instance's provider configuration. This is only set
|
||||
// when using provider iteration on resources or modules
|
||||
ProviderKey addrs.InstanceKey
|
||||
}
|
||||
|
||||
// NewResourceInstance constructs and returns a new ResourceInstance, ready to
|
||||
|
@ -118,8 +118,9 @@ func (i *ResourceInstance) DeepCopy() *ResourceInstance {
|
||||
}
|
||||
|
||||
return &ResourceInstance{
|
||||
Current: i.Current.DeepCopy(),
|
||||
Deposed: deposed,
|
||||
Current: i.Current.DeepCopy(),
|
||||
Deposed: deposed,
|
||||
ProviderKey: i.ProviderKey,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ func TestState(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
childModule := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
@ -254,6 +255,7 @@ func TestStateDeepCopy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
rootModule.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -288,6 +290,7 @@ func TestStateDeepCopy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
childModule := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
@ -326,6 +329,7 @@ func TestStateHasResourceInstanceObjects(t *testing.T) {
|
||||
Status: ObjectReady,
|
||||
},
|
||||
providerConfig,
|
||||
addrs.NoKey,
|
||||
)
|
||||
},
|
||||
true,
|
||||
@ -339,6 +343,7 @@ func TestStateHasResourceInstanceObjects(t *testing.T) {
|
||||
Status: ObjectReady,
|
||||
},
|
||||
childModuleProviderConfig,
|
||||
addrs.NoKey,
|
||||
)
|
||||
},
|
||||
true,
|
||||
@ -352,6 +357,7 @@ func TestStateHasResourceInstanceObjects(t *testing.T) {
|
||||
Status: ObjectTainted,
|
||||
},
|
||||
providerConfig,
|
||||
addrs.NoKey,
|
||||
)
|
||||
},
|
||||
true,
|
||||
@ -366,6 +372,7 @@ func TestStateHasResourceInstanceObjects(t *testing.T) {
|
||||
Status: ObjectTainted,
|
||||
},
|
||||
providerConfig,
|
||||
addrs.NoKey,
|
||||
)
|
||||
},
|
||||
true,
|
||||
@ -384,6 +391,7 @@ func TestStateHasResourceInstanceObjects(t *testing.T) {
|
||||
Status: ObjectTainted,
|
||||
},
|
||||
providerConfig,
|
||||
addrs.NoKey,
|
||||
)
|
||||
s := ss.Lock()
|
||||
delete(s.Modules[""].Resources["test.foo"].Instances, addrs.NoKey)
|
||||
@ -400,6 +408,7 @@ func TestStateHasResourceInstanceObjects(t *testing.T) {
|
||||
Status: ObjectReady,
|
||||
},
|
||||
providerConfig,
|
||||
addrs.NoKey,
|
||||
)
|
||||
},
|
||||
false, // data resources aren't managed resources, so they don't count
|
||||
@ -437,6 +446,7 @@ func TestState_MoveAbsResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
src := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "foo"}.Absolute(addrs.RootModuleInstance)
|
||||
|
||||
@ -504,6 +514,7 @@ func TestState_MoveAbsResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
cm.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -520,6 +531,7 @@ func TestState_MoveAbsResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
src := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "child"}.Absolute(srcModule)
|
||||
@ -569,6 +581,7 @@ func TestState_MoveAbsResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
src := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "child"}.Absolute(srcModule)
|
||||
@ -615,6 +628,7 @@ func TestState_MoveAbsResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
src := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "child"}.Absolute(srcModule)
|
||||
@ -660,6 +674,7 @@ func TestState_MaybeMoveAbsResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
src := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "foo"}.Absolute(addrs.RootModuleInstance)
|
||||
@ -700,6 +715,7 @@ func TestState_MoveAbsResourceInstance(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
// src resource from the state above
|
||||
src := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_thing", Name: "foo"}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
|
||||
@ -770,6 +786,7 @@ func TestState_MaybeMoveAbsResourceInstance(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// For a little extra fun, let's go from a resource to a resource instance: test_thing.foo to test_thing.bar[1]
|
||||
@ -816,6 +833,7 @@ func TestState_MoveModuleInstance(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
dstModule := addrs.RootModuleInstance.Child("child", addrs.IntKey(3))
|
||||
@ -863,6 +881,7 @@ func TestState_MaybeMoveModuleInstance(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
dst := addrs.RootModuleInstance.Child("kinder", addrs.StringKey("b"))
|
||||
@ -905,6 +924,7 @@ func TestState_MoveModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
moduleInstance := addrs.RootModuleInstance.Child("kinder", addrs.StringKey("a"))
|
||||
@ -924,6 +944,7 @@ func TestState_MoveModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
_, mc := srcModule.Call()
|
||||
@ -977,6 +998,7 @@ func TestState_MoveModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
_, dstMC := addrs.RootModule.Child("child").Call()
|
||||
|
@ -90,18 +90,29 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||
}
|
||||
}
|
||||
|
||||
providerAddr, addrDiags := addrs.ParseAbsProviderConfigStr(rsV4.ProviderConfig)
|
||||
diags.Append(addrDiags)
|
||||
if addrDiags.HasErrors() {
|
||||
// If ParseAbsProviderConfigStr returns an error, the state may have
|
||||
// been written before Provider FQNs were introduced and the
|
||||
// AbsProviderConfig string format will need normalization. If so,
|
||||
// we treat it like a legacy provider (namespace "-") and let the
|
||||
// provider installer handle detecting the FQN.
|
||||
var legacyAddrDiags tfdiags.Diagnostics
|
||||
providerAddr, legacyAddrDiags = addrs.ParseLegacyAbsProviderConfigStr(rsV4.ProviderConfig)
|
||||
if legacyAddrDiags.HasErrors() {
|
||||
continue
|
||||
var providerAddr addrs.AbsProviderConfig
|
||||
var addrDiags tfdiags.Diagnostics
|
||||
if rsV4.ProviderConfig != "" {
|
||||
providerAddr, addrDiags = addrs.ParseAbsProviderConfigStr(rsV4.ProviderConfig)
|
||||
if addrDiags.HasErrors() {
|
||||
// If ParseAbsProviderConfigStr returns an error, the state may have
|
||||
// been written before Provider FQNs were introduced and the
|
||||
// AbsProviderConfig string format will need normalization. If so,
|
||||
// we treat it like a legacy provider (namespace "-") and let the
|
||||
// provider installer handle detecting the FQN.
|
||||
var legacyAddrDiags tfdiags.Diagnostics
|
||||
providerAddr, legacyAddrDiags = addrs.ParseLegacyAbsProviderConfigStr(rsV4.ProviderConfig)
|
||||
if legacyAddrDiags.HasErrors() {
|
||||
// Neither parse formats are valid, let's report the original error
|
||||
diags = diags.Append(addrDiags)
|
||||
continue
|
||||
}
|
||||
|
||||
// Valid legacy address, but may contain warnings
|
||||
diags = diags.Append(legacyAddrDiags)
|
||||
} else {
|
||||
// Valid address, but may contain warnings
|
||||
diags = diags.Append(addrDiags)
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,6 +121,9 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||
// Ensure the resource container object is present in the state.
|
||||
ms.SetResourceProvider(rAddr, providerAddr)
|
||||
|
||||
// Keep track of instance providers for validation
|
||||
var instanceProviders []addrs.AbsProviderConfig
|
||||
|
||||
for _, isV4 := range rsV4.Instances {
|
||||
keyRaw := isV4.IndexKey
|
||||
var key addrs.InstanceKey
|
||||
@ -137,6 +151,30 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||
key = addrs.NoKey
|
||||
}
|
||||
|
||||
if isV4.ProviderConfig != "" && rsV4.ProviderConfig != "" {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Warning,
|
||||
"Provider field conflict in state",
|
||||
fmt.Sprintf("Resource %s has a provider address %s, as well as instance %s with provider address %s.", rAddr.Absolute(moduleAddr), rsV4.ProviderConfig, key, isV4.ProviderConfig),
|
||||
))
|
||||
}
|
||||
|
||||
if isV4.ProviderConfig == "" && rsV4.ProviderConfig == "" {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Provider field missing state",
|
||||
fmt.Sprintf("Resource %s is missing a provider address, both on the resource and the resource instances.", rAddr.Absolute(moduleAddr)),
|
||||
))
|
||||
}
|
||||
|
||||
instanceProvider := providerAddr
|
||||
instanceProviderKey := addrs.NoKey
|
||||
if isV4.ProviderConfig != "" {
|
||||
instanceProvider, instanceProviderKey, addrDiags = addrs.ParseAbsProviderConfigInstanceStr(isV4.ProviderConfig)
|
||||
diags = diags.Append(addrDiags)
|
||||
instanceProviders = append(instanceProviders, instanceProvider)
|
||||
}
|
||||
|
||||
instAddr := rAddr.Instance(key)
|
||||
|
||||
obj := &states.ResourceInstanceObjectSrc{
|
||||
@ -235,7 +273,7 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||
continue
|
||||
}
|
||||
|
||||
ms.SetResourceInstanceDeposed(instAddr, dk, obj, providerAddr)
|
||||
ms.SetResourceInstanceDeposed(instAddr, dk, obj, instanceProvider, instanceProviderKey)
|
||||
default:
|
||||
is := ms.ResourceInstance(instAddr)
|
||||
if is.HasCurrent() {
|
||||
@ -247,16 +285,21 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||
continue
|
||||
}
|
||||
|
||||
ms.SetResourceInstanceCurrent(instAddr, obj, providerAddr)
|
||||
ms.SetResourceInstanceCurrent(instAddr, obj, instanceProvider, instanceProviderKey)
|
||||
}
|
||||
}
|
||||
|
||||
// We repeat this after creating the instances because
|
||||
// SetResourceInstanceCurrent automatically resets this metadata based
|
||||
// on the incoming objects. That behavior is useful when we're making
|
||||
// piecemeal updates to the state during an apply, but when we're
|
||||
// reading the state file we want to reflect its contents exactly.
|
||||
ms.SetResourceProvider(rAddr, providerAddr)
|
||||
// Validate instance providers
|
||||
for i := 1; i < len(instanceProviders); i++ {
|
||||
if instanceProviders[i-1].String() != instanceProviders[i].String() {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Provider instance field conflict in state",
|
||||
fmt.Sprintf("Resource %s has instances with different provider addresses: %q != %q.", rAddr.Absolute(moduleAddr), instanceProviders[i-1], instanceProviders[i]),
|
||||
))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The root module is special in that we persist its attributes and thus
|
||||
@ -389,12 +432,25 @@ func writeStateV4(file *File, w io.Writer, enc encryption.StateEncryption) tfdia
|
||||
continue
|
||||
}
|
||||
|
||||
hasProviderInstanceKeys := false
|
||||
for _, is := range rs.Instances {
|
||||
if is.ProviderKey != addrs.NoKey {
|
||||
hasProviderInstanceKeys = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var providerConfig string
|
||||
if !hasProviderInstanceKeys {
|
||||
providerConfig = rs.ProviderConfig.String()
|
||||
}
|
||||
|
||||
sV4.Resources = append(sV4.Resources, resourceStateV4{
|
||||
Module: moduleAddr.String(),
|
||||
Mode: mode,
|
||||
Type: resourceAddr.Type,
|
||||
Name: resourceAddr.Name,
|
||||
ProviderConfig: rs.ProviderConfig.String(),
|
||||
ProviderConfig: providerConfig,
|
||||
Instances: []instanceObjectStateV4{},
|
||||
})
|
||||
rsV4 := &(sV4.Resources[len(sV4.Resources)-1])
|
||||
@ -404,7 +460,7 @@ func writeStateV4(file *File, w io.Writer, enc encryption.StateEncryption) tfdia
|
||||
var objDiags tfdiags.Diagnostics
|
||||
rsV4.Instances, objDiags = appendInstanceObjectStateV4(
|
||||
rs, is, key, is.Current, states.NotDeposed,
|
||||
rsV4.Instances,
|
||||
rsV4.Instances, hasProviderInstanceKeys,
|
||||
)
|
||||
diags = diags.Append(objDiags)
|
||||
}
|
||||
@ -412,7 +468,7 @@ func writeStateV4(file *File, w io.Writer, enc encryption.StateEncryption) tfdia
|
||||
var objDiags tfdiags.Diagnostics
|
||||
rsV4.Instances, objDiags = appendInstanceObjectStateV4(
|
||||
rs, is, key, obj, dk,
|
||||
rsV4.Instances,
|
||||
rsV4.Instances, hasProviderInstanceKeys,
|
||||
)
|
||||
diags = diags.Append(objDiags)
|
||||
}
|
||||
@ -452,7 +508,7 @@ func writeStateV4(file *File, w io.Writer, enc encryption.StateEncryption) tfdia
|
||||
return diags
|
||||
}
|
||||
|
||||
func appendInstanceObjectStateV4(rs *states.Resource, is *states.ResourceInstance, key addrs.InstanceKey, obj *states.ResourceInstanceObjectSrc, deposed states.DeposedKey, isV4s []instanceObjectStateV4) ([]instanceObjectStateV4, tfdiags.Diagnostics) {
|
||||
func appendInstanceObjectStateV4(rs *states.Resource, is *states.ResourceInstance, key addrs.InstanceKey, obj *states.ResourceInstanceObjectSrc, deposed states.DeposedKey, isV4s []instanceObjectStateV4, hasProviderInstanceKeys bool) ([]instanceObjectStateV4, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
var status string
|
||||
@ -495,6 +551,11 @@ func appendInstanceObjectStateV4(rs *states.Resource, is *states.ResourceInstanc
|
||||
}
|
||||
}
|
||||
|
||||
var providerConfig string
|
||||
if hasProviderInstanceKeys {
|
||||
providerConfig = rs.ProviderConfig.InstanceString(is.ProviderKey)
|
||||
}
|
||||
|
||||
// Extract paths from path value marks
|
||||
var paths []cty.Path
|
||||
for _, vm := range obj.AttrSensitivePaths {
|
||||
@ -509,6 +570,7 @@ func appendInstanceObjectStateV4(rs *states.Resource, is *states.ResourceInstanc
|
||||
IndexKey: rawKey,
|
||||
Deposed: string(deposed),
|
||||
Status: status,
|
||||
ProviderConfig: providerConfig,
|
||||
SchemaVersion: obj.SchemaVersion,
|
||||
AttributesFlat: obj.AttrsFlat,
|
||||
AttributesRaw: obj.AttrsJSON,
|
||||
@ -704,20 +766,23 @@ type outputStateV4 struct {
|
||||
Sensitive bool `json:"sensitive,omitempty"`
|
||||
}
|
||||
|
||||
// Note: the ProviderConfig field is only set on either the resource or the resource instance object
|
||||
// It should never be set on both
|
||||
type resourceStateV4 struct {
|
||||
Module string `json:"module,omitempty"`
|
||||
Mode string `json:"mode"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
EachMode string `json:"each,omitempty"`
|
||||
ProviderConfig string `json:"provider"`
|
||||
ProviderConfig string `json:"provider,omitempty"`
|
||||
Instances []instanceObjectStateV4 `json:"instances"`
|
||||
}
|
||||
|
||||
type instanceObjectStateV4 struct {
|
||||
IndexKey interface{} `json:"index_key,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Deposed string `json:"deposed,omitempty"`
|
||||
IndexKey interface{} `json:"index_key,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Deposed string `json:"deposed,omitempty"`
|
||||
ProviderConfig string `json:"provider,omitempty"`
|
||||
|
||||
SchemaVersion uint64 `json:"schema_version"`
|
||||
AttributesRaw json.RawMessage `json:"attributes,omitempty"`
|
||||
|
@ -273,12 +273,12 @@ func (s *SyncState) RemoveResourceIfEmpty(addr addrs.AbsResource) bool {
|
||||
//
|
||||
// If the containing module for this resource or the resource itself are not
|
||||
// already tracked in state then they will be added as a side-effect.
|
||||
func (s *SyncState) SetResourceInstanceCurrent(addr addrs.AbsResourceInstance, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) {
|
||||
func (s *SyncState) SetResourceInstanceCurrent(addr addrs.AbsResourceInstance, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig, providerKey addrs.InstanceKey) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
ms := s.state.EnsureModule(addr.Module)
|
||||
ms.SetResourceInstanceCurrent(addr.Resource, obj.DeepCopy(), provider)
|
||||
ms.SetResourceInstanceCurrent(addr.Resource, obj.DeepCopy(), provider, providerKey)
|
||||
s.maybePruneModule(addr.Module)
|
||||
}
|
||||
|
||||
@ -305,12 +305,12 @@ func (s *SyncState) SetResourceInstanceCurrent(addr addrs.AbsResourceInstance, o
|
||||
//
|
||||
// If the containing module for this resource or the resource itself are not
|
||||
// already tracked in state then they will be added as a side-effect.
|
||||
func (s *SyncState) SetResourceInstanceDeposed(addr addrs.AbsResourceInstance, key DeposedKey, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) {
|
||||
func (s *SyncState) SetResourceInstanceDeposed(addr addrs.AbsResourceInstance, key DeposedKey, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig, providerKey addrs.InstanceKey) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
ms := s.state.EnsureModule(addr.Module)
|
||||
ms.SetResourceInstanceDeposed(addr.Resource, key, obj.DeepCopy(), provider)
|
||||
ms.SetResourceInstanceDeposed(addr.Resource, key, obj.DeepCopy(), provider, providerKey)
|
||||
s.maybePruneModule(addr.Module)
|
||||
}
|
||||
|
||||
@ -443,7 +443,7 @@ func (s *SyncState) RemovePlannedResourceInstanceObjects() {
|
||||
if is.Current != nil && is.Current.Status == ObjectPlanned {
|
||||
// Setting the current instance to nil removes it from the
|
||||
// state altogether if there are not also deposed instances.
|
||||
ms.SetResourceInstanceCurrent(instAddr, nil, rs.ProviderConfig)
|
||||
ms.SetResourceInstanceCurrent(instAddr, nil, rs.ProviderConfig, addrs.NoKey)
|
||||
}
|
||||
|
||||
for dk, obj := range is.Deposed {
|
||||
|
@ -294,13 +294,15 @@ func (c *Context) watchStop(walker *ContextGraphWalker) (chan struct{}, <-chan s
|
||||
// Copy the providers so that a misbehaved blocking Stop doesn't
|
||||
// completely hang OpenTofu.
|
||||
walker.providerLock.Lock()
|
||||
ps := make([]providers.Interface, 0, len(walker.providerCache))
|
||||
for _, p := range walker.providerCache {
|
||||
ps = append(ps, p)
|
||||
toStop := make([]providers.Interface, 0, len(walker.providerCache))
|
||||
for _, providerMap := range walker.providerCache {
|
||||
for _, provider := range providerMap {
|
||||
toStop = append(toStop, provider)
|
||||
}
|
||||
}
|
||||
defer walker.providerLock.Unlock()
|
||||
|
||||
for _, p := range ps {
|
||||
for _, p := range toStop {
|
||||
// We ignore the error for now since there isn't any reasonable
|
||||
// action to take if there is an error here, since the stop is still
|
||||
// advisory: OpenTofu will exit once the graph node completes.
|
||||
|
@ -21,11 +21,14 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/checks"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
)
|
||||
|
||||
// Test that the PreApply hook is called with the correct deposed key
|
||||
@ -46,6 +49,7 @@ func TestContext2Apply_createBeforeDestroy_deposedKeyPreApply(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -55,6 +59,7 @@ func TestContext2Apply_createBeforeDestroy_deposedKeyPreApply(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
hook := new(MockHook)
|
||||
@ -229,7 +234,7 @@ resource "test_instance" "a" {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"id":"a","value":"old","type":"test"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
|
||||
// test_instance.b depended on test_instance.a, and therefor should be
|
||||
// destroyed before any changes to test_instance.a
|
||||
@ -237,7 +242,7 @@ resource "test_instance" "a" {
|
||||
AttrsJSON: []byte(`{"id":"b"}`),
|
||||
Status: states.ObjectReady,
|
||||
Dependencies: []addrs.ConfigResource{addrA.ContainingResource().Config()},
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -279,6 +284,7 @@ func TestApply_updateDependencies(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
binAddr.Resource,
|
||||
@ -290,6 +296,7 @@ func TestApply_updateDependencies(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
bazAddr.Resource,
|
||||
@ -302,6 +309,7 @@ func TestApply_updateDependencies(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
barAddr.Resource,
|
||||
@ -310,6 +318,7 @@ func TestApply_updateDependencies(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
m := testModuleInline(t, map[string]string{
|
||||
@ -428,7 +437,7 @@ resource "test_resource" "b" {
|
||||
},
|
||||
},
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -587,6 +596,7 @@ resource "test_object" "x" {
|
||||
AttrsJSON: []byte(`{"test_string":"deposed"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -765,6 +775,7 @@ resource "test_object" "b" {
|
||||
AttrsJSON: []byte(`{"test_string":"ok"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.b").Resource,
|
||||
@ -773,6 +784,7 @@ resource "test_object" "b" {
|
||||
AttrsJSON: []byte(`{"test_string":"ok"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1475,6 +1487,7 @@ resource "test_object" "x" {
|
||||
AttrsJSON: []byte(`{"test_string":"ok"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1525,6 +1538,7 @@ resource "test_object" "y" {
|
||||
AttrsJSON: []byte(`{"test_string":"x"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1681,6 +1695,7 @@ output "from_resource" {
|
||||
AttrsJSON: []byte(`{"test_string":"wrong_val"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1736,6 +1751,7 @@ output "from_resource" {
|
||||
AttrsJSON: []byte(`{"test_string":"wrong val"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
mod.SetOutputValue("from_resource", cty.StringVal("wrong val"), false)
|
||||
|
||||
@ -1806,6 +1822,7 @@ resource "test_object" "y" {
|
||||
AttrsJSON: []byte(`{"test_string":"y"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2318,6 +2335,7 @@ func TestContext2Apply_forgetOrphanAndDeposed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr(addr).Resource,
|
||||
@ -2328,6 +2346,7 @@ func TestContext2Apply_forgetOrphanAndDeposed(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -2358,6 +2377,372 @@ func TestContext2Apply_forgetOrphanAndDeposed(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext2Apply_providerExpandWithTargetOrExclude(t *testing.T) {
|
||||
// This test is covering a potentially-tricky interaction between the
|
||||
// logic that updates the provider instance references for resource
|
||||
// instances in state snapshots, and the -target/-exclude features which
|
||||
// cause OpenTofu to skip visiting certain objects.
|
||||
//
|
||||
// The main priority is that we never leave the final state snapshot
|
||||
// in a form that would cause errors or incorrect behavior on a future
|
||||
// plan/apply round. This test covers the current way we resolve the
|
||||
// ambiguity at the time of writing -- by updating the provider
|
||||
// instance addresses of all instances of any resource where at least
|
||||
// one instance is included in the plan -- but if future changes make
|
||||
// this test fail then it might be valid to introduce a different rule
|
||||
// as long as it still guarantees to create a valid final state snapshot.
|
||||
|
||||
rsrcFirst := addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "mock",
|
||||
Name: "first",
|
||||
}.Absolute(addrs.RootModuleInstance)
|
||||
rsrcFirstInstA := rsrcFirst.Instance(addrs.StringKey("a"))
|
||||
rsrcFirstInstB := rsrcFirst.Instance(addrs.StringKey("b"))
|
||||
rsrcSecond := addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "mock",
|
||||
Name: "second",
|
||||
}.Absolute(addrs.RootModuleInstance)
|
||||
rsrcSecondInstA := rsrcSecond.Instance(addrs.StringKey("a"))
|
||||
rsrcSecondInstB := rsrcSecond.Instance(addrs.StringKey("b"))
|
||||
|
||||
// We use the same test sequence for both -target and -exclude, with
|
||||
// makeStep2PlanOpts providing whichever filter is appropriate for
|
||||
// each test.
|
||||
// For correct operation the plan options must cause OpenTofu to
|
||||
// skip both instances of mock.second and visit at least one instance
|
||||
// of mock.first.
|
||||
runTest := func(t *testing.T, makeStep2PlanOpts func(plans.Mode) *PlanOpts) {
|
||||
mockProviderAddr := addrs.NewBuiltInProvider("mock")
|
||||
providerConfigBefore := addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: mockProviderAddr,
|
||||
Alias: "before",
|
||||
}
|
||||
providerConfigAfter := addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: mockProviderAddr,
|
||||
Alias: "after",
|
||||
}
|
||||
normalPlanOpts := &PlanOpts{
|
||||
Mode: plans.NormalMode,
|
||||
}
|
||||
p := &MockProvider{
|
||||
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
|
||||
Provider: providers.Schema{
|
||||
Block: &configschema.Block{},
|
||||
},
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"mock": {
|
||||
Block: &configschema.Block{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// For this particular test we'll also save state snapshots in JSON format,
|
||||
// so that we're exercising the state snapshot writer and reader in similar way
|
||||
// to how OpenTofu CLI would do it, in case its normalization rules and
|
||||
// consistency checks cause any problems that we can't notice when we're just
|
||||
// passing pointers to the live data structure.
|
||||
var stateJSON []byte
|
||||
readStateSnapshot := func(t *testing.T) *states.State {
|
||||
t.Helper()
|
||||
if len(stateJSON) == 0 {
|
||||
return states.NewState()
|
||||
}
|
||||
ret, err := statefile.Read(bytes.NewReader(stateJSON), encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read latest state snapshot: %s", err)
|
||||
}
|
||||
return ret.State
|
||||
}
|
||||
writeStateSnapshot := func(t *testing.T, state *states.State) {
|
||||
t.Helper()
|
||||
f := &statefile.File{
|
||||
State: state,
|
||||
TerraformVersion: version.SemVer,
|
||||
}
|
||||
buf := bytes.NewBuffer(nil)
|
||||
err := statefile.Write(f, buf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write new state snapshot: %s", err)
|
||||
}
|
||||
stateJSON = buf.Bytes()
|
||||
}
|
||||
assertResourceInstanceProviderInstance := func(
|
||||
t *testing.T,
|
||||
state *states.State,
|
||||
addr addrs.AbsResourceInstance,
|
||||
wantConfigAddr addrs.AbsProviderConfig,
|
||||
wantKey addrs.InstanceKey,
|
||||
) {
|
||||
t.Helper()
|
||||
rsrcAddr := addr.ContainingResource()
|
||||
r := state.Resource(rsrcAddr)
|
||||
if r == nil {
|
||||
t.Fatalf("state has no record of %s", rsrcAddr)
|
||||
}
|
||||
ri := r.Instance(addr.Resource.Key)
|
||||
if ri == nil {
|
||||
t.Fatalf("state has no record of %s", addr)
|
||||
}
|
||||
ok := true
|
||||
if got, want := r.ProviderConfig, wantConfigAddr; got.String() != want.String() {
|
||||
t.Errorf(
|
||||
"%s has incorrect provider configuration address\ngot: %s\nwant: %s",
|
||||
rsrcAddr, got, want,
|
||||
)
|
||||
ok = false
|
||||
}
|
||||
if got, want := ri.ProviderKey, wantKey; got != want {
|
||||
t.Errorf(
|
||||
"%s has incorrect provider instance key\ngot: %s\nwant: %s",
|
||||
addr, got, want,
|
||||
)
|
||||
ok = false
|
||||
}
|
||||
if !ok {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
t.Log("Step 1: Apply with a multi-instance provider config and two resources to create our initial state")
|
||||
{
|
||||
state := readStateSnapshot(t)
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
terraform {
|
||||
required_providers {
|
||||
mock = {
|
||||
source = "terraform.io/builtin/mock"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
instances = toset(["a", "b"])
|
||||
}
|
||||
|
||||
provider "mock" {
|
||||
alias = "before"
|
||||
for_each = local.instances
|
||||
}
|
||||
|
||||
resource "mock" "first" {
|
||||
# NOTE: This is a bad example to follow in a real config,
|
||||
# since it would not be possible to remove elements from
|
||||
# local.instances without encountering an error. We don't
|
||||
# intend to do that for this test, though.
|
||||
for_each = local.instances
|
||||
provider = mock.before[each.key]
|
||||
}
|
||||
|
||||
resource "mock" "second" {
|
||||
for_each = local.instances
|
||||
provider = mock.before[each.key]
|
||||
}
|
||||
`,
|
||||
})
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewBuiltInProvider("mock"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
plan, diags := ctx.Plan(m, state, normalPlanOpts)
|
||||
assertNoErrors(t, diags)
|
||||
|
||||
newState, diags := ctx.Apply(plan, m)
|
||||
assertNoErrors(t, diags)
|
||||
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcFirstInstA,
|
||||
providerConfigBefore, addrs.StringKey("a"),
|
||||
)
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcFirstInstB,
|
||||
providerConfigBefore, addrs.StringKey("b"),
|
||||
)
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcSecondInstA,
|
||||
providerConfigBefore, addrs.StringKey("a"),
|
||||
)
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcSecondInstB,
|
||||
providerConfigBefore, addrs.StringKey("b"),
|
||||
)
|
||||
|
||||
writeStateSnapshot(t, newState)
|
||||
}
|
||||
|
||||
t.Log("Step 2: Change the provider configuration address in config but then apply with some graph nodes excluded")
|
||||
{
|
||||
state := readStateSnapshot(t)
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
terraform {
|
||||
required_providers {
|
||||
mock = {
|
||||
source = "terraform.io/builtin/mock"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
instances = toset(["a", "b"])
|
||||
}
|
||||
|
||||
provider "mock" {
|
||||
alias = "after"
|
||||
for_each = local.instances
|
||||
}
|
||||
|
||||
resource "mock" "first" {
|
||||
for_each = local.instances
|
||||
provider = mock.after[each.key]
|
||||
}
|
||||
|
||||
resource "mock" "second" {
|
||||
for_each = local.instances
|
||||
provider = mock.after[each.key]
|
||||
}
|
||||
`,
|
||||
})
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewBuiltInProvider("mock"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
plan, diags := ctx.Plan(m, state, makeStep2PlanOpts(plans.NormalMode))
|
||||
assertNoErrors(t, diags)
|
||||
|
||||
newState, diags := ctx.Apply(plan, m)
|
||||
assertNoErrors(t, diags)
|
||||
|
||||
// Because makeStep2PlanOpts told us to retain at least one
|
||||
// instance of mock.first, both instances should've been
|
||||
// updated to refer to the new provider instance addresses.
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcFirstInstA,
|
||||
providerConfigAfter, addrs.StringKey("a"),
|
||||
)
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcFirstInstB,
|
||||
providerConfigAfter, addrs.StringKey("b"),
|
||||
)
|
||||
// Because makeStep2PlanOpts told us to exclude both instances
|
||||
// of mock.second, they continue to refer to the original
|
||||
// provider instance addresses.
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcSecondInstA,
|
||||
providerConfigBefore, addrs.StringKey("a"),
|
||||
)
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcSecondInstB,
|
||||
providerConfigBefore, addrs.StringKey("b"),
|
||||
)
|
||||
|
||||
writeStateSnapshot(t, newState)
|
||||
}
|
||||
|
||||
t.Log("Step 3: Remove the mock.first resource completely to destroy both instances using the updated provider config")
|
||||
{
|
||||
state := readStateSnapshot(t)
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
terraform {
|
||||
required_providers {
|
||||
mock = {
|
||||
source = "terraform.io/builtin/mock"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
instances = toset(["a", "b"])
|
||||
}
|
||||
|
||||
provider "mock" {
|
||||
alias = "after"
|
||||
for_each = local.instances
|
||||
}
|
||||
|
||||
# mock.first intentionally removed, which should succeed
|
||||
# because the incoming state snapshot should remember that
|
||||
# it was associated with mock.after .
|
||||
|
||||
resource "mock" "second" {
|
||||
for_each = local.instances
|
||||
provider = mock.after[each.key]
|
||||
}
|
||||
`,
|
||||
})
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewBuiltInProvider("mock"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
plan, diags := ctx.Plan(m, state, normalPlanOpts)
|
||||
assertNoErrors(t, diags)
|
||||
|
||||
newState, diags := ctx.Apply(plan, m)
|
||||
assertNoErrors(t, diags)
|
||||
|
||||
// The whole resource state for mock.first should've been removed now.
|
||||
if rs := newState.Resource(rsrcFirst); rs != nil {
|
||||
t.Errorf("final state still contains %s", rsrcFirst)
|
||||
}
|
||||
|
||||
// We didn't target or exclude anything this time, so we
|
||||
// should now have both instances of mock.second updated
|
||||
// to refer to the new provider config.
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcSecondInstA,
|
||||
providerConfigAfter, addrs.StringKey("a"),
|
||||
)
|
||||
assertResourceInstanceProviderInstance(
|
||||
t, newState,
|
||||
rsrcSecondInstB,
|
||||
providerConfigAfter, addrs.StringKey("b"),
|
||||
)
|
||||
|
||||
writeStateSnapshot(t, newState)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("with target", func(t *testing.T) {
|
||||
runTest(t, func(planMode plans.Mode) *PlanOpts {
|
||||
return &PlanOpts{
|
||||
Mode: planMode,
|
||||
Targets: []addrs.Targetable{
|
||||
rsrcFirstInstA,
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
t.Run("with exclude", func(t *testing.T) {
|
||||
runTest(t, func(planMode plans.Mode) *PlanOpts {
|
||||
return &PlanOpts{
|
||||
Mode: planMode,
|
||||
Excludes: []addrs.Targetable{
|
||||
rsrcSecondInstA,
|
||||
rsrcSecondInstB,
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// All exclude flag tests in this file, from here forward, are inspired by some counterpart target flag test
|
||||
// either from this file or from context_apply_test.go
|
||||
func TestContext2Apply_moduleProviderAliasExcludes(t *testing.T) {
|
||||
@ -3000,6 +3385,7 @@ func TestContext2Apply_excludedDestroyCountDeps(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -3008,6 +3394,7 @@ func TestContext2Apply_excludedDestroyCountDeps(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-cde345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -3016,6 +3403,7 @@ func TestContext2Apply_excludedDestroyCountDeps(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-def345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -3025,6 +3413,7 @@ func TestContext2Apply_excludedDestroyCountDeps(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3074,6 +3463,7 @@ func TestContext2Apply_excludedDependentDestroyCountDeps(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -3082,6 +3472,7 @@ func TestContext2Apply_excludedDependentDestroyCountDeps(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-cde345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -3090,6 +3481,7 @@ func TestContext2Apply_excludedDependentDestroyCountDeps(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-def345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -3099,6 +3491,7 @@ func TestContext2Apply_excludedDependentDestroyCountDeps(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3154,6 +3547,7 @@ func TestContext2Apply_excludedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -3162,6 +3556,7 @@ func TestContext2Apply_excludedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
child.SetResourceInstanceCurrent(
|
||||
@ -3171,6 +3566,7 @@ func TestContext2Apply_excludedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -3179,6 +3575,7 @@ func TestContext2Apply_excludedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3230,31 +3627,37 @@ func TestContext2Apply_excludedDestroyCountIndex(t *testing.T) {
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
foo,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
foo,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
foo,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[0]").Resource,
|
||||
bar,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[1]").Resource,
|
||||
bar,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[2]").Resource,
|
||||
bar,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3552,6 +3955,7 @@ func TestContext2Apply_excludedResourceOrphanModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"abc","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3604,6 +4008,7 @@ func TestContext2Apply_excludedOrphanModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"abc","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3654,6 +4059,7 @@ func TestContext2Apply_excludedWithTaintedInState(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"ifailedprovisioners"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
|
@ -472,7 +472,7 @@ check "error" {
|
||||
addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
plan: map[string]checksTestingStatus{
|
||||
"error": {
|
||||
@ -572,7 +572,7 @@ check "passing" {
|
||||
addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
plan: map[string]checksTestingStatus{
|
||||
"passing": {
|
||||
|
@ -462,6 +462,7 @@ func TestContext2Apply_resourceDependsOnModuleStateOnly(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.child.aws_instance.child")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
child.SetResourceInstanceCurrent(
|
||||
@ -471,6 +472,7 @@ func TestContext2Apply_resourceDependsOnModuleStateOnly(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"child"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
{
|
||||
@ -944,6 +946,7 @@ func TestContext2Apply_createBeforeDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "require_new": "abc"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -1013,6 +1016,7 @@ func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) {
|
||||
CreateBeforeDestroy: true,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -1023,6 +1027,7 @@ func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{fooAddr.ContainingResource().Config()},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1072,6 +1077,7 @@ func TestContext2Apply_createBeforeDestroy_dependsNonCBD(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "require_new": "abc"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo").Resource,
|
||||
@ -1080,6 +1086,7 @@ func TestContext2Apply_createBeforeDestroy_dependsNonCBD(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo", "require_new": "abc"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1133,6 +1140,7 @@ func TestContext2Apply_createBeforeDestroy_hook(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "require_new": "abc"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
var actual []cty.Value
|
||||
@ -1194,6 +1202,7 @@ func TestContext2Apply_createBeforeDestroy_deposedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr("aws_instance.bar[0]").Resource,
|
||||
@ -1203,6 +1212,7 @@ func TestContext2Apply_createBeforeDestroy_deposedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[1]").Resource,
|
||||
@ -1211,6 +1221,7 @@ func TestContext2Apply_createBeforeDestroy_deposedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr("aws_instance.bar[1]").Resource,
|
||||
@ -1220,6 +1231,7 @@ func TestContext2Apply_createBeforeDestroy_deposedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1271,6 +1283,7 @@ func TestContext2Apply_createBeforeDestroy_deposedOnly(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -1280,6 +1293,7 @@ func TestContext2Apply_createBeforeDestroy_deposedOnly(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1321,6 +1335,7 @@ func TestContext2Apply_destroyComputed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo", "output": "value"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -1367,6 +1382,7 @@ func testContext2Apply_destroyDependsOn(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo").Resource,
|
||||
@ -1376,6 +1392,7 @@ func testContext2Apply_destroyDependsOn(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.bar")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// Record the order we see Apply
|
||||
@ -1432,6 +1449,7 @@ func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -1457,6 +1475,7 @@ func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// It is possible for this to be racy, so we loop a number of times
|
||||
@ -1526,6 +1545,7 @@ func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -1551,6 +1571,7 @@ func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// It is possible for this to be racy, so we loop a number of times
|
||||
@ -1663,6 +1684,7 @@ func TestContext2Apply_destroyData(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"-"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/null"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
hook := &testHook{}
|
||||
@ -1722,6 +1744,7 @@ func TestContext2Apply_destroySkipsCBD(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -1730,6 +1753,7 @@ func TestContext2Apply_destroySkipsCBD(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1768,6 +1792,7 @@ func TestContext2Apply_destroyModuleVarProviderConfig(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -1844,6 +1869,7 @@ func getContextForApply_destroyCrossProviders(t *testing.T, m *configs.Config, p
|
||||
AttrsJSON: []byte(`{"id":"test"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
child.SetResourceInstanceCurrent(
|
||||
@ -1853,6 +1879,7 @@ func getContextForApply_destroyCrossProviders(t *testing.T, m *configs.Config, p
|
||||
AttrsJSON: []byte(`{"id": "vpc-aaabbb12", "value":"test"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2199,6 +2226,7 @@ func TestContext2Apply_countDecrease(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo": "foo","type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -2207,6 +2235,7 @@ func TestContext2Apply_countDecrease(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo": "foo","type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -2215,6 +2244,7 @@ func TestContext2Apply_countDecrease(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "foo": "foo", "type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2249,6 +2279,7 @@ func TestContext2Apply_countDecreaseToOneX(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "foo": "foo", "type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -2257,6 +2288,7 @@ func TestContext2Apply_countDecreaseToOneX(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -2265,6 +2297,7 @@ func TestContext2Apply_countDecreaseToOneX(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2319,6 +2352,7 @@ func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "foo": "foo", "type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
@ -2327,6 +2361,7 @@ func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz", "type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2395,6 +2430,7 @@ func TestContext2Apply_countTainted(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "type": "aws_instance", "foo": "foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -2652,6 +2688,7 @@ func TestContext2Apply_moduleDestroyOrder(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"a"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root := state.EnsureModule(addrs.RootModuleInstance)
|
||||
root.SetResourceInstanceCurrent(
|
||||
@ -2662,6 +2699,7 @@ func TestContext2Apply_moduleDestroyOrder(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.child.aws_instance.a")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2787,7 +2825,7 @@ func TestContext2Apply_orphanResource(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(oneAddr.Instance(addrs.IntKey(0)), &states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
}, providerAddr)
|
||||
}, providerAddr, addrs.NoKey)
|
||||
})
|
||||
|
||||
if state.String() != want.String() {
|
||||
@ -2859,6 +2897,7 @@ func TestContext2Apply_moduleOrphanInheritAlias(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2922,6 +2961,7 @@ func TestContext2Apply_moduleOrphanProvider(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2962,6 +3002,7 @@ func TestContext2Apply_moduleOrphanGrandchildProvider(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3131,6 +3172,7 @@ func TestContext2Apply_moduleProviderCloseNested(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3168,6 +3210,7 @@ func TestContext2Apply_moduleVarRefExisting(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo","foo":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4453,6 +4496,7 @@ func TestContext2Apply_provisionerFail_createBeforeDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","require_new":"abc"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4492,6 +4536,7 @@ func TestContext2Apply_error_createBeforeDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "require_new": "abc","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4538,6 +4583,7 @@ func TestContext2Apply_errorDestroy_createBeforeDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar", "require_new": "abc"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4596,6 +4642,7 @@ func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
p.PlanResourceChangeFn = testDiffFn
|
||||
@ -4885,6 +4932,7 @@ func TestContext2Apply_provisionerDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4932,6 +4980,7 @@ func TestContext2Apply_provisionerDestroyFail(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4996,6 +5045,7 @@ func TestContext2Apply_provisionerDestroyFailContinue(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5063,6 +5113,7 @@ func TestContext2Apply_provisionerDestroyFailContinueFail(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5129,6 +5180,7 @@ func TestContext2Apply_provisionerDestroyTainted(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5575,6 +5627,7 @@ func TestContext2Apply_outputDiffVars(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5796,6 +5849,7 @@ func TestContext2Apply_destroyNestedModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5834,6 +5888,7 @@ func TestContext2Apply_destroyDeeplyNestedModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -6233,6 +6288,7 @@ func TestContext2Apply_destroyOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -6271,6 +6327,7 @@ func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -6391,6 +6448,7 @@ func TestContext2Apply_errorDestroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
plan, diags := ctx.Plan(m, state, DefaultPlanOpts)
|
||||
@ -6523,6 +6581,7 @@ func TestContext2Apply_errorUpdateNullNew(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
plan, diags := ctx.Plan(m, state, DefaultPlanOpts)
|
||||
@ -6573,6 +6632,7 @@ func TestContext2Apply_errorPartial(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -6657,6 +6717,7 @@ func TestContext2Apply_hookOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -6896,6 +6957,7 @@ func TestContext2Apply_taintX(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz","num": "2", "type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -6942,6 +7004,7 @@ func TestContext2Apply_taintDep(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz","num": "2", "type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -6951,6 +7014,7 @@ func TestContext2Apply_taintDep(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -6993,6 +7057,7 @@ func TestContext2Apply_taintDepRequiresNew(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz","num": "2", "type": "aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -7002,6 +7067,7 @@ func TestContext2Apply_taintDepRequiresNew(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7243,6 +7309,7 @@ func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -7252,6 +7319,7 @@ func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7293,6 +7361,7 @@ func TestContext2Apply_targetedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -7301,6 +7370,7 @@ func TestContext2Apply_targetedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
child.SetResourceInstanceCurrent(
|
||||
@ -7310,6 +7380,7 @@ func TestContext2Apply_targetedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -7318,6 +7389,7 @@ func TestContext2Apply_targetedDestroyModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7376,31 +7448,37 @@ func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) {
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
foo,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
foo,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
foo,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[0]").Resource,
|
||||
bar,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[1]").Resource,
|
||||
bar,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[2]").Resource,
|
||||
bar,
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7654,6 +7732,7 @@ func TestContext2Apply_targetedResourceOrphanModule(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"abc","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7889,6 +7968,7 @@ func TestContext2Apply_createBefore_depends(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
root.SetResourceInstanceCurrent(
|
||||
@ -7915,6 +7995,7 @@ func TestContext2Apply_createBefore_depends(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -8017,6 +8098,7 @@ func TestContext2Apply_singleDestroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
root.SetResourceInstanceCurrent(
|
||||
@ -8043,6 +8125,7 @@ func TestContext2Apply_singleDestroy(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -8227,6 +8310,7 @@ func TestContext2Apply_targetedWithTaintedInState(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"ifailedprovisioners"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -8360,6 +8444,7 @@ func TestContext2Apply_ignoreChangesWithDep(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123","ami":"ami-abcd1234"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -8368,6 +8453,7 @@ func TestContext2Apply_ignoreChangesWithDep(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-bcd234","ami":"i-bcd234"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_eip.foo[0]").Resource,
|
||||
@ -8386,6 +8472,7 @@ func TestContext2Apply_ignoreChangesWithDep(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_eip.foo[1]").Resource,
|
||||
@ -8404,6 +8491,7 @@ func TestContext2Apply_ignoreChangesWithDep(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -8830,6 +8918,7 @@ func TestContext2Apply_destroyWithLocals(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetOutputValue("name", cty.StringVal("test-bar"), false)
|
||||
|
||||
@ -8925,6 +9014,7 @@ func TestContext2Apply_destroyWithProviders(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"].baz`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -8979,6 +9069,7 @@ func TestContext2Apply_providersFromState(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
aliasedProviderState := states.NewState()
|
||||
@ -8990,6 +9081,7 @@ func TestContext2Apply_providersFromState(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"].bar`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
moduleProviderState := states.NewState()
|
||||
@ -9001,6 +9093,7 @@ func TestContext2Apply_providersFromState(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`module.child.provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
for _, tc := range []struct {
|
||||
@ -9080,6 +9173,7 @@ func TestContext2Apply_plannedInterpolatedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -9130,6 +9224,7 @@ func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.a[1]").Resource,
|
||||
@ -9138,6 +9233,7 @@ func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetOutputValue("out", cty.ListVal([]cty.Value{cty.StringVal("foo"), cty.StringVal("foo")}), false)
|
||||
|
||||
@ -9193,6 +9289,7 @@ func TestContext2Apply_scaleInMultivarRef(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.two").Resource,
|
||||
@ -9201,6 +9298,7 @@ func TestContext2Apply_scaleInMultivarRef(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -9356,6 +9454,7 @@ func TestContext2Apply_issue19908(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -9473,6 +9572,7 @@ func TestContext2Apply_moduleReplaceCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
modB := state.EnsureModule(addrs.RootModuleInstance.Child("b", addrs.NoKey))
|
||||
@ -9490,6 +9590,7 @@ func TestContext2Apply_moduleReplaceCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
aBefore, _ := plans.NewDynamicValue(
|
||||
@ -9612,6 +9713,7 @@ func TestContext2Apply_destroyDataCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -9637,6 +9739,7 @@ func TestContext2Apply_destroyDataCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -9652,6 +9755,7 @@ func TestContext2Apply_destroyDataCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
Providers := map[addrs.Provider]providers.Factory{
|
||||
@ -9759,6 +9863,7 @@ func TestContext2Apply_taintedDestroyFailure(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -9774,6 +9879,7 @@ func TestContext2Apply_taintedDestroyFailure(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -9789,6 +9895,7 @@ func TestContext2Apply_taintedDestroyFailure(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
Providers := map[addrs.Provider]providers.Factory{
|
||||
@ -9964,6 +10071,7 @@ func TestContext2Apply_cbdCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -9989,6 +10097,7 @@ func TestContext2Apply_cbdCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -10004,6 +10113,7 @@ func TestContext2Apply_cbdCycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
Providers := map[addrs.Provider]providers.Factory{
|
||||
@ -11237,6 +11347,7 @@ locals {
|
||||
CreateBeforeDestroy: true,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_instance.a[1]").Resource,
|
||||
@ -11247,6 +11358,7 @@ locals {
|
||||
CreateBeforeDestroy: true,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_instance.b").Resource,
|
||||
@ -11257,6 +11369,7 @@ locals {
|
||||
CreateBeforeDestroy: true,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_instance.c").Resource,
|
||||
@ -11270,6 +11383,7 @@ locals {
|
||||
CreateBeforeDestroy: true,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
p := testProvider("test")
|
||||
@ -12181,6 +12295,7 @@ resource "test_resource" "foo" {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -12724,7 +12839,7 @@ func TestContext2Apply_errorRestorePrivateData(t *testing.T) {
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
Private: []byte("private"),
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -12769,7 +12884,7 @@ func TestContext2Apply_errorRestoreStatus(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"test_string":"foo"}`),
|
||||
Private: []byte("private"),
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.b")},
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
|
@ -635,18 +635,126 @@ variable "obfmod" {
|
||||
},
|
||||
})
|
||||
|
||||
diags := ctx.Validate(m)
|
||||
_, diags := ctx.Plan(m, nil, nil)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("Expected error!")
|
||||
}
|
||||
expected := `Unknown provider function: Provider "module.mod.provider[\"registry.opentofu.org/hashicorp/aws\"]" does not have a function "arn_parse_custom" or has not been configured`
|
||||
expected := `Function not found in provider: Function "provider::aws::arn_parse_custom" was not registered by provider`
|
||||
if expected != diags.Err().Error() {
|
||||
t.Fatalf("Expected error %q, got %q", expected, diags.Err().Error())
|
||||
}
|
||||
if p.GetFunctionsCalled {
|
||||
t.Fatalf("Unexpected function call")
|
||||
if !p.GetFunctionsCalled {
|
||||
t.Fatalf("Expected function call")
|
||||
}
|
||||
if p.CallFunctionCalled {
|
||||
t.Fatalf("Unexpected function call")
|
||||
}
|
||||
}
|
||||
|
||||
// Defaulted stub provider
|
||||
func TestContext2Functions_providerFunctionsForEachCount(t *testing.T) {
|
||||
p := testProvider("aws")
|
||||
addr := addrs.ImpliedProviderForUnqualifiedType("aws")
|
||||
|
||||
// Explicitly non-parallel
|
||||
t.Setenv("foo", "bar")
|
||||
defer providers.SchemaCache.Remove(addr)
|
||||
|
||||
p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
|
||||
Functions: map[string]providers.FunctionSpec{
|
||||
"arn_parse": providers.FunctionSpec{
|
||||
Parameters: []providers.FunctionParameterSpec{{
|
||||
Name: "arn",
|
||||
Type: cty.String,
|
||||
}},
|
||||
Return: cty.Bool,
|
||||
},
|
||||
},
|
||||
}
|
||||
p.CallFunctionResponse = &providers.CallFunctionResponse{
|
||||
Result: cty.True,
|
||||
}
|
||||
|
||||
// SchemaCache is initialzed earlier on in the command package
|
||||
providers.SchemaCache.Set(addr, *p.GetProviderSchemaResponse)
|
||||
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
provider "aws" {
|
||||
for_each = {"a": 1, "b": 2}
|
||||
alias = "iter"
|
||||
}
|
||||
module "mod" {
|
||||
source = "./mod"
|
||||
for_each = {"a": 1, "b": 2}
|
||||
providers = {
|
||||
aws = aws.iter[each.key]
|
||||
}
|
||||
}
|
||||
`,
|
||||
"mod/mod.tf": `
|
||||
terraform {
|
||||
required_providers {
|
||||
aws = ">=5.70.0"
|
||||
}
|
||||
}
|
||||
|
||||
variable "obfmod" {
|
||||
type = object({
|
||||
arns = optional(list(string))
|
||||
})
|
||||
description = "Configuration for xxx."
|
||||
|
||||
validation {
|
||||
condition = alltrue([
|
||||
for arn in var.obfmod.arns: can(provider::aws::arn_parse(arn))
|
||||
])
|
||||
error_message = "All arns MUST BE a valid AWS ARN format."
|
||||
}
|
||||
|
||||
default = {
|
||||
arns = [
|
||||
"arn:partition:service:region:account-id:resource-id",
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
diags := ctx.Validate(m)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
if !p.GetProviderSchemaCalled {
|
||||
t.Fatalf("Unexpected function call")
|
||||
}
|
||||
if p.GetFunctionsCalled {
|
||||
t.Fatalf("Unexpected function call")
|
||||
}
|
||||
if !p.CallFunctionCalled {
|
||||
t.Fatalf("Unexpected function call")
|
||||
}
|
||||
|
||||
p.GetProviderSchemaCalled = false
|
||||
p.GetFunctionsCalled = false
|
||||
p.CallFunctionCalled = false
|
||||
_, diags = ctx.Plan(m, nil, nil)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
if !p.GetProviderSchemaCalled {
|
||||
t.Fatalf("Unexpected function call")
|
||||
}
|
||||
if p.GetFunctionsCalled {
|
||||
t.Fatalf("Expected function call")
|
||||
}
|
||||
if !p.CallFunctionCalled {
|
||||
t.Fatalf("Expected function call")
|
||||
}
|
||||
}
|
||||
|
@ -7,16 +7,20 @@ package tofu
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/zclconf/go-cty-debug/ctydebug"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
func TestContextImport_basic(t *testing.T) {
|
||||
@ -115,6 +119,187 @@ resource "aws_instance" "foo" {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextImport_multiInstanceProviderConfig(t *testing.T) {
|
||||
// This test deals with the situation of importing into a resource instance
|
||||
// whose resource has a dynamic instance key in its "provider" argument,
|
||||
// and thus the import step needs to perform dynamic provider instance
|
||||
// selection to determine exactly which provider instance to use.
|
||||
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
terraform {
|
||||
required_providers {
|
||||
test = {
|
||||
source = "terraform.io/builtin/test"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "test" {
|
||||
alias = "multi"
|
||||
for_each = {
|
||||
a = {}
|
||||
b = {}
|
||||
}
|
||||
|
||||
marker = each.key
|
||||
}
|
||||
|
||||
resource "test_thing" "test" {
|
||||
for_each = { "foo" = "a" }
|
||||
provider = test.multi[each.value]
|
||||
}
|
||||
`})
|
||||
|
||||
resourceTypeSchema := providers.Schema{
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"import_marker": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"refresh_marker": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
providerSchema := &providers.GetProviderSchemaResponse{
|
||||
Provider: providers.Schema{
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"marker": {
|
||||
Type: cty.String,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_thing": resourceTypeSchema,
|
||||
},
|
||||
}
|
||||
|
||||
// Unlike most context tests, this one uses a real factory function so that
|
||||
// we can instantiate multiple instances and distinguish them.
|
||||
providerFactory := func() (providers.Interface, error) {
|
||||
// The following uses log.Printf instead of t.Logf so that the logs can interleave with the
|
||||
// verbose trace logs produced by the main logic in this package, to make the order of operations clearer.
|
||||
// To run just this test with trace logs:
|
||||
// TF_LOG=trace go test ./internal/tofu -run '^TestContextImport_multiInstanceProviderConfig$'
|
||||
|
||||
ret := &MockProvider{}
|
||||
var configuredMarker cty.Value
|
||||
log.Printf("[TRACE] TestContextImport_multiInstanceProviderConfig: creating new instance of provider 'test' at %p", ret)
|
||||
|
||||
ret.GetProviderSchemaResponse = providerSchema
|
||||
ret.ConfigureProviderFn = func(req providers.ConfigureProviderRequest) providers.ConfigureProviderResponse {
|
||||
configuredMarker = req.Config.GetAttr("marker")
|
||||
log.Printf("[TRACE] TestContextImport_multiInstanceProviderConfig: ConfigureProvider for %p with marker = %#v", ret, configuredMarker)
|
||||
return providers.ConfigureProviderResponse{}
|
||||
}
|
||||
ret.ImportResourceStateFn = func(req providers.ImportResourceStateRequest) providers.ImportResourceStateResponse {
|
||||
log.Printf("[TRACE] TestContextImport_multiInstanceProviderConfig: ImportResourceState for %p with marker = %#v", ret, configuredMarker)
|
||||
if configuredMarker == cty.NilVal {
|
||||
return providers.ImportResourceStateResponse{
|
||||
Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("ImportResourceState before ConfigureProvider")),
|
||||
}
|
||||
}
|
||||
return providers.ImportResourceStateResponse{
|
||||
ImportedResources: []providers.ImportedResource{
|
||||
{
|
||||
TypeName: "test_thing",
|
||||
State: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal(req.ID),
|
||||
"import_marker": configuredMarker,
|
||||
"refresh_marker": cty.NullVal(cty.String), // we'll populate this in ReadResource
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
ret.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
|
||||
log.Printf("[TRACE] TestContextImport_multiInstanceProviderConfig: ReadResource for %p with marker = %#v", ret, configuredMarker)
|
||||
if configuredMarker == cty.NilVal {
|
||||
return providers.ReadResourceResponse{
|
||||
Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("ReadResource before ConfigureProvider")),
|
||||
}
|
||||
}
|
||||
return providers.ReadResourceResponse{
|
||||
NewState: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": req.PriorState.GetAttr("id"),
|
||||
"import_marker": req.PriorState.GetAttr("import_marker"),
|
||||
"refresh_marker": configuredMarker,
|
||||
}),
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewBuiltInProvider("test"): providerFactory,
|
||||
},
|
||||
})
|
||||
|
||||
existingInstanceKey := addrs.StringKey("foo")
|
||||
existingInstanceAddr := addrs.RootModuleInstance.ResourceInstance(
|
||||
addrs.ManagedResourceMode, "test_thing", "test", existingInstanceKey,
|
||||
)
|
||||
t.Logf("importing into %s, which should succeed because it's configured", existingInstanceAddr)
|
||||
log.Printf("[TRACE] TestContextImport_multiInstanceProviderConfig: importing into %s, which should succeed because it's configured", existingInstanceAddr)
|
||||
state, diags := ctx.Import(m, states.NewState(), &ImportOpts{
|
||||
Targets: []*ImportTarget{
|
||||
{
|
||||
CommandLineImportTarget: &CommandLineImportTarget{
|
||||
Addr: existingInstanceAddr,
|
||||
ID: "fake-import-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
assertNoErrors(t, diags)
|
||||
|
||||
resourceState := state.Resource(existingInstanceAddr.ContainingResource())
|
||||
|
||||
if got, want := len(resourceState.Instances), 1; got != want {
|
||||
t.Errorf("unexpected number of instances %d; want %d", got, want)
|
||||
}
|
||||
|
||||
instanceState := resourceState.Instances[existingInstanceKey]
|
||||
if instanceState == nil {
|
||||
t.Fatal("no instance with key \"foo\" in final state")
|
||||
}
|
||||
if got, want := instanceState.ProviderKey, addrs.StringKey("a"); got != want {
|
||||
t.Errorf("wrong provider key %s; want %s", got, want)
|
||||
}
|
||||
if instanceState.Current == nil {
|
||||
t.Fatal("final resource instance has no current object")
|
||||
}
|
||||
|
||||
gotObjState, err := instanceState.Current.Decode(resourceTypeSchema.Block.ImpliedType())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to decode final resource instance object state: %s", err)
|
||||
}
|
||||
wantObjState := &states.ResourceInstanceObject{
|
||||
Value: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("fake-import-id"),
|
||||
"import_marker": cty.StringVal("a"),
|
||||
"refresh_marker": cty.StringVal("a"),
|
||||
}),
|
||||
Status: states.ObjectReady,
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
}
|
||||
if diff := cmp.Diff(wantObjState, gotObjState, ctydebug.CmpOptions); diff != "" {
|
||||
t.Error("wrong final object state\n" + diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextImport_importResourceWithSensitiveDataSource(t *testing.T) {
|
||||
p := testProvider("aws")
|
||||
m := testModuleInline(t, map[string]string{
|
||||
@ -218,6 +403,7 @@ func TestContextImport_collision(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -446,6 +446,7 @@ func TestContext2Input_dataSourceRequiresRefresh(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("null"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -860,16 +860,17 @@ func (c *Context) planGraph(config *configs.Config, prevRunState *states.State,
|
||||
return graph, walkPlan, diags
|
||||
case plans.RefreshOnlyMode:
|
||||
graph, diags := (&PlanGraphBuilder{
|
||||
Config: config,
|
||||
State: prevRunState,
|
||||
RootVariableValues: opts.SetVariables,
|
||||
Plugins: c.plugins,
|
||||
Targets: opts.Targets,
|
||||
Excludes: opts.Excludes,
|
||||
skipRefresh: opts.SkipRefresh,
|
||||
skipPlanChanges: true, // this activates "refresh only" mode.
|
||||
Operation: walkPlan,
|
||||
ExternalReferences: opts.ExternalReferences,
|
||||
Config: config,
|
||||
State: prevRunState,
|
||||
RootVariableValues: opts.SetVariables,
|
||||
Plugins: c.plugins,
|
||||
Targets: opts.Targets,
|
||||
Excludes: opts.Excludes,
|
||||
skipRefresh: opts.SkipRefresh,
|
||||
skipPlanChanges: true, // this activates "refresh only" mode.
|
||||
Operation: walkPlan,
|
||||
ExternalReferences: opts.ExternalReferences,
|
||||
ProviderFunctionTracker: providerFunctionTracker,
|
||||
}).Build(addrs.RootModuleInstance)
|
||||
return graph, walkPlan, diags
|
||||
case plans.DestroyMode:
|
||||
|
@ -80,7 +80,7 @@ resource "test_object" "a" {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"arg":"previous_run"}`),
|
||||
Status: states.ObjectTainted,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -209,6 +209,7 @@ data "test_data_source" "foo" {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -251,7 +252,7 @@ output "out" {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr(`data.test_object.a["old"]`), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"test_string":"foo"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -375,6 +376,7 @@ resource "test_resource" "b" {
|
||||
AttrsJSON: []byte(`{"id":"a"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr(`module.mod["old"].test_resource.b`),
|
||||
@ -382,6 +384,7 @@ resource "test_resource" "b" {
|
||||
AttrsJSON: []byte(`{"id":"b","value":"d"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
oldDataAddr,
|
||||
@ -389,6 +392,7 @@ resource "test_resource" "b" {
|
||||
AttrsJSON: []byte(`{"id":"d"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -674,6 +678,7 @@ data "test_data_source" "a" {
|
||||
AttrsJSON: []byte(`{"id":"boop","valid":false}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -886,6 +891,7 @@ resource "test_resource" "b" {
|
||||
AttrsJSON: []byte(`{"id":"main","valid":false}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
managedAddrB,
|
||||
@ -893,6 +899,7 @@ resource "test_resource" "b" {
|
||||
AttrsJSON: []byte(`{"id":"checker","valid":true}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -986,7 +993,7 @@ resource "test_object" "a" {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"arg":"before"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1086,7 +1093,7 @@ resource "test_object" "a" {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"arg":"before"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1226,7 +1233,7 @@ provider "test" {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"test_string":"foo"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1262,7 +1269,7 @@ func TestContext2Plan_movedResourceBasic(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -1326,11 +1333,11 @@ func TestContext2Plan_movedResourceCollision(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrNoKey, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addrZeroKey, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -1432,11 +1439,11 @@ func TestContext2Plan_movedResourceCollisionDestroy(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrNoKey, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addrZeroKey, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -1544,7 +1551,7 @@ func TestContext2Plan_movedResourceUntargeted(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -1890,12 +1897,12 @@ resource "test_object" "b" {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addrB, &states.ResourceInstanceObjectSrc{
|
||||
// old_list is no longer in the schema
|
||||
AttrsJSON: []byte(`{"old_list":["used to be","a list here"]}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -1953,12 +1960,12 @@ resource "test_object" "b" {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addrB, &states.ResourceInstanceObjectSrc{
|
||||
// old_list is no longer in the schema
|
||||
AttrsJSON: []byte(`{"old_list":["used to be","a list here"]}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -2021,7 +2028,7 @@ func TestContext2Plan_movedResourceRefreshOnly(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -2093,7 +2100,7 @@ func TestContext2Plan_refreshOnlyMode(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"arg":"before"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -2229,7 +2236,7 @@ func TestContext2Plan_refreshOnlyMode_deposed(t *testing.T) {
|
||||
s.SetResourceInstanceDeposed(addr, deposedKey, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"arg":"before"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -2366,11 +2373,11 @@ func TestContext2Plan_refreshOnlyMode_orphan(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addr.Instance(addrs.IntKey(0)), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"arg":"before"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addr.Instance(addrs.IntKey(1)), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"arg":"before"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -2583,6 +2590,7 @@ data "test_data_source" "foo" {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_instance.bar").Resource,
|
||||
@ -2597,6 +2605,7 @@ data "test_data_source" "foo" {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2640,11 +2649,11 @@ func TestContext2Plan_forceReplace(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addrB, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -2708,11 +2717,11 @@ func TestContext2Plan_forceReplaceIncompleteAddr(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addr0, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addr1, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -2828,6 +2837,7 @@ output "output" {
|
||||
AttrsJSON: []byte(`{"id":"foo","value":"a"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
one.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr(`data.test_data_source.d`).Resource,
|
||||
@ -2836,6 +2846,7 @@ output "output" {
|
||||
AttrsJSON: []byte(`{"id":"data"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
two.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr(`test_resource.x`).Resource,
|
||||
@ -2844,6 +2855,7 @@ output "output" {
|
||||
AttrsJSON: []byte(`{"id":"foo","value":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
two.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr(`data.test_data_source.d`).Resource,
|
||||
@ -2852,6 +2864,7 @@ output "output" {
|
||||
AttrsJSON: []byte(`{"id":"data"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2919,7 +2932,7 @@ func TestContext2Plan_moduleExpandOrphansResourceInstance(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrNoKey, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -3094,7 +3107,7 @@ resource "test_resource" "a" {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr("test_resource.a"), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"value":"boop","output":"blorp"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
_, diags := ctx.Plan(m, state, &PlanOpts{
|
||||
Mode: plans.RefreshOnlyMode,
|
||||
@ -3163,7 +3176,7 @@ resource "test_resource" "a" {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr("test_resource.a"), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"value":"boop","output":"blorp"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
p.ReadResourceFn = func(req providers.ReadResourceRequest) (resp providers.ReadResourceResponse) {
|
||||
newVal, err := cty.Transform(req.PriorState, func(path cty.Path, v cty.Value) (cty.Value, error) {
|
||||
@ -3216,7 +3229,7 @@ resource "test_resource" "a" {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr("test_resource.a"), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"value":"boop","output":"blorp"}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
p.ReadResourceFn = func(req providers.ReadResourceRequest) (resp providers.ReadResourceResponse) {
|
||||
newVal, err := cty.Transform(req.PriorState, func(path cty.Path, v cty.Value) (cty.Value, error) {
|
||||
@ -3888,6 +3901,7 @@ resource "test_object" "b" {
|
||||
Status: states.ObjectReady,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.b[0]"),
|
||||
@ -3896,6 +3910,7 @@ resource "test_object" "b" {
|
||||
Status: states.ObjectReady,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
for _, configuration := range configurations {
|
||||
@ -3977,7 +3992,7 @@ data "test_object" "a" {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr(`data.test_object.a`), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"id":"old","obj":[{"args":["string"]}]}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4018,6 +4033,7 @@ resource "test_object" "b" {
|
||||
Dependencies: []addrs.ConfigResource{mustResourceInstanceAddr("test_object.b").ContainingResource().Config()},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.b").Resource,
|
||||
@ -4026,6 +4042,7 @@ resource "test_object" "b" {
|
||||
AttrsJSON: []byte(`{"test_string":"b"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4139,6 +4156,7 @@ resource "test_object" "b" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.a[0]").Resource,
|
||||
@ -4148,6 +4166,7 @@ resource "test_object" "b" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4318,6 +4337,7 @@ output "out" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
mod.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.a[1]").Resource,
|
||||
@ -4327,6 +4347,7 @@ output "out" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4461,6 +4482,7 @@ resource "test_object" "a" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -5575,6 +5597,7 @@ import {
|
||||
AttrsJSON: []byte(`{"test_string":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
plan, diags := ctx.Plan(m, state, DefaultPlanOpts)
|
||||
@ -7012,7 +7035,7 @@ func TestContext2Plan_removedResourceBasic(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr(addr.String()),
|
||||
desposedKey,
|
||||
@ -7022,6 +7045,7 @@ func TestContext2Plan_removedResourceBasic(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -7092,7 +7116,7 @@ func TestContext2Plan_removedModuleBasic(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr(addr.String()),
|
||||
desposedKey,
|
||||
@ -7102,6 +7126,7 @@ func TestContext2Plan_removedModuleBasic(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -7174,11 +7199,11 @@ func TestContext2Plan_removedModuleForgetsAllInstances(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrFirst, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addrSecond, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7240,11 +7265,11 @@ func TestContext2Plan_removedResourceForgetsAllInstances(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrFirst, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
s.SetResourceInstanceCurrent(addrSecond, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7308,7 +7333,7 @@ func TestContext2Plan_removedResourceInChildModuleFromParentModule(t *testing.T)
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7370,7 +7395,7 @@ func TestContext2Plan_removedResourceInChildModuleFromChildModule(t *testing.T)
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7433,7 +7458,7 @@ func TestContext2Plan_removedResourceInGrandchildModuleFromRootModule(t *testing
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7496,7 +7521,7 @@ func TestContext2Plan_removedChildModuleForgetsResourceInGrandchildModule(t *tes
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7564,7 +7589,7 @@ func TestContext2Plan_movedAndRemovedResourceAtTheSameTime(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addrA, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7629,7 +7654,7 @@ func TestContext2Plan_removedResourceButResourceBlockStillExists(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7678,7 +7703,7 @@ func TestContext2Plan_removedResourceButResourceBlockStillExistsInChildModule(t
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
@ -7727,7 +7752,7 @@ func TestContext2Plan_removedModuleButModuleBlockStillExists(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{}`),
|
||||
Status: states.ObjectReady,
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`))
|
||||
}, mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`), addrs.NoKey)
|
||||
})
|
||||
|
||||
p := simpleMockProvider()
|
||||
|
@ -95,6 +95,7 @@ func TestContext2Plan_createBefore_deposed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr("aws_instance.foo").Resource,
|
||||
@ -104,6 +105,7 @@ func TestContext2Plan_createBefore_deposed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -810,6 +812,7 @@ func TestContext2Plan_moduleOrphans(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -882,6 +885,7 @@ func TestContext2Plan_moduleOrphansWithProvisioner(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"top","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child1 := state.EnsureModule(addrs.RootModuleInstance.Child("parent", addrs.NoKey).Child("child1", addrs.NoKey))
|
||||
child1.SetResourceInstanceCurrent(
|
||||
@ -891,6 +895,7 @@ func TestContext2Plan_moduleOrphansWithProvisioner(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child2 := state.EnsureModule(addrs.RootModuleInstance.Child("parent", addrs.NoKey).Child("child2", addrs.NoKey))
|
||||
child2.SetResourceInstanceCurrent(
|
||||
@ -900,6 +905,7 @@ func TestContext2Plan_moduleOrphansWithProvisioner(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1376,6 +1382,7 @@ func TestContext2Plan_preventDestroy_bad(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1415,6 +1422,7 @@ func TestContext2Plan_preventDestroy_good(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1446,6 +1454,7 @@ func TestContext2Plan_preventDestroy_countBad(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -1454,6 +1463,7 @@ func TestContext2Plan_preventDestroy_countBad(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1502,6 +1512,7 @@ func TestContext2Plan_preventDestroy_countGood(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -1510,6 +1521,7 @@ func TestContext2Plan_preventDestroy_countGood(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc345"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1553,6 +1565,7 @@ func TestContext2Plan_preventDestroy_countGoodNoChange(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123","current":"0","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1584,6 +1597,7 @@ func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -1981,6 +1995,7 @@ func TestContext2Plan_dataResourceBecomesComputed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123","foo":"baz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2603,6 +2618,7 @@ func TestContext2Plan_countDecreaseToOne(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"foo","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -2611,6 +2627,7 @@ func TestContext2Plan_countDecreaseToOne(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -2619,6 +2636,7 @@ func TestContext2Plan_countDecreaseToOne(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2703,6 +2721,7 @@ func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","type":"aws_instance","foo":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2780,6 +2799,7 @@ func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"foo","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2863,6 +2883,7 @@ func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"foo","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
@ -2871,6 +2892,7 @@ func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo":"foo","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -2971,6 +2993,7 @@ func TestContext2Plan_countIncreaseWithSplatReference(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","name":"foo 0"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -2979,6 +3002,7 @@ func TestContext2Plan_countIncreaseWithSplatReference(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","name":"foo 1"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[0]").Resource,
|
||||
@ -2987,6 +3011,7 @@ func TestContext2Plan_countIncreaseWithSplatReference(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo_name":"foo 0"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[1]").Resource,
|
||||
@ -2995,6 +3020,7 @@ func TestContext2Plan_countIncreaseWithSplatReference(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","foo_name":"foo 1"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3135,6 +3161,7 @@ func TestContext2Plan_destroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.two").Resource,
|
||||
@ -3143,6 +3170,7 @@ func TestContext2Plan_destroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3196,6 +3224,7 @@ func TestContext2Plan_moduleDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
child.SetResourceInstanceCurrent(
|
||||
@ -3205,6 +3234,7 @@ func TestContext2Plan_moduleDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3258,6 +3288,7 @@ func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"a"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
bModule := state.EnsureModule(addrs.RootModuleInstance.Child("b_module", addrs.NoKey))
|
||||
bModule.SetResourceInstanceCurrent(
|
||||
@ -3267,6 +3298,7 @@ func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"b"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3320,6 +3352,7 @@ func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar0"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -3328,6 +3361,7 @@ func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar1"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3441,6 +3475,7 @@ func TestContext2Plan_diffVar(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","num":"2","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3556,6 +3591,7 @@ func TestContext2Plan_orphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3638,6 +3674,7 @@ func TestContext2Plan_state(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -3740,6 +3777,7 @@ func TestContext2Plan_requiresReplace(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"v":"hello"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3798,6 +3836,7 @@ func TestContext2Plan_taint(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","num":"2","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar").Resource,
|
||||
@ -3806,6 +3845,7 @@ func TestContext2Plan_taint(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"baz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3884,6 +3924,7 @@ func TestContext2Plan_taintIgnoreChanges(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo","vars":"foo","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -3948,6 +3989,7 @@ func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -3956,6 +3998,7 @@ func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -3964,6 +4007,7 @@ func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
@ -4314,6 +4358,7 @@ func TestContext2Plan_targetedOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-789xyz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.nottargeted").Resource,
|
||||
@ -4322,6 +4367,7 @@ func TestContext2Plan_targetedOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4379,6 +4425,7 @@ func TestContext2Plan_excludedOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-789xyz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.nottargeted").Resource,
|
||||
@ -4387,6 +4434,7 @@ func TestContext2Plan_excludedOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4445,6 +4493,7 @@ func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-789xyz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.nottargeted").Resource,
|
||||
@ -4453,6 +4502,7 @@ func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4507,6 +4557,7 @@ func TestContext2Plan_excludedModuleOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-789xyz"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.nottargeted").Resource,
|
||||
@ -4515,6 +4566,7 @@ func TestContext2Plan_excludedModuleOrphan(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -4790,6 +4842,7 @@ func TestContext2Plan_targetedOverTen(t *testing.T) {
|
||||
AttrsJSON: []byte(attrs),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}
|
||||
|
||||
@ -4844,6 +4897,7 @@ func TestContext2Plan_excludedOverTen(t *testing.T) {
|
||||
AttrsJSON: []byte(attrs),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}
|
||||
|
||||
@ -4942,6 +4996,7 @@ func TestContext2Plan_ignoreChanges(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","ami":"ami-abcd1234","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5014,6 +5069,7 @@ func TestContext2Plan_ignoreChangesWildcard(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","ami":"ami-abcd1234","instance":"t2.micro","type":"aws_instance","foo":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5079,6 +5135,7 @@ func TestContext2Plan_ignoreChangesInMap(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
m := testModule(t, "plan-ignore-changes-in-map")
|
||||
@ -5136,6 +5193,7 @@ func TestContext2Plan_ignoreChangesSensitive(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"bar","ami":"ami-abcd1234","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5527,6 +5585,7 @@ func TestContext2Plan_ignoreChangesWithFlatmaps(t *testing.T) {
|
||||
}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -5598,6 +5657,7 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo0","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -5606,6 +5666,7 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo1","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[0]").Resource,
|
||||
@ -5615,6 +5676,7 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.bar[1]").Resource,
|
||||
@ -5624,6 +5686,7 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.baz[0]").Resource,
|
||||
@ -5633,6 +5696,7 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.bar")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.baz[1]").Resource,
|
||||
@ -5642,6 +5706,7 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("aws_instance.bar")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
@ -6263,6 +6328,7 @@ resource "aws_instance" "foo" {
|
||||
AttrsJSON: []byte(`{"id":"child","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
state.EnsureModule(addrs.RootModuleInstance.Child("mod", addrs.IntKey(1))).SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo").Resource,
|
||||
@ -6271,6 +6337,7 @@ resource "aws_instance" "foo" {
|
||||
AttrsJSON: []byte(`{"id":"child","type":"aws_instance"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
p := testProvider("aws")
|
||||
@ -6672,6 +6739,7 @@ data "test_data_source" "foo" {}
|
||||
AttrsJSON: []byte(`{"id":"data_id", "foo":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -6721,6 +6789,7 @@ resource "test_instance" "b" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_instance.b").Resource,
|
||||
@ -6730,6 +6799,7 @@ resource "test_instance" "b" {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_instance.a")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7068,6 +7138,7 @@ resource "test_instance" "a" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7240,6 +7311,7 @@ resource "test_instance" "a" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7303,6 +7375,7 @@ resource "test_instance" "a" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7361,6 +7434,7 @@ resource "test_instance" "a" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7400,6 +7474,7 @@ resource "test_instance" "a" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// the provider for this data source is no longer in the config, but that
|
||||
@ -7412,6 +7487,7 @@ resource "test_instance" "a" {
|
||||
Dependencies: []addrs.ConfigResource{},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/local/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -7469,6 +7545,7 @@ resource "test_resource" "foo" {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
plan, diags := ctx.Plan(m, state, SimplePlanOpts(plans.NormalMode, testInputValuesUnset(m.Module.Variables)))
|
||||
|
@ -36,6 +36,7 @@ func TestContext2Refresh(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo","foo":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
@ -98,6 +99,7 @@ func TestContext2Refresh_dynamicAttr(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1435,6 +1437,7 @@ func TestContext2Refresh_orphanModule(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
|
||||
child.SetResourceInstanceCurrent(
|
||||
@ -1445,6 +1448,7 @@ func TestContext2Refresh_orphanModule(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{{Module: addrs.Module{"module.grandchild"}}},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
grandchild := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey).Child("grandchild", addrs.NoKey))
|
||||
testSetResourceInstanceCurrent(grandchild, "aws_instance.baz", `{"id":"i-cde345"}`, `provider["registry.opentofu.org/hashicorp/aws"]`)
|
||||
@ -1574,6 +1578,7 @@ func TestContext2Refresh_schemaUpgradeFlatmap(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1656,6 +1661,7 @@ func TestContext2Refresh_schemaUpgradeJSON(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -1793,6 +1799,7 @@ func TestRefresh_updateLifecycle(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
m := testModuleInline(t, map[string]string{
|
||||
@ -1846,6 +1853,7 @@ func TestContext2Refresh_dataSourceOrphan(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
p := testProvider("test")
|
||||
p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) (resp providers.ReadDataSourceResponse) {
|
||||
@ -1936,6 +1944,7 @@ resource "test_resource" "foo" {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
|
@ -44,7 +44,7 @@ type EvalContext interface {
|
||||
// It is an error to initialize the same provider more than once. This
|
||||
// method will panic if the module instance address of the given provider
|
||||
// configuration does not match the Path() of the EvalContext.
|
||||
InitProvider(addr addrs.AbsProviderConfig) (providers.Interface, error)
|
||||
InitProvider(addr addrs.AbsProviderConfig, key addrs.InstanceKey) (providers.Interface, error)
|
||||
|
||||
// Provider gets the provider instance with the given address (already
|
||||
// initialized) or returns nil if the provider isn't initialized.
|
||||
@ -53,7 +53,7 @@ type EvalContext interface {
|
||||
// resources in one module are able to use providers from other modules.
|
||||
// InitProvider must've been called on the EvalContext of the module
|
||||
// that owns the given provider before calling this method.
|
||||
Provider(addrs.AbsProviderConfig) providers.Interface
|
||||
Provider(addrs.AbsProviderConfig, addrs.InstanceKey) providers.Interface
|
||||
|
||||
// ProviderSchema retrieves the schema for a particular provider, which
|
||||
// must have already been initialized with InitProvider.
|
||||
@ -75,7 +75,7 @@ type EvalContext interface {
|
||||
//
|
||||
// This method will panic if the module instance address of the given
|
||||
// provider configuration does not match the Path() of the EvalContext.
|
||||
ConfigureProvider(addrs.AbsProviderConfig, cty.Value) tfdiags.Diagnostics
|
||||
ConfigureProvider(addrs.AbsProviderConfig, addrs.InstanceKey, cty.Value) tfdiags.Diagnostics
|
||||
|
||||
// ProviderInput and SetProviderInput are used to configure providers
|
||||
// from user input.
|
||||
|
@ -67,7 +67,7 @@ type BuiltinEvalContext struct {
|
||||
InputValue UIInput
|
||||
|
||||
ProviderLock *sync.Mutex
|
||||
ProviderCache map[string]providers.Interface
|
||||
ProviderCache map[string]map[addrs.InstanceKey]providers.Interface
|
||||
ProviderInputConfig map[string]map[string]cty.Value
|
||||
|
||||
ProvisionerLock *sync.Mutex
|
||||
@ -128,14 +128,18 @@ func (ctx *BuiltinEvalContext) Input() UIInput {
|
||||
return ctx.InputValue
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (providers.Interface, error) {
|
||||
func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig, providerKey addrs.InstanceKey) (providers.Interface, error) {
|
||||
ctx.ProviderLock.Lock()
|
||||
defer ctx.ProviderLock.Unlock()
|
||||
|
||||
key := addr.String()
|
||||
|
||||
if ctx.ProviderCache[key] == nil {
|
||||
ctx.ProviderCache[key] = make(map[addrs.InstanceKey]providers.Interface)
|
||||
}
|
||||
|
||||
// If we have already initialized, it is an error
|
||||
if _, ok := ctx.ProviderCache[key]; ok {
|
||||
if _, ok := ctx.ProviderCache[key][providerKey]; ok {
|
||||
return nil, fmt.Errorf("%s is already initialized", addr)
|
||||
}
|
||||
|
||||
@ -156,17 +160,22 @@ func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (provi
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] BuiltinEvalContext: Initialized %q provider for %s", addr.String(), addr)
|
||||
ctx.ProviderCache[key] = p
|
||||
log.Printf("[TRACE] BuiltinEvalContext: Initialized %q%s provider for %s", addr.String(), providerKey, addr)
|
||||
ctx.ProviderCache[key][providerKey] = p
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface {
|
||||
func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig, key addrs.InstanceKey) providers.Interface {
|
||||
ctx.ProviderLock.Lock()
|
||||
defer ctx.ProviderLock.Unlock()
|
||||
|
||||
return ctx.ProviderCache[addr.String()]
|
||||
pm, ok := ctx.ProviderCache[addr.String()]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return pm[key]
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) (providers.ProviderSchema, error) {
|
||||
@ -177,17 +186,27 @@ func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error
|
||||
ctx.ProviderLock.Lock()
|
||||
defer ctx.ProviderLock.Unlock()
|
||||
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
key := addr.String()
|
||||
provider := ctx.ProviderCache[key]
|
||||
if provider != nil {
|
||||
providerMap := ctx.ProviderCache[key]
|
||||
if providerMap != nil {
|
||||
for _, provider := range providerMap {
|
||||
err := provider.Close()
|
||||
if err != nil {
|
||||
diags = diags.Append(err)
|
||||
}
|
||||
}
|
||||
delete(ctx.ProviderCache, key)
|
||||
return provider.Close()
|
||||
}
|
||||
if diags.HasErrors() {
|
||||
return diags.Err()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, cfg cty.Value) tfdiags.Diagnostics {
|
||||
func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, providerKey addrs.InstanceKey, cfg cty.Value) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
if !addr.Module.Equal(ctx.Path().Module()) {
|
||||
// This indicates incorrect use of ConfigureProvider: it should be used
|
||||
@ -195,9 +214,9 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, c
|
||||
panic(fmt.Sprintf("%s configured by wrong module %s", addr, ctx.Path()))
|
||||
}
|
||||
|
||||
p := ctx.Provider(addr)
|
||||
p := ctx.Provider(addr, providerKey)
|
||||
if p == nil {
|
||||
diags = diags.Append(fmt.Errorf("%s not initialized", addr))
|
||||
diags = diags.Append(fmt.Errorf("%s not initialized", addr.InstanceString(providerKey)))
|
||||
return diags
|
||||
}
|
||||
|
||||
@ -433,7 +452,7 @@ func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, source
|
||||
}
|
||||
|
||||
scope := ctx.Evaluator.Scope(data, self, source, func(pf addrs.ProviderFunction, rng tfdiags.SourceRange) (*function.Function, tfdiags.Diagnostics) {
|
||||
absPc, ok := ctx.ProviderFunctionTracker.Lookup(ctx.PathValue.Module(), pf)
|
||||
providedBy, ok := ctx.ProviderFunctionTracker.Lookup(ctx.PathValue.Module(), pf)
|
||||
if !ok {
|
||||
// This should not be possible if references are tracked correctly
|
||||
return nil, tfdiags.Diagnostics{}.Append(&hcl.Diagnostic{
|
||||
@ -444,14 +463,28 @@ func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, source
|
||||
})
|
||||
}
|
||||
|
||||
provider := ctx.Provider(absPc)
|
||||
var providerKey addrs.InstanceKey
|
||||
if providedBy.KeyExpression != nil && ctx.Evaluator.Operation != walkValidate {
|
||||
moduleInstanceForKey := ctx.PathValue[:len(providedBy.KeyModule)]
|
||||
if !moduleInstanceForKey.Module().Equal(providedBy.KeyModule) {
|
||||
panic(fmt.Sprintf("Invalid module key expression location %s in function %s", providedBy.KeyModule, pf.String()))
|
||||
}
|
||||
|
||||
var keyDiags tfdiags.Diagnostics
|
||||
providerKey, keyDiags = resolveProviderModuleInstance(ctx, providedBy.KeyExpression, moduleInstanceForKey, ctx.PathValue.String()+" "+pf.String())
|
||||
if keyDiags.HasErrors() {
|
||||
return nil, keyDiags
|
||||
}
|
||||
}
|
||||
|
||||
provider := ctx.Provider(providedBy.Provider, providerKey)
|
||||
|
||||
if provider == nil {
|
||||
// This should not be possible if references are tracked correctly
|
||||
return nil, tfdiags.Diagnostics{}.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "BUG: Uninitialized function provider",
|
||||
Detail: fmt.Sprintf("Provider %q has not yet been initialized", absPc.String()),
|
||||
Summary: "Uninitialized function provider",
|
||||
Detail: fmt.Sprintf("Provider %q has not yet been initialized", providedBy.Provider.String()),
|
||||
Subject: rng.ToHCL().Ptr(),
|
||||
})
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func TestBuildingEvalContextInitProvider(t *testing.T) {
|
||||
ctx := testBuiltinEvalContext(t)
|
||||
ctx = ctx.WithPath(addrs.RootModuleInstance).(*BuiltinEvalContext)
|
||||
ctx.ProviderLock = &lock
|
||||
ctx.ProviderCache = make(map[string]providers.Interface)
|
||||
ctx.ProviderCache = make(map[string]map[addrs.InstanceKey]providers.Interface)
|
||||
ctx.Plugins = newContextPlugins(map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): providers.FactoryFixed(testP),
|
||||
}, nil)
|
||||
@ -78,11 +78,11 @@ func TestBuildingEvalContextInitProvider(t *testing.T) {
|
||||
Alias: "foo",
|
||||
}
|
||||
|
||||
_, err := ctx.InitProvider(providerAddrDefault)
|
||||
_, err := ctx.InitProvider(providerAddrDefault, addrs.NoKey)
|
||||
if err != nil {
|
||||
t.Fatalf("error initializing provider test: %s", err)
|
||||
}
|
||||
_, err = ctx.InitProvider(providerAddrAlias)
|
||||
_, err = ctx.InitProvider(providerAddrAlias, addrs.NoKey)
|
||||
if err != nil {
|
||||
t.Fatalf("error initializing provider test.foo: %s", err)
|
||||
}
|
||||
|
@ -183,14 +183,14 @@ func (c *MockEvalContext) Input() UIInput {
|
||||
return c.InputInput
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) InitProvider(addr addrs.AbsProviderConfig) (providers.Interface, error) {
|
||||
func (c *MockEvalContext) InitProvider(addr addrs.AbsProviderConfig, _ addrs.InstanceKey) (providers.Interface, error) {
|
||||
c.InitProviderCalled = true
|
||||
c.InitProviderType = addr.String()
|
||||
c.InitProviderAddr = addr
|
||||
return c.InitProviderProvider, c.InitProviderError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface {
|
||||
func (c *MockEvalContext) Provider(addr addrs.AbsProviderConfig, _ addrs.InstanceKey) providers.Interface {
|
||||
c.ProviderCalled = true
|
||||
c.ProviderAddr = addr
|
||||
return c.ProviderProvider
|
||||
@ -208,8 +208,7 @@ func (c *MockEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, cfg cty.Value) tfdiags.Diagnostics {
|
||||
|
||||
func (c *MockEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, _ addrs.InstanceKey, cfg cty.Value) tfdiags.Diagnostics {
|
||||
c.ConfigureProviderCalled = true
|
||||
c.ConfigureProviderAddr = addr
|
||||
c.ConfigureProviderConfig = cfg
|
||||
|
@ -15,7 +15,11 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/configs/hcl2shim"
|
||||
"github.com/opentofu/opentofu/internal/lang"
|
||||
"github.com/opentofu/opentofu/internal/lang/evalchecks"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
func buildProviderConfig(ctx EvalContext, addr addrs.AbsProviderConfig, config *configs.Provider) hcl.Body {
|
||||
@ -47,15 +51,75 @@ func buildProviderConfig(ctx EvalContext, addr addrs.AbsProviderConfig, config *
|
||||
}
|
||||
}
|
||||
|
||||
func resolveProviderResourceInstance(ctx EvalContext, keyExpr hcl.Expression, resourcePath addrs.AbsResourceInstance) (addrs.InstanceKey, tfdiags.Diagnostics) {
|
||||
keyData := ctx.InstanceExpander().GetResourceInstanceRepetitionData(resourcePath)
|
||||
keyScope := ctx.EvaluationScope(nil, nil, keyData)
|
||||
return resolveProviderInstance(keyExpr, keyScope, resourcePath.String())
|
||||
}
|
||||
|
||||
func resolveProviderModuleInstance(ctx EvalContext, keyExpr hcl.Expression, modulePath addrs.ModuleInstance, source string) (addrs.InstanceKey, tfdiags.Diagnostics) {
|
||||
keyData := ctx.InstanceExpander().GetModuleInstanceRepetitionData(modulePath)
|
||||
keyScope := ctx.WithPath(modulePath).EvaluationScope(nil, nil, keyData)
|
||||
return resolveProviderInstance(keyExpr, keyScope, source)
|
||||
}
|
||||
|
||||
func resolveProviderInstance(keyExpr hcl.Expression, keyScope *lang.Scope, source string) (addrs.InstanceKey, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
keyVal, keyDiags := keyScope.EvalExpr(keyExpr, cty.DynamicPseudoType)
|
||||
diags = diags.Append(keyDiags)
|
||||
if keyDiags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
if keyVal.HasMark(marks.Sensitive) {
|
||||
return nil, diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider instance key",
|
||||
Detail: "A provider instance key must not be derived from a sensitive value.",
|
||||
Subject: keyExpr.Range().Ptr(),
|
||||
Extra: evalchecks.DiagnosticCausedBySensitive(true),
|
||||
})
|
||||
}
|
||||
if keyVal.IsNull() {
|
||||
return nil, diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider instance key",
|
||||
Detail: "A provider instance key must not be null.",
|
||||
Subject: keyExpr.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
if !keyVal.IsKnown() {
|
||||
return nil, diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider instance key",
|
||||
Detail: fmt.Sprintf("The provider instance key for %s depends on values that cannot be determined until apply, and so OpenTofu cannot select a provider instance to create a plan for this resource instance.", source),
|
||||
Subject: keyExpr.Range().Ptr(),
|
||||
Extra: evalchecks.DiagnosticCausedByUnknown(true),
|
||||
})
|
||||
}
|
||||
|
||||
parsedKey, parsedErr := addrs.ParseInstanceKey(keyVal)
|
||||
if parsedErr != nil {
|
||||
return nil, diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid provider instance key",
|
||||
Detail: fmt.Sprintf("The given instance key is unsuitable: %s.", tfdiags.FormatError(parsedErr)),
|
||||
Subject: keyExpr.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
return parsedKey, diags
|
||||
}
|
||||
|
||||
// getProvider returns the providers.Interface and schema for a given provider.
|
||||
func getProvider(ctx EvalContext, addr addrs.AbsProviderConfig) (providers.Interface, providers.ProviderSchema, error) {
|
||||
func getProvider(ctx EvalContext, addr addrs.AbsProviderConfig, providerKey addrs.InstanceKey) (providers.Interface, providers.ProviderSchema, error) {
|
||||
if addr.Provider.Type == "" {
|
||||
// Should never happen
|
||||
panic("GetProvider used with uninitialized provider configuration address")
|
||||
}
|
||||
provider := ctx.Provider(addr)
|
||||
provider := ctx.Provider(addr, providerKey)
|
||||
if provider == nil {
|
||||
return nil, providers.ProviderSchema{}, fmt.Errorf("provider %s not initialized", addr)
|
||||
return nil, providers.ProviderSchema{}, fmt.Errorf("provider %s not initialized", addr.InstanceString(providerKey))
|
||||
}
|
||||
// Not all callers require a schema, so we will leave checking for a nil
|
||||
// schema to the callers.
|
||||
|
@ -246,6 +246,7 @@ func TestEvaluatorGetResource(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
}).SyncWrapper()
|
||||
|
||||
@ -420,6 +421,7 @@ func TestEvaluatorGetResource_changes(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
}).SyncWrapper()
|
||||
|
||||
|
@ -104,6 +104,7 @@ func TestApplyGraphBuilder_depCbd(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -113,6 +114,7 @@ func TestApplyGraphBuilder_depCbd(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
b := &ApplyGraphBuilder{
|
||||
@ -270,6 +272,7 @@ func TestApplyGraphBuilder_destroyStateOnly(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -279,6 +282,7 @@ func TestApplyGraphBuilder_destroyStateOnly(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.child.test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
b := &ApplyGraphBuilder{
|
||||
@ -332,6 +336,7 @@ func TestApplyGraphBuilder_destroyCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"B"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -341,6 +346,7 @@ func TestApplyGraphBuilder_destroyCount(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{addrA.ContainingResource().Config()},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
b := &ApplyGraphBuilder{
|
||||
@ -393,6 +399,7 @@ func TestApplyGraphBuilder_moduleDestroy(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
modB := state.EnsureModule(addrs.RootModuleInstance.Child("B", addrs.NoKey))
|
||||
modB.SetResourceInstanceCurrent(
|
||||
@ -403,6 +410,7 @@ func TestApplyGraphBuilder_moduleDestroy(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.A.test_object.foo")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
b := &ApplyGraphBuilder{
|
||||
@ -546,6 +554,7 @@ func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -571,6 +580,7 @@ func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
b := &ApplyGraphBuilder{
|
||||
@ -649,6 +659,7 @@ func TestApplyGraphBuilder_updateFromCBDOrphan(t *testing.T) {
|
||||
CreateBeforeDestroy: true,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -671,6 +682,7 @@ func TestApplyGraphBuilder_updateFromCBDOrphan(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
b := &ApplyGraphBuilder{
|
||||
@ -721,6 +733,7 @@ func TestApplyGraphBuilder_orphanedWithProvider(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"].foo`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
b := &ApplyGraphBuilder{
|
||||
|
@ -60,7 +60,7 @@ type ContextGraphWalker struct {
|
||||
variableValues map[string]map[string]cty.Value
|
||||
|
||||
providerLock sync.Mutex
|
||||
providerCache map[string]providers.Interface
|
||||
providerCache map[string]map[addrs.InstanceKey]providers.Interface
|
||||
|
||||
provisionerLock sync.Mutex
|
||||
provisionerCache map[string]provisioners.Interface
|
||||
@ -129,7 +129,7 @@ func (w *ContextGraphWalker) EvalContext() EvalContext {
|
||||
|
||||
func (w *ContextGraphWalker) init() {
|
||||
w.contexts = make(map[string]*BuiltinEvalContext)
|
||||
w.providerCache = make(map[string]providers.Interface)
|
||||
w.providerCache = make(map[string]map[addrs.InstanceKey]providers.Interface)
|
||||
w.provisionerCache = make(map[string]provisioners.Interface)
|
||||
w.variableValues = make(map[string]map[string]cty.Value)
|
||||
|
||||
|
@ -24,6 +24,6 @@ var (
|
||||
// GraphNodeExecutable
|
||||
func (n *NodeDestroyableDataResourceInstance) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
|
||||
log.Printf("[TRACE] NodeDestroyableDataResourceInstance: removing state object for %s", n.Addr)
|
||||
ctx.State().SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider)
|
||||
ctx.State().SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider.ProviderConfig, nil)
|
||||
return nil
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ func TestNodeDataDestroyExecute(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
ctx := &MockEvalContext{
|
||||
StateState: state.SyncWrapper(),
|
||||
|
@ -73,6 +73,14 @@ func (n *nodeExpandModule) References() []*addrs.Reference {
|
||||
forEachRefs, _ := lang.ReferencesInExpr(addrs.ParseRef, n.ModuleCall.ForEach)
|
||||
refs = append(refs, forEachRefs...)
|
||||
}
|
||||
|
||||
for _, passed := range n.ModuleCall.Providers {
|
||||
if passed.InParent.KeyExpression != nil {
|
||||
providerRefs, _ := lang.ReferencesInExpr(addrs.ParseRef, passed.InParent.KeyExpression)
|
||||
refs = append(refs, providerRefs...)
|
||||
}
|
||||
}
|
||||
|
||||
return refs
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -26,34 +27,74 @@ var (
|
||||
)
|
||||
|
||||
// GraphNodeExecutable
|
||||
func (n *NodeApplyableProvider) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
|
||||
_, err := ctx.InitProvider(n.Addr)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
provider, _, err := getProvider(ctx, n.Addr)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
func (n *NodeApplyableProvider) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
|
||||
instances, diags := n.initInstances(ctx, op)
|
||||
|
||||
for key, provider := range instances {
|
||||
diags = diags.Append(n.executeInstance(ctx, op, key, provider))
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
func (n *NodeApplyableProvider) initInstances(ctx EvalContext, op walkOperation) (map[addrs.InstanceKey]providers.Interface, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
var initKeys []addrs.InstanceKey
|
||||
// config -> init (different due to validate skipping most for_each logic)
|
||||
instanceKeys := make(map[addrs.InstanceKey]addrs.InstanceKey)
|
||||
if n.Config == nil || n.Config.Instances == nil {
|
||||
initKeys = append(initKeys, addrs.NoKey)
|
||||
instanceKeys[addrs.NoKey] = addrs.NoKey
|
||||
} else if op == walkValidate {
|
||||
// Instances are set AND we are validating
|
||||
initKeys = append(initKeys, addrs.NoKey)
|
||||
for key := range n.Config.Instances {
|
||||
instanceKeys[key] = addrs.NoKey
|
||||
}
|
||||
} else {
|
||||
// Instances are set AND we are not validating
|
||||
for key := range n.Config.Instances {
|
||||
initKeys = append(initKeys, key)
|
||||
instanceKeys[key] = key
|
||||
}
|
||||
}
|
||||
|
||||
for _, key := range initKeys {
|
||||
_, err := ctx.InitProvider(n.Addr, key)
|
||||
diags = diags.Append(err)
|
||||
}
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
instances := make(map[addrs.InstanceKey]providers.Interface)
|
||||
for configKey, initKey := range instanceKeys {
|
||||
provider, _, err := getProvider(ctx, n.Addr, initKey)
|
||||
diags = diags.Append(err)
|
||||
instances[configKey] = provider
|
||||
}
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
return instances, diags
|
||||
}
|
||||
func (n *NodeApplyableProvider) executeInstance(ctx EvalContext, op walkOperation, providerKey addrs.InstanceKey, provider providers.Interface) tfdiags.Diagnostics {
|
||||
switch op {
|
||||
case walkValidate:
|
||||
log.Printf("[TRACE] NodeApplyableProvider: validating configuration for %s", n.Addr)
|
||||
return diags.Append(n.ValidateProvider(ctx, provider))
|
||||
return n.ValidateProvider(ctx, providerKey, provider)
|
||||
case walkPlan, walkPlanDestroy, walkApply, walkDestroy:
|
||||
log.Printf("[TRACE] NodeApplyableProvider: configuring %s", n.Addr)
|
||||
return diags.Append(n.ConfigureProvider(ctx, provider, false))
|
||||
return n.ConfigureProvider(ctx, providerKey, provider, false)
|
||||
case walkImport:
|
||||
log.Printf("[TRACE] NodeApplyableProvider: configuring %s (requiring that configuration is wholly known)", n.Addr)
|
||||
return diags.Append(n.ConfigureProvider(ctx, provider, true))
|
||||
return n.ConfigureProvider(ctx, providerKey, provider, true)
|
||||
}
|
||||
return diags
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NodeApplyableProvider) ValidateProvider(ctx EvalContext, provider providers.Interface) (diags tfdiags.Diagnostics) {
|
||||
|
||||
func (n *NodeApplyableProvider) ValidateProvider(ctx EvalContext, providerKey addrs.InstanceKey, provider providers.Interface) tfdiags.Diagnostics {
|
||||
configBody := buildProviderConfig(ctx, n.Addr, n.ProviderConfig())
|
||||
|
||||
// if a provider config is empty (only an alias), return early and don't continue
|
||||
@ -65,7 +106,7 @@ func (n *NodeApplyableProvider) ValidateProvider(ctx EvalContext, provider provi
|
||||
}
|
||||
|
||||
schemaResp := provider.GetProviderSchema()
|
||||
diags = diags.Append(schemaResp.Diagnostics.InConfigBody(configBody, n.Addr.String()))
|
||||
diags := schemaResp.Diagnostics.InConfigBody(configBody, n.Addr.String())
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
@ -79,6 +120,9 @@ func (n *NodeApplyableProvider) ValidateProvider(ctx EvalContext, provider provi
|
||||
}
|
||||
|
||||
data := EvalDataForNoInstanceKey
|
||||
if n.Config != nil && n.Config.Instances != nil {
|
||||
data = n.Config.Instances[providerKey]
|
||||
}
|
||||
|
||||
configVal, _, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, data)
|
||||
if evalDiags.HasErrors() {
|
||||
@ -103,19 +147,22 @@ func (n *NodeApplyableProvider) ValidateProvider(ctx EvalContext, provider provi
|
||||
// ConfigureProvider configures a provider that is already initialized and retrieved.
|
||||
// If verifyConfigIsKnown is true, ConfigureProvider will return an error if the
|
||||
// provider configVal is not wholly known and is meant only for use during import.
|
||||
func (n *NodeApplyableProvider) ConfigureProvider(ctx EvalContext, provider providers.Interface, verifyConfigIsKnown bool) (diags tfdiags.Diagnostics) {
|
||||
func (n *NodeApplyableProvider) ConfigureProvider(ctx EvalContext, providerKey addrs.InstanceKey, provider providers.Interface, verifyConfigIsKnown bool) tfdiags.Diagnostics {
|
||||
config := n.ProviderConfig()
|
||||
|
||||
configBody := buildProviderConfig(ctx, n.Addr, config)
|
||||
|
||||
resp := provider.GetProviderSchema()
|
||||
diags = diags.Append(resp.Diagnostics.InConfigBody(configBody, n.Addr.String()))
|
||||
diags := resp.Diagnostics.InConfigBody(configBody, n.Addr.String())
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
configSchema := resp.Provider.Block
|
||||
data := EvalDataForNoInstanceKey
|
||||
if n.Config != nil && n.Config.Instances != nil {
|
||||
data = n.Config.Instances[providerKey]
|
||||
}
|
||||
|
||||
configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, data)
|
||||
diags = diags.Append(evalDiags)
|
||||
@ -169,7 +216,7 @@ func (n *NodeApplyableProvider) ConfigureProvider(ctx EvalContext, provider prov
|
||||
log.Printf("[WARN] ValidateProviderConfig from %q changed the config value, but that value is unused", n.Addr)
|
||||
}
|
||||
|
||||
configDiags := ctx.ConfigureProvider(n.Addr, unmarkedConfigVal)
|
||||
configDiags := ctx.ConfigureProvider(n.Addr, providerKey, unmarkedConfigVal)
|
||||
diags = diags.Append(configDiags.InConfigBody(configBody, n.Addr.String()))
|
||||
if diags.HasErrors() && config == nil {
|
||||
// If there isn't an explicit "provider" block in the configuration,
|
||||
|
@ -5,7 +5,10 @@
|
||||
|
||||
package tofu
|
||||
|
||||
import "github.com/opentofu/opentofu/internal/tfdiags"
|
||||
import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
// NodeEvalableProvider represents a provider during an "eval" walk.
|
||||
// This special provider node type just initializes a provider and
|
||||
@ -19,6 +22,6 @@ var _ GraphNodeExecutable = (*NodeEvalableProvider)(nil)
|
||||
|
||||
// GraphNodeExecutable
|
||||
func (n *NodeEvalableProvider) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
|
||||
_, err := ctx.InitProvider(n.Addr)
|
||||
_, err := ctx.InitProvider(n.Addr, addrs.NoKey)
|
||||
return diags.Append(err)
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ func TestNodeApplyableProvider_Validate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ValidateProvider(ctx, provider)
|
||||
diags := node.ValidateProvider(ctx, addrs.NoKey, provider)
|
||||
if diags.HasErrors() {
|
||||
t.Errorf("unexpected error with valid config: %s", diags.Err())
|
||||
}
|
||||
@ -308,7 +308,7 @@ func TestNodeApplyableProvider_Validate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ValidateProvider(ctx, provider)
|
||||
diags := node.ValidateProvider(ctx, addrs.NoKey, provider)
|
||||
if !diags.HasErrors() {
|
||||
t.Error("missing expected error with invalid config")
|
||||
}
|
||||
@ -321,7 +321,7 @@ func TestNodeApplyableProvider_Validate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ValidateProvider(ctx, provider)
|
||||
diags := node.ValidateProvider(ctx, addrs.NoKey, provider)
|
||||
if diags.HasErrors() {
|
||||
t.Errorf("unexpected error with empty config: %s", diags.Err())
|
||||
}
|
||||
@ -369,7 +369,7 @@ func TestNodeApplyableProvider_ConfigProvider(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ConfigureProvider(ctx, provider, false)
|
||||
diags := node.ConfigureProvider(ctx, addrs.NoKey, provider, false)
|
||||
if diags.HasErrors() {
|
||||
t.Errorf("unexpected error with valid config: %s", diags.Err())
|
||||
}
|
||||
@ -382,7 +382,7 @@ func TestNodeApplyableProvider_ConfigProvider(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ConfigureProvider(ctx, provider, false)
|
||||
diags := node.ConfigureProvider(ctx, addrs.NoKey, provider, false)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("missing expected error with nil config")
|
||||
}
|
||||
@ -403,7 +403,7 @@ func TestNodeApplyableProvider_ConfigProvider(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ConfigureProvider(ctx, provider, false)
|
||||
diags := node.ConfigureProvider(ctx, addrs.NoKey, provider, false)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("missing expected error with invalid config")
|
||||
}
|
||||
@ -458,7 +458,7 @@ func TestNodeApplyableProvider_ConfigProvider_config_fn_err(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ConfigureProvider(ctx, provider, false)
|
||||
diags := node.ConfigureProvider(ctx, addrs.NoKey, provider, false)
|
||||
if diags.HasErrors() {
|
||||
t.Errorf("unexpected error with valid config: %s", diags.Err())
|
||||
}
|
||||
@ -471,7 +471,7 @@ func TestNodeApplyableProvider_ConfigProvider_config_fn_err(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ConfigureProvider(ctx, provider, false)
|
||||
diags := node.ConfigureProvider(ctx, addrs.NoKey, provider, false)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("missing expected error with nil config")
|
||||
}
|
||||
@ -492,7 +492,7 @@ func TestNodeApplyableProvider_ConfigProvider_config_fn_err(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ConfigureProvider(ctx, provider, false)
|
||||
diags := node.ConfigureProvider(ctx, addrs.NoKey, provider, false)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("missing expected error with invalid config")
|
||||
}
|
||||
@ -518,7 +518,7 @@ func TestGetSchemaError(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
diags := node.ConfigureProvider(ctx, provider, false)
|
||||
diags := node.ConfigureProvider(ctx, addrs.NoKey, provider, false)
|
||||
for _, d := range diags {
|
||||
desc := d.Description()
|
||||
if desc.Address != providerAddr.String() {
|
||||
|
@ -77,11 +77,12 @@ type NodeAbstractResource struct {
|
||||
forceDependsOn bool
|
||||
|
||||
// The address of the provider this resource will use
|
||||
ResolvedProvider addrs.AbsProviderConfig
|
||||
ResolvedProvider ResolvedProvider
|
||||
|
||||
// storedProviderConfig is the provider address retrieved from the
|
||||
// state. This is defined here for access within the ProvidedBy method, but
|
||||
// will be set from the embedding instance type when the state is attached.
|
||||
storedProviderConfig addrs.AbsProviderConfig
|
||||
storedProviderConfig ResolvedProvider
|
||||
|
||||
// This resource may expand into instances which need to be imported.
|
||||
importTargets []*ImportTarget
|
||||
@ -293,28 +294,48 @@ func (n *NodeAbstractResource) DependsOn() []*addrs.Reference {
|
||||
return result
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResource) SetProvider(p addrs.AbsProviderConfig) {
|
||||
n.ResolvedProvider = p
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResource) SetProvider(resolved ResolvedProvider) {
|
||||
n.ResolvedProvider = resolved
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResource) ProvidedBy() addrs.ProviderConfig {
|
||||
func (n *NodeAbstractResource) ProvidedBy() RequestedProvider {
|
||||
// Once the provider is fully resolved, we can return the known value.
|
||||
if n.ResolvedProvider.Provider.Type != "" {
|
||||
return n.ResolvedProvider
|
||||
if n.ResolvedProvider.ProviderConfig.Provider.Type != "" {
|
||||
return RequestedProvider{
|
||||
ProviderConfig: n.ResolvedProvider.ProviderConfig,
|
||||
KeyExpression: n.ResolvedProvider.KeyExpression,
|
||||
KeyModule: n.ResolvedProvider.KeyModule,
|
||||
KeyResource: n.ResolvedProvider.KeyResource,
|
||||
KeyExact: n.ResolvedProvider.KeyExact,
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a config we prefer that above all else
|
||||
if n.Config != nil {
|
||||
return n.Config.ProviderConfigAddr()
|
||||
result := RequestedProvider{
|
||||
ProviderConfig: n.Config.ProviderConfigAddr(),
|
||||
}
|
||||
if n.Config.ProviderConfigRef != nil && n.Config.ProviderConfigRef.KeyExpression != nil {
|
||||
result.KeyResource = true
|
||||
result.KeyExpression = n.Config.ProviderConfigRef.KeyExpression
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// See if we have a valid provider config from the state.
|
||||
if n.storedProviderConfig.Provider.Type != "" {
|
||||
if n.storedProviderConfig.ProviderConfig.Provider.Type != "" {
|
||||
// An address from the state must match exactly, since we must ensure
|
||||
// we refresh/destroy a resource with the same provider configuration
|
||||
// that created it.
|
||||
return n.storedProviderConfig
|
||||
return RequestedProvider{
|
||||
ProviderConfig: n.storedProviderConfig.ProviderConfig,
|
||||
KeyExpression: n.storedProviderConfig.KeyExpression,
|
||||
KeyModule: n.storedProviderConfig.KeyModule,
|
||||
KeyResource: n.storedProviderConfig.KeyResource,
|
||||
KeyExact: n.storedProviderConfig.KeyExact,
|
||||
}
|
||||
}
|
||||
|
||||
// We might have an import target that is providing a specific provider,
|
||||
@ -325,29 +346,34 @@ func (n *NodeAbstractResource) ProvidedBy() addrs.ProviderConfig {
|
||||
// of them should be. They should also all have the same provider, so it
|
||||
// shouldn't matter which we check here, as they'll all give the same.
|
||||
if n.importTargets[0].Config != nil && n.importTargets[0].Config.ProviderConfigRef != nil {
|
||||
return addrs.LocalProviderConfig{
|
||||
LocalName: n.importTargets[0].Config.ProviderConfigRef.Name,
|
||||
Alias: n.importTargets[0].Config.ProviderConfigRef.Alias,
|
||||
return RequestedProvider{
|
||||
ProviderConfig: addrs.LocalProviderConfig{
|
||||
LocalName: n.importTargets[0].Config.ProviderConfigRef.Name,
|
||||
Alias: n.importTargets[0].Config.ProviderConfigRef.Alias,
|
||||
},
|
||||
// This is where we would specify a key expression if that was supported for import blocks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No provider configuration found; return a default address
|
||||
return addrs.LocalProviderConfig{
|
||||
LocalName: n.Addr.Resource.ImpliedProvider(), // Unused, see ProviderTransformer
|
||||
return RequestedProvider{
|
||||
ProviderConfig: addrs.LocalProviderConfig{
|
||||
LocalName: n.Addr.Resource.ImpliedProvider(), // Unused, see ProviderTransformer
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResource) Provider() addrs.Provider {
|
||||
if n.ResolvedProvider.Provider.Type != "" {
|
||||
return n.ResolvedProvider.Provider
|
||||
if n.ResolvedProvider.ProviderConfig.Provider.Type != "" {
|
||||
return n.ResolvedProvider.ProviderConfig.Provider
|
||||
}
|
||||
if n.Config != nil {
|
||||
return n.Config.Provider
|
||||
}
|
||||
if n.storedProviderConfig.Provider.Type != "" {
|
||||
return n.storedProviderConfig.Provider
|
||||
if n.storedProviderConfig.ProviderConfig.Provider.Type != "" {
|
||||
return n.storedProviderConfig.ProviderConfig.Provider
|
||||
}
|
||||
|
||||
if len(n.importTargets) > 0 {
|
||||
@ -460,7 +486,7 @@ func (n *NodeAbstractResource) writeResourceState(ctx EvalContext, addr addrs.Ab
|
||||
return diags
|
||||
}
|
||||
|
||||
state.SetResourceProvider(addr, n.ResolvedProvider)
|
||||
state.SetResourceProvider(addr, n.ResolvedProvider.ProviderConfig)
|
||||
expander.SetResourceCount(addr.Module, n.Addr.Resource, count)
|
||||
|
||||
case n.Config != nil && n.Config.ForEach != nil:
|
||||
@ -472,11 +498,11 @@ func (n *NodeAbstractResource) writeResourceState(ctx EvalContext, addr addrs.Ab
|
||||
|
||||
// This method takes care of all of the business logic of updating this
|
||||
// while ensuring that any existing instances are preserved, etc.
|
||||
state.SetResourceProvider(addr, n.ResolvedProvider)
|
||||
state.SetResourceProvider(addr, n.ResolvedProvider.ProviderConfig)
|
||||
expander.SetResourceForEach(addr.Module, n.Addr.Resource, forEach)
|
||||
|
||||
default:
|
||||
state.SetResourceProvider(addr, n.ResolvedProvider)
|
||||
state.SetResourceProvider(addr, n.ResolvedProvider.ProviderConfig)
|
||||
expander.SetResourceSingle(addr.Module, n.Addr.Resource)
|
||||
}
|
||||
|
||||
@ -485,9 +511,9 @@ func (n *NodeAbstractResource) writeResourceState(ctx EvalContext, addr addrs.Ab
|
||||
|
||||
// readResourceInstanceState reads the current object for a specific instance in
|
||||
// the state.
|
||||
func (n *NodeAbstractResource) readResourceInstanceState(ctx EvalContext, addr addrs.AbsResourceInstance) (*states.ResourceInstanceObject, tfdiags.Diagnostics) {
|
||||
func (n *NodeAbstractResourceInstance) readResourceInstanceState(ctx EvalContext, addr addrs.AbsResourceInstance) (*states.ResourceInstanceObject, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
if err != nil {
|
||||
diags = diags.Append(err)
|
||||
return nil, diags
|
||||
@ -526,9 +552,9 @@ func (n *NodeAbstractResource) readResourceInstanceState(ctx EvalContext, addr a
|
||||
|
||||
// readResourceInstanceStateDeposed reads the deposed object for a specific
|
||||
// instance in the state.
|
||||
func (n *NodeAbstractResource) readResourceInstanceStateDeposed(ctx EvalContext, addr addrs.AbsResourceInstance, key states.DeposedKey) (*states.ResourceInstanceObject, tfdiags.Diagnostics) {
|
||||
func (n *NodeAbstractResourceInstance) readResourceInstanceStateDeposed(ctx EvalContext, addr addrs.AbsResourceInstance, key states.DeposedKey) (*states.ResourceInstanceObject, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
if err != nil {
|
||||
diags = diags.Append(err)
|
||||
return nil, diags
|
||||
|
@ -46,6 +46,8 @@ type NodeAbstractResourceInstance struct {
|
||||
// During import we may generate configuration for a resource, which needs
|
||||
// to be stored in the final change.
|
||||
generatedConfigHCL string
|
||||
|
||||
ResolvedProviderKey addrs.InstanceKey
|
||||
}
|
||||
|
||||
// NewNodeAbstractResourceInstance creates an abstract resource instance graph
|
||||
@ -105,6 +107,67 @@ func (n *NodeAbstractResourceInstance) References() []*addrs.Reference {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) resolveProvider(ctx EvalContext) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
log.Printf("[TRACE] Resolving provider key for %s", n.Addr)
|
||||
|
||||
if n.ResolvedProvider.ProviderConfig.Provider.Type == "" {
|
||||
return diags.Append(fmt.Errorf("attempting to resolve an unset provider at %s", n.Addr))
|
||||
}
|
||||
|
||||
if n.ResolvedProvider.KeyExact != nil {
|
||||
// Pass through from state
|
||||
n.ResolvedProviderKey = n.ResolvedProvider.KeyExact
|
||||
} else if n.ResolvedProvider.KeyExpression != nil {
|
||||
if n.ResolvedProvider.KeyResource {
|
||||
// Resolved from resource instance
|
||||
n.ResolvedProviderKey, diags = resolveProviderResourceInstance(ctx, n.Config.ProviderConfigRef.KeyExpression, n.Addr)
|
||||
} else {
|
||||
// Resolved fro module instance
|
||||
moduleInstanceForKey := n.Addr.Module[:len(n.ResolvedProvider.KeyModule)]
|
||||
if !moduleInstanceForKey.Module().Equal(n.ResolvedProvider.KeyModule) {
|
||||
panic(fmt.Sprintf("Invalid module key expression location %s in resource %s", n.ResolvedProvider.KeyModule, n.Addr))
|
||||
}
|
||||
|
||||
n.ResolvedProviderKey, diags = resolveProviderModuleInstance(ctx, n.ResolvedProvider.KeyExpression, moduleInstanceForKey, n.Addr.String())
|
||||
}
|
||||
}
|
||||
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] Resolved provider key for %s as %s", n.Addr, n.ResolvedProviderKey)
|
||||
|
||||
// This duplicates a lot of getProvider() and should be refactored as the only place to resolve the provider eventually
|
||||
// This is also quite similar to ProviderTransformer's handling of removed providers for orphaned nodes
|
||||
if n.ResolvedProvider.ProviderConfig.Provider.Type == "" {
|
||||
// Should never happen
|
||||
panic("EnsureProvider used with uninitialized provider configuration address")
|
||||
}
|
||||
|
||||
provider := ctx.Provider(n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
if provider != nil {
|
||||
// All good
|
||||
return nil
|
||||
}
|
||||
|
||||
if n.ResolvedProviderKey == nil {
|
||||
// Probably an OpenTofu bug
|
||||
return diags.Append(fmt.Errorf("provider %s not initialized for resource %s", n.ResolvedProvider.ProviderConfig.InstanceString(n.ResolvedProviderKey), n.Addr))
|
||||
}
|
||||
|
||||
return diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Provider instance not present",
|
||||
fmt.Sprintf(
|
||||
"To work with %s its original provider instance at %s is required, but it has been removed. This occurs when an element is removed from the provider configuration's for_each collection while objects created by that the associated provider instance still exist in the state. Re-add the for_each element to destroy %s, after which you can remove the provider configuration again.\n\nThis is commonly caused by using the same for_each collection both for a resource (or its containing module) and its associated provider configuration. To successfully remove an instance of a resource it must be possible to remove the corresponding element from the resource's for_each collection while retaining the corresponding element in the provider's for_each collection.",
|
||||
n.Addr, n.ResolvedProvider.ProviderConfig.InstanceString(n.ResolvedProviderKey), n.Addr,
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
// StateDependencies returns the dependencies which will be saved in the state
|
||||
// for managed resources, or the most current dependencies for data resources.
|
||||
func (n *NodeAbstractResourceInstance) StateDependencies() []addrs.ConfigResource {
|
||||
@ -135,7 +198,10 @@ func (n *NodeAbstractResourceInstance) AttachResourceState(s *states.Resource) {
|
||||
}
|
||||
log.Printf("[TRACE] NodeAbstractResourceInstance.AttachResourceState for %s", n.Addr)
|
||||
n.instanceState = s.Instance(n.Addr.Resource.Key)
|
||||
n.storedProviderConfig = s.ProviderConfig
|
||||
n.storedProviderConfig = ResolvedProvider{
|
||||
ProviderConfig: s.ProviderConfig,
|
||||
KeyExact: n.instanceState.ProviderKey,
|
||||
}
|
||||
}
|
||||
|
||||
// readDiff returns the planned change for a particular resource instance
|
||||
@ -273,7 +339,7 @@ func (n *NodeAbstractResourceInstance) writeResourceInstanceStateDeposed(ctx Eva
|
||||
// objects you are intending to write.
|
||||
func (n *NodeAbstractResourceInstance) writeResourceInstanceStateImpl(ctx EvalContext, deposedKey states.DeposedKey, obj *states.ResourceInstanceObject, targetState phaseState) error {
|
||||
absAddr := n.Addr
|
||||
_, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -311,11 +377,11 @@ func (n *NodeAbstractResourceInstance) writeResourceInstanceStateImpl(ctx EvalCo
|
||||
var write func(src *states.ResourceInstanceObjectSrc)
|
||||
if deposedKey == states.NotDeposed {
|
||||
write = func(src *states.ResourceInstanceObjectSrc) {
|
||||
state.SetResourceInstanceCurrent(absAddr, src, n.ResolvedProvider)
|
||||
state.SetResourceInstanceCurrent(absAddr, src, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
}
|
||||
} else {
|
||||
write = func(src *states.ResourceInstanceObjectSrc) {
|
||||
state.SetResourceInstanceDeposed(absAddr, deposedKey, src, n.ResolvedProvider)
|
||||
state.SetResourceInstanceDeposed(absAddr, deposedKey, src, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,7 +430,7 @@ func (n *NodeAbstractResourceInstance) planForget(ctx EvalContext, currentState
|
||||
Before: currentState.Value,
|
||||
After: nullVal,
|
||||
},
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
}
|
||||
|
||||
return plan
|
||||
@ -377,7 +443,7 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState
|
||||
|
||||
absAddr := n.Addr
|
||||
|
||||
if n.ResolvedProvider.Provider.Type == "" {
|
||||
if n.ResolvedProvider.ProviderConfig.Provider.Type == "" {
|
||||
if deposedKey == "" {
|
||||
panic(fmt.Sprintf("planDestroy for %s does not have ProviderAddr set", absAddr))
|
||||
} else {
|
||||
@ -401,7 +467,7 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState
|
||||
Before: cty.NullVal(cty.DynamicPseudoType),
|
||||
After: cty.NullVal(cty.DynamicPseudoType),
|
||||
},
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
}
|
||||
return noop, nil
|
||||
}
|
||||
@ -412,7 +478,7 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState
|
||||
// operation.
|
||||
nullVal := cty.NullVal(unmarkedPriorVal.Type())
|
||||
|
||||
provider, _, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
provider, _, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return plan, diags.Append(err)
|
||||
}
|
||||
@ -452,7 +518,7 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState
|
||||
"Provider produced invalid plan",
|
||||
fmt.Sprintf(
|
||||
"Provider %q planned a non-null destroy value for %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.Provider, n.Addr),
|
||||
n.ResolvedProvider.ProviderConfig, n.Addr),
|
||||
),
|
||||
)
|
||||
return plan, diags
|
||||
@ -469,7 +535,7 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState
|
||||
After: nullVal,
|
||||
},
|
||||
Private: resp.PlannedPrivate,
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
}
|
||||
|
||||
return plan, diags
|
||||
@ -491,7 +557,7 @@ func (n *NodeAbstractResourceInstance) writeChange(ctx EvalContext, change *plan
|
||||
return nil
|
||||
}
|
||||
|
||||
_, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -542,7 +608,7 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state
|
||||
} else {
|
||||
log.Printf("[TRACE] NodeAbstractResourceInstance.refresh for %s (deposed object %s)", absAddr, deposedKey)
|
||||
}
|
||||
provider, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return state, diags.Append(err)
|
||||
}
|
||||
@ -617,7 +683,7 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state
|
||||
"Provider produced invalid object",
|
||||
fmt.Sprintf(
|
||||
"Provider %q planned an invalid value for %s during refresh: %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.Provider.String(), absAddr, tfdiags.FormatError(err),
|
||||
n.ResolvedProvider.ProviderConfig.String(), absAddr, tfdiags.FormatError(err),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -630,7 +696,7 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state
|
||||
// We had to fix up this object in some way, and we still need to
|
||||
// accept any changes for compatibility, so all we can do is log a
|
||||
// warning about the change.
|
||||
log.Printf("[WARN] Provider %q produced an invalid new value containing null blocks for %q during refresh\n", n.ResolvedProvider.Provider, n.Addr)
|
||||
log.Printf("[WARN] Provider %q produced an invalid new value containing null blocks for %q during refresh\n", n.ResolvedProvider.ProviderConfig.Provider, n.Addr)
|
||||
}
|
||||
|
||||
ret := state.DeepCopy()
|
||||
@ -643,7 +709,7 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state
|
||||
// external changes which will be handled by the subsequent plan.
|
||||
if errs := objchange.AssertObjectCompatible(schema, priorVal, ret.Value); len(errs) > 0 {
|
||||
var buf strings.Builder
|
||||
fmt.Fprintf(&buf, "[WARN] Provider %q produced an unexpected new value for %s during refresh.", n.ResolvedProvider.Provider.String(), absAddr)
|
||||
fmt.Fprintf(&buf, "[WARN] Provider %q produced an unexpected new value for %s during refresh.", n.ResolvedProvider.ProviderConfig.Provider.String(), absAddr)
|
||||
for _, err := range errs {
|
||||
fmt.Fprintf(&buf, "\n - %s", tfdiags.FormatError(err))
|
||||
}
|
||||
@ -682,7 +748,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
var keyData instances.RepetitionData
|
||||
|
||||
resource := n.Addr.Resource.Resource
|
||||
provider, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, keyData, diags.Append(err)
|
||||
}
|
||||
@ -863,7 +929,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
"Provider produced invalid plan",
|
||||
fmt.Sprintf(
|
||||
"Provider %q planned an invalid value for %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.Provider, tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
n.ResolvedProvider.ProviderConfig, tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -881,7 +947,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
var buf strings.Builder
|
||||
fmt.Fprintf(&buf,
|
||||
"[WARN] Provider %q produced an invalid plan for %s, but we are tolerating it because it is using the legacy plugin SDK.\n The following problems may be the cause of any confusing errors from downstream operations:",
|
||||
n.ResolvedProvider.Provider, n.Addr,
|
||||
n.ResolvedProvider.ProviderConfig, n.Addr,
|
||||
)
|
||||
for _, err := range errs {
|
||||
fmt.Fprintf(&buf, "\n - %s", tfdiags.FormatError(err))
|
||||
@ -894,7 +960,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
"Provider produced invalid plan",
|
||||
fmt.Sprintf(
|
||||
"Provider %q planned an invalid value for %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.Provider, tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
n.ResolvedProvider.ProviderConfig, tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -958,7 +1024,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
"Provider produced invalid plan",
|
||||
fmt.Sprintf(
|
||||
"Provider %q has indicated \"requires replacement\" on %s for a non-existent attribute path %#v.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.Provider, n.Addr, path,
|
||||
n.ResolvedProvider.ProviderConfig, n.Addr, path,
|
||||
),
|
||||
))
|
||||
continue
|
||||
@ -1098,7 +1164,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
"Provider produced invalid plan",
|
||||
fmt.Sprintf(
|
||||
"Provider %q planned an invalid value for %s%s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.Provider, n.Addr, tfdiags.FormatError(err),
|
||||
n.ResolvedProvider.ProviderConfig, n.Addr, tfdiags.FormatError(err),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -1161,7 +1227,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
Addr: n.Addr,
|
||||
PrevRunAddr: n.prevRunAddr(ctx),
|
||||
Private: plannedPrivate,
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
Change: plans.Change{
|
||||
Action: action,
|
||||
Before: priorVal,
|
||||
@ -1442,7 +1508,7 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
|
||||
|
||||
config := *n.Config
|
||||
|
||||
provider, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := n.getProvider(ctx)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return newVal, diags
|
||||
@ -1450,7 +1516,7 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource().Resource)
|
||||
if schema == nil {
|
||||
// Should be caught during validation, so we don't bother with a pretty error here
|
||||
diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ResolvedProvider, n.Addr.ContainingResource().Resource.Type))
|
||||
diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ResolvedProvider.ProviderConfig, n.Addr.ContainingResource().Resource.Type))
|
||||
return newVal, diags
|
||||
}
|
||||
|
||||
@ -1516,7 +1582,7 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
|
||||
"Provider produced invalid object",
|
||||
fmt.Sprintf(
|
||||
"Provider %q produced an invalid value for %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider, tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
n.ResolvedProvider.ProviderConfig, tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -1530,7 +1596,7 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
|
||||
"Provider produced null object",
|
||||
fmt.Sprintf(
|
||||
"Provider %q produced a null value for %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider, n.Addr,
|
||||
n.ResolvedProvider.ProviderConfig, n.Addr,
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -1541,7 +1607,7 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
|
||||
"Provider produced invalid object",
|
||||
fmt.Sprintf(
|
||||
"Provider %q produced a value for %s that is not wholly known.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider, n.Addr,
|
||||
n.ResolvedProvider.ProviderConfig, n.Addr,
|
||||
),
|
||||
))
|
||||
|
||||
@ -1569,17 +1635,17 @@ func (n *NodeAbstractResourceInstance) providerMetas(ctx EvalContext) (cty.Value
|
||||
var diags tfdiags.Diagnostics
|
||||
metaConfigVal := cty.NullVal(cty.DynamicPseudoType)
|
||||
|
||||
_, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return metaConfigVal, diags.Append(err)
|
||||
}
|
||||
if n.ProviderMetas != nil {
|
||||
if m, ok := n.ProviderMetas[n.ResolvedProvider.Provider]; ok && m != nil {
|
||||
if m, ok := n.ProviderMetas[n.ResolvedProvider.ProviderConfig.Provider]; ok && m != nil {
|
||||
// if the provider doesn't support this feature, throw an error
|
||||
if providerSchema.ProviderMeta.Block == nil {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: fmt.Sprintf("Provider %s doesn't support provider_meta", n.ResolvedProvider.Provider.String()),
|
||||
Summary: fmt.Sprintf("Provider %s doesn't support provider_meta", n.ResolvedProvider.ProviderConfig.Provider.String()),
|
||||
Detail: fmt.Sprintf("The resource %s belongs to a provider that doesn't support provider_meta blocks", n.Addr.Resource),
|
||||
Subject: &m.ProviderRange,
|
||||
})
|
||||
@ -1607,7 +1673,7 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule
|
||||
var keyData instances.RepetitionData
|
||||
var configVal cty.Value
|
||||
|
||||
_, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, keyData, diags.Append(err)
|
||||
}
|
||||
@ -1616,7 +1682,7 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource().Resource)
|
||||
if schema == nil {
|
||||
// Should be caught during validation, so we don't bother with a pretty error here
|
||||
diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ResolvedProvider, n.Addr.ContainingResource().Resource.Type))
|
||||
diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ResolvedProvider.ProviderConfig, n.Addr.ContainingResource().Resource.Type))
|
||||
return nil, nil, keyData, diags
|
||||
}
|
||||
|
||||
@ -1710,7 +1776,7 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule
|
||||
plannedChange := &plans.ResourceInstanceChange{
|
||||
Addr: n.Addr,
|
||||
PrevRunAddr: n.prevRunAddr(ctx),
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
Change: plans.Change{
|
||||
Action: plans.Read,
|
||||
Before: priorVal,
|
||||
@ -1786,7 +1852,7 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule
|
||||
plannedChange = &plans.ResourceInstanceChange{
|
||||
Addr: n.Addr,
|
||||
PrevRunAddr: n.prevRunAddr(ctx),
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
Change: plans.Change{
|
||||
Action: plans.Read,
|
||||
Before: priorVal,
|
||||
@ -1881,7 +1947,7 @@ func (n *NodeAbstractResourceInstance) applyDataSource(ctx EvalContext, planned
|
||||
var diags tfdiags.Diagnostics
|
||||
var keyData instances.RepetitionData
|
||||
|
||||
_, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return nil, keyData, diags.Append(err)
|
||||
}
|
||||
@ -1899,7 +1965,7 @@ func (n *NodeAbstractResourceInstance) applyDataSource(ctx EvalContext, planned
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource().Resource)
|
||||
if schema == nil {
|
||||
// Should be caught during validation, so we don't bother with a pretty error here
|
||||
diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ResolvedProvider, n.Addr.ContainingResource().Resource.Type))
|
||||
diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ResolvedProvider.ProviderConfig, n.Addr.ContainingResource().Resource.Type))
|
||||
return nil, keyData, diags
|
||||
}
|
||||
|
||||
@ -2259,7 +2325,7 @@ func (n *NodeAbstractResourceInstance) apply(
|
||||
return state, diags
|
||||
}
|
||||
|
||||
provider, providerSchema, err := n.getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := n.getProvider(ctx)
|
||||
if err != nil {
|
||||
return nil, diags.Append(err)
|
||||
}
|
||||
@ -2387,7 +2453,7 @@ func (n *NodeAbstractResourceInstance) apply(
|
||||
"Provider produced invalid object",
|
||||
fmt.Sprintf(
|
||||
"Provider %q produced an invalid nil value after apply for %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.String(), n.Addr.String(),
|
||||
n.ResolvedProvider.ProviderConfig.String(), n.Addr.String(),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -2400,7 +2466,7 @@ func (n *NodeAbstractResourceInstance) apply(
|
||||
"Provider produced invalid object",
|
||||
fmt.Sprintf(
|
||||
"Provider %q produced an invalid value after apply for %s. The result cannot not be saved in the OpenTofu state.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.ResolvedProvider.String(), tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
n.ResolvedProvider.ProviderConfig.String(), tfdiags.FormatErrorPrefixed(err, n.Addr.String()),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -2470,7 +2536,7 @@ func (n *NodeAbstractResourceInstance) apply(
|
||||
// to notice in the logs if an inconsistency beyond the type system
|
||||
// leads to a downstream provider failure.
|
||||
var buf strings.Builder
|
||||
fmt.Fprintf(&buf, "[WARN] Provider %q produced an unexpected new value for %s, but we are tolerating it because it is using the legacy plugin SDK.\n The following problems may be the cause of any confusing errors from downstream operations:", n.ResolvedProvider.String(), n.Addr)
|
||||
fmt.Fprintf(&buf, "[WARN] Provider %q produced an unexpected new value for %s, but we are tolerating it because it is using the legacy plugin SDK.\n The following problems may be the cause of any confusing errors from downstream operations:", n.ResolvedProvider.ProviderConfig.String(), n.Addr)
|
||||
for _, err := range errs {
|
||||
fmt.Fprintf(&buf, "\n - %s", tfdiags.FormatError(err))
|
||||
}
|
||||
@ -2490,7 +2556,7 @@ func (n *NodeAbstractResourceInstance) apply(
|
||||
"Provider produced inconsistent result after apply",
|
||||
fmt.Sprintf(
|
||||
"When applying changes to %s, provider %q produced an unexpected new value: %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
n.Addr, n.ResolvedProvider.String(), tfdiags.FormatError(err),
|
||||
n.Addr, n.ResolvedProvider.ProviderConfig.String(), tfdiags.FormatError(err),
|
||||
),
|
||||
))
|
||||
}
|
||||
@ -2579,8 +2645,8 @@ func resourceInstancePrevRunAddr(ctx EvalContext, currentAddr addrs.AbsResourceI
|
||||
return table.OldAddr(currentAddr)
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) getProvider(ctx EvalContext, addr addrs.AbsProviderConfig) (providers.Interface, providers.ProviderSchema, error) {
|
||||
underlyingProvider, schema, err := getProvider(ctx, addr)
|
||||
func (n *NodeAbstractResourceInstance) getProvider(ctx EvalContext) (providers.Interface, providers.ProviderSchema, error) {
|
||||
underlyingProvider, schema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
if err != nil {
|
||||
return nil, providers.ProviderSchema{}, err
|
||||
}
|
||||
|
@ -131,9 +131,11 @@ func TestNodeAbstractResourceInstanceProvider(t *testing.T) {
|
||||
// function. (This would not be valid for some other functions.)
|
||||
Addr: test.Addr,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
Addr: test.Addr.ConfigResource(),
|
||||
Config: test.Config,
|
||||
storedProviderConfig: test.StoredProviderConfig,
|
||||
Addr: test.Addr.ConfigResource(),
|
||||
Config: test.Config,
|
||||
storedProviderConfig: ResolvedProvider{
|
||||
ProviderConfig: test.StoredProviderConfig,
|
||||
},
|
||||
},
|
||||
}
|
||||
got := node.Provider()
|
||||
@ -170,7 +172,7 @@ func TestNodeAbstractResourceInstance_WriteResourceInstanceState(t *testing.T) {
|
||||
Addr: mustResourceInstanceAddr("aws_instance.foo"),
|
||||
// instanceState: obj,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
ctx.ProviderProvider = mockProvider
|
||||
|
@ -145,7 +145,7 @@ func TestNodeAbstractResourceSetProvider(t *testing.T) {
|
||||
p := node.ProvidedBy()
|
||||
|
||||
// the implied non-exact provider should be "terraform"
|
||||
lpc, ok := p.(addrs.LocalProviderConfig)
|
||||
lpc, ok := p.ProviderConfig.(addrs.LocalProviderConfig)
|
||||
if !ok {
|
||||
t.Fatalf("expected LocalProviderConfig, got %#v\n", p)
|
||||
}
|
||||
@ -165,10 +165,10 @@ func TestNodeAbstractResourceSetProvider(t *testing.T) {
|
||||
Alias: "test",
|
||||
}
|
||||
|
||||
node.SetProvider(resolved)
|
||||
node.SetProvider(ResolvedProvider{ProviderConfig: resolved})
|
||||
p = node.ProvidedBy()
|
||||
|
||||
apc, ok := p.(addrs.AbsProviderConfig)
|
||||
apc, ok := p.ProviderConfig.(addrs.AbsProviderConfig)
|
||||
if !ok {
|
||||
t.Fatalf("expected AbsProviderConfig, got %#v\n", p)
|
||||
}
|
||||
@ -193,7 +193,7 @@ func TestNodeAbstractResource_ReadResourceInstanceState(t *testing.T) {
|
||||
|
||||
tests := map[string]struct {
|
||||
State *states.State
|
||||
Node *NodeAbstractResource
|
||||
Node *NodeAbstractResourceInstance
|
||||
ExpectedInstanceId string
|
||||
}{
|
||||
"ReadState gets primary instance state": {
|
||||
@ -211,12 +211,12 @@ func TestNodeAbstractResource_ReadResourceInstanceState(t *testing.T) {
|
||||
s.SetResourceInstanceCurrent(oneAddr.Instance(addrs.NoKey), &states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
}, providerAddr)
|
||||
}, providerAddr, addrs.NoKey)
|
||||
}),
|
||||
Node: &NodeAbstractResource{
|
||||
Node: &NodeAbstractResourceInstance{NodeAbstractResource: NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("aws_instance.bar"),
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
},
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
}},
|
||||
ExpectedInstanceId: "i-abc123",
|
||||
},
|
||||
}
|
||||
@ -230,7 +230,7 @@ func TestNodeAbstractResource_ReadResourceInstanceState(t *testing.T) {
|
||||
|
||||
ctx.ProviderProvider = providers.Interface(mockProvider)
|
||||
|
||||
got, readDiags := test.Node.readResourceInstanceState(ctx, test.Node.Addr.Resource.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
|
||||
got, readDiags := test.Node.readResourceInstanceState(ctx, test.Node.NodeAbstractResource.Addr.Resource.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
|
||||
if readDiags.HasErrors() {
|
||||
t.Fatalf("[%s] Got err: %#v", k, readDiags.Err())
|
||||
}
|
||||
@ -259,7 +259,7 @@ func TestNodeAbstractResource_ReadResourceInstanceStateDeposed(t *testing.T) {
|
||||
|
||||
tests := map[string]struct {
|
||||
State *states.State
|
||||
Node *NodeAbstractResource
|
||||
Node *NodeAbstractResourceInstance
|
||||
ExpectedInstanceId string
|
||||
}{
|
||||
"ReadStateDeposed gets deposed instance": {
|
||||
@ -277,12 +277,12 @@ func TestNodeAbstractResource_ReadResourceInstanceStateDeposed(t *testing.T) {
|
||||
s.SetResourceInstanceDeposed(oneAddr.Instance(addrs.NoKey), states.DeposedKey("00000001"), &states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||
}, providerAddr)
|
||||
}, providerAddr, addrs.NoKey)
|
||||
}),
|
||||
Node: &NodeAbstractResource{
|
||||
Node: &NodeAbstractResourceInstance{NodeAbstractResource: NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("aws_instance.bar"),
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
},
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
}},
|
||||
ExpectedInstanceId: "i-abc123",
|
||||
},
|
||||
}
|
||||
@ -296,7 +296,7 @@ func TestNodeAbstractResource_ReadResourceInstanceStateDeposed(t *testing.T) {
|
||||
|
||||
key := states.DeposedKey("00000001") // shim from legacy state assigns 0th deposed index this key
|
||||
|
||||
got, readDiags := test.Node.readResourceInstanceStateDeposed(ctx, test.Node.Addr.Resource.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), key)
|
||||
got, readDiags := test.Node.readResourceInstanceStateDeposed(ctx, test.Node.NodeAbstractResource.Addr.Resource.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), key)
|
||||
if readDiags.HasErrors() {
|
||||
t.Fatalf("[%s] Got err: %#v", k, readDiags.Err())
|
||||
}
|
||||
|
@ -141,6 +141,11 @@ func (n *NodeApplyableResourceInstance) Execute(ctx EvalContext, op walkOperatio
|
||||
return diags
|
||||
}
|
||||
|
||||
diags = n.resolveProvider(ctx)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
// Eval info is different depending on what kind of resource this is
|
||||
switch n.Config.Mode {
|
||||
case addrs.ManagedResourceMode:
|
||||
@ -153,7 +158,7 @@ func (n *NodeApplyableResourceInstance) Execute(ctx EvalContext, op walkOperatio
|
||||
}
|
||||
|
||||
func (n *NodeApplyableResourceInstance) dataResourceExecute(ctx EvalContext) (diags tfdiags.Diagnostics) {
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
@ -221,7 +226,7 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
|
||||
var deposedKey states.DeposedKey
|
||||
|
||||
addr := n.ResourceInstanceAddr().Resource
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
@ -443,7 +448,7 @@ func (n *NodeApplyableResourceInstance) checkPlannedChange(ctx EvalContext, plan
|
||||
"Provider produced inconsistent final plan",
|
||||
fmt.Sprintf(
|
||||
"When expanding the plan for %s to include new values learned so far during apply, provider %q changed the planned action from %s to %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
absAddr, n.ResolvedProvider.Provider.String(),
|
||||
absAddr, n.ResolvedProvider.ProviderConfig.Provider.String(),
|
||||
plannedChange.Action, actualChange.Action,
|
||||
),
|
||||
))
|
||||
@ -457,7 +462,7 @@ func (n *NodeApplyableResourceInstance) checkPlannedChange(ctx EvalContext, plan
|
||||
"Provider produced inconsistent final plan",
|
||||
fmt.Sprintf(
|
||||
"When expanding the plan for %s to include new values learned so far during apply, provider %q produced an invalid new value for %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
||||
absAddr, n.ResolvedProvider.Provider.String(), tfdiags.FormatError(err),
|
||||
absAddr, n.ResolvedProvider.ProviderConfig.Provider.String(), tfdiags.FormatError(err),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ func TestNodeExpandApplyableResourceExecute(t *testing.T) {
|
||||
Type: "test_instance",
|
||||
Name: "foo",
|
||||
},
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
}},
|
||||
},
|
||||
}
|
||||
diags := node.Execute(ctx, walkApply)
|
||||
|
@ -328,12 +328,12 @@ func (n *NodeDestroyDeposedResourceInstanceObject) writeResourceInstanceState(ct
|
||||
|
||||
if obj == nil {
|
||||
// No need to encode anything: we'll just write it directly.
|
||||
state.SetResourceInstanceDeposed(absAddr, key, nil, n.ResolvedProvider)
|
||||
state.SetResourceInstanceDeposed(absAddr, key, nil, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
log.Printf("[TRACE] writeResourceInstanceStateDeposed: removing state object for %s deposed %s", absAddr, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -351,7 +351,7 @@ func (n *NodeDestroyDeposedResourceInstanceObject) writeResourceInstanceState(ct
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] writeResourceInstanceStateDeposed: writing state object for %s deposed %s", absAddr, key)
|
||||
state.SetResourceInstanceDeposed(absAddr, key, src, n.ResolvedProvider)
|
||||
state.SetResourceInstanceDeposed(absAddr, key, src, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ func TestNodePlanDeposedResourceInstanceObject_Execute(t *testing.T) {
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
Addr: absResource,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`)},
|
||||
},
|
||||
},
|
||||
DeposedKey: deposedKey,
|
||||
@ -133,7 +133,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_Execute(t *testing.T) {
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
Addr: absResource,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`)},
|
||||
},
|
||||
},
|
||||
DeposedKey: deposedKey,
|
||||
@ -174,7 +174,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_WriteResourceInstanceState(t *
|
||||
node := &NodeDestroyDeposedResourceInstanceObject{
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
Addr: mustResourceInstanceAddr("aws_instance.foo"),
|
||||
},
|
||||
@ -206,7 +206,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_ExecuteMissingState(t *testing
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
Addr: mustResourceInstanceAddr("test_object.foo"),
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`)},
|
||||
},
|
||||
},
|
||||
DeposedKey: states.NewDeposedKey(),
|
||||
@ -229,7 +229,7 @@ func TestNodeForgetDeposedResourceInstanceObject_Execute(t *testing.T) {
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
Addr: absResource,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`)},
|
||||
},
|
||||
},
|
||||
DeposedKey: deposedKey,
|
||||
@ -261,6 +261,7 @@ func initMockEvalContext(resourceAddrs string, deposedKey states.DeposedKey) (*M
|
||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
schema := providers.ProviderSchema{
|
||||
|
@ -49,10 +49,10 @@ func (n *NodeDestroyResourceInstance) Name() string {
|
||||
return n.ResourceInstanceAddr().String() + " (destroy)"
|
||||
}
|
||||
|
||||
func (n *NodeDestroyResourceInstance) ProvidedBy() addrs.ProviderConfig {
|
||||
func (n *NodeDestroyResourceInstance) ProvidedBy() RequestedProvider {
|
||||
if n.Addr.Resource.Resource.Mode == addrs.DataResourceMode {
|
||||
// indicate that this node does not require a configured provider
|
||||
return nil
|
||||
return RequestedProvider{}
|
||||
}
|
||||
return n.NodeAbstractResourceInstance.ProvidedBy()
|
||||
}
|
||||
@ -143,6 +143,10 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation)
|
||||
// Eval info is different depending on what kind of resource this is
|
||||
switch addr.Resource.Resource.Mode {
|
||||
case addrs.ManagedResourceMode:
|
||||
diags = n.resolveProvider(ctx)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
return n.managedResourceExecute(ctx)
|
||||
case addrs.DataResourceMode:
|
||||
return n.dataResourceExecute(ctx)
|
||||
@ -164,7 +168,7 @@ func (n *NodeDestroyResourceInstance) managedResourceExecute(ctx EvalContext) (d
|
||||
var changeApply *plans.ResourceInstanceChange
|
||||
var state *states.ResourceInstanceObject
|
||||
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
@ -234,6 +238,6 @@ func (n *NodeDestroyResourceInstance) managedResourceExecute(ctx EvalContext) (d
|
||||
|
||||
func (n *NodeDestroyResourceInstance) dataResourceExecute(ctx EvalContext) (diags tfdiags.Diagnostics) {
|
||||
log.Printf("[TRACE] NodeDestroyResourceInstance: removing state object for %s", n.Addr)
|
||||
ctx.State().SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider)
|
||||
ctx.State().SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
return diags.Append(updateStateHook(ctx))
|
||||
}
|
||||
|
@ -18,9 +18,10 @@ import (
|
||||
)
|
||||
|
||||
type graphNodeImportState struct {
|
||||
Addr addrs.AbsResourceInstance // Addr is the resource address to import into
|
||||
ID string // ID is the ID to import as
|
||||
ResolvedProvider addrs.AbsProviderConfig // provider node address after resolution
|
||||
Addr addrs.AbsResourceInstance // Addr is the resource address to import into
|
||||
ID string // ID is the ID to import as
|
||||
ResolvedProvider ResolvedProvider // provider node address after resolution
|
||||
ResolvedProviderKey addrs.InstanceKey // resolved from ResolvedProviderKeyExpr+ResolvedProviderKeyPath in method Execute
|
||||
|
||||
Schema *configschema.Block // Schema for processing the configuration body
|
||||
SchemaVersion uint64 // Schema version of "Schema", as decided by the provider
|
||||
@ -41,20 +42,26 @@ func (n *graphNodeImportState) Name() string {
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *graphNodeImportState) ProvidedBy() addrs.ProviderConfig {
|
||||
func (n *graphNodeImportState) ProvidedBy() RequestedProvider {
|
||||
// This has already been resolved by nodeExpandPlannableResource
|
||||
return n.ResolvedProvider
|
||||
return RequestedProvider{
|
||||
ProviderConfig: n.ResolvedProvider.ProviderConfig,
|
||||
KeyExpression: n.ResolvedProvider.KeyExpression,
|
||||
KeyModule: n.ResolvedProvider.KeyModule,
|
||||
KeyResource: n.ResolvedProvider.KeyResource,
|
||||
KeyExact: n.ResolvedProvider.KeyExact,
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *graphNodeImportState) Provider() addrs.Provider {
|
||||
// This has already been resolved by nodeExpandPlannableResource
|
||||
return n.ResolvedProvider.Provider
|
||||
return n.ResolvedProvider.ProviderConfig.Provider
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *graphNodeImportState) SetProvider(addr addrs.AbsProviderConfig) {
|
||||
n.ResolvedProvider = addr
|
||||
func (n *graphNodeImportState) SetProvider(resolved ResolvedProvider) {
|
||||
n.ResolvedProvider = resolved
|
||||
}
|
||||
|
||||
// GraphNodeModuleInstance
|
||||
@ -72,7 +79,27 @@ func (n *graphNodeImportState) Execute(ctx EvalContext, op walkOperation) (diags
|
||||
// Reset our states
|
||||
n.states = nil
|
||||
|
||||
provider, _, err := getProvider(ctx, n.ResolvedProvider)
|
||||
// FIXME, yuck: borrowing some logic that's currently only available for the abstract resource instance
|
||||
// node, even though graphNodeImportState doesn't actually embed that type for some reason.
|
||||
// Let's factor this logic out somewhere that's explicitly shareable.
|
||||
asAbsNode := &NodeAbstractResourceInstance{
|
||||
Addr: n.Addr,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
Addr: n.Addr.ConfigResource(),
|
||||
Config: n.Config,
|
||||
Schema: n.Schema,
|
||||
SchemaVersion: n.SchemaVersion,
|
||||
ResolvedProvider: n.ResolvedProvider,
|
||||
},
|
||||
}
|
||||
diags = diags.Append(asAbsNode.resolveProvider(ctx))
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
n.ResolvedProviderKey = asAbsNode.ResolvedProviderKey
|
||||
log.Printf("[TRACE] graphNodeImportState: importing using %s instance %s", n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
|
||||
provider, _, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
@ -172,12 +199,13 @@ func (n *graphNodeImportState) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||
// safe.
|
||||
for i, state := range n.states {
|
||||
g.Add(&graphNodeImportStateSub{
|
||||
TargetAddr: addrs[i],
|
||||
State: state,
|
||||
ResolvedProvider: n.ResolvedProvider,
|
||||
Schema: n.Schema,
|
||||
SchemaVersion: n.SchemaVersion,
|
||||
Config: n.Config,
|
||||
TargetAddr: addrs[i],
|
||||
State: state,
|
||||
ResolvedProvider: n.ResolvedProvider,
|
||||
ResolvedProviderKey: n.ResolvedProviderKey,
|
||||
Schema: n.Schema,
|
||||
SchemaVersion: n.SchemaVersion,
|
||||
Config: n.Config,
|
||||
})
|
||||
}
|
||||
|
||||
@ -191,14 +219,14 @@ func (n *graphNodeImportState) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||
// and is part of the subgraph. This node is responsible for refreshing
|
||||
// and adding a resource to the state once it is imported.
|
||||
type graphNodeImportStateSub struct {
|
||||
TargetAddr addrs.AbsResourceInstance
|
||||
State providers.ImportedResource
|
||||
ResolvedProvider addrs.AbsProviderConfig
|
||||
TargetAddr addrs.AbsResourceInstance
|
||||
State providers.ImportedResource
|
||||
ResolvedProvider ResolvedProvider
|
||||
ResolvedProviderKey addrs.InstanceKey // the dynamic instance ResolvedProvider
|
||||
|
||||
Schema *configschema.Block // Schema for processing the configuration body
|
||||
SchemaVersion uint64 // Schema version of "Schema", as decided by the provider
|
||||
Config *configs.Resource // Config is the resource in the config
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
@ -230,6 +258,7 @@ func (n *graphNodeImportStateSub) Execute(ctx EvalContext, op walkOperation) (di
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: n.ResolvedProvider,
|
||||
},
|
||||
ResolvedProviderKey: n.ResolvedProviderKey,
|
||||
}
|
||||
state, refreshDiags := riNode.refresh(ctx, states.NotDeposed, state)
|
||||
diags = diags.Append(refreshDiags)
|
||||
|
@ -128,6 +128,7 @@ func (n *nodeExpandPlannableResource) DynamicExpand(ctx EvalContext) (*Graph, er
|
||||
// Add the config and state since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
// ResolvedProviderKey set in AttachResourceState
|
||||
a.Schema = n.Schema
|
||||
a.ProvisionerSchemas = n.ProvisionerSchemas
|
||||
a.ProviderMetas = n.ProviderMetas
|
||||
@ -380,6 +381,7 @@ func (n *nodeExpandPlannableResource) resourceInstanceSubgraph(ctx EvalContext,
|
||||
// Add the config and state since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
// ResolvedProviderKey will be set during AttachResourceState
|
||||
a.Schema = n.Schema
|
||||
a.ProvisionerSchemas = n.ProvisionerSchemas
|
||||
a.ProviderMetas = n.ProviderMetas
|
||||
@ -427,6 +429,6 @@ func (n *nodeExpandPlannableResource) resourceInstanceSubgraph(ctx EvalContext,
|
||||
Steps: steps,
|
||||
Name: "nodeExpandPlannableResource",
|
||||
}
|
||||
graph, diags := b.Build(addr.Module)
|
||||
return graph, diags.ErrWithWarnings()
|
||||
graph, graphDiags := b.Build(addr.Module)
|
||||
return graph, diags.Append(graphDiags).ErrWithWarnings()
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ func (n *NodePlanDestroyableResourceInstance) dataResourceExecute(ctx EvalContex
|
||||
Before: cty.NullVal(cty.DynamicPseudoType),
|
||||
After: cty.NullVal(cty.DynamicPseudoType),
|
||||
},
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
}
|
||||
return diags.Append(n.writeChange(ctx, change, ""))
|
||||
}
|
||||
|
@ -86,6 +86,11 @@ var (
|
||||
func (n *NodePlannableResourceInstance) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
|
||||
addr := n.ResourceInstanceAddr()
|
||||
|
||||
diags := n.resolveProvider(ctx)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
// Eval info is different depending on what kind of resource this is
|
||||
switch addr.Resource.Resource.Mode {
|
||||
case addrs.ManagedResourceMode:
|
||||
@ -103,7 +108,7 @@ func (n *NodePlannableResourceInstance) dataResourceExecute(ctx EvalContext) (di
|
||||
|
||||
var change *plans.ResourceInstanceChange
|
||||
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
_, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
@ -164,7 +169,7 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext)
|
||||
checkRuleSeverity = tfdiags.Warning
|
||||
}
|
||||
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
@ -294,7 +299,7 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext)
|
||||
change := &plans.ResourceInstanceChange{
|
||||
Addr: n.Addr,
|
||||
PrevRunAddr: n.prevRunAddr(ctx),
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderAddr: n.ResolvedProvider.ProviderConfig,
|
||||
Change: plans.Change{
|
||||
// we only need a placeholder, so this will be a NoOp
|
||||
Action: plans.NoOp,
|
||||
@ -532,6 +537,7 @@ func (n *NodePlannableResourceInstance) importState(ctx EvalContext, addr addrs.
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: n.ResolvedProvider,
|
||||
},
|
||||
ResolvedProviderKey: n.ResolvedProviderKey,
|
||||
}
|
||||
instanceRefreshState, refreshDiags := riNode.refresh(ctx, states.NotDeposed, importedState)
|
||||
diags = diags.Append(refreshDiags)
|
||||
@ -632,7 +638,7 @@ func (n *NodePlannableResourceInstance) importState(ctx EvalContext, addr addrs.
|
||||
Name: n.Addr.Resource.Resource.Name,
|
||||
Config: remain,
|
||||
Managed: &configs.ManagedResource{},
|
||||
Provider: n.ResolvedProvider.Provider,
|
||||
Provider: n.ResolvedProvider.ProviderConfig.Provider,
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,8 +681,8 @@ func (n *NodePlannableResourceInstance) generateHCLStringAttributes(addr addrs.A
|
||||
)
|
||||
|
||||
providerAddr := addrs.LocalProviderConfig{
|
||||
LocalName: n.ResolvedProvider.Provider.Type,
|
||||
Alias: n.ResolvedProvider.Alias,
|
||||
LocalName: n.ResolvedProvider.ProviderConfig.Provider.Type,
|
||||
Alias: n.ResolvedProvider.ProviderConfig.Alias,
|
||||
}
|
||||
|
||||
return genconfig.GenerateResourceContents(addr, filteredSchema, providerAddr, state.Value)
|
||||
|
@ -57,6 +57,10 @@ func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOp
|
||||
// Eval info is different depending on what kind of resource this is
|
||||
switch addr.Resource.Resource.Mode {
|
||||
case addrs.ManagedResourceMode:
|
||||
diags := n.resolveProvider(ctx)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
return n.managedResourceExecute(ctx)
|
||||
case addrs.DataResourceMode:
|
||||
return n.dataResourceExecute(ctx)
|
||||
@ -65,10 +69,10 @@ func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOp
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NodePlannableResourceInstanceOrphan) ProvidedBy() addrs.ProviderConfig {
|
||||
func (n *NodePlannableResourceInstanceOrphan) ProvidedBy() RequestedProvider {
|
||||
if n.Addr.Resource.Resource.Mode == addrs.DataResourceMode {
|
||||
// indicate that this node does not require a configured provider
|
||||
return nil
|
||||
return RequestedProvider{}
|
||||
}
|
||||
return n.NodeAbstractResourceInstance.ProvidedBy()
|
||||
}
|
||||
@ -80,10 +84,10 @@ func (n *NodePlannableResourceInstanceOrphan) dataResourceExecute(ctx EvalContex
|
||||
// we need to update both the refresh state to refresh the current data
|
||||
// source, and the working state for plan-time evaluations.
|
||||
refreshState := ctx.RefreshState()
|
||||
refreshState.SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider)
|
||||
refreshState.SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
|
||||
workingState := ctx.State()
|
||||
workingState.SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider)
|
||||
workingState.SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,7 @@ func TestNodeResourcePlanOrphan_Execute(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
schema := providers.ProviderSchema{
|
||||
@ -142,10 +143,10 @@ func TestNodeResourcePlanOrphan_Execute(t *testing.T) {
|
||||
node := NodePlannableResourceInstanceOrphan{
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
}},
|
||||
},
|
||||
Addr: absResource,
|
||||
},
|
||||
@ -188,6 +189,7 @@ func TestNodeResourcePlanOrphanExecute_alreadyDeleted(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
refreshState := state.DeepCopy()
|
||||
prevRunState := state.DeepCopy()
|
||||
@ -217,10 +219,10 @@ func TestNodeResourcePlanOrphanExecute_alreadyDeleted(t *testing.T) {
|
||||
node := NodePlannableResourceInstanceOrphan{
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
}},
|
||||
},
|
||||
Addr: mustResourceInstanceAddr("test_object.foo"),
|
||||
},
|
||||
@ -270,6 +272,7 @@ func TestNodeResourcePlanOrphanExecute_deposed(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
refreshState := state.DeepCopy()
|
||||
prevRunState := state.DeepCopy()
|
||||
@ -299,10 +302,10 @@ func TestNodeResourcePlanOrphanExecute_deposed(t *testing.T) {
|
||||
node := NodePlannableResourceInstanceOrphan{
|
||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
}},
|
||||
},
|
||||
Addr: mustResourceInstanceAddr("test_object.foo"),
|
||||
},
|
||||
|
@ -282,7 +282,7 @@ var connectionBlockSupersetSchema = &configschema.Block{
|
||||
func (n *NodeValidatableResource) validateResource(ctx EvalContext) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
|
||||
provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, addrs.NoKey) // Provider Instance Keys are ignored during validate
|
||||
diags = diags.Append(err)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
|
@ -189,7 +189,7 @@ func TestNodeValidatableResource_ValidateResource_managedResource(t *testing.T)
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_foo.bar"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
@ -257,7 +257,7 @@ func TestNodeValidatableResource_ValidateResource_managedResourceCount(t *testin
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_foo.bar"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
@ -303,7 +303,7 @@ func TestNodeValidatableResource_ValidateResource_dataSource(t *testing.T) {
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_foo.bar"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
@ -339,7 +339,7 @@ func TestNodeValidatableResource_ValidateResource_valid(t *testing.T) {
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_object.foo"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
@ -376,7 +376,7 @@ func TestNodeValidatableResource_ValidateResource_warningsAndErrorsPassedThrough
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_foo.bar"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
@ -438,7 +438,7 @@ func TestNodeValidatableResource_ValidateResource_invalidDependsOn(t *testing.T)
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_foo.bar"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
@ -522,7 +522,7 @@ func TestNodeValidatableResource_ValidateResource_invalidIgnoreChangesNonexisten
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_foo.bar"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
@ -605,7 +605,7 @@ func TestNodeValidatableResource_ValidateResource_invalidIgnoreChangesComputed(t
|
||||
NodeAbstractResource: &NodeAbstractResource{
|
||||
Addr: mustConfigResourceAddr("test_foo.bar"),
|
||||
Config: rc,
|
||||
ResolvedProvider: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`)},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,7 @@ func testSetResourceInstanceCurrent(module *states.Module, resource, attrsJson,
|
||||
AttrsJSON: []byte(attrsJson),
|
||||
},
|
||||
mustProviderConfig(provider),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}
|
||||
|
||||
@ -168,6 +169,7 @@ func testSetResourceInstanceTainted(module *states.Module, resource, attrsJson,
|
||||
AttrsJSON: []byte(attrsJson),
|
||||
},
|
||||
mustProviderConfig(provider),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ run "test_case" {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
provider: &MockProvider{
|
||||
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
|
||||
@ -123,7 +123,7 @@ run "test_case" {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
provider: &MockProvider{
|
||||
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
|
||||
@ -183,7 +183,7 @@ run "test_case" {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
variables: InputValues{
|
||||
"value": {
|
||||
@ -240,7 +240,7 @@ run "test_case" {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
provider: &MockProvider{
|
||||
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
|
||||
@ -303,7 +303,7 @@ run "test_case" {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
provider: &MockProvider{
|
||||
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
|
||||
@ -403,7 +403,7 @@ run "test_case" {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
plan: &plans.Plan{
|
||||
Changes: &plans.Changes{
|
||||
@ -479,7 +479,7 @@ run "test_case" {
|
||||
addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
})
|
||||
}, addrs.NoKey)
|
||||
}),
|
||||
plan: &plans.Plan{
|
||||
Changes: &plans.Changes{
|
||||
|
@ -105,6 +105,7 @@ func TestCBDEdgeTransformer(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -114,6 +115,7 @@ func TestCBDEdgeTransformer(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := cbdTestGraph(t, "transform-destroy-cbd-edge-basic", changes, state)
|
||||
@ -166,6 +168,7 @@ func TestCBDEdgeTransformerMulti(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -174,6 +177,7 @@ func TestCBDEdgeTransformerMulti(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"B"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.C").Resource,
|
||||
@ -186,6 +190,7 @@ func TestCBDEdgeTransformerMulti(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := cbdTestGraph(t, "transform-destroy-cbd-edge-multi", changes, state)
|
||||
@ -242,6 +247,7 @@ func TestCBDEdgeTransformer_depNonCBDCount(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B[0]").Resource,
|
||||
@ -251,6 +257,7 @@ func TestCBDEdgeTransformer_depNonCBDCount(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B[1]").Resource,
|
||||
@ -260,6 +267,7 @@ func TestCBDEdgeTransformer_depNonCBDCount(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := cbdTestGraph(t, "transform-cbd-destroy-edge-count", changes, state)
|
||||
@ -319,6 +327,7 @@ func TestCBDEdgeTransformer_depNonCBDCountBoth(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.A[1]").Resource,
|
||||
@ -327,6 +336,7 @@ func TestCBDEdgeTransformer_depNonCBDCountBoth(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B[0]").Resource,
|
||||
@ -336,6 +346,7 @@ func TestCBDEdgeTransformer_depNonCBDCountBoth(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B[1]").Resource,
|
||||
@ -345,6 +356,7 @@ func TestCBDEdgeTransformer_depNonCBDCountBoth(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := cbdTestGraph(t, "transform-cbd-destroy-edge-both-count", changes, state)
|
||||
|
@ -102,7 +102,7 @@ func (t *DestroyEdgeTransformer) tryInterProviderDestroyEdge(g *Graph, from, to
|
||||
// from the same provider instance.
|
||||
getComparableProvider := func(pc GraphNodeProviderConsumer) string {
|
||||
p := pc.ProvidedBy()
|
||||
switch p := p.(type) {
|
||||
switch p := p.ProviderConfig.(type) {
|
||||
case addrs.AbsProviderConfig:
|
||||
return p.String()
|
||||
case addrs.LocalProviderConfig:
|
||||
|
@ -33,6 +33,7 @@ func TestDestroyEdgeTransformer_basic(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -42,6 +43,7 @@ func TestDestroyEdgeTransformer_basic(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
if err := (&AttachStateTransformer{State: state}).Transform(&g); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -74,6 +76,7 @@ func TestDestroyEdgeTransformer_multi(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -83,6 +86,7 @@ func TestDestroyEdgeTransformer_multi(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.C").Resource,
|
||||
@ -95,6 +99,7 @@ func TestDestroyEdgeTransformer_multi(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
if err := (&AttachStateTransformer{State: state}).Transform(&g); err != nil {
|
||||
@ -143,6 +148,7 @@ func TestDestroyEdgeTransformer_module(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.child.test_object.b")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.b").Resource,
|
||||
@ -151,6 +157,7 @@ func TestDestroyEdgeTransformer_module(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"b","test_string":"x"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
if err := (&AttachStateTransformer{State: state}).Transform(&g); err != nil {
|
||||
@ -186,6 +193,7 @@ func TestDestroyEdgeTransformer_moduleOnly(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"a"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.b").Resource,
|
||||
@ -197,6 +205,7 @@ func TestDestroyEdgeTransformer_moduleOnly(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
child.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.c").Resource,
|
||||
@ -209,6 +218,7 @@ func TestDestroyEdgeTransformer_moduleOnly(t *testing.T) {
|
||||
},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}
|
||||
|
||||
@ -269,6 +279,7 @@ func TestDestroyEdgeTransformer_destroyThenUpdate(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A","test_string":"old"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -278,6 +289,7 @@ func TestDestroyEdgeTransformer_destroyThenUpdate(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
if err := (&AttachStateTransformer{State: state}).Transform(&g); err != nil {
|
||||
@ -367,6 +379,7 @@ func TestPruneUnusedNodesTransformer_rootModuleOutputValues(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
providerCfgAddr,
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
changes := plans.NewChanges()
|
||||
@ -461,6 +474,7 @@ func TestDestroyEdgeTransformer_noOp(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.B").Resource,
|
||||
@ -470,6 +484,7 @@ func TestDestroyEdgeTransformer_noOp(t *testing.T) {
|
||||
Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("test_object.C").Resource,
|
||||
@ -480,6 +495,7 @@ func TestDestroyEdgeTransformer_noOp(t *testing.T) {
|
||||
mustConfigResourceAddr("test_object.B")},
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
if err := (&AttachStateTransformer{State: state}).Transform(&g); err != nil {
|
||||
@ -540,6 +556,7 @@ func TestDestroyEdgeTransformer_dataDependsOn(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"A"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/test"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
if err := (&AttachStateTransformer{State: state}).Transform(&g); err != nil {
|
||||
|
@ -46,10 +46,10 @@ func TestGraphNodeImportStateExecute(t *testing.T) {
|
||||
Name: "foo",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
ID: "bar",
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
diags := node.Execute(ctx, walkImport)
|
||||
@ -102,10 +102,10 @@ func TestGraphNodeImportStateSubExecute(t *testing.T) {
|
||||
Name: "foo",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
State: importedResource,
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
}},
|
||||
}
|
||||
diags := node.Execute(ctx, walkImport)
|
||||
if diags.HasErrors() {
|
||||
@ -164,10 +164,10 @@ func TestGraphNodeImportStateSubExecuteNull(t *testing.T) {
|
||||
Name: "foo",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
State: importedResource,
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ResolvedProvider: ResolvedProvider{ProviderConfig: addrs.AbsProviderConfig{
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
}},
|
||||
}
|
||||
diags := node.Execute(ctx, walkImport)
|
||||
if !diags.HasErrors() {
|
||||
|
@ -23,6 +23,7 @@ func TestOrphanResourceCountTransformer(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
@ -31,6 +32,7 @@ func TestOrphanResourceCountTransformer(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -39,6 +41,7 @@ func TestOrphanResourceCountTransformer(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := Graph{Path: addrs.RootModuleInstance}
|
||||
@ -74,6 +77,7 @@ func TestOrphanResourceCountTransformer_zero(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
@ -82,6 +86,7 @@ func TestOrphanResourceCountTransformer_zero(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -90,6 +95,7 @@ func TestOrphanResourceCountTransformer_zero(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := Graph{Path: addrs.RootModuleInstance}
|
||||
@ -125,6 +131,7 @@ func TestOrphanResourceCountTransformer_oneIndex(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
@ -133,6 +140,7 @@ func TestOrphanResourceCountTransformer_oneIndex(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -141,6 +149,7 @@ func TestOrphanResourceCountTransformer_oneIndex(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := Graph{Path: addrs.RootModuleInstance}
|
||||
@ -176,6 +185,7 @@ func TestOrphanResourceCountTransformer_deposed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[0]").Resource,
|
||||
@ -184,6 +194,7 @@ func TestOrphanResourceCountTransformer_deposed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceCurrent(
|
||||
mustResourceInstanceAddr("aws_instance.foo[1]").Resource,
|
||||
@ -192,6 +203,7 @@ func TestOrphanResourceCountTransformer_deposed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
root.SetResourceInstanceDeposed(
|
||||
mustResourceInstanceAddr("aws_instance.foo[2]").Resource,
|
||||
@ -201,6 +213,7 @@ func TestOrphanResourceCountTransformer_deposed(t *testing.T) {
|
||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
g := Graph{Path: addrs.RootModuleInstance}
|
||||
@ -246,6 +259,7 @@ func TestOrphanResourceCountTransformer_ForEachEdgesAdded(t *testing.T) {
|
||||
Status: states.ObjectReady,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// NoKey'd resource
|
||||
@ -262,6 +276,7 @@ func TestOrphanResourceCountTransformer_ForEachEdgesAdded(t *testing.T) {
|
||||
Status: states.ObjectReady,
|
||||
},
|
||||
mustProviderConfig(`provider["registry.opentofu.org/hashicorp/aws"]`),
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -35,6 +35,7 @@ func TestOrphanResourceInstanceTransformer(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// The orphan
|
||||
@ -54,6 +55,7 @@ func TestOrphanResourceInstanceTransformer(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
|
||||
// A deposed orphan should not be handled by this transformer
|
||||
@ -74,6 +76,7 @@ func TestOrphanResourceInstanceTransformer(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("test"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -123,6 +126,7 @@ func TestOrphanResourceInstanceTransformer_countGood(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -140,6 +144,7 @@ func TestOrphanResourceInstanceTransformer_countGood(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -188,6 +193,7 @@ func TestOrphanResourceInstanceTransformer_countBad(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -205,6 +211,7 @@ func TestOrphanResourceInstanceTransformer_countBad(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
@ -253,6 +260,7 @@ func TestOrphanResourceInstanceTransformer_modules(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
addrs.Resource{
|
||||
@ -270,6 +278,7 @@ func TestOrphanResourceInstanceTransformer_modules(t *testing.T) {
|
||||
Provider: addrs.NewDefaultProvider("aws"),
|
||||
Module: addrs.RootModule,
|
||||
},
|
||||
addrs.NoKey,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/dag"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
@ -62,6 +61,22 @@ type GraphNodeCloseProvider interface {
|
||||
CloseProviderAddr() addrs.AbsProviderConfig
|
||||
}
|
||||
|
||||
type RequestedProvider struct {
|
||||
ProviderConfig addrs.ProviderConfig
|
||||
KeyExpression hcl.Expression
|
||||
KeyModule addrs.Module
|
||||
KeyResource bool
|
||||
KeyExact addrs.InstanceKey
|
||||
}
|
||||
|
||||
type ResolvedProvider struct {
|
||||
ProviderConfig addrs.AbsProviderConfig
|
||||
KeyExpression hcl.Expression
|
||||
KeyModule addrs.Module
|
||||
KeyResource bool
|
||||
KeyExact addrs.InstanceKey
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer is an interface that nodes that require
|
||||
// a provider must implement. ProvidedBy must return the address of the provider
|
||||
// to use, which will be resolved to a configuration either in the same module
|
||||
@ -80,13 +95,13 @@ type GraphNodeProviderConsumer interface {
|
||||
// resolved elsewhere and must be referenced directly. No inheritence
|
||||
// logic is allowed.
|
||||
// Examples: state, resource instance (resolved),
|
||||
ProvidedBy() addrs.ProviderConfig
|
||||
ProvidedBy() RequestedProvider
|
||||
|
||||
// Provider() returns the Provider FQN for the node.
|
||||
Provider() (provider addrs.Provider)
|
||||
|
||||
// Set the resolved provider address for this resource.
|
||||
SetProvider(addrs.AbsProviderConfig)
|
||||
SetProvider(ResolvedProvider)
|
||||
}
|
||||
|
||||
// ProviderTransformer is a GraphTransformer that maps resources to providers
|
||||
@ -114,11 +129,11 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
||||
continue
|
||||
}
|
||||
req := pv.ProvidedBy()
|
||||
if req == nil {
|
||||
if req.ProviderConfig == nil {
|
||||
// no provider is required
|
||||
continue
|
||||
}
|
||||
switch providerAddr := req.(type) {
|
||||
switch providerAddr := req.ProviderConfig.(type) {
|
||||
case addrs.AbsProviderConfig:
|
||||
target := m[providerAddr.String()]
|
||||
if target == nil {
|
||||
@ -148,10 +163,18 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
||||
// error instead.
|
||||
if p, ok := target.(*graphNodeProxyProvider); ok {
|
||||
target = p.Target()
|
||||
// We are ignoring p.keyExpr here for now
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] ProviderTransformer: %q (%T) needs exactly %s", dag.VertexName(v), v, dag.VertexName(target))
|
||||
pv.SetProvider(target.ProviderAddr())
|
||||
pv.SetProvider(ResolvedProvider{
|
||||
ProviderConfig: target.ProviderAddr(),
|
||||
// Pass through key data
|
||||
KeyExpression: req.KeyExpression,
|
||||
KeyModule: req.KeyModule,
|
||||
KeyResource: req.KeyResource,
|
||||
KeyExact: req.KeyExact,
|
||||
})
|
||||
g.Connect(dag.BasicEdge(v, target))
|
||||
case addrs.LocalProviderConfig:
|
||||
// We assume that the value returned from Provider() has already been
|
||||
@ -197,13 +220,30 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
||||
continue
|
||||
}
|
||||
|
||||
resolved := ResolvedProvider{
|
||||
KeyResource: req.KeyResource,
|
||||
KeyExpression: req.KeyExpression,
|
||||
}
|
||||
|
||||
// see if this is a proxy provider pointing to another concrete config
|
||||
if p, ok := target.(*graphNodeProxyProvider); ok {
|
||||
target = p.Target()
|
||||
|
||||
targetExpr, targetPath := p.TargetExpr()
|
||||
if targetExpr != nil {
|
||||
if resolved.KeyResource {
|
||||
// Module key and resource key are both required. This is not allowed!
|
||||
diags = diags.Append(fmt.Errorf("provider instance key provided for both resource and module at %q, this is a bug and should be reported", dag.VertexName(v)))
|
||||
continue
|
||||
}
|
||||
resolved.KeyExpression = targetExpr
|
||||
resolved.KeyModule = targetPath
|
||||
}
|
||||
}
|
||||
resolved.ProviderConfig = target.ProviderAddr()
|
||||
|
||||
log.Printf("[DEBUG] ProviderTransformer: %q (%T) needs %s", dag.VertexName(v), v, dag.VertexName(target))
|
||||
pv.SetProvider(target.ProviderAddr())
|
||||
pv.SetProvider(resolved)
|
||||
g.Connect(dag.BasicEdge(v, target))
|
||||
default:
|
||||
panic(fmt.Sprintf("BUG: Invalid provider address type %T for %#v", req, req))
|
||||
@ -222,20 +262,26 @@ type ProviderFunctionReference struct {
|
||||
ProviderAlias string
|
||||
}
|
||||
|
||||
type FunctionProvidedBy struct {
|
||||
Provider addrs.AbsProviderConfig
|
||||
KeyModule addrs.Module
|
||||
KeyExpression hcl.Expression
|
||||
}
|
||||
|
||||
// ProviderFunctionMapping maps a provider used by functions at a given location in the graph to the actual AbsProviderConfig
|
||||
// that's required. This is due to the provider inheritence logic and proxy logic in the below
|
||||
// transformer needing to be known in other parts of the application.
|
||||
// Ideally, this would not be needed and be built like the ProviderTransformer. Unfortunately, it's
|
||||
// a significant refactor to get to that point which adds a lot of complexity.
|
||||
type ProviderFunctionMapping map[ProviderFunctionReference]addrs.AbsProviderConfig
|
||||
type ProviderFunctionMapping map[ProviderFunctionReference]FunctionProvidedBy
|
||||
|
||||
func (m ProviderFunctionMapping) Lookup(module addrs.Module, pf addrs.ProviderFunction) (addrs.AbsProviderConfig, bool) {
|
||||
addr, ok := m[ProviderFunctionReference{
|
||||
func (m ProviderFunctionMapping) Lookup(module addrs.Module, pf addrs.ProviderFunction) (FunctionProvidedBy, bool) {
|
||||
providedBy, ok := m[ProviderFunctionReference{
|
||||
ModulePath: module.String(),
|
||||
ProviderName: pf.ProviderName,
|
||||
ProviderAlias: pf.ProviderAlias,
|
||||
}]
|
||||
return addr, ok
|
||||
return providedBy, ok
|
||||
}
|
||||
|
||||
// ProviderFunctionTransformer is a GraphTransformer that maps nodes which reference functions to providers
|
||||
@ -318,32 +364,8 @@ func (t *ProviderFunctionTransformer) Transform(g *Graph) error {
|
||||
// Providers with configuration will already exist within the graph and can be directly referenced
|
||||
log.Printf("[TRACE] ProviderFunctionTransformer: exact match for %s serving %s", absPc, dag.VertexName(v))
|
||||
} else {
|
||||
// At this point, all provider schemas should be loaded. We
|
||||
// can now check to see if configuration is optional for this function.
|
||||
providerSchema, ok := providers.SchemaCache.Get(absPc.Provider)
|
||||
if !ok {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Unknown provider for function",
|
||||
Detail: fmt.Sprintf("Provider %q does not have it's schema initialized", absPc.Provider),
|
||||
Subject: ref.SourceRange.ToHCL().Ptr(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
_, functionOk := providerSchema.Functions[pf.Function]
|
||||
if !functionOk {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Unknown provider function",
|
||||
Detail: fmt.Sprintf("Provider %q does not have a function %q or has not been configured", absPc, pf.Function),
|
||||
Subject: ref.SourceRange.ToHCL().Ptr(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
// If this provider doesn't need to be configured then we can just
|
||||
// stub it out with an init-only provider node, which will just
|
||||
// start up the provider and fetch its schema.
|
||||
// If this provider doesn't exist, stub it out with an init-only provider node
|
||||
// This works for unconfigured functions only, but that validation is elsewhere
|
||||
stubAddr := addrs.AbsProviderConfig{
|
||||
Module: addrs.RootModule,
|
||||
Provider: absPc.Provider,
|
||||
@ -364,9 +386,13 @@ func (t *ProviderFunctionTransformer) Transform(g *Graph) error {
|
||||
}
|
||||
}
|
||||
|
||||
var targetExpr hcl.Expression
|
||||
var targetPath addrs.Module
|
||||
|
||||
// see if this is a proxy provider pointing to another concrete config
|
||||
if p, ok := provider.(*graphNodeProxyProvider); ok {
|
||||
provider = p.Target()
|
||||
targetExpr, targetPath = p.TargetExpr()
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] ProviderFunctionTransformer: %q (%T) needs %s", dag.VertexName(v), v, dag.VertexName(provider))
|
||||
@ -374,7 +400,11 @@ func (t *ProviderFunctionTransformer) Transform(g *Graph) error {
|
||||
|
||||
// Save for future lookups
|
||||
providerReferences[key] = provider
|
||||
t.ProviderFunctionTracker[key] = provider.ProviderAddr()
|
||||
t.ProviderFunctionTracker[key] = FunctionProvidedBy{
|
||||
Provider: provider.ProviderAddr(),
|
||||
KeyModule: targetPath,
|
||||
KeyExpression: targetExpr,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -585,8 +615,9 @@ func (n *graphNodeCloseProvider) DotNode(name string, opts *dag.DotOpts) *dag.Do
|
||||
// configurations, and are removed after all the resources have been connected
|
||||
// to their providers.
|
||||
type graphNodeProxyProvider struct {
|
||||
addr addrs.AbsProviderConfig
|
||||
target GraphNodeProvider
|
||||
addr addrs.AbsProviderConfig
|
||||
target GraphNodeProvider
|
||||
keyExpr hcl.Expression
|
||||
}
|
||||
|
||||
var (
|
||||
@ -616,6 +647,25 @@ func (n *graphNodeProxyProvider) Target() GraphNodeProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// Find the *single* keyExpression that is used in the provider
|
||||
// chain. This is not ideal, but it works with current constraints on this feature
|
||||
func (n *graphNodeProxyProvider) TargetExpr() (hcl.Expression, addrs.Module) {
|
||||
switch t := n.target.(type) {
|
||||
case *graphNodeProxyProvider:
|
||||
targetExpr, targetPath := t.TargetExpr()
|
||||
if targetExpr != nil && n.keyExpr != nil {
|
||||
// This should have already been handled during provider validation
|
||||
panic(fmt.Sprintf("BUG: Only one key expression allowed in module provider chain: %q", n.Name()))
|
||||
}
|
||||
if n.keyExpr != nil {
|
||||
return n.keyExpr, n.ModulePath()
|
||||
}
|
||||
return targetExpr, targetPath
|
||||
default:
|
||||
return n.keyExpr, n.ModulePath()
|
||||
}
|
||||
}
|
||||
|
||||
// ProviderConfigTransformer adds all provider nodes from the configuration and
|
||||
// attaches the configs.
|
||||
type ProviderConfigTransformer struct {
|
||||
@ -816,8 +866,9 @@ func (t *ProviderConfigTransformer) addProxyProviders(g *Graph, c *configs.Confi
|
||||
}
|
||||
|
||||
proxy := &graphNodeProxyProvider{
|
||||
addr: fullAddr,
|
||||
target: parentProvider,
|
||||
addr: fullAddr,
|
||||
target: parentProvider,
|
||||
keyExpr: pair.InParent.KeyExpression,
|
||||
}
|
||||
|
||||
concreteProvider := t.providers[fullName]
|
||||
|
@ -57,6 +57,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.terraform.io/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -65,6 +66,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.terraform.io/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
@ -76,6 +78,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -84,6 +87,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
@ -99,6 +103,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.terraform.io/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -107,6 +112,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.terraform.io/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
@ -118,6 +124,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -126,6 +133,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.terraform.io/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
@ -141,6 +149,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -149,6 +158,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
@ -160,6 +170,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -168,6 +179,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
@ -183,6 +195,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.terraform.io/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -191,6 +204,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.terraform.io/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
@ -202,6 +216,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/random"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
s.SetResourceInstanceCurrent(
|
||||
mustParseInstAddr("aws_instance.example"),
|
||||
@ -210,6 +225,7 @@ func TestMigrateStateProviderAddresses(t *testing.T) {
|
||||
AttrsJSON: []byte(`{}`),
|
||||
},
|
||||
makeRootProviderAddr("registry.opentofu.org/hashicorp/aws"),
|
||||
addrs.NoKey,
|
||||
)
|
||||
}),
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user