helper/schema: final state for lists/objects works
This commit is contained in:
parent
06d30a559a
commit
c3f1f49640
|
@ -44,6 +44,14 @@ func (d *ResourceData) Set(key string, value interface{}) error {
|
|||
return d.setObject("", parts, d.schema, value)
|
||||
}
|
||||
|
||||
// State returns the new ResourceState after the diff and any Set
|
||||
// calls.
|
||||
func (d *ResourceData) State() *terraform.ResourceState {
|
||||
var result terraform.ResourceState
|
||||
result.Attributes = d.stateObject("", d.schema)
|
||||
return &result
|
||||
}
|
||||
|
||||
func (d *ResourceData) get(
|
||||
k string,
|
||||
parts []string,
|
||||
|
@ -316,3 +324,85 @@ func (d *ResourceData) setPrimitive(
|
|||
d.setMap[k] = set
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ResourceData) stateList(
|
||||
prefix string,
|
||||
schema *Schema) map[string]string {
|
||||
countRaw := d.get(prefix, []string{"#"}, schema)
|
||||
if countRaw == nil {
|
||||
return nil
|
||||
}
|
||||
count := countRaw.(int)
|
||||
|
||||
result := make(map[string]string)
|
||||
result[prefix + ".#"] = strconv.FormatInt(int64(count), 10)
|
||||
for i := 0; i < count; i++ {
|
||||
key := fmt.Sprintf("%s.%d", prefix, i)
|
||||
|
||||
var m map[string]string
|
||||
switch t := schema.Elem.(type) {
|
||||
case *Resource:
|
||||
m = d.stateObject(key, t.Schema)
|
||||
case *Schema:
|
||||
m = d.stateSingle(key, t)
|
||||
}
|
||||
|
||||
for k, v := range m {
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (d *ResourceData) stateObject(
|
||||
prefix string,
|
||||
schema map[string]*Schema) map[string]string {
|
||||
result := make(map[string]string)
|
||||
for k, v := range schema {
|
||||
key := k
|
||||
if prefix != "" {
|
||||
key = prefix + "." + key
|
||||
}
|
||||
|
||||
for k1, v1 := range d.stateSingle(key, v) {
|
||||
result[k1] = v1
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (d *ResourceData) statePrimitive(
|
||||
prefix string,
|
||||
schema *Schema) map[string]string {
|
||||
v := d.getPrimitive(prefix, nil, schema)
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var vs string
|
||||
switch schema.Type {
|
||||
case TypeString:
|
||||
vs = v.(string)
|
||||
case TypeInt:
|
||||
vs = strconv.FormatInt(int64(v.(int)), 10)
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown type: %s", schema.Type))
|
||||
}
|
||||
|
||||
return map[string]string{
|
||||
prefix: vs,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ResourceData) stateSingle(
|
||||
prefix string,
|
||||
schema *Schema) map[string]string {
|
||||
switch schema.Type {
|
||||
case TypeList:
|
||||
return d.stateList(prefix, schema)
|
||||
default:
|
||||
return d.statePrimitive(prefix, schema)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -615,3 +615,184 @@ func TestResourceDataSet(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceDataState(t *testing.T) {
|
||||
cases := []struct {
|
||||
Schema map[string]*Schema
|
||||
State *terraform.ResourceState
|
||||
Diff *terraform.ResourceDiff
|
||||
Set map[string]interface{}
|
||||
Result *terraform.ResourceState
|
||||
}{
|
||||
// Basic primitive in diff
|
||||
{
|
||||
Schema: map[string]*Schema{
|
||||
"availability_zone": &Schema{
|
||||
Type: TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
|
||||
State: nil,
|
||||
|
||||
Diff: &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"availability_zone": &terraform.ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "foo",
|
||||
RequiresNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Result: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"availability_zone": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Basic primitive set override
|
||||
{
|
||||
Schema: map[string]*Schema{
|
||||
"availability_zone": &Schema{
|
||||
Type: TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
|
||||
State: nil,
|
||||
|
||||
Diff: &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"availability_zone": &terraform.ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "foo",
|
||||
RequiresNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Set: map[string]interface{}{
|
||||
"availability_zone": "bar",
|
||||
},
|
||||
|
||||
Result: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"availability_zone": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// List
|
||||
{
|
||||
Schema: map[string]*Schema{
|
||||
"ports": &Schema{
|
||||
Type: TypeList,
|
||||
Required: true,
|
||||
Elem: &Schema{Type: TypeInt},
|
||||
},
|
||||
},
|
||||
|
||||
State: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"ports.#": "1",
|
||||
"ports.0": "80",
|
||||
},
|
||||
},
|
||||
|
||||
Diff: &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"ports.#": &terraform.ResourceAttrDiff{
|
||||
Old: "1",
|
||||
New: "2",
|
||||
},
|
||||
"ports.1": &terraform.ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "100",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Result: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"ports.#": "2",
|
||||
"ports.0": "80",
|
||||
"ports.1": "100",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// List of resources
|
||||
{
|
||||
Schema: map[string]*Schema{
|
||||
"ingress": &Schema{
|
||||
Type: TypeList,
|
||||
Required: true,
|
||||
Elem: &Resource{
|
||||
Schema: map[string]*Schema{
|
||||
"from": &Schema{
|
||||
Type: TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
State: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"ingress.#": "1",
|
||||
"ingress.0.from": "80",
|
||||
},
|
||||
},
|
||||
|
||||
Diff: &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"ingress.#": &terraform.ResourceAttrDiff{
|
||||
Old: "1",
|
||||
New: "2",
|
||||
},
|
||||
"ingress.0.from": &terraform.ResourceAttrDiff{
|
||||
Old: "80",
|
||||
New: "150",
|
||||
},
|
||||
"ingress.1.from": &terraform.ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "100",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Result: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"ingress.#": "2",
|
||||
"ingress.0.from": "150",
|
||||
"ingress.1.from": "100",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
for k, v := range tc.Set {
|
||||
if err := d.Set(k, v); err != nil {
|
||||
t.Fatalf("%d err: %s", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
actual := d.State()
|
||||
if !reflect.DeepEqual(actual, tc.Result) {
|
||||
t.Fatalf("Bad: %d\n\n%#v", i, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue