helper/schema: couple more tests around Computed (+ fix)

This commit is contained in:
Mitchell Hashimoto 2014-08-16 09:49:22 -07:00
parent 3a46d21527
commit 7bc0be4b81
4 changed files with 116 additions and 6 deletions

View File

@ -66,6 +66,10 @@ func (r *Resource) InternalValidate() error {
return fmt.Errorf("%s: Cannot be both Required and Computed", k)
}
if len(v.ComputedWhen) > 0 && !v.Computed {
return fmt.Errorf("%s: ComputedWhen can only be set with Computed", k)
}
if v.Type == TypeList {
if v.Elem == nil {
return fmt.Errorf("%s: Elem must be set for lists", k)

View File

@ -94,6 +94,20 @@ func TestResourceInternalValidate(t *testing.T) {
},
true,
},
// Required but computed
{
&Resource{
Schema: map[string]*Schema{
"foo": &Schema{
Type: TypeInt,
Required: true,
ComputedWhen: []string{"foo"},
},
},
},
true,
},
}
for i, tc := range cases {

View File

@ -30,9 +30,13 @@ type Schema struct {
Optional bool
Required bool
// The fields below relate to diffs: if Computed is true, then the
// result of this value is computed (unless specified by config).
// If ForceNew is true
// The fields below relate to diffs.
//
// If Computed is true, then the result of this value is computed
// (unless specified by config) on creation.
//
// If ForceNew is true, then a change in this resource necessitates
// the creation of a new resource.
Computed bool
ForceNew bool
@ -43,6 +47,11 @@ type Schema struct {
// the element type is just a simple value. If it is *Resource, the
// element type is a complex structure, potentially with its own lifecycle.
Elem interface{}
// ComputedWhen is a set of queries on the configuration. Whenever any
// of these things is changed, it will require a recompute (this requires
// that Computed is set to true).
ComputedWhen []string
}
func (s *Schema) finalizeDiff(
@ -51,9 +60,17 @@ func (s *Schema) finalizeDiff(
return d
}
if s.Computed && d.New == "" {
// Computed attribute without a new value set
d.NewComputed = true
if s.Computed {
if d.Old != "" && d.New == "" {
// This is a computed value with an old value set already,
// just let it go.
return nil
}
if d.New == "" {
// Computed attribute without a new value set
d.NewComputed = true
}
}
if s.ForceNew {
@ -95,6 +112,12 @@ func (m schemaMap) Diff(
}
}
for k, v := range result.Attributes {
if v == nil {
delete(result.Attributes, k)
}
}
if result.Empty() {
// If we don't have any diff elements, just return nil
return nil, nil

View File

@ -436,6 +436,75 @@ func TestSchemaMap_Diff(t *testing.T) {
Err: true,
},
/*
* ComputedWhen
*/
{
Schema: map[string]*Schema{
"availability_zone": &Schema{
Type: TypeString,
Computed: true,
ComputedWhen: []string{"port"},
},
"port": &Schema{
Type: TypeInt,
Optional: true,
},
},
State: &terraform.ResourceState{
Attributes: map[string]string{
"availability_zone": "foo",
"port": "80",
},
},
Config: map[string]interface{}{
"port": 80,
},
Diff: nil,
Err: false,
},
{
Schema: map[string]*Schema{
"availability_zone": &Schema{
Type: TypeString,
Computed: true,
ComputedWhen: []string{"port"},
},
"port": &Schema{
Type: TypeInt,
Optional: true,
},
},
State: &terraform.ResourceState{
Attributes: map[string]string{
"port": "80",
},
},
Config: map[string]interface{}{
"port": 80,
},
Diff: &terraform.ResourceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"availability_zone": &terraform.ResourceAttrDiff{
NewComputed: true,
},
},
},
Err: false,
},
}
for i, tc := range cases {