helper/schema: basic set
This commit is contained in:
parent
bf6ad07505
commit
2d74a3cadd
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResourceData is used to query and set the attributes of a resource.
|
// ResourceData is used to query and set the attributes of a resource.
|
||||||
|
@ -13,6 +14,7 @@ type ResourceData struct {
|
||||||
schema map[string]*Schema
|
schema map[string]*Schema
|
||||||
state *terraform.ResourceState
|
state *terraform.ResourceState
|
||||||
diff *terraform.ResourceDiff
|
diff *terraform.ResourceDiff
|
||||||
|
set map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the data for the given key, or nil if the key doesn't exist.
|
// Get returns the data for the given key, or nil if the key doesn't exist.
|
||||||
|
@ -29,6 +31,19 @@ func (d *ResourceData) Get(key string) interface{} {
|
||||||
return d.getObject("", parts, d.schema)
|
return d.getObject("", parts, d.schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set sets the value for the given key.
|
||||||
|
//
|
||||||
|
// If the key is invalid or the value is not a correct type, an error
|
||||||
|
// will be returned.
|
||||||
|
func (d *ResourceData) Set(key string, value interface{}) error {
|
||||||
|
if d.set == nil {
|
||||||
|
d.set = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(key, ".")
|
||||||
|
return d.setObject("", parts, d.schema, value)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *ResourceData) get(
|
func (d *ResourceData) get(
|
||||||
k string,
|
k string,
|
||||||
parts []string,
|
parts []string,
|
||||||
|
@ -85,7 +100,12 @@ func (d *ResourceData) getList(
|
||||||
// Special case if we're accessing the count of the list
|
// Special case if we're accessing the count of the list
|
||||||
if idx == "#" {
|
if idx == "#" {
|
||||||
schema := &Schema{Type: TypeInt}
|
schema := &Schema{Type: TypeInt}
|
||||||
return d.get(k+".#", parts, schema)
|
result := d.get(k+".#", parts, schema)
|
||||||
|
if result == nil {
|
||||||
|
result = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
key := fmt.Sprintf("%s.%s", k, idx)
|
key := fmt.Sprintf("%s.%s", k, idx)
|
||||||
|
@ -112,17 +132,30 @@ func (d *ResourceData) getPrimitive(
|
||||||
parts []string,
|
parts []string,
|
||||||
schema *Schema) interface{} {
|
schema *Schema) interface{} {
|
||||||
var result string
|
var result string
|
||||||
|
var resultSet bool
|
||||||
if d.state != nil {
|
if d.state != nil {
|
||||||
result = d.state.Attributes[k]
|
result, resultSet = d.state.Attributes[k]
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.diff != nil {
|
if d.diff != nil {
|
||||||
attrD, ok := d.diff.Attributes[k]
|
attrD, ok := d.diff.Attributes[k]
|
||||||
if ok {
|
if ok {
|
||||||
result = attrD.New
|
result = attrD.New
|
||||||
|
resultSet = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.set != nil {
|
||||||
|
if v, ok := d.set[k]; ok {
|
||||||
|
result = v
|
||||||
|
resultSet = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !resultSet {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
switch schema.Type {
|
switch schema.Type {
|
||||||
case TypeString:
|
case TypeString:
|
||||||
// Use the value as-is. We just put this case here to be explicit.
|
// Use the value as-is. We just put this case here to be explicit.
|
||||||
|
@ -142,3 +175,55 @@ func (d *ResourceData) getPrimitive(
|
||||||
panic(fmt.Sprintf("Unknown type: %s", schema.Type))
|
panic(fmt.Sprintf("Unknown type: %s", schema.Type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *ResourceData) setObject(
|
||||||
|
k string,
|
||||||
|
parts []string,
|
||||||
|
schema map[string]*Schema,
|
||||||
|
value interface{}) error {
|
||||||
|
if len(parts) > 0 {
|
||||||
|
// We're setting a specific key in an object
|
||||||
|
key := parts[0]
|
||||||
|
parts = parts[1:]
|
||||||
|
|
||||||
|
s, ok := schema[key]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("%s (internal): unknown key to set: %s", k, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if k != "" {
|
||||||
|
// If we're not at the root, then we need to append
|
||||||
|
// the key to get the full key path.
|
||||||
|
key = fmt.Sprintf("%s.%s", k, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.setPrimitive(key, s, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("can't set full object yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *ResourceData) setPrimitive(
|
||||||
|
k string,
|
||||||
|
schema *Schema,
|
||||||
|
v interface{}) error {
|
||||||
|
var set string
|
||||||
|
switch schema.Type {
|
||||||
|
case TypeString:
|
||||||
|
if err := mapstructure.Decode(v, &set); err != nil {
|
||||||
|
return fmt.Errorf("%s: %s", k, err)
|
||||||
|
}
|
||||||
|
case TypeInt:
|
||||||
|
var n int
|
||||||
|
if err := mapstructure.Decode(v, &n); err != nil {
|
||||||
|
return fmt.Errorf("%s: %s", k, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
set = strconv.FormatInt(int64(n), 10)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown type: %s", schema.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.set[k] = set
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -314,3 +314,100 @@ func TestResourceDataGet(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResourceDataSet(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Schema map[string]*Schema
|
||||||
|
State *terraform.ResourceState
|
||||||
|
Diff *terraform.ResourceDiff
|
||||||
|
Key string
|
||||||
|
Value interface{}
|
||||||
|
Err bool
|
||||||
|
GetKey string
|
||||||
|
GetValue interface{}
|
||||||
|
}{
|
||||||
|
// Basic good
|
||||||
|
{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"availability_zone": &Schema{
|
||||||
|
Type: TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
State: nil,
|
||||||
|
|
||||||
|
Diff: nil,
|
||||||
|
|
||||||
|
Key: "availability_zone",
|
||||||
|
Value: "foo",
|
||||||
|
|
||||||
|
GetKey: "availability_zone",
|
||||||
|
GetValue: "foo",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Basic int
|
||||||
|
{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"port": &Schema{
|
||||||
|
Type: TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
State: nil,
|
||||||
|
|
||||||
|
Diff: nil,
|
||||||
|
|
||||||
|
Key: "port",
|
||||||
|
Value: 80,
|
||||||
|
|
||||||
|
GetKey: "port",
|
||||||
|
GetValue: 80,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Invalid type
|
||||||
|
{
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"availability_zone": &Schema{
|
||||||
|
Type: TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
State: nil,
|
||||||
|
|
||||||
|
Diff: nil,
|
||||||
|
|
||||||
|
Key: "availability_zone",
|
||||||
|
Value: 80,
|
||||||
|
Err: true,
|
||||||
|
|
||||||
|
GetKey: "availability_zone",
|
||||||
|
GetValue: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range cases {
|
||||||
|
d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Set(tc.Key, tc.Value)
|
||||||
|
if (err != nil) != tc.Err {
|
||||||
|
t.Fatalf("%d err: %s", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := d.Get(tc.GetKey)
|
||||||
|
if !reflect.DeepEqual(v, tc.GetValue) {
|
||||||
|
t.Fatalf("Get Bad: %d\n\n%#v", i, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue