diff --git a/helper/schema/field_reader.go b/helper/schema/field_reader.go index 6636d3058..2046581b7 100644 --- a/helper/schema/field_reader.go +++ b/helper/schema/field_reader.go @@ -82,6 +82,8 @@ func addrToSchema(addr []string, schemaMap map[string]*Schema) []*Schema { fallthrough case TypeInt: fallthrough + case TypeFloat: + fallthrough case TypeString: if len(addr) > 0 { return nil diff --git a/helper/schema/field_reader_diff.go b/helper/schema/field_reader_diff.go index f13e3ece3..aaacd5d68 100644 --- a/helper/schema/field_reader_diff.go +++ b/helper/schema/field_reader_diff.go @@ -41,10 +41,10 @@ func (r *DiffFieldReader) ReadField(address []string) (FieldReadResult, error) { switch schema.Type { case TypeBool: fallthrough - case TypeFloat: - fallthrough case TypeInt: fallthrough + case TypeFloat: + fallthrough case TypeString: return r.readPrimitive(address, schema) case TypeList: diff --git a/helper/schema/field_reader_map.go b/helper/schema/field_reader_map.go index 569cf9d91..b2ed73605 100644 --- a/helper/schema/field_reader_map.go +++ b/helper/schema/field_reader_map.go @@ -23,10 +23,10 @@ func (r *MapFieldReader) ReadField(address []string) (FieldReadResult, error) { switch schema.Type { case TypeBool: fallthrough - case TypeFloat: - fallthrough case TypeInt: fallthrough + case TypeFloat: + fallthrough case TypeString: return r.readPrimitive(address, schema) case TypeList: diff --git a/helper/schema/field_writer_map.go b/helper/schema/field_writer_map.go index 1da3d2578..b9064709f 100644 --- a/helper/schema/field_writer_map.go +++ b/helper/schema/field_writer_map.go @@ -78,6 +78,8 @@ func (w *MapFieldWriter) set(addr []string, value interface{}) error { fallthrough case TypeInt: fallthrough + case TypeFloat: + fallthrough case TypeString: return w.setPrimitive(addr, value, schema) case TypeList: @@ -235,8 +237,13 @@ func (w *MapFieldWriter) setPrimitive( if err := mapstructure.Decode(v, &n); err != nil { return fmt.Errorf("%s: %s", k, err) } - set = strconv.FormatInt(int64(n), 10) + case TypeFloat: + var n float64 + if err := mapstructure.Decode(v, &n); err != nil { + return fmt.Errorf("%s: %s", k, err) + } + set = strconv.FormatFloat(float64(n), 'G', -1, 64) default: return fmt.Errorf("Unknown type: %#v", schema.Type) } diff --git a/helper/schema/resource_data_test.go b/helper/schema/resource_data_test.go index 618973cde..f7b211810 100644 --- a/helper/schema/resource_data_test.go +++ b/helper/schema/resource_data_test.go @@ -1,6 +1,7 @@ package schema import ( + "math" "reflect" "testing" @@ -615,6 +616,81 @@ func TestResourceDataGet(t *testing.T) { Value: []interface{}{}, }, + + // #20 Float zero + { + Schema: map[string]*Schema{ + "ratio": &Schema{ + Type: TypeFloat, + Optional: true, + Computed: true, + }, + }, + + State: nil, + + Diff: nil, + + Key: "ratio", + + Value: 0.0, + }, + + // #21 Float given + { + Schema: map[string]*Schema{ + "ratio": &Schema{ + Type: TypeFloat, + Optional: true, + Computed: true, + }, + }, + + State: &terraform.InstanceState{ + Attributes: map[string]string{ + "ratio": "0.5", + }, + }, + + + Diff: nil, + + Key: "ratio", + + Value: 0.5, + }, + + // #22 Float diff + { + Schema: map[string]*Schema{ + "ratio": &Schema{ + Type: TypeFloat, + Optional: true, + Computed: true, + }, + }, + + State: &terraform.InstanceState{ + Attributes: map[string]string{ + "ratio": "-0.5", + }, + }, + + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "ratio": &terraform.ResourceAttrDiff{ + Old: "-0.5", + New: "33.0", + }, + }, + }, + + + Key: "ratio", + + Value: 33.0, + }, } for i, tc := range cases { @@ -1412,6 +1488,52 @@ func TestResourceDataSet(t *testing.T) { return v }, }, + + // #12: List of floats, set list + { + Schema: map[string]*Schema{ + "ratios": &Schema{ + Type: TypeList, + Computed: true, + Elem: &Schema{Type: TypeFloat}, + }, + }, + + State: nil, + + Diff: nil, + + Key: "ratios", + Value: []float64{1.0, 2.2, 5.5}, + + GetKey: "ratios", + GetValue: []interface{}{1.0, 2.2, 5.5}, + }, + + // #12: Set of floats, set list + { + Schema: map[string]*Schema{ + "ratios": &Schema{ + Type: TypeSet, + Computed: true, + Elem: &Schema{Type: TypeFloat}, + Set: func(a interface{}) int { + return int(math.Float64bits(a.(float64))) + }, + }, + }, + + State: nil, + + Diff: nil, + + Key: "ratios", + Value: []float64{1.0, 2.2, 5.5}, + + GetKey: "ratios", + GetValue: []interface{}{1.0, 2.2, 5.5}, + }, + } for i, tc := range cases { diff --git a/helper/schema/schema.go b/helper/schema/schema.go index e9441b4e0..f16df2d72 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -78,6 +78,7 @@ type Schema struct { // // TypeBool - bool // TypeInt - int + // TypeFloat - float64 // TypeString - string // TypeList - []interface{} // TypeMap - map[string]interface{} @@ -406,6 +407,8 @@ func (m schemaMap) Input( fallthrough case TypeInt: fallthrough + case TypeFloat: + fallthrough case TypeString: value, err = m.inputString(input, k, v) default: @@ -1084,6 +1087,12 @@ func (m schemaMap) validatePrimitive( if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } + case TypeFloat: + // Verify that we can parse this as an int + var n float64 + if err := mapstructure.WeakDecode(raw, &n); err != nil { + return nil, []error{err} + } case TypeString: // Verify that we can parse this as a string var n string