config: substring containing computed value replaces element
This commit is contained in:
parent
abd68c2c87
commit
2feaebdca5
|
@ -152,12 +152,12 @@ func (w *interpolationWalker) Primitive(v reflect.Value) error {
|
|||
if w.loc == reflectwalk.SliceElem {
|
||||
parts := strings.Split(replaceVal, InterpSplitDelim)
|
||||
for _, p := range parts {
|
||||
if p == UnknownVariableValue {
|
||||
if strings.Contains(p, UnknownVariableValue) {
|
||||
remove = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if replaceVal == UnknownVariableValue {
|
||||
} else if strings.Contains(replaceVal, UnknownVariableValue) {
|
||||
remove = true
|
||||
}
|
||||
if remove {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/config/lang"
|
||||
"github.com/hashicorp/terraform/config/lang/ast"
|
||||
"github.com/mitchellh/reflectwalk"
|
||||
)
|
||||
|
@ -124,7 +125,7 @@ func TestInterpolationWalker_replace(t *testing.T) {
|
|||
"foo": "hello, ${var.foo}",
|
||||
},
|
||||
Output: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"foo": "hello, bar",
|
||||
},
|
||||
Value: "bar",
|
||||
},
|
||||
|
@ -170,11 +171,38 @@ func TestInterpolationWalker_replace(t *testing.T) {
|
|||
Output: map[string]interface{}{},
|
||||
Value: UnknownVariableValue + InterpSplitDelim + "baz",
|
||||
},
|
||||
|
||||
{
|
||||
Input: map[string]interface{}{
|
||||
"foo": []interface{}{
|
||||
"${var.foo}/32",
|
||||
"bing",
|
||||
},
|
||||
},
|
||||
Output: map[string]interface{}{},
|
||||
Value: UnknownVariableValue,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
fn := func(ast.Node) (string, error) {
|
||||
return tc.Value, nil
|
||||
config := &lang.EvalConfig{
|
||||
GlobalScope: &ast.BasicScope{
|
||||
VarMap: map[string]ast.Variable{
|
||||
"var.foo": ast.Variable{
|
||||
Value: tc.Value,
|
||||
Type: ast.TypeString,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fn := func(root ast.Node) (string, error) {
|
||||
value, _, err := lang.Eval(root, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return value.(string), nil
|
||||
}
|
||||
|
||||
w := &interpolationWalker{F: fn, Replace: true}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/lang/ast"
|
||||
"github.com/hashicorp/terraform/helper/hashcode"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
|
@ -48,16 +50,6 @@ func TestConfigFieldReader(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func testConfig(
|
||||
t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
|
||||
rc, err := config.NewRawConfig(raw)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
return terraform.NewResourceConfig(rc)
|
||||
}
|
||||
|
||||
func TestConfigFieldReader_DefaultHandling(t *testing.T) {
|
||||
schema := map[string]*Schema{
|
||||
"strWithDefault": &Schema{
|
||||
|
@ -142,3 +134,116 @@ func TestConfigFieldReader_DefaultHandling(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigFieldReader_ComputedSet(t *testing.T) {
|
||||
schema := map[string]*Schema{
|
||||
"strSet": &Schema{
|
||||
Type: TypeSet,
|
||||
Elem: &Schema{Type: TypeString},
|
||||
Set: func(v interface{}) int {
|
||||
return hashcode.String(v.(string))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
Addr []string
|
||||
Result FieldReadResult
|
||||
Config *terraform.ResourceConfig
|
||||
Err bool
|
||||
}{
|
||||
"set, normal": {
|
||||
[]string{"strSet"},
|
||||
FieldReadResult{
|
||||
Value: map[int]interface{}{
|
||||
2356372769: "foo",
|
||||
},
|
||||
Exists: true,
|
||||
Computed: false,
|
||||
},
|
||||
testConfig(t, map[string]interface{}{
|
||||
"strSet": []interface{}{"foo"},
|
||||
}),
|
||||
false,
|
||||
},
|
||||
|
||||
"set, computed element": {
|
||||
[]string{"strSet"},
|
||||
FieldReadResult{
|
||||
Value: nil,
|
||||
Exists: true,
|
||||
Computed: true,
|
||||
},
|
||||
testConfigInterpolate(t, map[string]interface{}{
|
||||
"strSet": []interface{}{"${var.foo}"},
|
||||
}, map[string]ast.Variable{
|
||||
"var.foo": ast.Variable{
|
||||
Value: config.UnknownVariableValue,
|
||||
Type: ast.TypeString,
|
||||
},
|
||||
}),
|
||||
false,
|
||||
},
|
||||
|
||||
"set, computed element substring": {
|
||||
[]string{"strSet"},
|
||||
FieldReadResult{
|
||||
Value: nil,
|
||||
Exists: true,
|
||||
Computed: true,
|
||||
},
|
||||
testConfigInterpolate(t, map[string]interface{}{
|
||||
"strSet": []interface{}{"${var.foo}/32"},
|
||||
}, map[string]ast.Variable{
|
||||
"var.foo": ast.Variable{
|
||||
Value: config.UnknownVariableValue,
|
||||
Type: ast.TypeString,
|
||||
},
|
||||
}),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
r := &ConfigFieldReader{
|
||||
Schema: schema,
|
||||
Config: tc.Config,
|
||||
}
|
||||
out, err := r.ReadField(tc.Addr)
|
||||
if (err != nil) != tc.Err {
|
||||
t.Fatalf("%s: err: %s", name, err)
|
||||
}
|
||||
if s, ok := out.Value.(*Set); ok {
|
||||
// If it is a set, convert to the raw map
|
||||
out.Value = s.m
|
||||
if len(s.m) == 0 {
|
||||
out.Value = nil
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(tc.Result, out) {
|
||||
t.Fatalf("%s: bad: %#v", name, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testConfig(
|
||||
t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
|
||||
return testConfigInterpolate(t, raw, nil)
|
||||
}
|
||||
|
||||
func testConfigInterpolate(
|
||||
t *testing.T,
|
||||
raw map[string]interface{},
|
||||
vs map[string]ast.Variable) *terraform.ResourceConfig {
|
||||
rc, err := config.NewRawConfig(raw)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if len(vs) > 0 {
|
||||
if err := rc.Interpolate(vs); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return terraform.NewResourceConfig(rc)
|
||||
}
|
||||
|
|
|
@ -2165,6 +2165,42 @@ func TestSchemaMap_Diff(t *testing.T) {
|
|||
|
||||
Err: false,
|
||||
},
|
||||
|
||||
// #56 - Set element computed substring
|
||||
{
|
||||
Schema: map[string]*Schema{
|
||||
"ports": &Schema{
|
||||
Type: TypeSet,
|
||||
Required: true,
|
||||
Elem: &Schema{Type: TypeInt},
|
||||
Set: func(a interface{}) int {
|
||||
return a.(int)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
State: nil,
|
||||
|
||||
Config: map[string]interface{}{
|
||||
"ports": []interface{}{1, "${var.foo}32"},
|
||||
},
|
||||
|
||||
ConfigVariables: map[string]string{
|
||||
"var.foo": config.UnknownVariableValue,
|
||||
},
|
||||
|
||||
Diff: &terraform.InstanceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"ports.#": &terraform.ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "",
|
||||
NewComputed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Err: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
|
|
Loading…
Reference in New Issue