aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/helper/schema/resource.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/schema/resource.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/resource.go98
1 files changed, 82 insertions, 16 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/resource.go b/vendor/github.com/hashicorp/terraform/helper/schema/resource.go
index ddba109..d3be2d6 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/resource.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/resource.go
@@ -85,6 +85,37 @@ type Resource struct {
85 Delete DeleteFunc 85 Delete DeleteFunc
86 Exists ExistsFunc 86 Exists ExistsFunc
87 87
88 // CustomizeDiff is a custom function for working with the diff that
89 // Terraform has created for this resource - it can be used to customize the
90 // diff that has been created, diff values not controlled by configuration,
91 // or even veto the diff altogether and abort the plan. It is passed a
92 // *ResourceDiff, a structure similar to ResourceData but lacking most write
93 // functions like Set, while introducing new functions that work with the
94 // diff such as SetNew, SetNewComputed, and ForceNew.
95 //
96 // The phases Terraform runs this in, and the state available via functions
97 // like Get and GetChange, are as follows:
98 //
99 // * New resource: One run with no state
100 // * Existing resource: One run with state
101 // * Existing resource, forced new: One run with state (before ForceNew),
102 // then one run without state (as if new resource)
103 // * Tainted resource: No runs (custom diff logic is skipped)
104 // * Destroy: No runs (standard diff logic is skipped on destroy diffs)
105 //
106 // This function needs to be resilient to support all scenarios.
107 //
108 // If this function needs to access external API resources, remember to flag
109 // the RequiresRefresh attribute mentioned below to ensure that
110 // -refresh=false is blocked when running plan or apply, as this means that
111 // this resource requires refresh-like behaviour to work effectively.
112 //
113 // For the most part, only computed fields can be customized by this
114 // function.
115 //
116 // This function is only allowed on regular resources (not data sources).
117 CustomizeDiff CustomizeDiffFunc
118
88 // Importer is the ResourceImporter implementation for this resource. 119 // Importer is the ResourceImporter implementation for this resource.
89 // If this is nil, then this resource does not support importing. If 120 // If this is nil, then this resource does not support importing. If
90 // this is non-nil, then it supports importing and ResourceImporter 121 // this is non-nil, then it supports importing and ResourceImporter
@@ -93,9 +124,7 @@ type Resource struct {
93 Importer *ResourceImporter 124 Importer *ResourceImporter
94 125
95 // If non-empty, this string is emitted as a warning during Validate. 126 // If non-empty, this string is emitted as a warning during Validate.
96 // This is a private interface for now, for use by DataSourceResourceShim, 127 DeprecationMessage string
97 // and not for general use. (But maybe later...)
98 deprecationMessage string
99 128
100 // Timeouts allow users to specify specific time durations in which an 129 // Timeouts allow users to specify specific time durations in which an
101 // operation should time out, to allow them to extend an action to suit their 130 // operation should time out, to allow them to extend an action to suit their
@@ -126,6 +155,9 @@ type ExistsFunc func(*ResourceData, interface{}) (bool, error)
126type StateMigrateFunc func( 155type StateMigrateFunc func(
127 int, *terraform.InstanceState, interface{}) (*terraform.InstanceState, error) 156 int, *terraform.InstanceState, interface{}) (*terraform.InstanceState, error)
128 157
158// See Resource documentation.
159type CustomizeDiffFunc func(*ResourceDiff, interface{}) error
160
129// Apply creates, updates, and/or deletes a resource. 161// Apply creates, updates, and/or deletes a resource.
130func (r *Resource) Apply( 162func (r *Resource) Apply(
131 s *terraform.InstanceState, 163 s *terraform.InstanceState,
@@ -202,11 +234,11 @@ func (r *Resource) Apply(
202 return r.recordCurrentSchemaVersion(data.State()), err 234 return r.recordCurrentSchemaVersion(data.State()), err
203} 235}
204 236
205// Diff returns a diff of this resource and is API compatible with the 237// Diff returns a diff of this resource.
206// ResourceProvider interface.
207func (r *Resource) Diff( 238func (r *Resource) Diff(
208 s *terraform.InstanceState, 239 s *terraform.InstanceState,
209 c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { 240 c *terraform.ResourceConfig,
241 meta interface{}) (*terraform.InstanceDiff, error) {
210 242
211 t := &ResourceTimeout{} 243 t := &ResourceTimeout{}
212 err := t.ConfigDecode(r, c) 244 err := t.ConfigDecode(r, c)
@@ -215,7 +247,7 @@ func (r *Resource) Diff(
215 return nil, fmt.Errorf("[ERR] Error decoding timeout: %s", err) 247 return nil, fmt.Errorf("[ERR] Error decoding timeout: %s", err)
216 } 248 }
217 249
218 instanceDiff, err := schemaMap(r.Schema).Diff(s, c) 250 instanceDiff, err := schemaMap(r.Schema).Diff(s, c, r.CustomizeDiff, meta)
219 if err != nil { 251 if err != nil {
220 return instanceDiff, err 252 return instanceDiff, err
221 } 253 }
@@ -235,8 +267,8 @@ func (r *Resource) Diff(
235func (r *Resource) Validate(c *terraform.ResourceConfig) ([]string, []error) { 267func (r *Resource) Validate(c *terraform.ResourceConfig) ([]string, []error) {
236 warns, errs := schemaMap(r.Schema).Validate(c) 268 warns, errs := schemaMap(r.Schema).Validate(c)
237 269
238 if r.deprecationMessage != "" { 270 if r.DeprecationMessage != "" {
239 warns = append(warns, r.deprecationMessage) 271 warns = append(warns, r.DeprecationMessage)
240 } 272 }
241 273
242 return warns, errs 274 return warns, errs
@@ -248,7 +280,6 @@ func (r *Resource) ReadDataApply(
248 d *terraform.InstanceDiff, 280 d *terraform.InstanceDiff,
249 meta interface{}, 281 meta interface{},
250) (*terraform.InstanceState, error) { 282) (*terraform.InstanceState, error) {
251
252 // Data sources are always built completely from scratch 283 // Data sources are always built completely from scratch
253 // on each read, so the source state is always nil. 284 // on each read, so the source state is always nil.
254 data, err := schemaMap(r.Schema).Data(nil, d) 285 data, err := schemaMap(r.Schema).Data(nil, d)
@@ -346,6 +377,11 @@ func (r *Resource) InternalValidate(topSchemaMap schemaMap, writable bool) error
346 if r.Create != nil || r.Update != nil || r.Delete != nil { 377 if r.Create != nil || r.Update != nil || r.Delete != nil {
347 return fmt.Errorf("must not implement Create, Update or Delete") 378 return fmt.Errorf("must not implement Create, Update or Delete")
348 } 379 }
380
381 // CustomizeDiff cannot be defined for read-only resources
382 if r.CustomizeDiff != nil {
383 return fmt.Errorf("cannot implement CustomizeDiff")
384 }
349 } 385 }
350 386
351 tsm := topSchemaMap 387 tsm := topSchemaMap
@@ -393,19 +429,43 @@ func (r *Resource) InternalValidate(topSchemaMap schemaMap, writable bool) error
393 return err 429 return err
394 } 430 }
395 } 431 }
432
433 for k, f := range tsm {
434 if isReservedResourceFieldName(k, f) {
435 return fmt.Errorf("%s is a reserved field name", k)
436 }
437 }
396 } 438 }
397 439
398 // Resource-specific checks 440 // Data source
399 for k, _ := range tsm { 441 if r.isTopLevel() && !writable {
400 if isReservedResourceFieldName(k) { 442 tsm = schemaMap(r.Schema)
401 return fmt.Errorf("%s is a reserved field name for a resource", k) 443 for k, _ := range tsm {
444 if isReservedDataSourceFieldName(k) {
445 return fmt.Errorf("%s is a reserved field name", k)
446 }
402 } 447 }
403 } 448 }
404 449
405 return schemaMap(r.Schema).InternalValidate(tsm) 450 return schemaMap(r.Schema).InternalValidate(tsm)
406} 451}
407 452
408func isReservedResourceFieldName(name string) bool { 453func isReservedDataSourceFieldName(name string) bool {
454 for _, reservedName := range config.ReservedDataSourceFields {
455 if name == reservedName {
456 return true
457 }
458 }
459 return false
460}
461
462func isReservedResourceFieldName(name string, s *Schema) bool {
463 // Allow phasing out "id"
464 // See https://github.com/terraform-providers/terraform-provider-aws/pull/1626#issuecomment-328881415
465 if name == "id" && (s.Deprecated != "" || s.Removed != "") {
466 return false
467 }
468
409 for _, reservedName := range config.ReservedResourceFields { 469 for _, reservedName := range config.ReservedResourceFields {
410 if name == reservedName { 470 if name == reservedName {
411 return true 471 return true
@@ -430,6 +490,12 @@ func (r *Resource) Data(s *terraform.InstanceState) *ResourceData {
430 panic(err) 490 panic(err)
431 } 491 }
432 492
493 // load the Resource timeouts
494 result.timeouts = r.Timeouts
495 if result.timeouts == nil {
496 result.timeouts = &ResourceTimeout{}
497 }
498
433 // Set the schema version to latest by default 499 // Set the schema version to latest by default
434 result.meta = map[string]interface{}{ 500 result.meta = map[string]interface{}{
435 "schema_version": strconv.Itoa(r.SchemaVersion), 501 "schema_version": strconv.Itoa(r.SchemaVersion),
@@ -450,7 +516,7 @@ func (r *Resource) TestResourceData() *ResourceData {
450// Returns true if the resource is "top level" i.e. not a sub-resource. 516// Returns true if the resource is "top level" i.e. not a sub-resource.
451func (r *Resource) isTopLevel() bool { 517func (r *Resource) isTopLevel() bool {
452 // TODO: This is a heuristic; replace with a definitive attribute? 518 // TODO: This is a heuristic; replace with a definitive attribute?
453 return r.Create != nil 519 return (r.Create != nil || r.Read != nil)
454} 520}
455 521
456// Determines if a given InstanceState needs to be migrated by checking the 522// Determines if a given InstanceState needs to be migrated by checking the