aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
diff options
context:
space:
mode:
authorappilon <apilon@hashicorp.com>2019-02-27 16:43:31 -0500
committerGitHub <noreply@github.com>2019-02-27 16:43:31 -0500
commit844b5a68d8af4791755b8f0ad293cc99f5959183 (patch)
tree255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/hashicorp/terraform/helper/schema/schema.go
parent303b299eeb6b06e939e35905e4b34cb410dd9dc3 (diff)
parent15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (diff)
downloadterraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.tar.gz
terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.tar.zst
terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.zip
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[MODULES] Switch to Go Modules
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/schema/schema.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/schema.go252
1 files changed, 173 insertions, 79 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
index acb5618..0ea5aad 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
@@ -21,9 +21,13 @@ import (
21 "strings" 21 "strings"
22 22
23 "github.com/hashicorp/terraform/terraform" 23 "github.com/hashicorp/terraform/terraform"
24 "github.com/mitchellh/copystructure"
24 "github.com/mitchellh/mapstructure" 25 "github.com/mitchellh/mapstructure"
25) 26)
26 27
28// Name of ENV variable which (if not empty) prefers panic over error
29const PanicOnErr = "TF_SCHEMA_PANIC_ON_ERROR"
30
27// type used for schema package context keys 31// type used for schema package context keys
28type contextKey string 32type contextKey string
29 33
@@ -116,12 +120,16 @@ type Schema struct {
116 ForceNew bool 120 ForceNew bool
117 StateFunc SchemaStateFunc 121 StateFunc SchemaStateFunc
118 122
119 // The following fields are only set for a TypeList or TypeSet Type. 123 // The following fields are only set for a TypeList, TypeSet, or TypeMap.
120 // 124 //
121 // Elem must be either a *Schema or a *Resource only if the Type is 125 // Elem represents the element type. For a TypeMap, it must be a *Schema
122 // TypeList, and represents what the element type is. If it is *Schema, 126 // with a Type of TypeString, otherwise it may be either a *Schema or a
123 // the element type is just a simple value. If it is *Resource, the 127 // *Resource. If it is *Schema, the element type is just a simple value.
124 // element type is a complex structure, potentially with its own lifecycle. 128 // If it is *Resource, the element type is a complex structure,
129 // potentially with its own lifecycle.
130 Elem interface{}
131
132 // The following fields are only set for a TypeList or TypeSet.
125 // 133 //
126 // MaxItems defines a maximum amount of items that can exist within a 134 // MaxItems defines a maximum amount of items that can exist within a
127 // TypeSet or TypeList. Specific use cases would be if a TypeSet is being 135 // TypeSet or TypeList. Specific use cases would be if a TypeSet is being
@@ -138,7 +146,6 @@ type Schema struct {
138 // ["foo"] automatically. This is primarily for legacy reasons and the 146 // ["foo"] automatically. This is primarily for legacy reasons and the
139 // ambiguity is not recommended for new usage. Promotion is only allowed 147 // ambiguity is not recommended for new usage. Promotion is only allowed
140 // for primitive element types. 148 // for primitive element types.
141 Elem interface{}
142 MaxItems int 149 MaxItems int
143 MinItems int 150 MinItems int
144 PromoteSingle bool 151 PromoteSingle bool
@@ -192,7 +199,7 @@ type Schema struct {
192 Sensitive bool 199 Sensitive bool
193} 200}
194 201
195// SchemaDiffSuppresFunc is a function which can be used to determine 202// SchemaDiffSuppressFunc is a function which can be used to determine
196// whether a detected diff on a schema element is "valid" or not, and 203// whether a detected diff on a schema element is "valid" or not, and
197// suppress it from the plan if necessary. 204// suppress it from the plan if necessary.
198// 205//
@@ -289,8 +296,7 @@ func (s *Schema) ZeroValue() interface{} {
289 } 296 }
290} 297}
291 298
292func (s *Schema) finalizeDiff( 299func (s *Schema) finalizeDiff(d *terraform.ResourceAttrDiff, customized bool) *terraform.ResourceAttrDiff {
293 d *terraform.ResourceAttrDiff) *terraform.ResourceAttrDiff {
294 if d == nil { 300 if d == nil {
295 return d 301 return d
296 } 302 }
@@ -331,13 +337,20 @@ func (s *Schema) finalizeDiff(
331 } 337 }
332 338
333 if s.Computed { 339 if s.Computed {
334 if d.Old != "" && d.New == "" { 340 // FIXME: This is where the customized bool from getChange finally
335 // This is a computed value with an old value set already, 341 // comes into play. It allows the previously incorrect behavior
336 // just let it go. 342 // of an empty string being used as "unset" when the value is
337 return nil 343 // computed. This should be removed once we can properly
344 // represent an unset/nil value from the configuration.
345 if !customized {
346 if d.Old != "" && d.New == "" {
347 // This is a computed value with an old value set already,
348 // just let it go.
349 return nil
350 }
338 } 351 }
339 352
340 if d.New == "" { 353 if d.New == "" && !d.NewComputed {
341 // Computed attribute without a new value set 354 // Computed attribute without a new value set
342 d.NewComputed = true 355 d.NewComputed = true
343 } 356 }
@@ -354,6 +367,13 @@ func (s *Schema) finalizeDiff(
354// schemaMap is a wrapper that adds nice functions on top of schemas. 367// schemaMap is a wrapper that adds nice functions on top of schemas.
355type schemaMap map[string]*Schema 368type schemaMap map[string]*Schema
356 369
370func (m schemaMap) panicOnError() bool {
371 if os.Getenv(PanicOnErr) != "" {
372 return true
373 }
374 return false
375}
376
357// Data returns a ResourceData for the given schema, state, and diff. 377// Data returns a ResourceData for the given schema, state, and diff.
358// 378//
359// The diff is optional. 379// The diff is optional.
@@ -361,17 +381,30 @@ func (m schemaMap) Data(
361 s *terraform.InstanceState, 381 s *terraform.InstanceState,
362 d *terraform.InstanceDiff) (*ResourceData, error) { 382 d *terraform.InstanceDiff) (*ResourceData, error) {
363 return &ResourceData{ 383 return &ResourceData{
364 schema: m, 384 schema: m,
365 state: s, 385 state: s,
366 diff: d, 386 diff: d,
387 panicOnError: m.panicOnError(),
367 }, nil 388 }, nil
368} 389}
369 390
391// DeepCopy returns a copy of this schemaMap. The copy can be safely modified
392// without affecting the original.
393func (m *schemaMap) DeepCopy() schemaMap {
394 copy, err := copystructure.Config{Lock: true}.Copy(m)
395 if err != nil {
396 panic(err)
397 }
398 return *copy.(*schemaMap)
399}
400
370// Diff returns the diff for a resource given the schema map, 401// Diff returns the diff for a resource given the schema map,
371// state, and configuration. 402// state, and configuration.
372func (m schemaMap) Diff( 403func (m schemaMap) Diff(
373 s *terraform.InstanceState, 404 s *terraform.InstanceState,
374 c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { 405 c *terraform.ResourceConfig,
406 customizeDiff CustomizeDiffFunc,
407 meta interface{}) (*terraform.InstanceDiff, error) {
375 result := new(terraform.InstanceDiff) 408 result := new(terraform.InstanceDiff)
376 result.Attributes = make(map[string]*terraform.ResourceAttrDiff) 409 result.Attributes = make(map[string]*terraform.ResourceAttrDiff)
377 410
@@ -381,9 +414,10 @@ func (m schemaMap) Diff(
381 } 414 }
382 415
383 d := &ResourceData{ 416 d := &ResourceData{
384 schema: m, 417 schema: m,
385 state: s, 418 state: s,
386 config: c, 419 config: c,
420 panicOnError: m.panicOnError(),
387 } 421 }
388 422
389 for k, schema := range m { 423 for k, schema := range m {
@@ -393,6 +427,29 @@ func (m schemaMap) Diff(
393 } 427 }
394 } 428 }
395 429
430 // Remove any nil diffs just to keep things clean
431 for k, v := range result.Attributes {
432 if v == nil {
433 delete(result.Attributes, k)
434 }
435 }
436
437 // If this is a non-destroy diff, call any custom diff logic that has been
438 // defined.
439 if !result.DestroyTainted && customizeDiff != nil {
440 mc := m.DeepCopy()
441 rd := newResourceDiff(mc, c, s, result)
442 if err := customizeDiff(rd, meta); err != nil {
443 return nil, err
444 }
445 for _, k := range rd.UpdatedKeys() {
446 err := m.diff(k, mc[k], result, rd, false)
447 if err != nil {
448 return nil, err
449 }
450 }
451 }
452
396 // If the diff requires a new resource, then we recompute the diff 453 // If the diff requires a new resource, then we recompute the diff
397 // so we have the complete new resource diff, and preserve the 454 // so we have the complete new resource diff, and preserve the
398 // RequiresNew fields where necessary so the user knows exactly what 455 // RequiresNew fields where necessary so the user knows exactly what
@@ -418,6 +475,21 @@ func (m schemaMap) Diff(
418 } 475 }
419 } 476 }
420 477
478 // Re-run customization
479 if !result2.DestroyTainted && customizeDiff != nil {
480 mc := m.DeepCopy()
481 rd := newResourceDiff(mc, c, d.state, result2)
482 if err := customizeDiff(rd, meta); err != nil {
483 return nil, err
484 }
485 for _, k := range rd.UpdatedKeys() {
486 err := m.diff(k, mc[k], result2, rd, false)
487 if err != nil {
488 return nil, err
489 }
490 }
491 }
492
421 // Force all the fields to not force a new since we know what we 493 // Force all the fields to not force a new since we know what we
422 // want to force new. 494 // want to force new.
423 for k, attr := range result2.Attributes { 495 for k, attr := range result2.Attributes {
@@ -456,13 +528,6 @@ func (m schemaMap) Diff(
456 result = result2 528 result = result2
457 } 529 }
458 530
459 // Remove any nil diffs just to keep things clean
460 for k, v := range result.Attributes {
461 if v == nil {
462 delete(result.Attributes, k)
463 }
464 }
465
466 // Go through and detect all of the ComputedWhens now that we've 531 // Go through and detect all of the ComputedWhens now that we've
467 // finished the diff. 532 // finished the diff.
468 // TODO 533 // TODO
@@ -681,11 +746,23 @@ func isValidFieldName(name string) bool {
681 return re.MatchString(name) 746 return re.MatchString(name)
682} 747}
683 748
749// resourceDiffer is an interface that is used by the private diff functions.
750// This helps facilitate diff logic for both ResourceData and ResoureDiff with
751// minimal divergence in code.
752type resourceDiffer interface {
753 diffChange(string) (interface{}, interface{}, bool, bool, bool)
754 Get(string) interface{}
755 GetChange(string) (interface{}, interface{})
756 GetOk(string) (interface{}, bool)
757 HasChange(string) bool
758 Id() string
759}
760
684func (m schemaMap) diff( 761func (m schemaMap) diff(
685 k string, 762 k string,
686 schema *Schema, 763 schema *Schema,
687 diff *terraform.InstanceDiff, 764 diff *terraform.InstanceDiff,
688 d *ResourceData, 765 d resourceDiffer,
689 all bool) error { 766 all bool) error {
690 767
691 unsupressedDiff := new(terraform.InstanceDiff) 768 unsupressedDiff := new(terraform.InstanceDiff)
@@ -706,12 +783,14 @@ func (m schemaMap) diff(
706 } 783 }
707 784
708 for attrK, attrV := range unsupressedDiff.Attributes { 785 for attrK, attrV := range unsupressedDiff.Attributes {
709 if schema.DiffSuppressFunc != nil && 786 switch rd := d.(type) {
710 attrV != nil && 787 case *ResourceData:
711 schema.DiffSuppressFunc(attrK, attrV.Old, attrV.New, d) { 788 if schema.DiffSuppressFunc != nil &&
712 continue 789 attrV != nil &&
790 schema.DiffSuppressFunc(attrK, attrV.Old, attrV.New, rd) {
791 continue
792 }
713 } 793 }
714
715 diff.Attributes[attrK] = attrV 794 diff.Attributes[attrK] = attrV
716 } 795 }
717 796
@@ -722,9 +801,9 @@ func (m schemaMap) diffList(
722 k string, 801 k string,
723 schema *Schema, 802 schema *Schema,
724 diff *terraform.InstanceDiff, 803 diff *terraform.InstanceDiff,
725 d *ResourceData, 804 d resourceDiffer,
726 all bool) error { 805 all bool) error {
727 o, n, _, computedList := d.diffChange(k) 806 o, n, _, computedList, customized := d.diffChange(k)
728 if computedList { 807 if computedList {
729 n = nil 808 n = nil
730 } 809 }
@@ -791,10 +870,13 @@ func (m schemaMap) diffList(
791 oldStr = "" 870 oldStr = ""
792 } 871 }
793 872
794 diff.Attributes[k+".#"] = countSchema.finalizeDiff(&terraform.ResourceAttrDiff{ 873 diff.Attributes[k+".#"] = countSchema.finalizeDiff(
795 Old: oldStr, 874 &terraform.ResourceAttrDiff{
796 New: newStr, 875 Old: oldStr,
797 }) 876 New: newStr,
877 },
878 customized,
879 )
798 } 880 }
799 881
800 // Figure out the maximum 882 // Figure out the maximum
@@ -841,13 +923,13 @@ func (m schemaMap) diffMap(
841 k string, 923 k string,
842 schema *Schema, 924 schema *Schema,
843 diff *terraform.InstanceDiff, 925 diff *terraform.InstanceDiff,
844 d *ResourceData, 926 d resourceDiffer,
845 all bool) error { 927 all bool) error {
846 prefix := k + "." 928 prefix := k + "."
847 929
848 // First get all the values from the state 930 // First get all the values from the state
849 var stateMap, configMap map[string]string 931 var stateMap, configMap map[string]string
850 o, n, _, nComputed := d.diffChange(k) 932 o, n, _, nComputed, customized := d.diffChange(k)
851 if err := mapstructure.WeakDecode(o, &stateMap); err != nil { 933 if err := mapstructure.WeakDecode(o, &stateMap); err != nil {
852 return fmt.Errorf("%s: %s", k, err) 934 return fmt.Errorf("%s: %s", k, err)
853 } 935 }
@@ -899,6 +981,7 @@ func (m schemaMap) diffMap(
899 Old: oldStr, 981 Old: oldStr,
900 New: newStr, 982 New: newStr,
901 }, 983 },
984 customized,
902 ) 985 )
903 } 986 }
904 987
@@ -916,16 +999,22 @@ func (m schemaMap) diffMap(
916 continue 999 continue
917 } 1000 }
918 1001
919 diff.Attributes[prefix+k] = schema.finalizeDiff(&terraform.ResourceAttrDiff{ 1002 diff.Attributes[prefix+k] = schema.finalizeDiff(
920 Old: old, 1003 &terraform.ResourceAttrDiff{
921 New: v, 1004 Old: old,
922 }) 1005 New: v,
1006 },
1007 customized,
1008 )
923 } 1009 }
924 for k, v := range stateMap { 1010 for k, v := range stateMap {
925 diff.Attributes[prefix+k] = schema.finalizeDiff(&terraform.ResourceAttrDiff{ 1011 diff.Attributes[prefix+k] = schema.finalizeDiff(
926 Old: v, 1012 &terraform.ResourceAttrDiff{
927 NewRemoved: true, 1013 Old: v,
928 }) 1014 NewRemoved: true,
1015 },
1016 customized,
1017 )
929 } 1018 }
930 1019
931 return nil 1020 return nil
@@ -935,10 +1024,10 @@ func (m schemaMap) diffSet(
935 k string, 1024 k string,
936 schema *Schema, 1025 schema *Schema,
937 diff *terraform.InstanceDiff, 1026 diff *terraform.InstanceDiff,
938 d *ResourceData, 1027 d resourceDiffer,
939 all bool) error { 1028 all bool) error {
940 1029
941 o, n, _, computedSet := d.diffChange(k) 1030 o, n, _, computedSet, customized := d.diffChange(k)
942 if computedSet { 1031 if computedSet {
943 n = nil 1032 n = nil
944 } 1033 }
@@ -997,20 +1086,26 @@ func (m schemaMap) diffSet(
997 countStr = "" 1086 countStr = ""
998 } 1087 }
999 1088
1000 diff.Attributes[k+".#"] = countSchema.finalizeDiff(&terraform.ResourceAttrDiff{ 1089 diff.Attributes[k+".#"] = countSchema.finalizeDiff(
1001 Old: countStr, 1090 &terraform.ResourceAttrDiff{
1002 NewComputed: true, 1091 Old: countStr,
1003 }) 1092 NewComputed: true,
1093 },
1094 customized,
1095 )
1004 return nil 1096 return nil
1005 } 1097 }
1006 1098
1007 // If the counts are not the same, then record that diff 1099 // If the counts are not the same, then record that diff
1008 changed := oldLen != newLen 1100 changed := oldLen != newLen
1009 if changed || all { 1101 if changed || all {
1010 diff.Attributes[k+".#"] = countSchema.finalizeDiff(&terraform.ResourceAttrDiff{ 1102 diff.Attributes[k+".#"] = countSchema.finalizeDiff(
1011 Old: oldStr, 1103 &terraform.ResourceAttrDiff{
1012 New: newStr, 1104 Old: oldStr,
1013 }) 1105 New: newStr,
1106 },
1107 customized,
1108 )
1014 } 1109 }
1015 1110
1016 // Build the list of codes that will make up our set. This is the 1111 // Build the list of codes that will make up our set. This is the
@@ -1056,11 +1151,11 @@ func (m schemaMap) diffString(
1056 k string, 1151 k string,
1057 schema *Schema, 1152 schema *Schema,
1058 diff *terraform.InstanceDiff, 1153 diff *terraform.InstanceDiff,
1059 d *ResourceData, 1154 d resourceDiffer,
1060 all bool) error { 1155 all bool) error {
1061 var originalN interface{} 1156 var originalN interface{}
1062 var os, ns string 1157 var os, ns string
1063 o, n, _, computed := d.diffChange(k) 1158 o, n, _, computed, customized := d.diffChange(k)
1064 if schema.StateFunc != nil && n != nil { 1159 if schema.StateFunc != nil && n != nil {
1065 originalN = n 1160 originalN = n
1066 n = schema.StateFunc(n) 1161 n = schema.StateFunc(n)
@@ -1090,20 +1185,23 @@ func (m schemaMap) diffString(
1090 } 1185 }
1091 1186
1092 removed := false 1187 removed := false
1093 if o != nil && n == nil { 1188 if o != nil && n == nil && !computed {
1094 removed = true 1189 removed = true
1095 } 1190 }
1096 if removed && schema.Computed { 1191 if removed && schema.Computed {
1097 return nil 1192 return nil
1098 } 1193 }
1099 1194
1100 diff.Attributes[k] = schema.finalizeDiff(&terraform.ResourceAttrDiff{ 1195 diff.Attributes[k] = schema.finalizeDiff(
1101 Old: os, 1196 &terraform.ResourceAttrDiff{
1102 New: ns, 1197 Old: os,
1103 NewExtra: originalN, 1198 New: ns,
1104 NewRemoved: removed, 1199 NewExtra: originalN,
1105 NewComputed: computed, 1200 NewRemoved: removed,
1106 }) 1201 NewComputed: computed,
1202 },
1203 customized,
1204 )
1107 1205
1108 return nil 1206 return nil
1109} 1207}
@@ -1172,9 +1270,9 @@ func (m schemaMap) validateConflictingAttributes(
1172 } 1270 }
1173 1271
1174 for _, conflicting_key := range schema.ConflictsWith { 1272 for _, conflicting_key := range schema.ConflictsWith {
1175 if value, ok := c.Get(conflicting_key); ok { 1273 if _, ok := c.Get(conflicting_key); ok {
1176 return fmt.Errorf( 1274 return fmt.Errorf(
1177 "%q: conflicts with %s (%#v)", k, conflicting_key, value) 1275 "%q: conflicts with %s", k, conflicting_key)
1178 } 1276 }
1179 } 1277 }
1180 1278
@@ -1363,13 +1461,10 @@ func getValueType(k string, schema *Schema) (ValueType, error) {
1363 return vt, nil 1461 return vt, nil
1364 } 1462 }
1365 1463
1464 // If a Schema is provided to a Map, we use the Type of that schema
1465 // as the type for each element in the Map.
1366 if s, ok := schema.Elem.(*Schema); ok { 1466 if s, ok := schema.Elem.(*Schema); ok {
1367 if s.Elem == nil { 1467 return s.Type, nil
1368 return TypeString, nil
1369 }
1370 if vt, ok := s.Elem.(ValueType); ok {
1371 return vt, nil
1372 }
1373 } 1468 }
1374 1469
1375 if _, ok := schema.Elem.(*Resource); ok { 1470 if _, ok := schema.Elem.(*Resource); ok {
@@ -1430,7 +1525,6 @@ func (m schemaMap) validatePrimitive(
1430 raw interface{}, 1525 raw interface{},
1431 schema *Schema, 1526 schema *Schema,
1432 c *terraform.ResourceConfig) ([]string, []error) { 1527 c *terraform.ResourceConfig) ([]string, []error) {
1433
1434 // Catch if the user gave a complex type where a primitive was 1528 // Catch if the user gave a complex type where a primitive was
1435 // expected, so we can return a friendly error message that 1529 // expected, so we can return a friendly error message that
1436 // doesn't contain Go type system terminology. 1530 // doesn't contain Go type system terminology.