Merge pull request #10034 from hashicorp/b-diff-mismatch
terraform: when returning a raw attribute value, use hil conversion
This commit is contained in:
commit
cca3ed6c1a
|
@ -1,11 +1,14 @@
|
||||||
package schema
|
package schema
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/hil/ast"
|
"github.com/hashicorp/hil/ast"
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -391,6 +394,138 @@ func TestConfigFieldReader_ComputedSet(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigFieldReader_computedComplexSet(t *testing.T) {
|
||||||
|
hashfunc := func(v interface{}) int {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string)))
|
||||||
|
return hashcode.String(buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
schema := map[string]*Schema{
|
||||||
|
"set": &Schema{
|
||||||
|
Type: TypeSet,
|
||||||
|
Elem: &Resource{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"name": {
|
||||||
|
Type: TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"vhd_uri": {
|
||||||
|
Type: TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Set: hashfunc,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := map[string]struct {
|
||||||
|
Addr []string
|
||||||
|
Result FieldReadResult
|
||||||
|
Config *terraform.ResourceConfig
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
"set, normal": {
|
||||||
|
[]string{"set"},
|
||||||
|
FieldReadResult{
|
||||||
|
Value: map[string]interface{}{
|
||||||
|
"532860136": map[string]interface{}{
|
||||||
|
"name": "myosdisk1",
|
||||||
|
"vhd_uri": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Exists: true,
|
||||||
|
Computed: false,
|
||||||
|
},
|
||||||
|
testConfig(t, map[string]interface{}{
|
||||||
|
"set": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"name": "myosdisk1",
|
||||||
|
"vhd_uri": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
"set, computed element": {
|
||||||
|
[]string{"set"},
|
||||||
|
FieldReadResult{
|
||||||
|
Value: map[string]interface{}{
|
||||||
|
"~3596295623": map[string]interface{}{
|
||||||
|
"name": "myosdisk1",
|
||||||
|
"vhd_uri": "${var.foo}/bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Exists: true,
|
||||||
|
Computed: false,
|
||||||
|
},
|
||||||
|
testConfigInterpolate(t, map[string]interface{}{
|
||||||
|
"set": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"name": "myosdisk1",
|
||||||
|
"vhd_uri": "${var.foo}/bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, map[string]ast.Variable{
|
||||||
|
"var.foo": ast.Variable{
|
||||||
|
Value: config.UnknownVariableValue,
|
||||||
|
Type: ast.TypeUnknown,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
"set, computed element single": {
|
||||||
|
[]string{"set", "~3596295623", "vhd_uri"},
|
||||||
|
FieldReadResult{
|
||||||
|
Value: "${var.foo}/bar",
|
||||||
|
Exists: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
testConfigInterpolate(t, map[string]interface{}{
|
||||||
|
"set": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"name": "myosdisk1",
|
||||||
|
"vhd_uri": "${var.foo}/bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, map[string]ast.Variable{
|
||||||
|
"var.foo": ast.Variable{
|
||||||
|
Value: config.UnknownVariableValue,
|
||||||
|
Type: ast.TypeUnknown,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
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(
|
func testConfig(
|
||||||
t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
|
t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
|
||||||
return testConfigInterpolate(t, raw, nil)
|
return testConfigInterpolate(t, raw, nil)
|
||||||
|
|
|
@ -404,7 +404,8 @@ func (i *Interpolater) computeResourceVariable(
|
||||||
}
|
}
|
||||||
|
|
||||||
if attr, ok := r.Primary.Attributes[v.Field]; ok {
|
if attr, ok := r.Primary.Attributes[v.Field]; ok {
|
||||||
return &ast.Variable{Type: ast.TypeString, Value: attr}, nil
|
v, err := hil.InterfaceToVariable(attr)
|
||||||
|
return &v, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// computed list or map attribute
|
// computed list or map attribute
|
||||||
|
|
|
@ -569,6 +569,44 @@ func TestInterpolator_resourceMultiAttributesComputed(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInterpolator_resourceAttributeComputed(t *testing.T) {
|
||||||
|
lock := new(sync.RWMutex)
|
||||||
|
// The state would never be written with an UnknownVariableValue in it, but
|
||||||
|
// it can/does exist that way in memory during the plan phase.
|
||||||
|
state := &State{
|
||||||
|
Modules: []*ModuleState{
|
||||||
|
&ModuleState{
|
||||||
|
Path: rootModulePath,
|
||||||
|
Resources: map[string]*ResourceState{
|
||||||
|
"aws_route53_zone.yada": &ResourceState{
|
||||||
|
Type: "aws_route53_zone",
|
||||||
|
Primary: &InstanceState{
|
||||||
|
ID: "z-abc123",
|
||||||
|
Attributes: map[string]string{
|
||||||
|
"id": config.UnknownVariableValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
i := &Interpolater{
|
||||||
|
Module: testModule(t, "interpolate-multi-vars"),
|
||||||
|
StateLock: lock,
|
||||||
|
State: state,
|
||||||
|
}
|
||||||
|
|
||||||
|
scope := &InterpolationScope{
|
||||||
|
Path: rootModulePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
testInterpolate(t, i, scope, "aws_route53_zone.yada.id", ast.Variable{
|
||||||
|
Value: config.UnknownVariableValue,
|
||||||
|
Type: ast.TypeUnknown,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestInterpolater_selfVarWithoutResource(t *testing.T) {
|
func TestInterpolater_selfVarWithoutResource(t *testing.T) {
|
||||||
i := &Interpolater{}
|
i := &Interpolater{}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ func InterfaceToVariable(input interface{}) (ast.Variable, error) {
|
||||||
if err := hilMapstructureWeakDecode(input, &stringVal); err == nil {
|
if err := hilMapstructureWeakDecode(input, &stringVal); err == nil {
|
||||||
// Special case the unknown value to turn into "unknown"
|
// Special case the unknown value to turn into "unknown"
|
||||||
if stringVal == UnknownValue {
|
if stringVal == UnknownValue {
|
||||||
return ast.Variable{Type: ast.TypeUnknown}, nil
|
return ast.Variable{Value: UnknownValue, Type: ast.TypeUnknown}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise return the string value
|
// Otherwise return the string value
|
||||||
|
|
|
@ -1412,10 +1412,10 @@
|
||||||
"revisionTime": "2016-11-09T22:51:35Z"
|
"revisionTime": "2016-11-09T22:51:35Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "mZhRldYjh9MAXzdi3zihMX0A/JU=",
|
"checksumSHA1": "PjLBj8sicHOz2ZzuaMTPZ09OuFs=",
|
||||||
"path": "github.com/hashicorp/hil",
|
"path": "github.com/hashicorp/hil",
|
||||||
"revision": "ce4ab742a9dd2bb6e55050337333b2c56666e5a0",
|
"revision": "a69e0a85dd050184c00f6080fce138f2dadb1a4c",
|
||||||
"revisionTime": "2016-10-27T15:25:34Z"
|
"revisionTime": "2016-11-11T01:09:07Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "FFroNUb6Nn6xUQJMsVDTb4Cqzo4=",
|
"checksumSHA1": "FFroNUb6Nn6xUQJMsVDTb4Cqzo4=",
|
||||||
|
@ -1880,7 +1880,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "DVXnx4zyb0wkeIdIRjwjvR7Dslo=",
|
"checksumSHA1": "DVXnx4zyb0wkeIdIRjwjvR7Dslo=",
|
||||||
"origin": "github.com/hashicorp/terraform/vendor/github.com/mitchellh/go-ps",
|
|
||||||
"path": "github.com/mitchellh/go-ps",
|
"path": "github.com/mitchellh/go-ps",
|
||||||
"revision": "e2d21980687ce16e58469d98dcee92d27fbbd7fb",
|
"revision": "e2d21980687ce16e58469d98dcee92d27fbbd7fb",
|
||||||
"revisionTime": "2016-08-22T16:54:47Z"
|
"revisionTime": "2016-08-22T16:54:47Z"
|
||||||
|
|
Loading…
Reference in New Issue