1
1
mirror of https://github.com/mcuadros/ascode synced 2024-11-23 01:11:59 +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 { func NewRuntime(pm *terraform.PluginManager) *Runtime {
tf := types.MakeTerraform(pm) tf := types.NewTerraform(pm)
return &Runtime{ return &Runtime{
Terraform: tf, Terraform: tf,

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

@ -18,6 +18,11 @@ type ResourceCollection struct {
*starlark.List *starlark.List
} }
var _ starlark.Value = &ResourceCollection{}
var _ starlark.HasAttrs = &ResourceCollection{}
var _ starlark.Callable = &ResourceCollection{}
var _ starlark.Comparable = &ResourceCollection{}
func NewResourceCollection( func NewResourceCollection(
typ string, k Kind, block *configschema.Block, provider *Provider, parent *Resource, typ string, k Kind, block *configschema.Block, provider *Provider, parent *Resource,
) *ResourceCollection { ) *ResourceCollection {
@ -78,12 +83,12 @@ func (c *ResourceCollection) Freeze() {}
// Hash honors the starlark.Value interface. // Hash honors the starlark.Value interface.
func (c *ResourceCollection) Hash() (uint32, error) { 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. // Name honors the starlark.Callable interface.
func (c *ResourceCollection) Name() string { func (c *ResourceCollection) Name() string {
return c.typ return c.Type()
} }
// CallInternal honors the starlark.Callable interface. // CallInternal honors the starlark.Callable interface.
@ -279,6 +284,11 @@ type ProviderCollection struct {
*Dict *Dict
} }
var _ starlark.Value = &ProviderCollection{}
var _ starlark.HasAttrs = &ProviderCollection{}
var _ starlark.Callable = &ProviderCollection{}
var _ starlark.Comparable = &ProviderCollection{}
func NewProviderCollection(pm *terraform.PluginManager) *ProviderCollection { func NewProviderCollection(pm *terraform.PluginManager) *ProviderCollection {
return &ProviderCollection{ return &ProviderCollection{
pm: pm, 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. // Type honors the starlark.Value interface.
func (c *ProviderCollection) Type() string { func (c *ProviderCollection) Type() string {
return "ProviderCollection" return "ProviderCollection"
@ -306,12 +311,12 @@ func (c *ProviderCollection) Freeze() {}
// Hash honors the starlark.Value interface. // Hash honors the starlark.Value interface.
func (c *ProviderCollection) Hash() (uint32, error) { 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. // Name honors the starlark.Callable interface.
func (c *ProviderCollection) Name() string { func (c *ProviderCollection) Name() string {
return "foo" return c.Type()
} }
// CallInternal honors the starlark.Callable interface. // 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) 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 { if err != nil {
return nil, err return nil, err
} }

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

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

@ -73,7 +73,7 @@ func doTestPrint(t *testing.T, filename string, print func(*starlark.Thread, str
"hcl": BuiltinHCL(), "hcl": BuiltinHCL(),
"fn": BuiltinFunctionComputed(), "fn": BuiltinFunctionComputed(),
"evaluate": BuiltinEvaluate(), "evaluate": BuiltinEvaluate(),
"tf": MakeTerraform(pm), "tf": NewTerraform(pm),
} }
_, err := starlark.ExecFile(thread, filename, nil, predeclared) _, 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") return nil, fmt.Errorf("unexpected positional arguments count")
} }
p, err := MakeProvisioner(pm, name.GoString()) p, err := NewProvisioner(pm, name.GoString())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -38,7 +38,7 @@ type Provisioner struct {
*Resource *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) cli, meta, err := pm.Provisioner(typ)
if err != nil { if err != nil {
return nil, err return nil, err

@ -127,6 +127,11 @@ type Resource struct {
provisioners []*Provisioner 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 // MakeResource returns a new resource of the given kind, type based on the
// given configschema.Block. // given configschema.Block.
func MakeResource(name, typ string, k Kind, b *configschema.Block, provider *Provider, parent *Resource) *Resource { 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 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) { func (x *Resource) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) {
y := y_.(*Resource) y := y_.(*Resource)
switch op { switch op {

@ -51,13 +51,17 @@ type Terraform struct {
p *ProviderCollection p *ProviderCollection
} }
// MakeTerraform returns a new instance of Terraform // NewTerraform returns a new instance of Terraform
func MakeTerraform(pm *terraform.PluginManager) *Terraform { func NewTerraform(pm *terraform.PluginManager) *Terraform {
return &Terraform{ return &Terraform{
p: NewProviderCollection(pm), p: NewProviderCollection(pm),
} }
} }
var _ starlark.Value = &Terraform{}
var _ starlark.HasAttrs = &Terraform{}
var _ starlark.HasSetField = &Terraform{}
// Attr honors the starlark.HasAttrs interface. // Attr honors the starlark.HasAttrs interface.
func (t *Terraform) Attr(name string) (starlark.Value, error) { func (t *Terraform) Attr(name string) (starlark.Value, error) {
switch name { switch name {
@ -101,7 +105,7 @@ func (t *Terraform) Freeze() {} // immutable
// Hash honors the starlark.Value interface. // Hash honors the starlark.Value interface.
func (t *Terraform) Hash() (uint32, error) { 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. // String honors the starlark.Value interface.
@ -118,5 +122,3 @@ func (t *Terraform) Truth() starlark.Bool {
func (t *Terraform) Type() string { func (t *Terraform) Type() string {
return "Terraform" 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"], bar)
assert.eq(tf.provider["aws"]["bar"].region, "bar") assert.eq(tf.provider["aws"]["bar"].region, "bar")
# type
assert.eq(type(tf.provider), "ProviderCollection")
# backend # backend
assert.eq(tf.backend, None) assert.eq(tf.backend, None)