terraform: merge provider configs before validate [GH-1282]

This commit is contained in:
Mitchell Hashimoto 2015-03-25 16:28:52 -07:00
parent 1bbfb07b00
commit a0839da71a
5 changed files with 96 additions and 18 deletions

View File

@ -2505,6 +2505,9 @@ func TestContext2Input_provider(t *testing.T) {
actual = c.Config["foo"]
return nil
}
p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
return nil, c.CheckSet([]string{"foo"})
}
if err := ctx.Input(InputModeStd); err != nil {
t.Fatalf("err: %s", err)

View File

@ -6,17 +6,18 @@ import (
"github.com/hashicorp/terraform/config"
)
// EvalConfigProvider is an EvalNode implementation that configures
// a provider that is already initialized and retrieved.
type EvalConfigProvider struct {
// EvalBuildProviderConfig outputs a *ResourceConfig that is properly
// merged with parents and inputs on top of what is configured in the file.
type EvalBuildProviderConfig struct {
Provider string
Config **ResourceConfig
Output **ResourceConfig
}
func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
func (n *EvalBuildProviderConfig) Eval(ctx EvalContext) (interface{}, error) {
cfg := *n.Config
// If we have a configuration set, then use that
// If we have a configuration set, then merge that in
if input := ctx.ProviderInput(n.Provider); input != nil {
rc, err := config.NewRawConfig(input)
if err != nil {
@ -33,7 +34,19 @@ func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
cfg = NewResourceConfig(merged)
}
return nil, ctx.ConfigureProvider(n.Provider, cfg)
*n.Output = cfg
return nil, nil
}
// EvalConfigProvider is an EvalNode implementation that configures
// a provider that is already initialized and retrieved.
type EvalConfigProvider struct {
Provider string
Config **ResourceConfig
}
func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
return nil, ctx.ConfigureProvider(n.Provider, *n.Config)
}
// EvalInitProvider is an EvalNode implementation that initializes a provider

View File

@ -5,6 +5,71 @@ import (
"testing"
)
func TestEvalBuildProviderConfig_impl(t *testing.T) {
var _ EvalNode = new(EvalBuildProviderConfig)
}
func TestEvalBuildProviderConfig(t *testing.T) {
config := testResourceConfig(t, map[string]interface{}{})
provider := "foo"
n := &EvalBuildProviderConfig{
Provider: provider,
Config: &config,
Output: &config,
}
ctx := &MockEvalContext{
ParentProviderConfigConfig: testResourceConfig(t, map[string]interface{}{
"foo": "bar",
}),
ProviderInputConfig: map[string]interface{}{
"bar": "baz",
},
}
if _, err := n.Eval(ctx); err != nil {
t.Fatalf("err: %s", err)
}
expected := map[string]interface{}{
"foo": "bar",
"bar": "baz",
}
if !reflect.DeepEqual(config.Raw, expected) {
t.Fatalf("bad: %#v", config.Raw)
}
}
func TestEvalBuildProviderConfig_parentPriority(t *testing.T) {
config := testResourceConfig(t, map[string]interface{}{})
provider := "foo"
n := &EvalBuildProviderConfig{
Provider: provider,
Config: &config,
Output: &config,
}
ctx := &MockEvalContext{
ParentProviderConfigConfig: testResourceConfig(t, map[string]interface{}{
"foo": "bar",
}),
ProviderInputConfig: map[string]interface{}{
"foo": "baz",
},
}
if _, err := n.Eval(ctx); err != nil {
t.Fatalf("err: %s", err)
}
expected := map[string]interface{}{
"foo": "bar",
}
if !reflect.DeepEqual(config.Raw, expected) {
t.Fatalf("bad: %#v", config.Raw)
}
}
func TestEvalConfigProvider_impl(t *testing.T) {
var _ EvalNode = new(EvalConfigProvider)
}

View File

@ -57,21 +57,14 @@ RETURN:
// EvalValidateProvider is an EvalNode implementation that validates
// the configuration of a resource.
type EvalValidateProvider struct {
ProviderName string
Provider *ResourceProvider
Config **ResourceConfig
Provider *ResourceProvider
Config **ResourceConfig
}
func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) {
provider := *n.Provider
config := *n.Config
// Get the parent configuration if there is one
if parent := ctx.ParentProviderConfig(n.ProviderName); parent != nil {
merged := parent.raw.Merge(config.raw)
config = NewResourceConfig(merged)
}
warns, errs := provider.Validate(config)
if len(warns) == 0 && len(errs) == 0 {
return nil, nil

View File

@ -44,10 +44,14 @@ func ProviderEvalTree(n string, config *config.RawConfig) EvalNode {
Config: config,
Output: &resourceConfig,
},
&EvalBuildProviderConfig{
Provider: n,
Config: &resourceConfig,
Output: &resourceConfig,
},
&EvalValidateProvider{
ProviderName: n,
Provider: &provider,
Config: &resourceConfig,
Provider: &provider,
Config: &resourceConfig,
},
&EvalConfigProvider{
Provider: n,