config: providerconfigs can replace variables

This commit is contained in:
Mitchell Hashimoto 2014-06-05 12:52:07 -07:00
parent 3ccfd4d08c
commit d2c3db552a
3 changed files with 68 additions and 8 deletions

View File

@ -7,7 +7,6 @@ import (
"strings"
"github.com/hashicorp/terraform/depgraph"
"github.com/mitchellh/reflectwalk"
)
// ResourceGraphRoot is the name of the resource graph root that should be
@ -77,6 +76,20 @@ type UserVariable struct {
key string
}
// ReplaceVariables replaces the variables in the configuration
// with the given values.
//
// This replacement is not in place. Instead, this function will
// return a new resource with the variables replaced.
func (r *ProviderConfig) ReplaceVariables(
vs map[string]string) *ProviderConfig {
result := *r
if err := replaceVariables(result.Config, vs); err != nil {
panic(err)
}
return &result
}
// A unique identifier for this resource.
func (r *Resource) Id() string {
return fmt.Sprintf("%s.%s", r.Type, r.Name)
@ -103,20 +116,18 @@ func (r *Resource) ProviderConfigName(pcs map[string]*ProviderConfig) string {
// return a new resource with the variables replaced.
func (r *Resource) ReplaceVariables(vs map[string]string) *Resource {
result := *r
w := &variableReplaceWalker{
Values: vs,
}
if err := reflectwalk.Walk(result.Config, w); err != nil {
if err := replaceVariables(result.Config, vs); err != nil {
panic(err)
}
return &result
}
// ResourceGraph returns a dependency graph of the resources from this
// Terraform configuration.
//
// The graph can contain both *Resource and *ProviderConfig. When consuming
// the graph, you'll have to use type inference to determine what it is
// and the proper behavior.
func (c *Config) ResourceGraph() *depgraph.Graph {
// This tracks all the resource nouns
nouns := make(map[string]*depgraph.Noun)

View File

@ -64,6 +64,45 @@ func TestNewUserVariable(t *testing.T) {
}
}
func TestProviderConfigReplaceVariables(t *testing.T) {
r := &ProviderConfig{
Config: map[string]interface{}{
"foo": "${var.bar}",
},
}
values := map[string]string{
"var.bar": "value",
}
r2 := r.ReplaceVariables(values)
expected := &ProviderConfig{
Config: map[string]interface{}{
"foo": "value",
},
}
if !reflect.DeepEqual(r2, expected) {
t.Fatalf("bad: %#v", r2)
}
/*
TODO(mitchellh): Eventually, preserve original config...
expectedOriginal := &Resource{
Name: "foo",
Type: "bar",
Config: map[string]interface{}{
"foo": "${var.bar}",
},
}
if !reflect.DeepEqual(r, expectedOriginal) {
t.Fatalf("bad: %#v", r)
}
*/
}
func TestResourceProviderConfigName(t *testing.T) {
r := &Resource{
Name: "foo",

View File

@ -16,6 +16,16 @@ func init() {
varRegexp = regexp.MustCompile(`(?i)(\$+)\{([-.a-z0-9_]+)\}`)
}
// replaceVariables takes a configuration and a mapping of variables
// and performs the structure walking necessary to properly replace
// all the variables.
func replaceVariables(
c map[string]interface{},
vs map[string]string) error {
w := &variableReplaceWalker{Values: vs}
return reflectwalk.Walk(c, w)
}
// variableDetectWalker implements interfaces for the reflectwalk package
// (github.com/mitchellh/reflectwalk) that can be used to automatically
// pull out the variables that need replacing.