forked from hashicorp/terraform
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds functions for checking the type of variables
- Loading branch information
daniel.schroeder
committed
Oct 26, 2019
1 parent
8a34c33
commit 9eaa310
Showing
3 changed files
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package funcs | ||
|
||
import ( | ||
"github.com/zclconf/go-cty/cty" | ||
"github.com/zclconf/go-cty/cty/function" | ||
) | ||
|
||
var TypeFunc = function.New(&function.Spec{ | ||
Params: []function.Parameter{ | ||
{ | ||
Name: "variable", | ||
Type: cty.DynamicPseudoType, | ||
AllowNull: true, | ||
}, | ||
}, | ||
Type: function.StaticReturnType(cty.String), | ||
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { | ||
varType := getType(args[0]) | ||
return cty.StringVal(varType), nil | ||
}, | ||
}) | ||
|
||
// MakeIsTypeFunc constructs a "is..." function, like "isstring", which checks | ||
// the type of a given variable is of the expected type. | ||
// The given string checkType can be any type supported by the cty package | ||
func MakeIsTypeFunc(checkType string) function.Function { | ||
return function.New(&function.Spec{ | ||
Params: []function.Parameter{ | ||
{ | ||
Name: "variable", | ||
Type: cty.DynamicPseudoType, | ||
AllowNull: true, | ||
}, | ||
}, | ||
Type: function.StaticReturnType(cty.Bool), | ||
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { | ||
checked := getType(args[0]) == checkType | ||
return cty.BoolVal(checked), nil | ||
}, | ||
}) | ||
} | ||
|
||
func getType(arg cty.Value) string { | ||
var varType string | ||
|
||
// We have some special cases here, because var.Type().FriendlyName() does | ||
// not always give what we want. | ||
// In case the input var is null, it returns "any value" | ||
// For collection types it returns "list/map/set of strings" etc | ||
// We only want "list/map/set" instead. | ||
if arg.IsNull() { | ||
varType = "null" | ||
} else if arg.Type().IsListType() { | ||
varType = "list" | ||
} else if arg.Type().IsMapType() { | ||
varType = "map" | ||
} else if arg.Type().IsSetType() { | ||
varType = "set" | ||
} else { | ||
varType = arg.Type().FriendlyName() | ||
} | ||
|
||
return varType | ||
} | ||
|
||
// Type returns the type of a given var as string | ||
func Type(t cty.Value) (cty.Value, error) { | ||
return TypeFunc.Call([]cty.Value{t}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package funcs | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/zclconf/go-cty/cty" | ||
) | ||
|
||
func TestType(t *testing.T) { | ||
tests := []struct { | ||
Value cty.Value | ||
Want string | ||
}{ | ||
{ | ||
cty.BoolVal(true), | ||
"bool", | ||
}, | ||
{ | ||
cty.ListVal([]cty.Value{ | ||
cty.StringVal("foo"), | ||
cty.StringVal("bar"), | ||
}), | ||
"list", | ||
}, | ||
{ | ||
cty.MapVal(map[string]cty.Value{ | ||
"foo": cty.StringVal("foo"), | ||
"bar": cty.StringVal("bar")}), | ||
"map", | ||
}, | ||
{ | ||
cty.NilVal, | ||
"null", | ||
}, | ||
{ | ||
cty.NumberIntVal(42), | ||
"number", | ||
}, | ||
{ | ||
cty.ObjectVal(map[string]cty.Value{ | ||
"foo": cty.StringVal("foo"), | ||
"bar": cty.StringVal("bar")}), | ||
"object", | ||
}, | ||
{ | ||
cty.SetVal([]cty.Value{ | ||
cty.StringVal("foo"), | ||
cty.StringVal("bar"), | ||
}), | ||
"set", | ||
}, | ||
{ | ||
cty.StringVal("foo"), | ||
"string", | ||
}, | ||
{ | ||
cty.TupleVal([]cty.Value{ | ||
cty.StringVal("foo"), | ||
cty.StringVal("bar"), | ||
}), | ||
"tuple", | ||
}, | ||
} | ||
|
||
// prevValue is used to test negative results, to ensure the is* functions | ||
// do not just always return true | ||
prevValue := cty.NumberIntVal(42) | ||
|
||
for _, test := range tests { | ||
|
||
t.Run(fmt.Sprintf("type(%#v)", test.Value), func(t *testing.T) { | ||
got, err := Type(test.Value) | ||
|
||
if err != nil { | ||
t.Fatalf("unexpected error: %s", err) | ||
} | ||
|
||
if got.AsString() != test.Want { | ||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) | ||
} | ||
}) | ||
|
||
t.Run(fmt.Sprintf("is%s()", test.Want), func(t *testing.T) { | ||
f := MakeIsTypeFunc(test.Want) | ||
|
||
//testing for positive results | ||
got, err := f.Call([]cty.Value{test.Value}) | ||
|
||
if err != nil { | ||
t.Fatalf("unexpected error: %s", err) | ||
} | ||
|
||
if got.False() { | ||
t.Error("wrong result\ngot: false\nwant: true") | ||
} | ||
|
||
// testing for negative results | ||
got, err = f.Call([]cty.Value{prevValue}) | ||
|
||
if err != nil { | ||
t.Fatalf("unexpected error: %s", err) | ||
} | ||
|
||
if got.True() { | ||
t.Error("wrong result\ngot: true\nwant: false") | ||
} | ||
|
||
// preparing prevValue for next test iteration | ||
prevValue = test.Value | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters