From 66dbf91ffd37948c05c36a227c35e869c2cc2897 Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Fri, 3 Apr 2015 09:57:30 -0500 Subject: [PATCH] helper/schema: ensure ForceNew set when Update is not If a given resource does not define an `Update` function, then all of its attributes must be specified as `ForceNew`, lest Applys fail with "doesn't support update" like #1367. This is something we can detect automatically, so this adds a check for it when we validate provider implementations. --- .../aws/resource_aws_launch_configuration.go | 2 ++ .../google/resource_compute_route.go | 1 + helper/schema/resource.go | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/builtin/providers/aws/resource_aws_launch_configuration.go b/builtin/providers/aws/resource_aws_launch_configuration.go index 854c0feb9..a0a86a66f 100644 --- a/builtin/providers/aws/resource_aws_launch_configuration.go +++ b/builtin/providers/aws/resource_aws_launch_configuration.go @@ -84,6 +84,7 @@ func resourceAwsLaunchConfiguration() *schema.Resource { "associate_public_ip_address": &schema.Schema{ Type: schema.TypeBool, Optional: true, + ForceNew: true, Default: false, }, @@ -96,6 +97,7 @@ func resourceAwsLaunchConfiguration() *schema.Resource { "ebs_optimized": &schema.Schema{ Type: schema.TypeBool, Optional: true, + ForceNew: true, Default: false, }, diff --git a/builtin/providers/google/resource_compute_route.go b/builtin/providers/google/resource_compute_route.go index aec9e8d3d..1f52a2807 100644 --- a/builtin/providers/google/resource_compute_route.go +++ b/builtin/providers/google/resource_compute_route.go @@ -75,6 +75,7 @@ func resourceComputeRoute() *schema.Resource { "tags": &schema.Schema{ Type: schema.TypeSet, Optional: true, + ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: func(v interface{}) int { return hashcode.String(v.(string)) diff --git a/helper/schema/resource.go b/helper/schema/resource.go index 797d021ab..0c640e697 100644 --- a/helper/schema/resource.go +++ b/helper/schema/resource.go @@ -225,9 +225,31 @@ func (r *Resource) InternalValidate() error { return errors.New("resource is nil") } + if r.isTopLevel() { + // All non-Computed attributes must be ForceNew if Update is not defined + if r.Update == nil { + nonForceNewAttrs := make([]string, 0) + for k, v := range r.Schema { + if !v.ForceNew && !v.Computed { + nonForceNewAttrs = append(nonForceNewAttrs, k) + } + } + if len(nonForceNewAttrs) > 0 { + return fmt.Errorf( + "No Update defined, must set ForceNew on: %#v", nonForceNewAttrs) + } + } + } + return schemaMap(r.Schema).InternalValidate() } +// Returns true if the resource is "top level" i.e. not a sub-resource. +func (r *Resource) isTopLevel() bool { + // TODO: This is a heuristic; replace with a definitive attribute? + return r.Create != nil +} + // Determines if a given InstanceState needs to be migrated by checking the // stored version number with the current SchemaVersion func (r *Resource) checkSchemaVersion(is *terraform.InstanceState) (bool, int) {