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) {
|
||||
p := testProvider("aws")
|
||||
m := testModule(t, "validate-good")
|
||||
|
|
|
@ -33,6 +33,7 @@ type EvalContext interface {
|
|||
// is used to store the provider configuration for inheritance lookups
|
||||
// with ParentProviderConfig().
|
||||
ConfigureProvider(string, *ResourceConfig) error
|
||||
SetProviderConfig(string, *ResourceConfig) error
|
||||
ParentProviderConfig(string) *ResourceConfig
|
||||
|
||||
// ProviderInput and SetProviderInput are used to configure providers
|
||||
|
|
|
@ -106,6 +106,15 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(
|
|||
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)
|
||||
copy(providerPath, ctx.Path())
|
||||
providerPath[len(providerPath)-1] = n
|
||||
|
@ -115,7 +124,7 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(
|
|||
ctx.ProviderConfigCache[PathCacheKey(providerPath)] = cfg
|
||||
ctx.ProviderLock.Unlock()
|
||||
|
||||
return p.Configure(cfg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) ProviderInput(n string) map[string]interface{} {
|
||||
|
|
|
@ -38,6 +38,10 @@ type MockEvalContext struct {
|
|||
ConfigureProviderConfig *ResourceConfig
|
||||
ConfigureProviderError error
|
||||
|
||||
SetProviderConfigCalled bool
|
||||
SetProviderConfigName string
|
||||
SetProviderConfigConfig *ResourceConfig
|
||||
|
||||
ParentProviderConfigCalled bool
|
||||
ParentProviderConfigName string
|
||||
ParentProviderConfigConfig *ResourceConfig
|
||||
|
@ -107,6 +111,14 @@ func (c *MockEvalContext) ConfigureProvider(n string, cfg *ResourceConfig) error
|
|||
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 {
|
||||
c.ParentProviderConfigCalled = true
|
||||
c.ParentProviderConfigName = n
|
||||
|
|
|
@ -6,6 +6,17 @@ import (
|
|||
"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
|
||||
// merged with parents and inputs on top of what is configured in the file.
|
||||
type EvalBuildProviderConfig struct {
|
||||
|
|
|
@ -209,6 +209,11 @@ func (n *GraphNodeConfigProvider) ProviderName() string {
|
|||
return n.Provider.Name
|
||||
}
|
||||
|
||||
// GraphNodeProvider implementation
|
||||
func (n *GraphNodeConfigProvider) ProviderConfig() *config.RawConfig {
|
||||
return n.Provider.RawConfig
|
||||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *GraphNodeConfigProvider) Dot(name string) string {
|
||||
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"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
// they satisfy.
|
||||
type GraphNodeProvider interface {
|
||||
ProviderName() string
|
||||
ProviderConfig() *config.RawConfig
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer is an interface that nodes that require
|
||||
|
@ -28,7 +30,8 @@ type DisableProviderTransformer struct{}
|
|||
func (t *DisableProviderTransformer) Transform(g *Graph) error {
|
||||
for _, v := range g.Vertices() {
|
||||
// We only care about providers
|
||||
if _, ok := v.(GraphNodeProvider); !ok {
|
||||
pn, ok := v.(GraphNodeProvider)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -54,8 +57,13 @@ func (t *DisableProviderTransformer) Transform(g *Graph) error {
|
|||
continue
|
||||
}
|
||||
|
||||
// Disable the provider by removing it from the graph.
|
||||
g.Remove(v)
|
||||
// Disable the provider by replacing it with a "disabled" provider
|
||||
disabled := &graphNodeDisabledProvider{GraphNodeProvider: pn}
|
||||
if !g.Replace(v, disabled) {
|
||||
panic(fmt.Sprintf(
|
||||
"vertex disappeared from under us: %s",
|
||||
dag.VertexName(v)))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -134,6 +142,40 @@ func (t *PruneProviderTransformer) Transform(g *Graph) error {
|
|||
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 {
|
||||
ProviderNameValue string
|
||||
}
|
||||
|
@ -151,6 +193,10 @@ func (n *graphNodeMissingProvider) ProviderName() string {
|
|||
return n.ProviderNameValue
|
||||
}
|
||||
|
||||
func (n *graphNodeMissingProvider) ProviderConfig() *config.RawConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *graphNodeMissingProvider) Dot(name string) string {
|
||||
return fmt.Sprintf(
|
||||
|
|
|
@ -217,6 +217,8 @@ provider.foo
|
|||
|
||||
const testTransformDisableProviderBasicStr = `
|
||||
module.child
|
||||
provider.aws (disabled)
|
||||
provider.aws (disabled)
|
||||
`
|
||||
|
||||
const testTransformDisableProviderKeepStr = `
|
||||
|
|
Loading…
Reference in New Issue