Merge pull request #16586 from hashicorp/jbardin/providers
Store resolved providers in state
This commit is contained in:
commit
00b7715710
|
@ -53,6 +53,7 @@ func TestLocal_applyBasic(t *testing.T) {
|
|||
checkState(t, b.StateOutPath, `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -160,6 +161,7 @@ func TestLocal_applyError(t *testing.T) {
|
|||
checkState(t, b.StateOutPath, `
|
||||
test_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -211,6 +213,7 @@ func TestLocal_applyBackendFail(t *testing.T) {
|
|||
checkState(t, "errored.tfstate", `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
|
|
@ -199,48 +199,6 @@ func TestLocal_planDestroy(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestLocal_planDestroyNoConfig(t *testing.T) {
|
||||
b := TestLocal(t)
|
||||
p := TestLocalProvider(t, b, "test")
|
||||
terraform.TestStateFile(t, b.StatePath, testPlanState())
|
||||
|
||||
outDir := testTempDir(t)
|
||||
defer os.RemoveAll(outDir)
|
||||
planPath := filepath.Join(outDir, "plan.tfplan")
|
||||
|
||||
op := testOperationPlan()
|
||||
op.Destroy = true
|
||||
op.PlanRefresh = true
|
||||
op.Module = nil
|
||||
op.PlanOutPath = planPath
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
<-run.Done()
|
||||
if run.Err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if !p.RefreshCalled {
|
||||
t.Fatal("refresh should be called")
|
||||
}
|
||||
|
||||
if run.PlanEmpty {
|
||||
t.Fatal("plan should not be empty")
|
||||
}
|
||||
|
||||
plan := testReadPlan(t, planPath)
|
||||
for _, m := range plan.Diff.Modules {
|
||||
for _, r := range m.Resources {
|
||||
if !r.Destroy {
|
||||
t.Fatalf("bad: %#v", r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLocal_planOutPathNoChange(t *testing.T) {
|
||||
b := TestLocal(t)
|
||||
TestLocalProvider(t, b, "test")
|
||||
|
|
|
@ -37,6 +37,7 @@ func TestLocal_refresh(t *testing.T) {
|
|||
checkState(t, b.StateOutPath, `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -64,6 +65,7 @@ func TestLocal_refreshNilModule(t *testing.T) {
|
|||
checkState(t, b.StateOutPath, `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -94,6 +96,7 @@ func TestLocal_refreshNilModuleWithInput(t *testing.T) {
|
|||
checkState(t, b.StateOutPath, `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -137,6 +140,7 @@ func TestLocal_refreshInput(t *testing.T) {
|
|||
checkState(t, b.StateOutPath, `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -170,6 +174,7 @@ func TestLocal_refreshValidate(t *testing.T) {
|
|||
checkState(t, b.StateOutPath, `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ func TestLocal_backend(t *testing.T) {
|
|||
}
|
||||
|
||||
func checkState(t *testing.T, path, expected string) {
|
||||
t.Helper()
|
||||
// Read the state
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
|
@ -663,11 +663,11 @@ func TestImport_pluginDir(t *testing.T) {
|
|||
const testImportStr = `
|
||||
test_instance.foo:
|
||||
ID = yay
|
||||
provider = test
|
||||
provider = provider.test
|
||||
`
|
||||
|
||||
const testImportCustomProviderStr = `
|
||||
test_instance.foo:
|
||||
ID = yay
|
||||
provider = test.alias
|
||||
provider = provider.test.alias
|
||||
`
|
||||
|
|
|
@ -802,8 +802,10 @@ foo = "bar"
|
|||
const testRefreshStr = `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`
|
||||
const testRefreshCwdStr = `
|
||||
test_instance.foo:
|
||||
ID = yes
|
||||
provider = provider.test
|
||||
`
|
||||
|
|
|
@ -69,15 +69,6 @@ type ProviderConfig struct {
|
|||
Alias string
|
||||
Version string
|
||||
RawConfig *RawConfig
|
||||
|
||||
// Path records where the Provider was declared in a module tree, so that
|
||||
// it can be copied into child module providers yet still interpolated in
|
||||
// the correct scope.
|
||||
Path []string
|
||||
|
||||
// Inherited is used to skip validation of this config, since any
|
||||
// interpolated variables won't be declared at this level.
|
||||
Inherited bool
|
||||
}
|
||||
|
||||
// A resource represents a single Terraform resource in the configuration.
|
||||
|
@ -270,7 +261,9 @@ func (r *Resource) ProviderFullName() string {
|
|||
// the provider name is inferred from the resource type name.
|
||||
func ResourceProviderFullName(resourceType, explicitProvider string) string {
|
||||
if explicitProvider != "" {
|
||||
return explicitProvider
|
||||
// check for an explicit provider name, or return the original
|
||||
parts := strings.SplitAfter(explicitProvider, "provider.")
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
idx := strings.IndexRune(resourceType, '_')
|
||||
|
@ -817,10 +810,6 @@ func (c *Config) rawConfigs() map[string]*RawConfig {
|
|||
}
|
||||
|
||||
for _, pc := range c.ProviderConfigs {
|
||||
// this was an inherited config, so we don't validate it at this level.
|
||||
if pc.Inherited {
|
||||
continue
|
||||
}
|
||||
source := fmt.Sprintf("provider config '%s'", pc.Name)
|
||||
result[source] = pc.RawConfig
|
||||
}
|
||||
|
|
|
@ -851,7 +851,6 @@ func TestLoadFile_ignoreChanges(t *testing.T) {
|
|||
}
|
||||
|
||||
actual := resourcesStr(c.Resources)
|
||||
print(actual)
|
||||
if actual != strings.TrimSpace(ignoreChangesResourcesStr) {
|
||||
t.Fatalf("bad:\n%s", actual)
|
||||
}
|
||||
|
@ -943,7 +942,6 @@ func TestLoad_hclAttributes(t *testing.T) {
|
|||
}
|
||||
|
||||
actual := resourcesStr(c.Resources)
|
||||
print(actual)
|
||||
if actual != strings.TrimSpace(jsonAttributeStr) {
|
||||
t.Fatalf("bad:\n%s", actual)
|
||||
}
|
||||
|
@ -988,7 +986,6 @@ func TestLoad_jsonAttributes(t *testing.T) {
|
|||
}
|
||||
|
||||
actual := resourcesStr(c.Resources)
|
||||
print(actual)
|
||||
if actual != strings.TrimSpace(jsonAttributeStr) {
|
||||
t.Fatalf("bad:\n%s", actual)
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
provider "top" {}
|
||||
|
||||
provider "bottom" {
|
||||
alias = "foo"
|
||||
value = "from bottom"
|
||||
}
|
||||
|
||||
module "c" {
|
||||
source = "../c"
|
||||
providers = {
|
||||
"bottom" = "bottom.foo"
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
# Hello
|
||||
provider "bottom" {}
|
|
@ -1,11 +0,0 @@
|
|||
provider "top" {
|
||||
alias = "foo"
|
||||
value = "from top"
|
||||
}
|
||||
|
||||
module "a" {
|
||||
source = "./a"
|
||||
providers = {
|
||||
"top" = "top.foo"
|
||||
}
|
||||
}
|
|
@ -188,11 +188,6 @@ func (t *Tree) Load(s *Storage) error {
|
|||
// Set our tree up
|
||||
t.children = children
|
||||
|
||||
// if we're the root module, we can now set the provider inheritance
|
||||
if len(t.path) == 0 {
|
||||
t.inheritProviderConfigs(nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -348,93 +343,6 @@ func (t *Tree) getChildren(s *Storage) (map[string]*Tree, error) {
|
|||
return children, nil
|
||||
}
|
||||
|
||||
// inheritProviderConfig resolves all provider config inheritance after the
|
||||
// tree is loaded.
|
||||
//
|
||||
// If there is a provider block without a config, look in the parent's Module
|
||||
// block for a provider, and fetch that provider's configuration. If that
|
||||
// doesn't exist, assume a default empty config. Implicit providers can still
|
||||
// inherit their config all the way up from the root, so walk up the tree and
|
||||
// copy the first matching provider into the module.
|
||||
func (t *Tree) inheritProviderConfigs(stack []*Tree) {
|
||||
// the recursive calls only append, so we don't need to worry about copying
|
||||
// this slice.
|
||||
stack = append(stack, t)
|
||||
for _, c := range t.children {
|
||||
c.inheritProviderConfigs(stack)
|
||||
}
|
||||
|
||||
if len(stack) == 1 {
|
||||
return
|
||||
}
|
||||
|
||||
providers := make(map[string]*config.ProviderConfig)
|
||||
missingProviders := make(map[string]bool)
|
||||
|
||||
for _, p := range t.config.ProviderConfigs {
|
||||
providers[p.FullName()] = p
|
||||
}
|
||||
|
||||
for _, r := range t.config.Resources {
|
||||
p := r.ProviderFullName()
|
||||
if _, ok := providers[p]; !(ok || strings.Contains(p, ".")) {
|
||||
missingProviders[p] = true
|
||||
}
|
||||
}
|
||||
|
||||
// get our parent's module config block
|
||||
parent := stack[len(stack)-2]
|
||||
var parentModule *config.Module
|
||||
for _, m := range parent.config.Modules {
|
||||
if m.Name == t.name {
|
||||
parentModule = m
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if parentModule == nil {
|
||||
panic("can't be a module without a parent module config")
|
||||
}
|
||||
|
||||
// now look for providers that need a config
|
||||
for p, pc := range providers {
|
||||
if len(pc.RawConfig.RawMap()) > 0 {
|
||||
log.Printf("[TRACE] provider %q has a config, continuing", p)
|
||||
continue
|
||||
}
|
||||
|
||||
// this provider has no config yet, check for one being passed in
|
||||
parentProviderName, ok := parentModule.Providers[p]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var parentProvider *config.ProviderConfig
|
||||
// there's a config for us in the parent module
|
||||
for _, pp := range parent.config.ProviderConfigs {
|
||||
if pp.FullName() == parentProviderName {
|
||||
parentProvider = pp
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if parentProvider == nil {
|
||||
// no config found, assume defaults
|
||||
continue
|
||||
}
|
||||
|
||||
// Copy it in, but set an interpolation Scope.
|
||||
// An interpolation Scope always need to have "root"
|
||||
pc.Path = append([]string{RootName}, parent.path...)
|
||||
pc.RawConfig = parentProvider.RawConfig
|
||||
log.Printf("[TRACE] provider %q inheriting config from %q",
|
||||
strings.Join(append(t.Path(), pc.FullName()), "."),
|
||||
strings.Join(append(parent.Path(), parentProvider.FullName()), "."),
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Path is the full path to this tree.
|
||||
func (t *Tree) Path() []string {
|
||||
return t.path
|
||||
|
|
|
@ -3,7 +3,6 @@ package module
|
|||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
@ -548,69 +547,6 @@ func TestTreeValidate_unknownModule(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTreeProviders_basic(t *testing.T) {
|
||||
storage := testStorage(t, nil)
|
||||
tree := NewTree("", testConfig(t, "basic-parent-providers"))
|
||||
|
||||
storage.Mode = GetModeGet
|
||||
if err := tree.Load(storage); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
var a, b *Tree
|
||||
for _, child := range tree.Children() {
|
||||
if child.Name() == "a" {
|
||||
a = child
|
||||
}
|
||||
}
|
||||
|
||||
rootProviders := tree.config.ProviderConfigsByFullName()
|
||||
topRaw := rootProviders["top.foo"]
|
||||
|
||||
if a == nil {
|
||||
t.Fatal("could not find module 'a'")
|
||||
}
|
||||
|
||||
for _, child := range a.Children() {
|
||||
if child.Name() == "c" {
|
||||
b = child
|
||||
}
|
||||
}
|
||||
|
||||
if b == nil {
|
||||
t.Fatal("could not find module 'c'")
|
||||
}
|
||||
|
||||
aProviders := a.config.ProviderConfigsByFullName()
|
||||
bottomRaw := aProviders["bottom.foo"]
|
||||
bProviders := b.config.ProviderConfigsByFullName()
|
||||
bBottom := bProviders["bottom"]
|
||||
|
||||
// compare the configs
|
||||
// top.foo should have been copied to a.top
|
||||
aTop := aProviders["top"]
|
||||
if !reflect.DeepEqual(aTop.RawConfig.RawMap(), topRaw.RawConfig.RawMap()) {
|
||||
log.Fatalf("expected config %#v, got %#v",
|
||||
topRaw.RawConfig.RawMap(),
|
||||
aTop.RawConfig.RawMap(),
|
||||
)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(aTop.Path, []string{RootName}) {
|
||||
log.Fatalf(`expected scope for "top": {"root"}, got %#v`, aTop.Path)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(bBottom.RawConfig.RawMap(), bottomRaw.RawConfig.RawMap()) {
|
||||
t.Fatalf("expected config %#v, got %#v",
|
||||
bottomRaw.RawConfig.RawMap(),
|
||||
bBottom.RawConfig.RawMap(),
|
||||
)
|
||||
}
|
||||
if !reflect.DeepEqual(bBottom.Path, []string{RootName, "a"}) {
|
||||
t.Fatalf(`expected scope for "bottom": {"root", "a"}, got %#v`, bBottom.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTreeLoad_conflictingSubmoduleNames(t *testing.T) {
|
||||
storage := testStorage(t, nil)
|
||||
tree := NewTree("", testConfig(t, "conficting-submodule-names"))
|
||||
|
|
|
@ -129,6 +129,7 @@ func TestContext2Apply_escape(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = "bar"
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -160,6 +161,7 @@ func TestContext2Apply_resourceCountOneList(t *testing.T) {
|
|||
actual := strings.TrimSpace(state.String())
|
||||
expected := strings.TrimSpace(`null_resource.foo:
|
||||
ID = foo
|
||||
provider = provider.null
|
||||
|
||||
Outputs:
|
||||
|
||||
|
@ -578,6 +580,7 @@ amis_from_module = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-1234
|
|||
module.test:
|
||||
null_resource.noop:
|
||||
ID = foo
|
||||
provider = provider.null
|
||||
|
||||
Outputs:
|
||||
|
||||
|
@ -745,6 +748,7 @@ func TestContext2Apply_providerWarning(t *testing.T) {
|
|||
expected := strings.TrimSpace(`
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`)
|
||||
if actual != expected {
|
||||
t.Fatalf("got: \n%s\n\nexpected:\n%s", actual, expected)
|
||||
|
@ -1032,11 +1036,13 @@ func TestContext2Apply_createBeforeDestroy_dependsNonCBD(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
require_new = yes
|
||||
type = aws_instance
|
||||
value = foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
require_new = yes
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -1170,10 +1176,12 @@ func TestContext2Apply_createBeforeDestroy_deposedCount(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.bar.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.bar.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -1233,6 +1241,7 @@ func TestContext2Apply_createBeforeDestroy_deposedOnly(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.bar:
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -2007,6 +2016,7 @@ func TestContext2Apply_cancelBlock(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -2066,6 +2076,7 @@ func TestContext2Apply_cancelProvisioner(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo: (tainted)
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -2448,10 +2459,12 @@ func TestContext2Apply_mapVariableOverride(t *testing.T) {
|
|||
expected := strings.TrimSpace(`
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
ami = overridden
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
ami = image-1234
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -2619,7 +2632,7 @@ func TestContext2Apply_moduleInheritAlias(t *testing.T) {
|
|||
module.child:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws.eu
|
||||
provider = provider.aws.eu
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -3140,6 +3153,7 @@ func TestContext2Apply_moduleTarget(t *testing.T) {
|
|||
module.A:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
|
||||
|
@ -3149,6 +3163,7 @@ module.A:
|
|||
module.B:
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = foo
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -3929,6 +3944,7 @@ func TestContext2Apply_outputDependsOn(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
|
||||
Outputs:
|
||||
|
||||
|
@ -4560,6 +4576,7 @@ func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.web: (1 deposed)
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
Deposed ID 1 = foo
|
||||
`)
|
||||
|
||||
|
@ -4584,6 +4601,7 @@ aws_instance.web: (1 deposed)
|
|||
checkStateString(t, state, `
|
||||
aws_instance.web: (2 deposed)
|
||||
ID = baz
|
||||
provider = provider.aws
|
||||
Deposed ID 1 = foo
|
||||
Deposed ID 2 = bar
|
||||
`)
|
||||
|
@ -4611,6 +4629,7 @@ aws_instance.web: (2 deposed)
|
|||
checkStateString(t, state, `
|
||||
aws_instance.web: (1 deposed)
|
||||
ID = qux
|
||||
provider = provider.aws
|
||||
Deposed ID 1 = bar
|
||||
`)
|
||||
|
||||
|
@ -4632,6 +4651,7 @@ aws_instance.web: (1 deposed)
|
|||
checkStateString(t, state, `
|
||||
aws_instance.web:
|
||||
ID = quux
|
||||
provider = provider.aws
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -4672,6 +4692,7 @@ func TestContext2Apply_provisionerFailContinue(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -5067,6 +5088,7 @@ func TestContext2Apply_provisionerDestroyTainted(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -5935,11 +5957,12 @@ func TestContext2Apply_destroyOrder(t *testing.T) {
|
|||
|
||||
t.Logf("State 1: %s", state)
|
||||
|
||||
// Next, plan and apply config-less to force a destroy with "apply"
|
||||
// Next, plan and apply a destroy
|
||||
h.Active = true
|
||||
ctx = testContext2(t, &ContextOpts{
|
||||
Destroy: true,
|
||||
State: state,
|
||||
Module: module.NewEmptyTree(),
|
||||
Module: m,
|
||||
Hooks: []Hook{h},
|
||||
ProviderResolver: ResourceProviderResolverFixed(
|
||||
map[string]ResourceProviderFactory{
|
||||
|
@ -7370,6 +7393,7 @@ func TestContext2Apply_targeted(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -7402,10 +7426,13 @@ func TestContext2Apply_targetedCount(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.foo.2:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -7436,6 +7463,7 @@ func TestContext2Apply_targetedCountIndex(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`)
|
||||
}
|
||||
|
||||
|
@ -7673,10 +7701,12 @@ func TestContext2Apply_targetedModule(t *testing.T) {
|
|||
module.child:
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -7712,6 +7742,7 @@ func TestContext2Apply_targetedModuleDep(t *testing.T) {
|
|||
checkStateString(t, state, `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = foo
|
||||
type = aws_instance
|
||||
|
||||
|
@ -7721,6 +7752,7 @@ aws_instance.foo:
|
|||
module.child:
|
||||
aws_instance.mod:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
|
||||
Outputs:
|
||||
|
||||
|
@ -7795,6 +7827,7 @@ module.child1:
|
|||
module.child2:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
|
||||
Outputs:
|
||||
|
||||
|
@ -7836,6 +7869,7 @@ func TestContext2Apply_targetedModuleResource(t *testing.T) {
|
|||
module.child:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -8289,6 +8323,7 @@ func TestContext2Apply_issue5254(t *testing.T) {
|
|||
expected := strings.TrimSpace(`
|
||||
template_file.child:
|
||||
ID = foo
|
||||
provider = provider.template
|
||||
template = Hi
|
||||
type = template_file
|
||||
|
||||
|
@ -8296,6 +8331,7 @@ template_file.child:
|
|||
template_file.parent.*
|
||||
template_file.parent:
|
||||
ID = foo
|
||||
provider = provider.template
|
||||
template = Hi
|
||||
type = template_file
|
||||
`)
|
||||
|
@ -8371,6 +8407,7 @@ func TestContext2Apply_targetedWithTaintedInState(t *testing.T) {
|
|||
expected := strings.TrimSpace(`
|
||||
aws_instance.iambeingadded:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.ifailedprovisioners: (tainted)
|
||||
ID = ifailedprovisioners
|
||||
`)
|
||||
|
@ -8416,6 +8453,7 @@ func TestContext2Apply_ignoreChangesCreate(t *testing.T) {
|
|||
expected := strings.TrimSpace(`
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
required_field = set
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -8560,6 +8598,7 @@ func TestContext2Apply_ignoreChangesWildcard(t *testing.T) {
|
|||
expected := strings.TrimSpace(`
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
required_field = set
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -8820,6 +8859,7 @@ func TestContext2Apply_targetedModuleRecursive(t *testing.T) {
|
|||
module.child.subchild:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`)
|
||||
|
@ -8868,7 +8908,6 @@ func TestContext2Apply_destroyWithLocals(t *testing.T) {
|
|||
p.ApplyFn = testApplyFn
|
||||
p.DiffFn = func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
|
||||
d, err := testDiffFn(info, s, c)
|
||||
fmt.Println("DIFF:", d)
|
||||
return d, err
|
||||
}
|
||||
|
||||
|
@ -8977,10 +9016,79 @@ func TestContext2Apply_providerWithLocals(t *testing.T) {
|
|||
t.Fatal("expected no state, got:", state)
|
||||
}
|
||||
|
||||
// Destroy won't work because the local value is removed before the
|
||||
// provider. Once this is fixed this test will start to fail, and we
|
||||
// can remove the invalid interpolation string;
|
||||
if providerRegion != "bar" {
|
||||
t.Fatalf("expected region %q, got: %q", "bar", providerRegion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext2Apply_destroyWithProviders(t *testing.T) {
|
||||
m := testModule(t, "destroy-module-with-provider")
|
||||
p := testProvider("aws")
|
||||
p.ApplyFn = testApplyFn
|
||||
p.DiffFn = testDiffFn
|
||||
|
||||
s := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
},
|
||||
&ModuleState{
|
||||
Path: []string{"root", "child"},
|
||||
},
|
||||
&ModuleState{
|
||||
Path: []string{"root", "mod", "removed"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.child": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "bar",
|
||||
},
|
||||
// this provider doesn't exist
|
||||
Provider: "provider.aws.baz",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Module: m,
|
||||
ProviderResolver: ResourceProviderResolverFixed(
|
||||
map[string]ResourceProviderFactory{
|
||||
"aws": testProviderFuncFixed(p),
|
||||
},
|
||||
),
|
||||
State: s,
|
||||
Destroy: true,
|
||||
})
|
||||
|
||||
// test that we can't destroy if the provider is missing
|
||||
if _, err := ctx.Plan(); err == nil {
|
||||
t.Fatal("expected plan error, provider.aws.baz doesn't exist")
|
||||
}
|
||||
|
||||
// correct the state
|
||||
s.Modules[2].Resources["aws_instance.child"].Provider = "provider.aws.bar"
|
||||
|
||||
if _, err := ctx.Plan(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
state, err := ctx.Apply()
|
||||
if err != nil {
|
||||
t.Fatalf("error during apply: %s", err)
|
||||
}
|
||||
|
||||
got := strings.TrimSpace(state.String())
|
||||
|
||||
// This should fail once modules are removed from the state entirely.
|
||||
want := strings.TrimSpace(`
|
||||
<no state>
|
||||
module.child:
|
||||
<no state>
|
||||
module.mod.removed:
|
||||
<no state>`)
|
||||
|
||||
if got != want {
|
||||
t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -801,13 +801,13 @@ func TestContextImport_customProvider(t *testing.T) {
|
|||
const testImportStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportCountIndexStr = `
|
||||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportCollisionStr = `
|
||||
|
@ -820,7 +820,7 @@ const testImportModuleStr = `
|
|||
module.foo:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportModuleDepth2Str = `
|
||||
|
@ -828,7 +828,7 @@ const testImportModuleDepth2Str = `
|
|||
module.a.b:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportModuleDiffStr = `
|
||||
|
@ -838,7 +838,7 @@ module.bar:
|
|||
module.foo:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportModuleExistingStr = `
|
||||
|
@ -847,39 +847,39 @@ module.foo:
|
|||
ID = bar
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportMultiStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
aws_instance_thing.foo:
|
||||
ID = bar
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportMultiSameStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
aws_instance_thing.foo:
|
||||
ID = bar
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
aws_instance_thing.foo-1:
|
||||
ID = qux
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testImportRefreshStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
`
|
||||
|
||||
const testImportCustomProviderStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws.alias
|
||||
provider = provider.aws.alias
|
||||
`
|
||||
|
|
|
@ -564,6 +564,7 @@ func TestContext2Input_varWithDefault(t *testing.T) {
|
|||
expectedStr := strings.TrimSpace(`
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = 123
|
||||
type = aws_instance
|
||||
`)
|
||||
|
|
|
@ -3527,28 +3527,34 @@ STATE:
|
|||
|
||||
aws_instance.bar.0:
|
||||
ID = bar0
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo.*
|
||||
aws_instance.bar.1:
|
||||
ID = bar1
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo.*
|
||||
aws_instance.baz.0:
|
||||
ID = baz0
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
aws_instance.bar.*
|
||||
aws_instance.baz.1:
|
||||
ID = baz1
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
aws_instance.bar.*
|
||||
aws_instance.foo.0:
|
||||
ID = foo0
|
||||
provider = provider.aws
|
||||
aws_instance.foo.1:
|
||||
ID = foo1
|
||||
provider = provider.aws
|
||||
`)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
|
||||
|
|
|
@ -1110,3 +1110,53 @@ func TestContext2Refresh_noDiffHookOnScaleOut(t *testing.T) {
|
|||
t.Fatal("PostDiff should not have been called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext2Refresh_updateProviderInState(t *testing.T) {
|
||||
m := testModule(t, "update-resource-provider")
|
||||
p := testProvider("aws")
|
||||
|
||||
p.DiffFn = testDiffFn
|
||||
p.ApplyFn = testApplyFn
|
||||
|
||||
s := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.bar": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
Provider: "provider.aws.baz",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Module: m,
|
||||
ProviderResolver: ResourceProviderResolverFixed(
|
||||
map[string]ResourceProviderFactory{
|
||||
"aws": testProviderFuncFixed(p),
|
||||
},
|
||||
),
|
||||
State: s,
|
||||
})
|
||||
|
||||
expected := strings.TrimSpace(`
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws.foo`)
|
||||
|
||||
state, err := ctx.Refresh()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
actual := state.String()
|
||||
if actual != expected {
|
||||
t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ func TestNewContextState(t *testing.T) {
|
|||
}
|
||||
|
||||
func testContext2(t *testing.T, opts *ContextOpts) *Context {
|
||||
t.Helper()
|
||||
// Enable the shadow graph
|
||||
opts.Shadow = true
|
||||
|
||||
|
@ -360,6 +361,7 @@ func testProvisioner() *MockResourceProvisioner {
|
|||
}
|
||||
|
||||
func checkStateString(t *testing.T, state *State, expected string) {
|
||||
t.Helper()
|
||||
actual := strings.TrimSpace(state.String())
|
||||
expected = strings.TrimSpace(expected)
|
||||
|
||||
|
@ -380,6 +382,7 @@ func resourceState(resourceType, resourceID string) *ResourceState {
|
|||
// Test helper that gives a function 3 seconds to finish, assumes deadlock and
|
||||
// fails test if it does not.
|
||||
func testCheckDeadlock(t *testing.T, f func()) {
|
||||
t.Helper()
|
||||
timeout := make(chan bool, 1)
|
||||
done := make(chan bool, 1)
|
||||
go func() {
|
||||
|
@ -413,15 +416,18 @@ root
|
|||
const testContextRefreshModuleStr = `
|
||||
aws_instance.web: (tainted)
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
|
||||
module.child:
|
||||
aws_instance.web:
|
||||
ID = new
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testContextRefreshOutputStr = `
|
||||
aws_instance.web:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
|
||||
Outputs:
|
||||
|
@ -436,4 +442,5 @@ const testContextRefreshOutputPartialStr = `
|
|||
const testContextRefreshTaintedStr = `
|
||||
aws_instance.web: (tainted)
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
|
|
@ -262,13 +262,8 @@ func (ctx *BuiltinEvalContext) InterpolateProvider(
|
|||
var cfg *config.RawConfig
|
||||
|
||||
if pc != nil && pc.RawConfig != nil {
|
||||
path := pc.Path
|
||||
if len(path) == 0 {
|
||||
path = ctx.Path()
|
||||
}
|
||||
|
||||
scope := &InterpolationScope{
|
||||
Path: path,
|
||||
Path: ctx.Path(),
|
||||
Resource: r,
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ func (w *ContextGraphWalker) EnterPath(path []string) EvalContext {
|
|||
InputValue: w.Context.uiInput,
|
||||
Components: w.Context.components,
|
||||
ProviderCache: w.providerCache,
|
||||
//ProviderConfigCache: w.providerConfigCache,
|
||||
ProviderInputConfig: w.Context.providerInputConfig,
|
||||
ProviderLock: &w.providerLock,
|
||||
ProvisionerCache: w.provisionerCache,
|
||||
|
@ -150,7 +149,6 @@ func (w *ContextGraphWalker) ExitEvalTree(
|
|||
func (w *ContextGraphWalker) init() {
|
||||
w.contexts = make(map[string]*BuiltinEvalContext, 5)
|
||||
w.providerCache = make(map[string]ResourceProvider, 5)
|
||||
//w.providerConfigCache = make(map[string]*ResourceConfig, 5)
|
||||
w.provisionerCache = make(map[string]ResourceProvisioner, 5)
|
||||
w.interpolaterVars = make(map[string]map[string]interface{}, 5)
|
||||
}
|
||||
|
|
|
@ -108,7 +108,9 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
|
|||
// Get the state if we have it, if not we build it
|
||||
rs := n.ResourceState
|
||||
if rs == nil {
|
||||
rs = &ResourceState{}
|
||||
rs = &ResourceState{
|
||||
Provider: n.ResolvedProvider,
|
||||
}
|
||||
}
|
||||
|
||||
// If the config isn't empty we update the state
|
||||
|
@ -146,7 +148,7 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: rs.Type,
|
||||
Provider: rs.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: rs.Dependencies,
|
||||
State: &state, // state is nil here
|
||||
},
|
||||
|
@ -208,7 +210,7 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: rs.Type,
|
||||
Provider: rs.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: rs.Dependencies,
|
||||
State: &state,
|
||||
},
|
||||
|
|
|
@ -2,6 +2,7 @@ package terraform
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
|
@ -25,8 +26,13 @@ type NodeAbstractProvider struct {
|
|||
}
|
||||
|
||||
func ResolveProviderName(name string, path []string) string {
|
||||
if strings.Contains(name, "provider.") {
|
||||
// already resolved
|
||||
return name
|
||||
}
|
||||
|
||||
name = fmt.Sprintf("provider.%s", name)
|
||||
if len(path) > 1 {
|
||||
if len(path) >= 1 {
|
||||
name = fmt.Sprintf("%s.%s", modulePrefixStr(path), name)
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ func (n *NodeApplyableResource) evalTreeDataResource(
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: n.Config.Type,
|
||||
Provider: n.Config.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: stateDeps,
|
||||
State: &state,
|
||||
},
|
||||
|
@ -308,7 +308,7 @@ func (n *NodeApplyableResource) evalTreeManagedResource(
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: n.Config.Type,
|
||||
Provider: n.Config.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: stateDeps,
|
||||
State: &state,
|
||||
},
|
||||
|
@ -332,7 +332,7 @@ func (n *NodeApplyableResource) evalTreeManagedResource(
|
|||
Else: &EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: n.Config.Type,
|
||||
Provider: n.Config.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: stateDeps,
|
||||
State: &state,
|
||||
},
|
||||
|
|
|
@ -149,7 +149,9 @@ func (n *NodeDestroyResource) EvalTree() EvalNode {
|
|||
// Get our state
|
||||
rs := n.ResourceState
|
||||
if rs == nil {
|
||||
rs = &ResourceState{}
|
||||
rs = &ResourceState{
|
||||
Provider: n.ResolvedProvider,
|
||||
}
|
||||
}
|
||||
|
||||
var diffApply *InstanceDiff
|
||||
|
@ -273,7 +275,7 @@ func (n *NodeDestroyResource) EvalTree() EvalNode {
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: n.Addr.Type,
|
||||
Provider: rs.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: rs.Dependencies,
|
||||
State: &state,
|
||||
},
|
||||
|
|
|
@ -112,7 +112,7 @@ func (n *NodePlannableResourceInstance) evalTreeDataResource(
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: n.Config.Type,
|
||||
Provider: n.Config.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: stateDeps,
|
||||
State: &state,
|
||||
},
|
||||
|
@ -177,7 +177,7 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: n.Config.Type,
|
||||
Provider: n.Config.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: stateDeps,
|
||||
State: &state,
|
||||
},
|
||||
|
|
|
@ -166,7 +166,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
|
|||
&EvalWriteState{
|
||||
Name: stateId,
|
||||
ResourceType: n.ResourceState.Type,
|
||||
Provider: n.ResourceState.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: n.ResourceState.Dependencies,
|
||||
State: &state,
|
||||
},
|
||||
|
@ -251,7 +251,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState(
|
|||
&EvalWriteState{
|
||||
Name: stateID,
|
||||
ResourceType: n.Config.Type,
|
||||
Provider: n.Config.Provider,
|
||||
Provider: n.ResolvedProvider,
|
||||
Dependencies: stateDeps,
|
||||
State: &state,
|
||||
},
|
||||
|
|
|
@ -220,11 +220,13 @@ func (h *HookRecordApplyOrder) PreApply(
|
|||
const testTerraformInputProviderStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = override
|
||||
foo = us-east-1
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = baz
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
@ -233,6 +235,7 @@ aws_instance.foo:
|
|||
const testTerraformInputProviderOnlyStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = us-west-2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -240,6 +243,7 @@ aws_instance.foo:
|
|||
const testTerraformInputVarOnlyStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = us-east-1
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -247,6 +251,7 @@ aws_instance.foo:
|
|||
const testTerraformInputVarOnlyUnsetStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = baz
|
||||
foo = foovalue
|
||||
type = aws_instance
|
||||
|
@ -255,11 +260,13 @@ aws_instance.foo:
|
|||
const testTerraformInputVarsStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = override
|
||||
foo = us-east-1
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = baz
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
@ -268,10 +275,12 @@ aws_instance.foo:
|
|||
const testTerraformApplyStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -279,11 +288,13 @@ aws_instance.foo:
|
|||
const testTerraformApplyDataBasicStr = `
|
||||
data.null_data_source.testing:
|
||||
ID = yo
|
||||
provider = provider.null
|
||||
`
|
||||
|
||||
const testTerraformApplyRefCountStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = 3
|
||||
type = aws_instance
|
||||
|
||||
|
@ -291,20 +302,24 @@ aws_instance.bar:
|
|||
aws_instance.foo
|
||||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.foo.2:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyProviderAliasStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = aws.bar
|
||||
provider = provider.aws.bar
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -312,9 +327,10 @@ aws_instance.foo:
|
|||
const testTerraformApplyProviderAliasConfigStr = `
|
||||
another_instance.bar:
|
||||
ID = foo
|
||||
provider = another.two
|
||||
provider = provider.another.two
|
||||
another_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.another
|
||||
`
|
||||
|
||||
const testTerraformApplyEmptyModuleStr = `
|
||||
|
@ -335,6 +351,7 @@ aws_secret_key = ZZZZ
|
|||
const testTerraformApplyDependsCreateBeforeStr = `
|
||||
aws_instance.lb:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
instance = foo
|
||||
type = aws_instance
|
||||
|
||||
|
@ -342,6 +359,7 @@ aws_instance.lb:
|
|||
aws_instance.web
|
||||
aws_instance.web:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
require_new = ami-new
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -349,6 +367,7 @@ aws_instance.web:
|
|||
const testTerraformApplyCreateBeforeStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
require_new = xyz
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -356,6 +375,7 @@ aws_instance.bar:
|
|||
const testTerraformApplyCreateBeforeUpdateStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = baz
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -363,12 +383,14 @@ aws_instance.bar:
|
|||
const testTerraformApplyCancelStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
`
|
||||
|
||||
const testTerraformApplyComputeStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = computed_dynamical
|
||||
type = aws_instance
|
||||
|
||||
|
@ -376,6 +398,7 @@ aws_instance.bar:
|
|||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
dynamical = computed_dynamical
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
@ -429,10 +452,12 @@ const testTerraformApplyCountTaintedStr = `
|
|||
const testTerraformApplyCountVariableStr = `
|
||||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = foo
|
||||
type = aws_instance
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = foo
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -440,6 +465,7 @@ aws_instance.foo.1:
|
|||
const testTerraformApplyCountVariableRefStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = 2
|
||||
type = aws_instance
|
||||
|
||||
|
@ -447,30 +473,37 @@ aws_instance.bar:
|
|||
aws_instance.foo
|
||||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyMinimalStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyModuleStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
||||
module.child:
|
||||
aws_instance.baz:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -478,6 +511,7 @@ module.child:
|
|||
const testTerraformApplyModuleBoolStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = 1
|
||||
type = aws_instance
|
||||
|
||||
|
@ -500,10 +534,12 @@ module.child:
|
|||
const testTerraformApplyMultiProviderStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
do_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.do
|
||||
num = 2
|
||||
type = do_instance
|
||||
`
|
||||
|
@ -513,8 +549,10 @@ const testTerraformApplyModuleOnlyProviderStr = `
|
|||
module.child:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
test_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.test
|
||||
`
|
||||
|
||||
const testTerraformApplyModuleProviderAliasStr = `
|
||||
|
@ -522,7 +560,7 @@ const testTerraformApplyModuleProviderAliasStr = `
|
|||
module.child:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = aws.eu
|
||||
provider = module.child.provider.aws.eu
|
||||
`
|
||||
|
||||
const testTerraformApplyModuleVarRefExistingStr = `
|
||||
|
@ -533,6 +571,7 @@ aws_instance.foo:
|
|||
module.child:
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
type = aws_instance
|
||||
value = bar
|
||||
`
|
||||
|
@ -555,11 +594,13 @@ module.child:
|
|||
const testTerraformApplyProvisionerStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
dynamical = computed_dynamical
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
@ -570,13 +611,16 @@ const testTerraformApplyProvisionerModuleStr = `
|
|||
module.child:
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyProvisionerFailStr = `
|
||||
aws_instance.bar: (tainted)
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -584,6 +628,7 @@ aws_instance.foo:
|
|||
const testTerraformApplyProvisionerFailCreateStr = `
|
||||
aws_instance.bar: (tainted)
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyProvisionerFailCreateNoIdStr = `
|
||||
|
@ -593,6 +638,7 @@ const testTerraformApplyProvisionerFailCreateNoIdStr = `
|
|||
const testTerraformApplyProvisionerFailCreateBeforeDestroyStr = `
|
||||
aws_instance.bar: (1 deposed)
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
require_new = abc
|
||||
Deposed ID 1 = foo (tainted)
|
||||
`
|
||||
|
@ -600,6 +646,7 @@ aws_instance.bar: (1 deposed)
|
|||
const testTerraformApplyProvisionerResourceRefStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -607,6 +654,7 @@ aws_instance.bar:
|
|||
const testTerraformApplyProvisionerSelfRefStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -614,14 +662,17 @@ aws_instance.foo:
|
|||
const testTerraformApplyProvisionerMultiSelfRefStr = `
|
||||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = number 0
|
||||
type = aws_instance
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = number 1
|
||||
type = aws_instance
|
||||
aws_instance.foo.2:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = number 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -629,10 +680,12 @@ aws_instance.foo.2:
|
|||
const testTerraformApplyProvisionerMultiSelfRefSingleStr = `
|
||||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = number 0
|
||||
type = aws_instance
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = number 1
|
||||
type = aws_instance
|
||||
|
||||
|
@ -640,6 +693,7 @@ aws_instance.foo.1:
|
|||
aws_instance.foo.0
|
||||
aws_instance.foo.2:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = number 2
|
||||
type = aws_instance
|
||||
|
||||
|
@ -650,6 +704,7 @@ aws_instance.foo.2:
|
|||
const testTerraformApplyProvisionerDiffStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -666,40 +721,47 @@ module.child.subchild:
|
|||
const testTerraformApplyErrorStr = `
|
||||
aws_instance.bar:
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
`
|
||||
|
||||
const testTerraformApplyErrorCreateBeforeDestroyStr = `
|
||||
aws_instance.bar:
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
require_new = abc
|
||||
`
|
||||
|
||||
const testTerraformApplyErrorDestroyCreateBeforeDestroyStr = `
|
||||
aws_instance.bar: (1 deposed)
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
Deposed ID 1 = bar
|
||||
`
|
||||
|
||||
const testTerraformApplyErrorPartialStr = `
|
||||
aws_instance.bar:
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
`
|
||||
|
||||
const testTerraformApplyResourceDependsOnModuleStr = `
|
||||
aws_instance.a:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
module.child
|
||||
|
@ -707,11 +769,13 @@ aws_instance.a:
|
|||
module.child:
|
||||
aws_instance.child:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyResourceDependsOnModuleDeepStr = `
|
||||
aws_instance.a:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
module.child
|
||||
|
@ -719,6 +783,7 @@ aws_instance.a:
|
|||
module.child.grandchild:
|
||||
aws_instance.c:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyResourceDependsOnModuleInModuleStr = `
|
||||
|
@ -726,17 +791,20 @@ const testTerraformApplyResourceDependsOnModuleInModuleStr = `
|
|||
module.child:
|
||||
aws_instance.b:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
|
||||
Dependencies:
|
||||
module.grandchild
|
||||
module.child.grandchild:
|
||||
aws_instance.c:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
`
|
||||
|
||||
const testTerraformApplyTaintStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -744,6 +812,7 @@ aws_instance.bar:
|
|||
const testTerraformApplyTaintDepStr = `
|
||||
aws_instance.bar:
|
||||
ID = bar
|
||||
provider = provider.aws
|
||||
foo = foo
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
@ -752,6 +821,7 @@ aws_instance.bar:
|
|||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -759,6 +829,7 @@ aws_instance.foo:
|
|||
const testTerraformApplyTaintDepRequireNewStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = foo
|
||||
require_new = yes
|
||||
type = aws_instance
|
||||
|
@ -767,6 +838,7 @@ aws_instance.bar:
|
|||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -774,10 +846,12 @@ aws_instance.foo:
|
|||
const testTerraformApplyOutputStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
||||
|
@ -789,10 +863,12 @@ foo_num = 2
|
|||
const testTerraformApplyOutputAddStr = `
|
||||
aws_instance.test.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = foo0
|
||||
type = aws_instance
|
||||
aws_instance.test.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = foo1
|
||||
type = aws_instance
|
||||
|
||||
|
@ -805,18 +881,22 @@ secondOutput = foo1
|
|||
const testTerraformApplyOutputListStr = `
|
||||
aws_instance.bar.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.bar.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.bar.2:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
||||
|
@ -828,18 +908,22 @@ foo_num = [bar,bar,bar]
|
|||
const testTerraformApplyOutputMultiStr = `
|
||||
aws_instance.bar.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.bar.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.bar.2:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
||||
|
@ -851,18 +935,22 @@ foo_num = bar,bar,bar
|
|||
const testTerraformApplyOutputMultiIndexStr = `
|
||||
aws_instance.bar.0:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.bar.1:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.bar.2:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
|
||||
|
@ -874,6 +962,7 @@ foo_num = bar
|
|||
const testTerraformApplyUnknownAttrStr = `
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
@ -881,12 +970,14 @@ aws_instance.foo:
|
|||
const testTerraformApplyVarsStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = foo
|
||||
baz = override
|
||||
foo = us-west-2
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = baz
|
||||
list = Hello,World
|
||||
map = Baz,Foo,Hello
|
||||
|
@ -897,6 +988,7 @@ aws_instance.foo:
|
|||
const testTerraformApplyVarsEnvStr = `
|
||||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider.aws
|
||||
bar = Hello,World
|
||||
baz = Baz,Foo,Hello
|
||||
foo = baz
|
||||
|
@ -1650,6 +1742,7 @@ STATE:
|
|||
const testTerraformInputHCL = `
|
||||
hcl_instance.hcltest:
|
||||
ID = foo
|
||||
provider = provider.hcl
|
||||
bar.w = z
|
||||
bar.x = y
|
||||
foo.# = 2
|
||||
|
@ -1661,6 +1754,7 @@ hcl_instance.hcltest:
|
|||
const testTerraformRefreshDataRefDataStr = `
|
||||
data.null_data_source.bar:
|
||||
ID = foo
|
||||
provider = provider.null
|
||||
bar = yes
|
||||
type = null_data_source
|
||||
|
||||
|
@ -1668,6 +1762,7 @@ data.null_data_source.bar:
|
|||
data.null_data_source.foo
|
||||
data.null_data_source.foo:
|
||||
ID = foo
|
||||
provider = provider.null
|
||||
foo = yes
|
||||
type = null_data_source
|
||||
`
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// this is the provider that should actually be used by orphaned resources
|
||||
provider "aws" {
|
||||
alias = "bar"
|
||||
}
|
||||
|
||||
module "mod" {
|
||||
source = "./mod"
|
||||
providers = {
|
||||
"aws.foo" = "aws.bar"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
provider "aws" {
|
||||
alias = "foo"
|
||||
}
|
||||
|
||||
// removed module configuration referencing aws.foo, which was passed in by the
|
||||
// root module
|
|
@ -0,0 +1,7 @@
|
|||
provider "aws" {
|
||||
alias = "baz"
|
||||
}
|
||||
|
||||
resource "aws_instance" "baz" {
|
||||
provider = "aws.baz"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
provider "aws" {
|
||||
alias = "bar"
|
||||
}
|
||||
|
||||
module "grandchild" {
|
||||
source = "./grandchild"
|
||||
providers = {
|
||||
"aws.baz" = "aws.bar"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
provider "aws" {
|
||||
alias = "foo"
|
||||
value = "config"
|
||||
}
|
||||
|
||||
module "child" {
|
||||
source = "child"
|
||||
providers = {
|
||||
"aws.bar" = "aws.foo"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
provider "aws" {
|
||||
alias = "bar"
|
||||
}
|
||||
|
||||
resource "aws_instance" "thing" {
|
||||
provider = "aws.bar"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
provider "aws" {
|
||||
alias = "foo"
|
||||
value = "config"
|
||||
}
|
||||
|
||||
module "child" {
|
||||
source = "child"
|
||||
providers = {
|
||||
"aws.bar" = "aws.foo"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
provider "aws" {
|
||||
alias = "foo"
|
||||
}
|
||||
|
||||
resource "aws_instance" "bar" {
|
||||
provider = "aws.foo"
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
)
|
||||
|
||||
// GraphNodeAttachProvider is an interface that must be implemented by nodes
|
||||
|
@ -19,62 +16,3 @@ type GraphNodeAttachProvider interface {
|
|||
// Sets the configuration
|
||||
AttachProvider(*config.ProviderConfig)
|
||||
}
|
||||
|
||||
// AttachProviderConfigTransformer goes through the graph and attaches
|
||||
// provider configuration structures to nodes that implement the interfaces
|
||||
// above.
|
||||
//
|
||||
// The attached configuration structures are directly from the configuration.
|
||||
// If they're going to be modified, a copy should be made.
|
||||
type AttachProviderConfigTransformer struct {
|
||||
Module *module.Tree // Module is the root module for the config
|
||||
}
|
||||
|
||||
func (t *AttachProviderConfigTransformer) Transform(g *Graph) error {
|
||||
if err := t.attachProviders(g); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *AttachProviderConfigTransformer) attachProviders(g *Graph) error {
|
||||
// Go through and find GraphNodeAttachProvider
|
||||
for _, v := range g.Vertices() {
|
||||
// Only care about GraphNodeAttachProvider implementations
|
||||
apn, ok := v.(GraphNodeAttachProvider)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Determine what we're looking for
|
||||
path := normalizeModulePath(apn.Path())
|
||||
path = path[1:]
|
||||
name := apn.ProviderName()
|
||||
log.Printf("[TRACE] Attach provider request: %#v %s", path, name)
|
||||
|
||||
// Get the configuration.
|
||||
tree := t.Module.Child(path)
|
||||
if tree == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Go through the provider configs to find the matching config
|
||||
for _, p := range tree.Config().ProviderConfigs {
|
||||
// Build the name, which is "name.alias" if an alias exists
|
||||
current := p.Name
|
||||
if p.Alias != "" {
|
||||
current += "." + p.Alias
|
||||
}
|
||||
|
||||
// If the configs match then attach!
|
||||
if current == name {
|
||||
log.Printf("[TRACE] Attaching provider config: %#v", p)
|
||||
apn.AttachProvider(p)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -133,78 +133,3 @@ func (t *ConfigTransformer) transformSingle(g *Graph, m *module.Tree) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ProviderConfigTransformer struct {
|
||||
Providers []string
|
||||
Concrete ConcreteProviderNodeFunc
|
||||
|
||||
// Module is the module to add resources from.
|
||||
Module *module.Tree
|
||||
}
|
||||
|
||||
func (t *ProviderConfigTransformer) Transform(g *Graph) error {
|
||||
// If no module is given, we don't do anything
|
||||
if t.Module == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the module isn't loaded, that is simply an error
|
||||
if !t.Module.Loaded() {
|
||||
return errors.New("module must be loaded for ProviderConfigTransformer")
|
||||
}
|
||||
|
||||
// Start the transformation process
|
||||
return t.transform(g, t.Module)
|
||||
}
|
||||
|
||||
func (t *ProviderConfigTransformer) transform(g *Graph, m *module.Tree) error {
|
||||
// If no config, do nothing
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add our resources
|
||||
if err := t.transformSingle(g, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Transform all the children.
|
||||
for _, c := range m.Children() {
|
||||
if err := t.transform(g, c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ProviderConfigTransformer) transformSingle(g *Graph, m *module.Tree) error {
|
||||
log.Printf("[TRACE] ProviderConfigTransformer: Starting for path: %v", m.Path())
|
||||
|
||||
// Get the configuration for this module
|
||||
conf := m.Config()
|
||||
|
||||
// Build the path we're at
|
||||
path := m.Path()
|
||||
if len(path) > 0 {
|
||||
path = append([]string{RootModuleName}, path...)
|
||||
}
|
||||
|
||||
// Write all the resources out
|
||||
for _, p := range conf.ProviderConfigs {
|
||||
name := p.Name
|
||||
if p.Alias != "" {
|
||||
name += "." + p.Alias
|
||||
}
|
||||
|
||||
v := t.Concrete(&NodeAbstractProvider{
|
||||
NameValue: name,
|
||||
PathValue: path,
|
||||
}).(dag.Vertex)
|
||||
|
||||
// Add it to the graph
|
||||
g.Add(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
|
|||
&EvalWriteStateDeposed{
|
||||
Name: n.ResourceName,
|
||||
ResourceType: n.ResourceType,
|
||||
Provider: n.ProviderName,
|
||||
Provider: n.ResolvedProvider,
|
||||
State: &state,
|
||||
Index: n.Index,
|
||||
},
|
||||
|
@ -157,7 +157,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
|
|||
&EvalWriteStateDeposed{
|
||||
Name: n.ResourceName,
|
||||
ResourceType: n.ResourceType,
|
||||
Provider: n.ProviderName,
|
||||
Provider: n.ResolvedProvider,
|
||||
State: &state,
|
||||
Index: n.Index,
|
||||
},
|
||||
|
|
|
@ -240,7 +240,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode {
|
|||
&EvalWriteState{
|
||||
Name: key.String(),
|
||||
ResourceType: info.Type,
|
||||
Provider: resourceProvider(info.Type, n.ProviderName),
|
||||
Provider: n.ResolvedProvider,
|
||||
State: &state,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
@ -18,10 +20,6 @@ func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, m
|
|||
Providers: providers,
|
||||
Concrete: concrete,
|
||||
},
|
||||
// Attach configuration to each provider instance
|
||||
&AttachProviderConfigTransformer{
|
||||
Module: mod,
|
||||
},
|
||||
// Add any remaining missing providers
|
||||
&MissingProviderTransformer{
|
||||
Providers: providers,
|
||||
|
@ -29,8 +27,8 @@ func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, m
|
|||
},
|
||||
// Connect the providers
|
||||
&ProviderTransformer{},
|
||||
// Disable unused providers
|
||||
&DisableProviderTransformer{},
|
||||
// Remove unused providers and proxies
|
||||
&PruneProviderTransformer{},
|
||||
// Connect provider to their parent provider nodes
|
||||
&ParentProviderTransformer{},
|
||||
)
|
||||
|
@ -54,7 +52,8 @@ type GraphNodeCloseProvider interface {
|
|||
|
||||
// GraphNodeProviderConsumer is an interface that nodes that require
|
||||
// a provider must implement. ProvidedBy must return the name of the provider
|
||||
// to use.
|
||||
// to use. This may be a provider by type, type.alias or a fully resolved
|
||||
// provider name
|
||||
type GraphNodeProviderConsumer interface {
|
||||
ProvidedBy() string
|
||||
// Set the resolved provider address for this resource.
|
||||
|
@ -107,6 +106,13 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
|||
break
|
||||
}
|
||||
|
||||
// see if this in an inherited provider
|
||||
if p, ok := target.(*graphNodeProxyProvider); ok {
|
||||
g.Remove(p)
|
||||
target = p.Target()
|
||||
key = target.(GraphNodeProvider).Name()
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] resource %s using provider %s", dag.VertexName(pv), key)
|
||||
pv.SetProvider(key)
|
||||
g.Connect(dag.BasicEdge(v, target))
|
||||
|
@ -122,7 +128,6 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
|||
// in the graph are evaluated.
|
||||
type CloseProviderTransformer struct{}
|
||||
|
||||
// FIXME: this doesn't close providers if the root provider is disabled
|
||||
func (t *CloseProviderTransformer) Transform(g *Graph) error {
|
||||
pm := providerVertexMap(g)
|
||||
cpm := make(map[string]*graphNodeCloseProvider)
|
||||
|
@ -248,22 +253,29 @@ func (t *ParentProviderTransformer) Transform(g *Graph) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PruneProviderTransformer is a GraphTransformer that prunes all the
|
||||
// providers that aren't needed from the graph. A provider is unneeded if
|
||||
// no resource or module is using that provider.
|
||||
// PruneProviderTransformer removes any providers that are not actually used by
|
||||
// anything, and provider proxies. This avoids the provider being initialized
|
||||
// and configured. This both saves resources but also avoids errors since
|
||||
// configuration may imply initialization which may require auth.
|
||||
type PruneProviderTransformer struct{}
|
||||
|
||||
func (t *PruneProviderTransformer) Transform(g *Graph) error {
|
||||
for _, v := range g.Vertices() {
|
||||
// We only care about the providers
|
||||
if pn, ok := v.(GraphNodeProvider); !ok || pn.ProviderName() == "" {
|
||||
// We only care about providers
|
||||
pn, ok := v.(GraphNodeProvider)
|
||||
if !ok || pn.ProviderName() == "" {
|
||||
continue
|
||||
}
|
||||
// Does anything depend on this? If not, then prune it.
|
||||
if s := g.UpEdges(v); s.Len() == 0 {
|
||||
if nv, ok := v.(dag.NamedVertex); ok {
|
||||
log.Printf("[DEBUG] Pruning provider with no dependencies: %s", nv.Name())
|
||||
|
||||
// ProxyProviders will have up edges, but we're now done with them in the graph
|
||||
if _, ok := v.(*graphNodeProxyProvider); ok {
|
||||
log.Printf("[DEBUG] pruning proxy provider %s", dag.VertexName(v))
|
||||
g.Remove(v)
|
||||
}
|
||||
|
||||
// Remove providers with no dependencies.
|
||||
if g.UpEdges(v).Len() == 0 {
|
||||
log.Printf("[DEBUG] pruning unused provider %s", dag.VertexName(v))
|
||||
g.Remove(v)
|
||||
}
|
||||
}
|
||||
|
@ -274,6 +286,11 @@ func (t *PruneProviderTransformer) Transform(g *Graph) error {
|
|||
// providerMapKey is a helper that gives us the key to use for the
|
||||
// maps returned by things such as providerVertexMap.
|
||||
func providerMapKey(k string, v dag.Vertex) string {
|
||||
if strings.Contains(k, "provider.") {
|
||||
// this is already resolved
|
||||
return k
|
||||
}
|
||||
|
||||
// we create a dummy provider to
|
||||
var path []string
|
||||
if sp, ok := v.(GraphNodeSubPath); ok {
|
||||
|
@ -349,21 +366,219 @@ func (n *graphNodeCloseProvider) RemoveIfNotTargeted() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// graphNodeProviderConsumerDummy is a struct that never enters the real
|
||||
// graph (though it could to no ill effect). It implements
|
||||
// GraphNodeProviderConsumer and GraphNodeSubpath as a way to force
|
||||
// certain transformations.
|
||||
type graphNodeProviderConsumerDummy struct {
|
||||
ProviderValue string
|
||||
PathValue []string
|
||||
// graphNodeProxyProvider is a GraphNodeProvider implementation that is used to
|
||||
// store the name and value of a provider node for inheritance between modules.
|
||||
// These nodes are only used to store the data while loading the provider
|
||||
// configurations, and are removed after all the resources have been connected
|
||||
// to their providers.
|
||||
type graphNodeProxyProvider struct {
|
||||
nameValue string
|
||||
path []string
|
||||
target GraphNodeProvider
|
||||
}
|
||||
|
||||
func (n *graphNodeProviderConsumerDummy) Path() []string {
|
||||
return n.PathValue
|
||||
func (n *graphNodeProxyProvider) ProviderName() string {
|
||||
return n.Target().ProviderName()
|
||||
}
|
||||
|
||||
func (n *graphNodeProviderConsumerDummy) ProvidedBy() string {
|
||||
return n.ProviderValue
|
||||
func (n *graphNodeProxyProvider) Name() string {
|
||||
return ResolveProviderName(n.nameValue, n.path)
|
||||
}
|
||||
|
||||
func (n *graphNodeProviderConsumerDummy) SetProvider(string) {}
|
||||
// find the concrete provider instance
|
||||
func (n *graphNodeProxyProvider) Target() GraphNodeProvider {
|
||||
switch t := n.target.(type) {
|
||||
case *graphNodeProxyProvider:
|
||||
return t.Target()
|
||||
default:
|
||||
return n.target
|
||||
}
|
||||
}
|
||||
|
||||
// ProviderConfigTransformer adds all provider nodes from the configuration and
|
||||
// attaches the configs.
|
||||
type ProviderConfigTransformer struct {
|
||||
Providers []string
|
||||
Concrete ConcreteProviderNodeFunc
|
||||
|
||||
// each provider node is stored here so that the proxy nodes can look up
|
||||
// their targets by name.
|
||||
providers map[string]GraphNodeProvider
|
||||
|
||||
// Module is the module to add resources from.
|
||||
Module *module.Tree
|
||||
}
|
||||
|
||||
func (t *ProviderConfigTransformer) Transform(g *Graph) error {
|
||||
// If no module is given, we don't do anything
|
||||
if t.Module == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the module isn't loaded, that is simply an error
|
||||
if !t.Module.Loaded() {
|
||||
return errors.New("module must be loaded for ProviderConfigTransformer")
|
||||
}
|
||||
|
||||
t.providers = make(map[string]GraphNodeProvider)
|
||||
|
||||
// Start the transformation process
|
||||
if err := t.transform(g, t.Module); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// finally attach the configs to the new nodes
|
||||
return t.attachProviderConfigs(g)
|
||||
}
|
||||
|
||||
func (t *ProviderConfigTransformer) transform(g *Graph, m *module.Tree) error {
|
||||
// If no config, do nothing
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add our resources
|
||||
if err := t.transformSingle(g, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Transform all the children.
|
||||
for _, c := range m.Children() {
|
||||
if err := t.transform(g, c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ProviderConfigTransformer) transformSingle(g *Graph, m *module.Tree) error {
|
||||
log.Printf("[TRACE] ProviderConfigTransformer: Starting for path: %v", m.Path())
|
||||
|
||||
// Get the configuration for this module
|
||||
conf := m.Config()
|
||||
|
||||
// Build the path we're at
|
||||
path := m.Path()
|
||||
if len(path) > 0 {
|
||||
path = append([]string{RootModuleName}, path...)
|
||||
}
|
||||
|
||||
// add all provider configs
|
||||
for _, p := range conf.ProviderConfigs {
|
||||
name := p.Name
|
||||
if p.Alias != "" {
|
||||
name += "." + p.Alias
|
||||
}
|
||||
|
||||
// if this is an empty config placeholder to accept a provier from a
|
||||
// parent module, add a proxy and continue.
|
||||
if t.addProxyProvider(g, m, p, name) {
|
||||
continue
|
||||
}
|
||||
|
||||
v := t.Concrete(&NodeAbstractProvider{
|
||||
NameValue: name,
|
||||
PathValue: path,
|
||||
})
|
||||
|
||||
// Add it to the graph
|
||||
g.Add(v)
|
||||
t.providers[ResolveProviderName(name, path)] = v.(GraphNodeProvider)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// add a ProxyProviderConfig if this was inherited from a parent module. Return
|
||||
// whether the proxy was added to the graph or not.
|
||||
func (t *ProviderConfigTransformer) addProxyProvider(g *Graph, m *module.Tree, pc *config.ProviderConfig, name string) bool {
|
||||
path := m.Path()
|
||||
|
||||
// This isn't a proxy if there's a config, or we're at the root
|
||||
if len(pc.RawConfig.RawMap()) > 0 || len(path) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
parentPath := path[:len(path)-1]
|
||||
parent := t.Module.Child(parentPath)
|
||||
if parent == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var parentCfg *config.Module
|
||||
for _, mod := range parent.Config().Modules {
|
||||
if mod.Name == m.Name() {
|
||||
parentCfg = mod
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if parentCfg == nil {
|
||||
panic("immaculately conceived module " + m.Name())
|
||||
}
|
||||
|
||||
parentProviderName, ok := parentCfg.Providers[name]
|
||||
if !ok {
|
||||
// this provider isn't listed in a parent module block, so we just have
|
||||
// an empty config
|
||||
return false
|
||||
}
|
||||
|
||||
// the parent module is passing in a provider
|
||||
fullParentName := ResolveProviderName(parentProviderName, parentPath)
|
||||
parentProvider := t.providers[fullParentName]
|
||||
|
||||
if parentProvider == nil {
|
||||
panic(fmt.Sprintf("missing provider %s in module %s", parentProviderName, m.Name()))
|
||||
}
|
||||
|
||||
v := &graphNodeProxyProvider{
|
||||
nameValue: name,
|
||||
path: path,
|
||||
target: parentProvider,
|
||||
}
|
||||
|
||||
// Add it to the graph
|
||||
g.Add(v)
|
||||
t.providers[ResolveProviderName(name, path)] = v
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *ProviderConfigTransformer) attachProviderConfigs(g *Graph) error {
|
||||
for _, v := range g.Vertices() {
|
||||
// Only care about GraphNodeAttachProvider implementations
|
||||
apn, ok := v.(GraphNodeAttachProvider)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Determine what we're looking for
|
||||
path := normalizeModulePath(apn.Path())[1:]
|
||||
name := apn.ProviderName()
|
||||
log.Printf("[TRACE] Attach provider request: %#v %s", path, name)
|
||||
|
||||
// Get the configuration.
|
||||
tree := t.Module.Child(path)
|
||||
if tree == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Go through the provider configs to find the matching config
|
||||
for _, p := range tree.Config().ProviderConfigs {
|
||||
// Build the name, which is "name.alias" if an alias exists
|
||||
current := p.Name
|
||||
if p.Alias != "" {
|
||||
current += "." + p.Alias
|
||||
}
|
||||
|
||||
// If the configs match then attach!
|
||||
if current == name {
|
||||
log.Printf("[TRACE] Attaching provider config: %#v", p)
|
||||
apn.AttachProvider(p)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// DisableProviderTransformer "disables" any providers that are not actually
|
||||
// used by anything. This avoids the provider being initialized and configured.
|
||||
// This both saves resources but also avoids errors since configuration
|
||||
// may imply initialization which may require auth.
|
||||
type DisableProviderTransformer struct{}
|
||||
|
||||
func (t *DisableProviderTransformer) Transform(g *Graph) error {
|
||||
for _, v := range g.Vertices() {
|
||||
// We only care about providers
|
||||
pn, ok := v.(GraphNodeProvider)
|
||||
if !ok || pn.ProviderName() == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have dependencies, then don't disable
|
||||
if g.UpEdges(v).Len() > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the path
|
||||
var path []string
|
||||
if pn, ok := v.(GraphNodeSubPath); ok {
|
||||
path = pn.Path()
|
||||
}
|
||||
|
||||
// Disable the provider by replacing it with a "disabled" provider
|
||||
disabled := &NodeDisabledProvider{
|
||||
NodeAbstractProvider: &NodeAbstractProvider{
|
||||
NameValue: pn.ProviderName(),
|
||||
PathValue: path,
|
||||
},
|
||||
}
|
||||
|
||||
if !g.Replace(v, disabled) {
|
||||
panic(fmt.Sprintf(
|
||||
"vertex disappeared from under us: %s",
|
||||
dag.VertexName(v)))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -445,6 +445,72 @@ func TestPruneProviderTransformer(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// the child module resource is attached to the configured parent provider
|
||||
func TestProviderConfigTransformer_parentProviders(t *testing.T) {
|
||||
mod := testModule(t, "transform-provider-inherit")
|
||||
concrete := func(a *NodeAbstractProvider) dag.Vertex { return a }
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformer{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
{
|
||||
tf := &AttachResourceConfigTransformer{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
tf := TransformProviders([]string{"aws"}, concrete, mod)
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformModuleProviderConfigStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// the child module resource is attached to the configured grand-parent provider
|
||||
func TestProviderConfigTransformer_grandparentProviders(t *testing.T) {
|
||||
mod := testModule(t, "transform-provider-grandchild-inherit")
|
||||
concrete := func(a *NodeAbstractProvider) dag.Vertex { return a }
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformer{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
{
|
||||
tf := &AttachResourceConfigTransformer{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
tf := TransformProviders([]string{"aws"}, concrete, mod)
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformModuleProviderGrandparentStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
const testTransformProviderBasicStr = `
|
||||
aws_instance.web
|
||||
provider.aws
|
||||
|
@ -481,9 +547,7 @@ module.sub.module.subsub.bar_instance.two
|
|||
module.sub.module.subsub.foo_instance.one
|
||||
module.sub.provider.foo
|
||||
module.sub.provider.foo
|
||||
provider.foo (disabled)
|
||||
provider.bar
|
||||
provider.foo (disabled)
|
||||
`
|
||||
|
||||
const testTransformMissingProviderModuleChildStr = `
|
||||
|
@ -545,3 +609,15 @@ provider.aws (close)
|
|||
provider.aws
|
||||
var.foo
|
||||
`
|
||||
|
||||
const testTransformModuleProviderConfigStr = `
|
||||
module.child.aws_instance.thing
|
||||
provider.aws.foo
|
||||
provider.aws.foo
|
||||
`
|
||||
|
||||
const testTransformModuleProviderGrandparentStr = `
|
||||
module.child.module.grandchild.aws_instance.baz
|
||||
provider.aws.foo
|
||||
provider.aws.foo
|
||||
`
|
||||
|
|
Loading…
Reference in New Issue