1
1
mirror of https://github.com/mcuadros/ascode synced 2024-11-22 17:02:03 +01:00

starlark/types: proper .Type() function implementation

Signed-off-by: Máximo Cuadros <mcuadros@gmail.com>
This commit is contained in:
Máximo Cuadros 2019-07-14 11:33:39 +02:00
parent d3d153ba25
commit 5eee1fa944
9 changed files with 38 additions and 40 deletions

@ -32,7 +32,7 @@ func (c *ResourceCollection) String() string {
// Type honors the starlark.Value interface.
func (c *ResourceCollection) Type() string {
return "collection"
return fmt.Sprintf("ResourceCollection<%s.%s>", c.kind, c.typ)
}
// Truth honors the starlark.Value interface.

@ -51,7 +51,7 @@ func NewComputedWithPath(r *Resource, t cty.Type, name, path string) *Computed {
}
func (*Computed) Type() string {
return "computed"
return "Computed"
}
func (c *Computed) InnerType() *Type {

@ -84,7 +84,7 @@ func (r *Resource) String() string {
// Type honors the starlark.Value interface.
func (r *Resource) Type() string {
return string(r.kind)
return fmt.Sprintf("Resource<%s.%s>", r.kind, r.typ)
}
// Truth honors the starlark.Value interface.

@ -5,21 +5,21 @@ aws = provider("aws", "2.13.0")
# compute of scalar
web = aws.resource.instance()
web.ami = aws.data.ami().id
assert.eq(type(web.ami), "computed")
assert.eq(str(web.ami), '"$${data.aws_ami.id_3.id}"')
assert.eq(type(web.ami), "Computed")
assert.eq(str(web.ami), '"${data.aws_ami.id_3.id}"')
# compute of set
table = aws.data.dynamodb_table()
assert.eq(str(table.ttl), '"$${data.aws_dynamodb_table.id_4.ttl}"')
assert.eq(str(table.ttl[0]), '"$${data.aws_dynamodb_table.id_4.ttl.0}"')
assert.eq(str(table.ttl[0].attribute_name), '"$${data.aws_dynamodb_table.id_4.ttl.0.attribute_name}"')
assert.eq(str(table.ttl), '"${data.aws_dynamodb_table.id_4.ttl}"')
assert.eq(str(table.ttl[0]), '"${data.aws_dynamodb_table.id_4.ttl.0}"')
assert.eq(str(table.ttl[0].attribute_name), '"${data.aws_dynamodb_table.id_4.ttl.0.attribute_name}"')
# compute of list
instance = aws.data.instance()
assert.eq(str(instance.credit_specification), '"$${data.aws_instance.id_5.credit_specification}"')
assert.eq(str(instance.credit_specification[0]), '"$${data.aws_instance.id_5.credit_specification.0}"')
assert.eq(str(instance.credit_specification[0].cpu_credits), '"$${data.aws_instance.id_5.credit_specification.0.cpu_credits}"')
assert.eq(str(instance.credit_specification), '"${data.aws_instance.id_5.credit_specification}"')
assert.eq(str(instance.credit_specification[0]), '"${data.aws_instance.id_5.credit_specification.0}"')
assert.eq(str(instance.credit_specification[0].cpu_credits), '"${data.aws_instance.id_5.credit_specification.0.cpu_credits}"')
# compute of map
computed = str(aws.resource.instance().root_block_device.volume_size)
assert.eq(computed, '"$${resource.aws_instance.id_6.root_block_device.volume_size}"')
assert.eq(computed, '"${resource.aws_instance.id_6.root_block_device.volume_size}"')

@ -3,11 +3,11 @@ load("assert.star", "assert")
p = provider("aws", "2.13.0")
d = p.data.ami()
assert.eq(type(d.filter), "collection")
assert.eq(type(d.filter), "ResourceCollection<nested.filter>")
bar = d.filter(name="bar", values=["qux"])
assert.eq(type(bar), "nested")
assert.eq(type(bar), "Resource<nested.filter>")
assert.eq(bar.name, "bar")
assert.eq(bar.values, ["qux"])

@ -8,9 +8,9 @@ assert.eq(len(dir(p.resource)), 506)
resources = dir(p.resource)
assert.contains(resources, "instance")
assert.eq(type(p.resource.instance), "collection")
assert.eq(type(p.resource.instance), "ResourceCollection<resource.aws_instance>")
assert.eq(type(p.resource.instance()), "Resource<resource.aws_instance>")
p.resource.instance()
p.resource.instance()
assert.eq(len(p.resource.instance), 2)

@ -11,11 +11,11 @@ assert.eq(qux.uid, 42)
assert.eq(qux.name, None)
# attr not-exists
assert.fails(lambda: qux.foo, "data has no .foo field or method")
assert.fails(lambda: qux.foo, "Resource<data.ignition_user> has no .foo field or method")
# attr id
assert.eq(type(qux.id), "computed")
assert.eq(str(qux.id), '"$${data.ignition_user.id_14.id}"')
assert.eq(type(qux.id), "Computed")
assert.eq(str(qux.id), '"${data.ignition_user.id_14.id}"')
# attr output assignation
aws = provider("aws", "2.13.0")
@ -48,7 +48,7 @@ assert.eq(p.data.user(groups=["foo"]), p.data.user(groups=["foo"]))
# constructor with name
quux = p.data.user("quux")
assert.eq(str(quux.id), '"$${data.ignition_user.quux.id}"')
assert.eq(str(quux.id), '"${data.ignition_user.quux.id}"')
# constructor from kwargs
bar = p.data.user(uid=42, system=True)
@ -59,7 +59,7 @@ assert.eq(bar.system, True)
fred = p.data.user("fred", uid=42, system=True)
assert.eq(fred.uid, 42)
assert.eq(fred.system, True)
assert.eq(str(fred.id), '"$${data.ignition_user.fred.id}"')
assert.eq(str(fred.id), '"${data.ignition_user.fred.id}"')
# constructor from dict
foo = p.data.user({"uid": 42, "system": True})
@ -70,7 +70,7 @@ assert.eq(foo.system, True)
baz = p.data.user("baz", {"uid": 42, "system": True})
assert.eq(baz.uid, 42)
assert.eq(baz.system, True)
assert.eq(str(baz.id), '"$${data.ignition_user.baz.id}"')
assert.eq(str(baz.id), '"${data.ignition_user.baz.id}"')
assert.eq(bar, foo)
assert.eq(foo, p.data.user(foo.__dict__))
@ -95,7 +95,7 @@ user.uid = 42
user.groups = ["foo", "bar"]
user.system = True
assert.eq(type(user), "data")
assert.eq(type(user), "Resource<data.ignition_user>")
assert.eq(user.__dict__, {
"name": "foo",
"uid": 42,

@ -2,6 +2,7 @@ package types
import (
"fmt"
"strings"
"github.com/zclconf/go-cty/cty"
"go.starlark.net/starlark"
@ -67,7 +68,7 @@ func (v *Value) Cty() cty.Value {
}
return cty.ListVal(values)
case "computed":
case "Computed":
return cty.StringVal(v.v.(*Computed).GoString())
default:
return cty.StringVal(fmt.Sprintf("unhandled: %s", v.t.typ))
@ -141,6 +142,11 @@ func NewTypeFromStarlark(typ string) (*Type, error) {
t := &Type{}
t.typ = typ
complex := strings.SplitN(typ, "<", 2)
if len(complex) == 2 {
typ = complex[0]
}
switch typ {
case "bool":
t.cty = cty.Bool
@ -148,13 +154,11 @@ func NewTypeFromStarlark(typ string) (*Type, error) {
t.cty = cty.Number
case "string":
t.cty = cty.String
case "collection":
case "list", "ResourceCollection":
t.cty = cty.List(cty.NilType)
case "nested", "data", "resource":
case "Resource":
t.cty = cty.Map(cty.NilType)
case "list":
t.cty = cty.List(cty.NilType)
case "computed":
case "Computed":
t.cty = cty.String
default:
return nil, fmt.Errorf("unexpected %q type", typ)

@ -30,16 +30,10 @@ func TestNewTypeFromStarlark_NonScalar(t *testing.T) {
typ := MustTypeFromStarlark("list")
assert.True(t, typ.Cty().IsListType())
typ = MustTypeFromStarlark("collection")
typ = MustTypeFromStarlark("ResourceCollection<bar>")
assert.True(t, typ.Cty().IsListType())
typ = MustTypeFromStarlark("data")
assert.True(t, typ.Cty().IsMapType())
typ = MustTypeFromStarlark("nested")
assert.True(t, typ.Cty().IsMapType())
typ = MustTypeFromStarlark("resource")
typ = MustTypeFromStarlark("Resource<foo>")
assert.True(t, typ.Cty().IsMapType())
}
@ -77,13 +71,13 @@ func TestTypeValidate(t *testing.T) {
{"int", starlark.Float(42.), false},
}
for _, tc := range testCases {
for i, tc := range testCases {
typ := MustTypeFromStarlark(tc.t)
err := typ.Validate(tc.v)
if tc.err {
assert.Error(t, err)
assert.Error(t, err, i)
} else {
assert.NoError(t, err)
assert.NoError(t, err, i)
}
}
}