1
1
mirror of https://github.com/mcuadros/ascode synced 2024-11-26 06:01:08 +01:00

ResourceInstance: pointer handling and dict loading

Signed-off-by: Máximo Cuadros <mcuadros@gmail.com>
This commit is contained in:
Máximo Cuadros 2019-06-27 09:50:17 +02:00
parent 0b7d9d05af
commit e26994b396
4 changed files with 155 additions and 13 deletions

37
examples/aws.star Normal file

@ -0,0 +1,37 @@
aws = provider("aws")
print(dir(aws))
ami = aws.data.ami("ubuntu")
ami.most_recent = True
ami.filter("name", values=["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"])
ami.filter("virtualization-type", values=["hvm"])
ami.owners = ["099720109477"]
print(ami.__dict__)
web = aws.resource.instance("web", instance_type="t2.micro")
#web.instance_type = "t2.micro"
#web.ami = ami.id
template = aws.resource.launch_template("example")
template.name_prefix = "example"
template.instance_type = "c5.larger"
group = aws.resource.autoscaling_group("example")
group.availability_zones = ["us-east-1a"]
group.desired_capacity = 1
group.max_size = 1
group.min_size = 1
#group.mixed_instances_policy.launch_template.launch_template_specification.launch_template_id = "foo"
group.mixed_instances_policy = {
"launch_template": {
"launch_template_specification": {
"launch_template_id": "bar"
}
}
}
print(group.__dict__)

@ -1,15 +1,15 @@
ignition = provider("ignition")
print("provider --->", dir(ignition))
user = ignition.user("test")
user = ignition.data.user("test")
user.name = "foo"
user.uid = 42
user.groups = ["foo", "bar"]
user.system = True
print(user.__dict__)
disk = ignition.disk("foo")
disk = ignition.data.disk("foo")
disk.device = "/dev/sda"
root = disk.partition("root")
@ -20,4 +20,4 @@ home = disk.partition("home")
home.start = root.size + root.start
home.size = 4 * 1024 * 1024
print(home.start)
print(disk.__dict__)

@ -59,11 +59,11 @@ func (m *PluginManager) getRemote(provider, version string) (discovery.PluginMet
func (m *PluginManager) getLocal(provider, version string) (discovery.PluginMeta, bool) {
set := discovery.FindPlugins("provider", []string{m.Path})
set = set.WithName(provider)
if len(set) == 0 {
return discovery.PluginMeta{}, false
}
set = set.WithName(provider)
if version != "" {
// set = set.WithVersion(version)
}

@ -17,24 +17,60 @@ type ResourceInstance struct {
values map[string]starlark.Value
}
func NewResourceInstanceConstructor(typ string, b *configschema.Block) starlark.Value {
func NewResourceInstanceConstructor(typ string, b *configschema.Block, ptrs *PointerList) starlark.Value {
return starlark.NewBuiltin(
fmt.Sprintf("_%s", typ),
func(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
name := args.Index(0).(starlark.String)
return MakeResourceInstance(string(name), typ, b)
resource, err := MakeResourceInstance(string(name), typ, b, kwargs)
if err != nil {
return nil, err
}
if ptrs != nil {
if err := ptrs.Append(resource); err != nil {
return nil, err
}
}
return resource, nil
},
)
}
func MakeResourceInstance(name, typ string, b *configschema.Block) (*ResourceInstance, error) {
return &ResourceInstance{
func MakeResourceInstance(name, typ string, b *configschema.Block, kwargs []starlark.Tuple) (*ResourceInstance, error) {
r := &ResourceInstance{
name: name,
typ: typ,
block: b,
values: make(map[string]starlark.Value),
}, nil
}
return r, r.loadKeywordArgs(kwargs)
}
func (r *ResourceInstance) loadDict(d *starlark.Dict) error {
for _, k := range d.Keys() {
name := k.(starlark.String)
value, _, _ := d.Get(k)
if err := r.SetField(string(name), value); err != nil {
return err
}
}
return nil
}
func (r *ResourceInstance) loadKeywordArgs(kwargs []starlark.Tuple) error {
for _, kwarg := range kwargs {
name := kwarg.Index(0).(starlark.String)
if err := r.SetField(string(name), kwarg.Index(1)); err != nil {
return err
}
}
return nil
}
// String honors the starlark.Value interface.
@ -62,8 +98,22 @@ func (r *ResourceInstance) Hash() (uint32, error) {
// Attr honors the starlark.HasAttrs interface.
func (r *ResourceInstance) Attr(name string) (starlark.Value, error) {
if name == "__dict__" {
return r.toDict(), nil
}
if b, ok := r.block.BlockTypes[name]; ok {
return NewResourceInstanceConstructor(name, &b.Block), nil
if b.MaxItems != 1 {
if _, ok := r.values[name]; !ok {
r.values[name] = NewPointerList()
}
return NewResourceInstanceConstructor(name, &b.Block, r.values[name].(*PointerList)), nil
}
if _, ok := r.values[name]; !ok {
r.values[name], _ = MakeResourceInstance("", name, &b.Block, nil)
}
}
if v, ok := r.values[name]; ok {
@ -79,7 +129,7 @@ func (r *ResourceInstance) getNestedBlockAttr(name string, b *configschema.Neste
}
var err error
r.values[name], err = MakeResourceInstance("", name, &b.Block)
r.values[name], err = MakeResourceInstance("", name, &b.Block, nil)
return r.values[name], err
}
@ -95,6 +145,7 @@ func (r *ResourceInstance) AttrNames() []string {
for k := range r.block.BlockTypes {
names[i] = k
i++
}
return names
@ -102,6 +153,10 @@ func (r *ResourceInstance) AttrNames() []string {
// SetField honors the starlark.HasSetField interface.
func (r *ResourceInstance) SetField(name string, v starlark.Value) error {
if b, ok := r.block.BlockTypes[name]; ok {
return r.setFieldFromNestedBlock(name, b, v)
}
attr, ok := r.block.Attributes[name]
if !ok {
errmsg := fmt.Sprintf("%s has no .%s field or method", r.typ, name)
@ -116,6 +171,52 @@ func (r *ResourceInstance) SetField(name string, v starlark.Value) error {
return nil
}
func (r *ResourceInstance) setFieldFromNestedBlock(name string, b *configschema.NestedBlock, v starlark.Value) error {
switch v.Type() {
case "dict":
resource, _ := r.Attr(name)
return resource.(*ResourceInstance).loadDict(v.(*starlark.Dict))
}
return fmt.Errorf("expected dict or list, got %s", v.Type())
}
func (r *ResourceInstance) toDict() *starlark.Dict {
d := starlark.NewDict(len(r.values))
for k, v := range r.values {
if r, ok := v.(*ResourceInstance); ok {
d.SetKey(starlark.String(k), r.toDict())
continue
}
if r, ok := v.(*PointerList); ok {
d.SetKey(starlark.String(k), r.toDict())
continue
}
d.SetKey(starlark.String(k), v)
}
return d
}
type PointerList struct {
*starlark.List
}
func NewPointerList() *PointerList {
return &PointerList{List: starlark.NewList(nil)}
}
func (l *PointerList) toDict() *starlark.List {
values := make([]starlark.Value, l.Len())
for i := 0; i < l.Len(); i++ {
values[i] = l.Index(i).(*ResourceInstance).toDict()
}
return starlark.NewList(values)
}
/*
NoneType # the type of None
bool # True or False
@ -169,7 +270,7 @@ func ValidateType(v starlark.Value, expected cty.Type) error {
return nil
}
case *starlark.List:
if expected.IsListType() {
if expected.IsListType() || expected.IsSetType() {
return ValidateListType(v.(*starlark.List), expected.ElementType())
}
}
@ -191,5 +292,9 @@ func ToStarlarkType(t cty.Type) string {
return "list"
}
if t.IsSetType() {
return "set"
}
return "(unknown)"
}