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

starlark/types: standarization contructors and interface checks

This commit is contained in:
Máximo Cuadros 2020-03-24 06:36:10 +01:00
parent 5ce0598bdc
commit 9f59c34ce6
No known key found for this signature in database
GPG Key ID: 17A5DFEDC735AE4B
10 changed files with 100 additions and 48 deletions

@ -39,7 +39,7 @@ type Runtime struct {
}
func NewRuntime(pm *terraform.PluginManager) *Runtime {
tf := types.MakeTerraform(pm)
tf := types.NewTerraform(pm)
return &Runtime{
Terraform: tf,

@ -44,7 +44,7 @@ func BuiltinBackend(pm *terraform.PluginManager) starlark.Value {
return nil, fmt.Errorf("unexpected positional arguments count")
}
p, err := MakeBackend(pm, name.GoString())
p, err := NewBackend(pm, name.GoString())
if err != nil {
return nil, err
}
@ -89,8 +89,12 @@ type Backend struct {
*Resource
}
// MakeBackend returns a new Backend instance based on given arguments,
func MakeBackend(pm *terraform.PluginManager, typ string) (*Backend, error) {
var _ starlark.Value = &Backend{}
var _ starlark.HasAttrs = &Backend{}
var _ starlark.Comparable = &Backend{}
// NewBackend returns a new Backend instance based on given arguments,
func NewBackend(pm *terraform.PluginManager, typ string) (*Backend, error) {
fn := binit.Backend(typ)
if fn == nil {
return nil, fmt.Errorf("unable to find backend %q", typ)
@ -105,6 +109,7 @@ func MakeBackend(pm *terraform.PluginManager, typ string) (*Backend, error) {
}, nil
}
// Attr honors the starlark.HasAttrs interface.
func (b *Backend) Attr(name string) (starlark.Value, error) {
switch name {
case "state":
@ -176,7 +181,7 @@ func (b *Backend) state(
return starlark.None, nil
}
return MakeState(b.pm, module, state)
return NewState(b.pm, module, state)
}
@ -218,8 +223,12 @@ type State struct {
pm *terraform.PluginManager
}
// MakeState returns a new instance of State based on the given arguments,
func MakeState(pm *terraform.PluginManager, module string, state *states.State) (*State, error) {
var _ starlark.Value = &State{}
var _ starlark.HasAttrs = &State{}
var _ starlark.Comparable = &State{}
// NewState returns a new instance of State based on the given arguments,
func NewState(pm *terraform.PluginManager, module string, state *states.State) (*State, error) {
var mod *states.Module
for _, m := range state.Modules {
if m.Addr.String() == module {
@ -244,7 +253,7 @@ func (s *State) initialize(state *states.State, mod *states.Module) error {
addrs := state.ProviderAddrs()
for _, addr := range addrs {
typ := addr.ProviderConfig.Type.Type
p, err := MakeProvider(s.pm, typ, "", addr.ProviderConfig.Alias)
p, err := NewProvider(s.pm, typ, "", addr.ProviderConfig.Alias)
if err != nil {
return err
}

@ -18,6 +18,11 @@ type ResourceCollection struct {
*starlark.List
}
var _ starlark.Value = &ResourceCollection{}
var _ starlark.HasAttrs = &ResourceCollection{}
var _ starlark.Callable = &ResourceCollection{}
var _ starlark.Comparable = &ResourceCollection{}
func NewResourceCollection(
typ string, k Kind, block *configschema.Block, provider *Provider, parent *Resource,
) *ResourceCollection {
@ -78,12 +83,12 @@ func (c *ResourceCollection) Freeze() {}
// Hash honors the starlark.Value interface.
func (c *ResourceCollection) Hash() (uint32, error) {
return 0, fmt.Errorf("unhashable type: ResourceCollection")
return 0, fmt.Errorf("unhashable type: %s", c.Type())
}
// Name honors the starlark.Callable interface.
func (c *ResourceCollection) Name() string {
return c.typ
return c.Type()
}
// CallInternal honors the starlark.Callable interface.
@ -279,6 +284,11 @@ type ProviderCollection struct {
*Dict
}
var _ starlark.Value = &ProviderCollection{}
var _ starlark.HasAttrs = &ProviderCollection{}
var _ starlark.Callable = &ProviderCollection{}
var _ starlark.Comparable = &ProviderCollection{}
func NewProviderCollection(pm *terraform.PluginManager) *ProviderCollection {
return &ProviderCollection{
pm: pm,
@ -286,11 +296,6 @@ func NewProviderCollection(pm *terraform.PluginManager) *ProviderCollection {
}
}
// String honors the starlark.Value interface.
func (c *ProviderCollection) String() string {
return "foo"
}
// Type honors the starlark.Value interface.
func (c *ProviderCollection) Type() string {
return "ProviderCollection"
@ -306,12 +311,12 @@ func (c *ProviderCollection) Freeze() {}
// Hash honors the starlark.Value interface.
func (c *ProviderCollection) Hash() (uint32, error) {
return 0, fmt.Errorf("unhashable type: ProviderCollection")
return 0, fmt.Errorf("unhashable type: %s", c.Type())
}
// Name honors the starlark.Callable interface.
func (c *ProviderCollection) Name() string {
return "foo"
return c.Type()
}
// CallInternal honors the starlark.Callable interface.
@ -336,7 +341,7 @@ func (c *ProviderCollection) MakeProvider(name, version, alias string, kwargs []
return nil, fmt.Errorf("already exists a provider %q with the alias %q", name, alias)
}
p, err := MakeProvider(c.pm, name, version, alias)
p, err := NewProvider(c.pm, name, version, alias)
if err != nil {
return nil, err
}

@ -18,6 +18,11 @@ type Computed struct {
sString
}
var _ starlark.Value = &Computed{}
var _ starlark.HasAttrs = &Computed{}
var _ starlark.Indexable = &Computed{}
var _ starlark.Comparable = &Computed{}
func NewComputed(r *Resource, t cty.Type, name string) *Computed {
var parts []string
var path string
@ -62,6 +67,7 @@ func NewComputedWithPath(r *Resource, t cty.Type, name, path string) *Computed {
}
}
// Type honors the starlark.Value interface.
func (c *Computed) Type() string {
return fmt.Sprintf("Computed<%s>", MustTypeFromCty(c.t).Starlark())
}
@ -71,6 +77,7 @@ func (c *Computed) InnerType() *Type {
return t
}
// Attr honors the starlark.HasAttrs interface.
func (c *Computed) Attr(name string) (starlark.Value, error) {
switch name {
case "__resource__":
@ -91,6 +98,7 @@ func (c *Computed) Attr(name string) (starlark.Value, error) {
return NewComputedWithPath(c.r, c.t.AttributeType(name), name, path), nil
}
// AttrNames honors the starlark.HasAttrs interface.
func (c *Computed) AttrNames() []string {
return []string{"__resource__", "__type__"}
}
@ -104,6 +112,7 @@ func (c *Computed) doNested(name, path string, t cty.Type, index int) *Computed
}
// Index honors the starlark.Indexable interface.
func (c *Computed) Index(i int) starlark.Value {
path := fmt.Sprintf("%s.%d", c.path, i)
@ -118,6 +127,7 @@ func (c *Computed) Index(i int) starlark.Value {
return starlark.None
}
// Len honors the starlark.Indexable interface.
func (c *Computed) Len() int {
if !c.t.IsSetType() && !c.t.IsListType() {
return 0

@ -41,7 +41,7 @@ func BuiltinProvider(pm *terraform.PluginManager) starlark.Value {
return nil, fmt.Errorf("unexpected positional arguments count")
}
p, err := MakeProvider(pm, typ.GoString(), version.GoString(), name.GoString())
p, err := NewProvider(pm, typ.GoString(), version.GoString(), name.GoString())
if err != nil {
return nil, err
}
@ -99,8 +99,12 @@ type Provider struct {
*Resource
}
// MakeProvider returns a new Provider instance from a given type, version and name.
func MakeProvider(pm *terraform.PluginManager, typ, version, name string) (*Provider, error) {
var _ starlark.Value = &Provider{}
var _ starlark.HasAttrs = &Provider{}
var _ starlark.Comparable = &Provider{}
// NewProvider returns a new Provider instance from a given type, version and name.
func NewProvider(pm *terraform.PluginManager, typ, version, name string) (*Provider, error) {
cli, meta, err := pm.Provider(typ, version, false)
if err != nil {
return nil, err
@ -164,7 +168,7 @@ func (p *Provider) AttrNames() []string {
return append(p.Resource.AttrNames(), "data", "resource", "__version__")
}
// CompareSameType honors starlark.Comprable interface.
// CompareSameType honors starlark.Comparable interface.
func (x *Provider) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) {
y := y_.(*Provider)
switch op {
@ -184,6 +188,9 @@ type ResourceCollectionGroup struct {
collections map[string]*ResourceCollection
}
var _ starlark.Value = &ResourceCollectionGroup{}
var _ starlark.HasAttrs = &ResourceCollectionGroup{}
func NewResourceCollectionGroup(p *Provider, k Kind, schemas map[string]providers.Schema) *ResourceCollectionGroup {
return &ResourceCollectionGroup{
provider: p,
@ -194,42 +201,53 @@ func NewResourceCollectionGroup(p *Provider, k Kind, schemas map[string]provider
}
// Path returns the path of the ResourceCollectionGroup.
func (r *ResourceCollectionGroup) Path() string {
return fmt.Sprintf("%s.%s", r.provider.typ, r.kind)
func (g *ResourceCollectionGroup) Path() string {
return fmt.Sprintf("%s.%s", g.provider.typ, g.kind)
}
func (r *ResourceCollectionGroup) String() string {
return fmt.Sprintf("ResourceCollectionGroup<%s>", r.Path())
// String honors the starlark.String interface.
func (g *ResourceCollectionGroup) String() string {
return fmt.Sprintf("ResourceCollectionGroup<%s>", g.Path())
}
func (r *ResourceCollectionGroup) Type() string {
// Type honors the starlark.Value interface.
func (*ResourceCollectionGroup) Type() string {
return "ResourceCollectionGroup"
}
func (m *ResourceCollectionGroup) Freeze() {}
func (m *ResourceCollectionGroup) Truth() starlark.Bool { return true }
func (m *ResourceCollectionGroup) Hash() (uint32, error) { return 1, nil }
// Freeze honors the starlark.Value interface.
func (*ResourceCollectionGroup) Freeze() {}
func (m *ResourceCollectionGroup) Attr(name string) (starlark.Value, error) {
name = m.provider.typ + "_" + name
// Truth honors the starlark.Value interface. True even if empty.
func (*ResourceCollectionGroup) Truth() starlark.Bool { return true }
if c, ok := m.collections[name]; ok {
// Hash honors the starlark.Value interface.
func (g *ResourceCollectionGroup) Hash() (uint32, error) {
return 0, fmt.Errorf("unhashable type: %s", g.Type())
}
// Attr honors the starlark.HasAttrs interface.
func (g *ResourceCollectionGroup) Attr(name string) (starlark.Value, error) {
name = g.provider.typ + "_" + name
if c, ok := g.collections[name]; ok {
return c, nil
}
if schema, ok := m.schemas[name]; ok {
m.collections[name] = NewResourceCollection(name, m.kind, schema.Block, m.provider, m.provider.Resource)
return m.collections[name], nil
if schema, ok := g.schemas[name]; ok {
g.collections[name] = NewResourceCollection(name, g.kind, schema.Block, g.provider, g.provider.Resource)
return g.collections[name], nil
}
return starlark.None, nil
}
func (s *ResourceCollectionGroup) AttrNames() []string {
names := make([]string, len(s.schemas))
// AttrNames honors the starlark.HasAttrs interface.
func (g *ResourceCollectionGroup) AttrNames() []string {
names := make([]string, len(g.schemas))
var i int
for k := range s.schemas {
for k := range g.schemas {
parts := strings.SplitN(k, "_", 2)
names[i] = parts[1]
i++

@ -73,7 +73,7 @@ func doTestPrint(t *testing.T, filename string, print func(*starlark.Thread, str
"hcl": BuiltinHCL(),
"fn": BuiltinFunctionComputed(),
"evaluate": BuiltinEvaluate(),
"tf": MakeTerraform(pm),
"tf": NewTerraform(pm),
}
_, err := starlark.ExecFile(thread, filename, nil, predeclared)

@ -23,7 +23,7 @@ func BuiltinProvisioner(pm *terraform.PluginManager) starlark.Value {
return nil, fmt.Errorf("unexpected positional arguments count")
}
p, err := MakeProvisioner(pm, name.GoString())
p, err := NewProvisioner(pm, name.GoString())
if err != nil {
return nil, err
}
@ -38,7 +38,7 @@ type Provisioner struct {
*Resource
}
func MakeProvisioner(pm *terraform.PluginManager, typ string) (*Provisioner, error) {
func NewProvisioner(pm *terraform.PluginManager, typ string) (*Provisioner, error) {
cli, meta, err := pm.Provisioner(typ)
if err != nil {
return nil, err

@ -127,6 +127,11 @@ type Resource struct {
provisioners []*Provisioner
}
var _ starlark.Value = &Resource{}
var _ starlark.HasAttrs = &Resource{}
var _ starlark.HasSetField = &Resource{}
var _ starlark.Comparable = &Resource{}
// MakeResource returns a new resource of the given kind, type based on the
// given configschema.Block.
func MakeResource(name, typ string, k Kind, b *configschema.Block, provider *Provider, parent *Resource) *Resource {
@ -418,7 +423,7 @@ func (r *Resource) addProvisioner(_ *starlark.Thread, _ *starlark.Builtin, args
return starlark.None, nil
}
// CompareSameType honors starlark.Comprable interface.
// CompareSameType honors starlark.Comparable interface.
func (x *Resource) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) {
y := y_.(*Resource)
switch op {

@ -51,13 +51,17 @@ type Terraform struct {
p *ProviderCollection
}
// MakeTerraform returns a new instance of Terraform
func MakeTerraform(pm *terraform.PluginManager) *Terraform {
// NewTerraform returns a new instance of Terraform
func NewTerraform(pm *terraform.PluginManager) *Terraform {
return &Terraform{
p: NewProviderCollection(pm),
}
}
var _ starlark.Value = &Terraform{}
var _ starlark.HasAttrs = &Terraform{}
var _ starlark.HasSetField = &Terraform{}
// Attr honors the starlark.HasAttrs interface.
func (t *Terraform) Attr(name string) (starlark.Value, error) {
switch name {
@ -101,7 +105,7 @@ func (t *Terraform) Freeze() {} // immutable
// Hash honors the starlark.Value interface.
func (t *Terraform) Hash() (uint32, error) {
return 0, fmt.Errorf("unhashable type: Terraform")
return 0, fmt.Errorf("unhashable type: %s", t.Type())
}
// String honors the starlark.Value interface.
@ -118,5 +122,3 @@ func (t *Terraform) Truth() starlark.Bool {
func (t *Terraform) Type() string {
return "Terraform"
}
var _ starlark.Value = &Terraform{}

@ -20,6 +20,9 @@ assert.eq(tf.provider["aws"]["bar"] == None, False)
assert.eq(tf.provider["aws"]["bar"], bar)
assert.eq(tf.provider["aws"]["bar"].region, "bar")
# type
assert.eq(type(tf.provider), "ProviderCollection")
# backend
assert.eq(tf.backend, None)