Skip to content

Commit

Permalink
tftypes: Fixed elements of Tuple and Map and attributes of `Objec…
Browse files Browse the repository at this point in the history
…t` having `DynamicPseudoType` as their type when unmarshaling JSON values from Terraform.
  • Loading branch information
bflad committed Aug 9, 2021
1 parent d87b2cd commit 7943864
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
8 changes: 8 additions & 0 deletions .changelog/94.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ tftypes: The `Is()` method on types implementing the `Type` interface now only p
```release-note:enhancement
tftypes: All types implementing the `Type` interface now provide an `Equal()` method for deep type checking and `UsableAs()` method for type conformance checking.
```

```release-note:bug
tftypes: Ensure `NewValue()` panics on `DynamicPseudoType` and known values.
```

```release-note:bug
tftypes: Fixed elements of `Tuple` and `Map` and attributes of `Object` having `DynamicPseudoType` as their type when unmarshaling JSON values from Terraform.
```
18 changes: 16 additions & 2 deletions tftypes/value_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,20 @@ func jsonUnmarshalMap(buf []byte, attrType Type, p *AttributePath) (Value, error
return Value{}, p.NewErrorf("invalid JSON, expected %q, got %q", json.Delim('}'), tok)
}

elTyp := attrType
if attrType.Is(DynamicPseudoType) {
var elements []Value
for _, val := range vals {
elements = append(elements, val)
}
elTyp, err = TypeFromElements(elements)
if err != nil {
return Value{}, p.NewErrorf("invalid elements for map: %w", err)
}
}

return NewValue(Map{
AttributeType: attrType,
AttributeType: elTyp,
}, vals), nil
}

Expand All @@ -381,6 +393,7 @@ func jsonUnmarshalTuple(buf []byte, elementTypes []Type, p *AttributePath) (Valu
// while generally in Go it's undesirable to treat empty and nil slices
// separately, in this case we're surfacing a non-Go-in-origin
// distinction, so we'll allow it.
types := []Type{}
vals := []Value{}

var idx int64
Expand All @@ -402,6 +415,7 @@ func jsonUnmarshalTuple(buf []byte, elementTypes []Type, p *AttributePath) (Valu
if err != nil {
return Value{}, err
}
types = append(types, val.Type())
vals = append(vals, val)
}

Expand All @@ -418,7 +432,7 @@ func jsonUnmarshalTuple(buf []byte, elementTypes []Type, p *AttributePath) (Valu
}

return NewValue(Tuple{
ElementTypes: elementTypes,
ElementTypes: types,
}, vals), nil
}

Expand Down
66 changes: 66 additions & 0 deletions tftypes/value_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,72 @@ func TestValueFromJSON(t *testing.T) {
},
json: `[{"value":true,"type":"bool"},{"value":false,"type":"bool"}]`,
},
"dynamic-set-of-bools": {
value: NewValue(Set{
ElementType: Bool,
}, []Value{
NewValue(Bool, true),
NewValue(Bool, false),
}),
typ: DynamicPseudoType,
json: `{"value":[true,false],"type":["set","bool"]}`,
},
"set-of-dynamic-bools": {
value: NewValue(Set{
ElementType: Bool,
}, []Value{
NewValue(Bool, true),
NewValue(Bool, false),
}),
typ: Set{
ElementType: DynamicPseudoType,
},
json: `[{"value":true,"type":"bool"},{"value":false,"type":"bool"}]`,
},
"dynamic-tuple-of-bools": {
value: NewValue(Tuple{
ElementTypes: []Type{Bool, Bool},
}, []Value{
NewValue(Bool, true),
NewValue(Bool, false),
}),
typ: DynamicPseudoType,
json: `{"value":[true,false],"type":["tuple",["bool","bool"]]}`,
},
"tuple-of-dynamic-bools": {
value: NewValue(Tuple{
ElementTypes: []Type{Bool, Bool},
}, []Value{
NewValue(Bool, true),
NewValue(Bool, false),
}),
typ: Tuple{
ElementTypes: []Type{DynamicPseudoType, DynamicPseudoType},
},
json: `[{"value":true,"type":"bool"},{"value":false,"type":"bool"}]`,
},
"dynamic-map-of-bools": {
value: NewValue(Map{
AttributeType: Bool,
}, map[string]Value{
"true": NewValue(Bool, true),
"false": NewValue(Bool, false),
}),
typ: DynamicPseudoType,
json: `{"value":{"true":true,"false":false},"type":["map","bool"]}`,
},
"map-of-dynamic-bools": {
value: NewValue(Map{
AttributeType: Bool,
}, map[string]Value{
"true": NewValue(Bool, true),
"false": NewValue(Bool, false),
}),
typ: Map{
AttributeType: DynamicPseudoType,
},
json: `{"true":{"value":true,"type":"bool"},"false":{"value":false,"type":"bool"}}`,
},
"object-of-bool_dynamic": {
value: NewValue(Object{
AttributeTypes: map[string]Type{
Expand Down

0 comments on commit 7943864

Please sign in to comment.