aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/config/hcl2shim/values.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/config/hcl2shim/values.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/config/hcl2shim/values.go109
1 files changed, 108 insertions, 1 deletions
diff --git a/vendor/github.com/hashicorp/terraform/config/hcl2shim/values.go b/vendor/github.com/hashicorp/terraform/config/hcl2shim/values.go
index 0b697a5..daeb0b8 100644
--- a/vendor/github.com/hashicorp/terraform/config/hcl2shim/values.go
+++ b/vendor/github.com/hashicorp/terraform/config/hcl2shim/values.go
@@ -6,6 +6,8 @@ import (
6 6
7 "github.com/hashicorp/hil/ast" 7 "github.com/hashicorp/hil/ast"
8 "github.com/zclconf/go-cty/cty" 8 "github.com/zclconf/go-cty/cty"
9
10 "github.com/hashicorp/terraform/configs/configschema"
9) 11)
10 12
11// UnknownVariableValue is a sentinel value that can be used 13// UnknownVariableValue is a sentinel value that can be used
@@ -14,6 +16,108 @@ import (
14// unknown keys. 16// unknown keys.
15const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66" 17const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66"
16 18
19// ConfigValueFromHCL2Block is like ConfigValueFromHCL2 but it works only for
20// known object values and uses the provided block schema to perform some
21// additional normalization to better mimic the shape of value that the old
22// HCL1/HIL-based codepaths would've produced.
23//
24// In particular, it discards the collections that we use to represent nested
25// blocks (other than NestingSingle) if they are empty, which better mimics
26// the HCL1 behavior because HCL1 had no knowledge of the schema and so didn't
27// know that an unspecified block _could_ exist.
28//
29// The given object value must conform to the schema's implied type or this
30// function will panic or produce incorrect results.
31//
32// This is primarily useful for the final transition from new-style values to
33// terraform.ResourceConfig before calling to a legacy provider, since
34// helper/schema (the old provider SDK) is particularly sensitive to these
35// subtle differences within its validation code.
36func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[string]interface{} {
37 if v.IsNull() {
38 return nil
39 }
40 if !v.IsKnown() {
41 panic("ConfigValueFromHCL2Block used with unknown value")
42 }
43 if !v.Type().IsObjectType() {
44 panic(fmt.Sprintf("ConfigValueFromHCL2Block used with non-object value %#v", v))
45 }
46
47 atys := v.Type().AttributeTypes()
48 ret := make(map[string]interface{})
49
50 for name := range schema.Attributes {
51 if _, exists := atys[name]; !exists {
52 continue
53 }
54
55 av := v.GetAttr(name)
56 if av.IsNull() {
57 // Skip nulls altogether, to better mimic how HCL1 would behave
58 continue
59 }
60 ret[name] = ConfigValueFromHCL2(av)
61 }
62
63 for name, blockS := range schema.BlockTypes {
64 if _, exists := atys[name]; !exists {
65 continue
66 }
67 bv := v.GetAttr(name)
68 if !bv.IsKnown() {
69 ret[name] = UnknownVariableValue
70 continue
71 }
72 if bv.IsNull() {
73 continue
74 }
75
76 switch blockS.Nesting {
77
78 case configschema.NestingSingle, configschema.NestingGroup:
79 ret[name] = ConfigValueFromHCL2Block(bv, &blockS.Block)
80
81 case configschema.NestingList, configschema.NestingSet:
82 l := bv.LengthInt()
83 if l == 0 {
84 // skip empty collections to better mimic how HCL1 would behave
85 continue
86 }
87
88 elems := make([]interface{}, 0, l)
89 for it := bv.ElementIterator(); it.Next(); {
90 _, ev := it.Element()
91 if !ev.IsKnown() {
92 elems = append(elems, UnknownVariableValue)
93 continue
94 }
95 elems = append(elems, ConfigValueFromHCL2Block(ev, &blockS.Block))
96 }
97 ret[name] = elems
98
99 case configschema.NestingMap:
100 if bv.LengthInt() == 0 {
101 // skip empty collections to better mimic how HCL1 would behave
102 continue
103 }
104
105 elems := make(map[string]interface{})
106 for it := bv.ElementIterator(); it.Next(); {
107 ek, ev := it.Element()
108 if !ev.IsKnown() {
109 elems[ek.AsString()] = UnknownVariableValue
110 continue
111 }
112 elems[ek.AsString()] = ConfigValueFromHCL2Block(ev, &blockS.Block)
113 }
114 ret[name] = elems
115 }
116 }
117
118 return ret
119}
120
17// ConfigValueFromHCL2 converts a value from HCL2 (really, from the cty dynamic 121// ConfigValueFromHCL2 converts a value from HCL2 (really, from the cty dynamic
18// types library that HCL2 uses) to a value type that matches what would've 122// types library that HCL2 uses) to a value type that matches what would've
19// been produced from the HCL-based interpolator for an equivalent structure. 123// been produced from the HCL-based interpolator for an equivalent structure.
@@ -73,7 +177,10 @@ func ConfigValueFromHCL2(v cty.Value) interface{} {
73 it := v.ElementIterator() 177 it := v.ElementIterator()
74 for it.Next() { 178 for it.Next() {
75 ek, ev := it.Element() 179 ek, ev := it.Element()
76 l[ek.AsString()] = ConfigValueFromHCL2(ev) 180 cv := ConfigValueFromHCL2(ev)
181 if cv != nil {
182 l[ek.AsString()] = cv
183 }
77 } 184 }
78 return l 185 return l
79 } 186 }