Merge pull request #1452 from hashicorp/b-inherit-validate
terraform: don't prune, but disable, inherited configs [GH-1447]
This commit is contained in:
commit
f0004186cf
|
@ -2258,6 +2258,29 @@ func TestContext2Validate_moduleProviderVar(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContext2Validate_moduleProviderInheritUnused(t *testing.T) {
|
||||||
|
m := testModule(t, "validate-module-pc-inherit-unused")
|
||||||
|
p := testProvider("aws")
|
||||||
|
c := testContext2(t, &ContextOpts{
|
||||||
|
Module: m,
|
||||||
|
Providers: map[string]ResourceProviderFactory{
|
||||||
|
"aws": testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
|
||||||
|
return nil, c.CheckSet([]string{"foo"})
|
||||||
|
}
|
||||||
|
|
||||||
|
w, e := c.Validate()
|
||||||
|
if len(w) > 0 {
|
||||||
|
t.Fatalf("bad: %#v", w)
|
||||||
|
}
|
||||||
|
if len(e) > 0 {
|
||||||
|
t.Fatalf("bad: %s", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestContext2Validate_orphans(t *testing.T) {
|
func TestContext2Validate_orphans(t *testing.T) {
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
m := testModule(t, "validate-good")
|
m := testModule(t, "validate-good")
|
||||||
|
|
|
@ -33,6 +33,7 @@ type EvalContext interface {
|
||||||
// is used to store the provider configuration for inheritance lookups
|
// is used to store the provider configuration for inheritance lookups
|
||||||
// with ParentProviderConfig().
|
// with ParentProviderConfig().
|
||||||
ConfigureProvider(string, *ResourceConfig) error
|
ConfigureProvider(string, *ResourceConfig) error
|
||||||
|
SetProviderConfig(string, *ResourceConfig) error
|
||||||
ParentProviderConfig(string) *ResourceConfig
|
ParentProviderConfig(string) *ResourceConfig
|
||||||
|
|
||||||
// ProviderInput and SetProviderInput are used to configure providers
|
// ProviderInput and SetProviderInput are used to configure providers
|
||||||
|
|
|
@ -106,6 +106,15 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(
|
||||||
return fmt.Errorf("Provider '%s' not initialized", n)
|
return fmt.Errorf("Provider '%s' not initialized", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := ctx.SetProviderConfig(n, cfg); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.Configure(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *BuiltinEvalContext) SetProviderConfig(
|
||||||
|
n string, cfg *ResourceConfig) error {
|
||||||
providerPath := make([]string, len(ctx.Path())+1)
|
providerPath := make([]string, len(ctx.Path())+1)
|
||||||
copy(providerPath, ctx.Path())
|
copy(providerPath, ctx.Path())
|
||||||
providerPath[len(providerPath)-1] = n
|
providerPath[len(providerPath)-1] = n
|
||||||
|
@ -115,7 +124,7 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(
|
||||||
ctx.ProviderConfigCache[PathCacheKey(providerPath)] = cfg
|
ctx.ProviderConfigCache[PathCacheKey(providerPath)] = cfg
|
||||||
ctx.ProviderLock.Unlock()
|
ctx.ProviderLock.Unlock()
|
||||||
|
|
||||||
return p.Configure(cfg)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) ProviderInput(n string) map[string]interface{} {
|
func (ctx *BuiltinEvalContext) ProviderInput(n string) map[string]interface{} {
|
||||||
|
|
|
@ -38,6 +38,10 @@ type MockEvalContext struct {
|
||||||
ConfigureProviderConfig *ResourceConfig
|
ConfigureProviderConfig *ResourceConfig
|
||||||
ConfigureProviderError error
|
ConfigureProviderError error
|
||||||
|
|
||||||
|
SetProviderConfigCalled bool
|
||||||
|
SetProviderConfigName string
|
||||||
|
SetProviderConfigConfig *ResourceConfig
|
||||||
|
|
||||||
ParentProviderConfigCalled bool
|
ParentProviderConfigCalled bool
|
||||||
ParentProviderConfigName string
|
ParentProviderConfigName string
|
||||||
ParentProviderConfigConfig *ResourceConfig
|
ParentProviderConfigConfig *ResourceConfig
|
||||||
|
@ -107,6 +111,14 @@ func (c *MockEvalContext) ConfigureProvider(n string, cfg *ResourceConfig) error
|
||||||
return c.ConfigureProviderError
|
return c.ConfigureProviderError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *MockEvalContext) SetProviderConfig(
|
||||||
|
n string, cfg *ResourceConfig) error {
|
||||||
|
c.SetProviderConfigCalled = true
|
||||||
|
c.SetProviderConfigName = n
|
||||||
|
c.SetProviderConfigConfig = cfg
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *MockEvalContext) ParentProviderConfig(n string) *ResourceConfig {
|
func (c *MockEvalContext) ParentProviderConfig(n string) *ResourceConfig {
|
||||||
c.ParentProviderConfigCalled = true
|
c.ParentProviderConfigCalled = true
|
||||||
c.ParentProviderConfigName = n
|
c.ParentProviderConfigName = n
|
||||||
|
|
|
@ -6,6 +6,17 @@ import (
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EvalSetProviderConfig sets the parent configuration for a provider
|
||||||
|
// without configuring that provider, validating it, etc.
|
||||||
|
type EvalSetProviderConfig struct {
|
||||||
|
Provider string
|
||||||
|
Config **ResourceConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *EvalSetProviderConfig) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
|
return nil, ctx.SetProviderConfig(n.Provider, *n.Config)
|
||||||
|
}
|
||||||
|
|
||||||
// EvalBuildProviderConfig outputs a *ResourceConfig that is properly
|
// EvalBuildProviderConfig outputs a *ResourceConfig that is properly
|
||||||
// merged with parents and inputs on top of what is configured in the file.
|
// merged with parents and inputs on top of what is configured in the file.
|
||||||
type EvalBuildProviderConfig struct {
|
type EvalBuildProviderConfig struct {
|
||||||
|
|
|
@ -209,6 +209,11 @@ func (n *GraphNodeConfigProvider) ProviderName() string {
|
||||||
return n.Provider.Name
|
return n.Provider.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GraphNodeProvider implementation
|
||||||
|
func (n *GraphNodeConfigProvider) ProviderConfig() *config.RawConfig {
|
||||||
|
return n.Provider.RawConfig
|
||||||
|
}
|
||||||
|
|
||||||
// GraphNodeDotter impl.
|
// GraphNodeDotter impl.
|
||||||
func (n *GraphNodeConfigProvider) Dot(name string) string {
|
func (n *GraphNodeConfigProvider) Dot(name string) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
resource "aws_instance" "foo" {}
|
|
@ -0,0 +1,7 @@
|
||||||
|
module "child" {
|
||||||
|
source = "./child"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "aws" {
|
||||||
|
foo = "set"
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
|
"github.com/hashicorp/terraform/config"
|
||||||
"github.com/hashicorp/terraform/dag"
|
"github.com/hashicorp/terraform/dag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
// they satisfy.
|
// they satisfy.
|
||||||
type GraphNodeProvider interface {
|
type GraphNodeProvider interface {
|
||||||
ProviderName() string
|
ProviderName() string
|
||||||
|
ProviderConfig() *config.RawConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeProviderConsumer is an interface that nodes that require
|
// GraphNodeProviderConsumer is an interface that nodes that require
|
||||||
|
@ -28,7 +30,8 @@ type DisableProviderTransformer struct{}
|
||||||
func (t *DisableProviderTransformer) Transform(g *Graph) error {
|
func (t *DisableProviderTransformer) Transform(g *Graph) error {
|
||||||
for _, v := range g.Vertices() {
|
for _, v := range g.Vertices() {
|
||||||
// We only care about providers
|
// We only care about providers
|
||||||
if _, ok := v.(GraphNodeProvider); !ok {
|
pn, ok := v.(GraphNodeProvider)
|
||||||
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +57,13 @@ func (t *DisableProviderTransformer) Transform(g *Graph) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable the provider by removing it from the graph.
|
// Disable the provider by replacing it with a "disabled" provider
|
||||||
g.Remove(v)
|
disabled := &graphNodeDisabledProvider{GraphNodeProvider: pn}
|
||||||
|
if !g.Replace(v, disabled) {
|
||||||
|
panic(fmt.Sprintf(
|
||||||
|
"vertex disappeared from under us: %s",
|
||||||
|
dag.VertexName(v)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -134,6 +142,40 @@ func (t *PruneProviderTransformer) Transform(g *Graph) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type graphNodeDisabledProvider struct {
|
||||||
|
GraphNodeProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeEvalable impl.
|
||||||
|
func (n *graphNodeDisabledProvider) EvalTree() EvalNode {
|
||||||
|
var resourceConfig *ResourceConfig
|
||||||
|
|
||||||
|
return &EvalOpFilter{
|
||||||
|
Ops: []walkOperation{walkValidate, walkRefresh, walkPlan, walkApply},
|
||||||
|
Node: &EvalSequence{
|
||||||
|
Nodes: []EvalNode{
|
||||||
|
&EvalInterpolate{
|
||||||
|
Config: n.ProviderConfig(),
|
||||||
|
Output: &resourceConfig,
|
||||||
|
},
|
||||||
|
&EvalBuildProviderConfig{
|
||||||
|
Provider: n.ProviderName(),
|
||||||
|
Config: &resourceConfig,
|
||||||
|
Output: &resourceConfig,
|
||||||
|
},
|
||||||
|
&EvalSetProviderConfig{
|
||||||
|
Provider: n.ProviderName(),
|
||||||
|
Config: &resourceConfig,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *graphNodeDisabledProvider) Name() string {
|
||||||
|
return fmt.Sprintf("%s (disabled)", dag.VertexName(n.GraphNodeProvider))
|
||||||
|
}
|
||||||
|
|
||||||
type graphNodeMissingProvider struct {
|
type graphNodeMissingProvider struct {
|
||||||
ProviderNameValue string
|
ProviderNameValue string
|
||||||
}
|
}
|
||||||
|
@ -151,6 +193,10 @@ func (n *graphNodeMissingProvider) ProviderName() string {
|
||||||
return n.ProviderNameValue
|
return n.ProviderNameValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *graphNodeMissingProvider) ProviderConfig() *config.RawConfig {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GraphNodeDotter impl.
|
// GraphNodeDotter impl.
|
||||||
func (n *graphNodeMissingProvider) Dot(name string) string {
|
func (n *graphNodeMissingProvider) Dot(name string) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
|
|
|
@ -217,6 +217,8 @@ provider.foo
|
||||||
|
|
||||||
const testTransformDisableProviderBasicStr = `
|
const testTransformDisableProviderBasicStr = `
|
||||||
module.child
|
module.child
|
||||||
|
provider.aws (disabled)
|
||||||
|
provider.aws (disabled)
|
||||||
`
|
`
|
||||||
|
|
||||||
const testTransformDisableProviderKeepStr = `
|
const testTransformDisableProviderKeepStr = `
|
||||||
|
|
Loading…
Reference in New Issue