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.
This commit is contained in:
Paul Hinze 2015-04-03 09:57:30 -05:00
parent 3751533c3a
commit 66dbf91ffd
3 changed files with 25 additions and 0 deletions

View File

@ -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,
},

View File

@ -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))

View File

@ -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) {