vendor: upgrade go-cty dependency to 1.4.1 (#24983)

* vendor: upgrade go-cty dependency to 1.4.1

This upgrade fixes a panic with inconsistent object element types.
This commit is contained in:
Kristin Laemmert 2020-05-18 14:10:19 -04:00 committed by GitHub
parent 78d8af18c2
commit a4c3c1d389
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 268 additions and 103 deletions

2
go.mod
View File

@ -121,7 +121,7 @@ require (
github.com/xanzy/ssh-agent v0.2.1
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 // indirect
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
github.com/zclconf/go-cty v1.4.0
github.com/zclconf/go-cty v1.4.1
github.com/zclconf/go-cty-yaml v1.0.1
go.uber.org/atomic v1.3.2 // indirect
go.uber.org/multierr v1.1.0 // indirect

2
go.sum
View File

@ -443,6 +443,8 @@ github.com/zclconf/go-cty v1.2.0 h1:sPHsy7ADcIZQP3vILvTjrh74ZA175TFP5vqiNK1UmlI=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.4.0 h1:+q+tmgyUB94HIdH/uVTIi/+kt3pt4sHwEZAcTyLoGsQ=
github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
github.com/zclconf/go-cty v1.4.1 h1:Xzr4m4utRDhHDifag1onwwUSq32HLoLBsp+w6tD0880=
github.com/zclconf/go-cty v1.4.1/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
github.com/zclconf/go-cty-yaml v1.0.1 h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8=
github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=

View File

@ -1,7 +0,0 @@
variable "foo" {
default = 123
}
resource "aws_instance" "foo" {
foo = "${var.foo}"
}

View File

@ -1,5 +0,0 @@
variable "in" {}
resource "aws_instance" "mod" {
value = "${var.in}"
}

View File

@ -1,7 +0,0 @@
resource "aws_instance" "foo" { }
resource "aws_instance" "bar" { }
module "child" {
source = "./child"
in = "one,${aws_instance.foo.id},${aws_instance.bar.id}"
}

View File

@ -0,0 +1,30 @@
# Required
variable "foo" {
}
# Optional
variable "bar" {
default = "baz"
}
# Mapping
variable "map" {
default = {
foo = "bar"
}
}
# Complex Object Types
variable "object_map" {
type = map(object({
foo = string,
bar = any
}))
}
variable "object_list" {
type = list(object({
foo = string,
bar = any
}))
}

View File

@ -0,0 +1,13 @@
test = [
{
foo = "blah1"
bar = {}
},
{
foo = "blah2"
bar = {
var1 = "val1",
var2 = "var2"
}
}
]

View File

@ -0,0 +1,30 @@
# Required
variable "foo" {
}
# Optional
variable "bar" {
default = "baz"
}
# Mapping
variable "map" {
default = {
foo = "bar"
}
}
# Complex Object Types
variable "object_map" {
type = map(object({
foo = string,
bar = any
}))
}
variable "object_list" {
type = list(object({
foo = string,
bar = any
}))
}

View File

@ -1,7 +0,0 @@
variable "foo" {}
variable "bar" {}
resource "aws_instance" "foo" {
foo = "${var.foo}"
bar = "${var.bar}"
}

View File

@ -1,21 +0,0 @@
variable "amis" {
default = {
us-west-2 = "bar"
}
}
variable "bar" {
default = "baz"
}
variable "foo" {}
resource "aws_instance" "foo" {
num = "2"
bar = var.bar
}
resource "aws_instance" "bar" {
foo = var.foo
bar = var.amis[var.foo]
}

View File

@ -1,15 +0,0 @@
# Required
variable "foo" {
}
# Optional
variable "bar" {
default = "baz"
}
# Mapping
variable "map" {
default = {
foo = "bar"
}
}

View File

@ -163,45 +163,120 @@ func TestVariables(t *testing.T) {
}
}
func TestSMCUserVariables(t *testing.T) {
c := testModule(t, "smc-uservars")
func TestCheckInputVariables(t *testing.T) {
c := testModule(t, "input-variables")
// No variables set
diags := checkInputVariables(c.Module.Variables, nil)
if !diags.HasErrors() {
t.Fatal("check succeeded, but want errors")
}
t.Run("No variables set", func(t *testing.T) {
// No variables set
diags := checkInputVariables(c.Module.Variables, nil)
if !diags.HasErrors() {
t.Fatal("check succeeded, but want errors")
}
// Required variables set, optional variables unset
// This is still an error at this layer, since it's the caller's
// responsibility to have already merged in any default values.
diags = checkInputVariables(c.Module.Variables, InputValues{
"foo": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCLIArg,
},
// Required variables set, optional variables unset
// This is still an error at this layer, since it's the caller's
// responsibility to have already merged in any default values.
diags = checkInputVariables(c.Module.Variables, InputValues{
"foo": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCLIArg,
},
})
if !diags.HasErrors() {
t.Fatal("check succeeded, but want errors")
}
})
if !diags.HasErrors() {
t.Fatal("check succeeded, but want errors")
}
// All variables set
diags = checkInputVariables(c.Module.Variables, InputValues{
"foo": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCLIArg,
},
"bar": &InputValue{
Value: cty.StringVal("baz"),
SourceType: ValueFromCLIArg,
},
"map": &InputValue{
Value: cty.StringVal("baz"), // okay because config has no type constraint
SourceType: ValueFromCLIArg,
},
t.Run("All variables set", func(t *testing.T) {
diags := checkInputVariables(c.Module.Variables, InputValues{
"foo": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCLIArg,
},
"bar": &InputValue{
Value: cty.StringVal("baz"),
SourceType: ValueFromCLIArg,
},
"map": &InputValue{
Value: cty.StringVal("baz"), // okay because config has no type constraint
SourceType: ValueFromCLIArg,
},
"object_map": &InputValue{
Value: cty.MapVal(map[string]cty.Value{
"uno": cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("baz"),
"bar": cty.NumberIntVal(2), // type = any
}),
"dos": cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("bat"),
"bar": cty.NumberIntVal(99), // type = any
}),
}),
SourceType: ValueFromCLIArg,
},
"object_list": &InputValue{
Value: cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("baz"),
"bar": cty.NumberIntVal(2), // type = any
}),
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("bang"),
"bar": cty.NumberIntVal(42), // type = any
}),
}),
SourceType: ValueFromCLIArg,
},
})
if diags.HasErrors() {
t.Fatalf("unexpected errors: %s", diags.Err())
}
})
t.Run("Invalid Complex Types", func(t *testing.T) {
diags := checkInputVariables(c.Module.Variables, InputValues{
"foo": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCLIArg,
},
"bar": &InputValue{
Value: cty.StringVal("baz"),
SourceType: ValueFromCLIArg,
},
"map": &InputValue{
Value: cty.StringVal("baz"), // okay because config has no type constraint
SourceType: ValueFromCLIArg,
},
"object_map": &InputValue{
Value: cty.MapVal(map[string]cty.Value{
"uno": cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("baz"),
"bar": cty.NumberIntVal(2), // type = any
}),
"dos": cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("bat"),
"bar": cty.NumberIntVal(99), // type = any
}),
}),
SourceType: ValueFromCLIArg,
},
"object_list": &InputValue{
Value: cty.TupleVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("baz"),
"bar": cty.NumberIntVal(2), // type = any
}),
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("bang"),
"bar": cty.StringVal("42"), // type = any, but mismatch with the first list item
}),
}),
SourceType: ValueFromCLIArg,
},
})
if diags.HasErrors() {
t.Fatalf("unexpected errors: %s", diags.Err())
}
})
if diags.HasErrors() {
//t.Fatal("check succeeded, but want errors")
t.Fatalf("unexpected errors: %s", diags.Err())
}
}

View File

@ -265,6 +265,7 @@ func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) co
// element conversions in elemConvs
return func(val cty.Value, path cty.Path) (cty.Value, error) {
elems := make([]cty.Value, 0, len(elemConvs))
elemTys := make([]cty.Type, 0, len(elems))
elemPath := append(path.Copy(), nil)
i := int64(0)
it := val.ElementIterator()
@ -284,10 +285,15 @@ func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) co
}
}
elems = append(elems, val)
elemTys = append(elemTys, val.Type())
i++
}
elems, err := conversionUnifyListElements(elems, elemPath, unsafe)
if err != nil {
return cty.NilVal, err
}
return cty.ListVal(elems), nil
}
}
@ -441,6 +447,7 @@ func conversionUnifyCollectionElements(elems map[string]cty.Value, path cty.Path
}
unifiedType, _ := unify(elemTypes, unsafe)
if unifiedType == cty.NilType {
return nil, path.NewErrorf("collection elements cannot be unified")
}
unifiedElems := make(map[string]cty.Value)
@ -486,3 +493,37 @@ func conversionCheckMapElementTypes(elems map[string]cty.Value, path cty.Path) e
return nil
}
func conversionUnifyListElements(elems []cty.Value, path cty.Path, unsafe bool) ([]cty.Value, error) {
elemTypes := make([]cty.Type, len(elems))
for i, elem := range elems {
elemTypes[i] = elem.Type()
}
unifiedType, _ := unify(elemTypes, unsafe)
if unifiedType == cty.NilType {
return nil, path.NewErrorf("collection elements cannot be unified")
}
ret := make([]cty.Value, len(elems))
elemPath := append(path.Copy(), nil)
for i, elem := range elems {
if elem.Type().Equals(unifiedType) {
ret[i] = elem
continue
}
conv := getConversion(elem.Type(), unifiedType, unsafe)
if conv == nil {
}
elemPath[len(elemPath)-1] = cty.IndexStep{
Key: cty.NumberIntVal(int64(i)),
}
val, err := conv(elem, elemPath)
if err != nil {
return nil, err
}
ret[i] = val
}
return ret, nil
}

View File

@ -163,8 +163,23 @@ func SetSymmetricDifference(sets ...cty.Value) (cty.Value, error) {
func setOperationReturnType(args []cty.Value) (ret cty.Type, err error) {
var etys []cty.Type
for _, arg := range args {
etys = append(etys, arg.Type().ElementType())
ty := arg.Type().ElementType()
// Do not unify types for empty dynamic pseudo typed collections. These
// will always convert to any other concrete type.
if arg.LengthInt() == 0 && ty.Equals(cty.DynamicPseudoType) {
continue
}
etys = append(etys, ty)
}
// If all element types were skipped (due to being empty dynamic collections),
// the return type should also be a set of dynamic pseudo type.
if len(etys) == 0 {
return cty.Set(cty.DynamicPseudoType), nil
}
newEty, _ := convert.UnifyUnsafe(etys)
if newEty == cty.NilType {
return cty.NilType, fmt.Errorf("given sets must all have compatible element types")

View File

@ -196,3 +196,9 @@ func (r pathSetRules) Equivalent(a, b interface{}) bool {
return true
}
// SameRules is true if both Rules instances are pathSetRules structs.
func (r pathSetRules) SameRules(other set.Rules) bool {
_, ok := other.(pathSetRules)
return ok
}

View File

@ -22,6 +22,10 @@ type Rules interface {
// though it is *not* required that two values with the same hash value
// be equivalent.
Equivalent(interface{}, interface{}) bool
// SameRules returns true if the instance is equivalent to another Rules
// instance.
SameRules(Rules) bool
}
// OrderedRules is an extension of Rules that can apply a partial order to

View File

@ -41,7 +41,7 @@ func NewSetFromSlice(rules Rules, vals []interface{}) Set {
}
func sameRules(s1 Set, s2 Set) bool {
return s1.rules == s2.rules
return s1.rules.SameRules(s2.rules)
}
func mustHaveSameRules(s1 Set, s2 Set) {
@ -53,7 +53,7 @@ func mustHaveSameRules(s1 Set, s2 Set) {
// HasRules returns true if and only if the receiving set has the given rules
// instance as its rules.
func (s Set) HasRules(rules Rules) bool {
return s.rules == rules
return s.rules.SameRules(rules)
}
// Rules returns the receiving set's rules instance.

View File

@ -65,6 +65,17 @@ func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool {
return eqv.v == true
}
// SameRules is only true if the other Rules instance is also a setRules struct,
// and the types are considered equal.
func (r setRules) SameRules(other set.Rules) bool {
rules, ok := other.(setRules)
if !ok {
return false
}
return r.Type.Equals(rules.Type)
}
// Less is an implementation of set.OrderedRules so that we can iterate over
// set elements in a consistent order, where such an order is possible.
func (r setRules) Less(v1, v2 interface{}) bool {

2
vendor/modules.txt vendored
View File

@ -582,7 +582,7 @@ github.com/xanzy/ssh-agent
# github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
## explicit
github.com/xlab/treeprint
# github.com/zclconf/go-cty v1.4.0
# github.com/zclconf/go-cty v1.4.1
## explicit
github.com/zclconf/go-cty/cty
github.com/zclconf/go-cty/cty/convert