Extend hcl2 support with more functions

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2020-12-23 12:33:55 +01:00
parent 74f76cf4e9
commit 96e7f3224a
90 changed files with 4425 additions and 198 deletions

View File

@ -44,7 +44,7 @@ var SetUnionFunc = function.New(&function.Spec{
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Union(s2)
}),
}, true),
})
var SetIntersectionFunc = function.New(&function.Spec{
@ -63,7 +63,7 @@ var SetIntersectionFunc = function.New(&function.Spec{
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Intersection(s2)
}),
}, false),
})
var SetSubtractFunc = function.New(&function.Spec{
@ -82,7 +82,7 @@ var SetSubtractFunc = function.New(&function.Spec{
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Subtract(s2)
}),
}, false),
})
var SetSymmetricDifferenceFunc = function.New(&function.Spec{
@ -100,8 +100,8 @@ var SetSymmetricDifferenceFunc = function.New(&function.Spec{
},
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Subtract(s2)
}),
return s1.SymmetricDifference(s2)
}, false),
})
// SetHasElement determines whether the given set contains the given value as an
@ -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.IsKnown() && 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")
@ -172,13 +187,21 @@ func setOperationReturnType(args []cty.Value) (ret cty.Type, err error) {
return cty.Set(newEty), nil
}
func setOperationImpl(f func(s1, s2 cty.ValueSet) cty.ValueSet) function.ImplFunc {
func setOperationImpl(f func(s1, s2 cty.ValueSet) cty.ValueSet, allowUnknowns bool) function.ImplFunc {
return func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
first := args[0]
first, err = convert.Convert(first, retType)
if err != nil {
return cty.NilVal, function.NewArgError(0, err)
}
if !allowUnknowns && !first.IsWhollyKnown() {
// This set function can produce a correct result only when all
// elements are known, because eventually knowing the unknown
// values may cause the result to have fewer known elements, or
// might cause a result with no unknown elements at all to become
// one with a different length.
return cty.UnknownVal(retType), nil
}
set := first.AsValueSet()
for i, arg := range args[1:] {
@ -186,6 +209,10 @@ func setOperationImpl(f func(s1, s2 cty.ValueSet) cty.ValueSet) function.ImplFun
if err != nil {
return cty.NilVal, function.NewArgError(i+1, err)
}
if !allowUnknowns && !arg.IsWhollyKnown() {
// (For the same reason as we did this check for "first" above.)
return cty.UnknownVal(retType), nil
}
argSet := arg.AsValueSet()
set = f(set, argSet)