Skip to content

Commit 4a1a60b

Browse files
committed
starlark/types: validate function and CallStack reccord
1 parent 2a18954 commit 4a1a60b

File tree

9 files changed

+312
-22
lines changed

9 files changed

+312
-22
lines changed

starlark/types/backend.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func MakeBackend(
5353
}
5454

5555
pm := t.Local(PluginManagerLocal).(*terraform.PluginManager)
56-
p, err := NewBackend(pm, name.GoString())
56+
p, err := NewBackend(pm, name.GoString(), t.CallStack())
5757
if err != nil {
5858
return nil, err
5959
}
@@ -101,7 +101,7 @@ var _ starlark.HasAttrs = &Backend{}
101101
var _ starlark.Comparable = &Backend{}
102102

103103
// NewBackend returns a new Backend instance based on given arguments,
104-
func NewBackend(pm *terraform.PluginManager, typ string) (*Backend, error) {
104+
func NewBackend(pm *terraform.PluginManager, typ string, cs starlark.CallStack) (*Backend, error) {
105105
fn := binit.Backend(typ)
106106
if fn == nil {
107107
return nil, fmt.Errorf("unable to find backend %q", typ)
@@ -112,7 +112,7 @@ func NewBackend(pm *terraform.PluginManager, typ string) (*Backend, error) {
112112
return &Backend{
113113
pm: pm,
114114
b: b,
115-
Resource: NewResource("", typ, BackendKind, b.ConfigSchema(), nil, nil),
115+
Resource: NewResource("", typ, BackendKind, b.ConfigSchema(), nil, nil, cs),
116116
}, nil
117117
}
118118

@@ -261,7 +261,7 @@ func (s *State) initialize(state *states.State, mod *states.Module) error {
261261
addrs := state.ProviderAddrs()
262262
for _, addr := range addrs {
263263
typ := addr.ProviderConfig.Type.Type
264-
p, err := NewProvider(s.pm, typ, "", addr.ProviderConfig.Alias)
264+
p, err := NewProvider(s.pm, typ, "", addr.ProviderConfig.Alias, nil)
265265
if err != nil {
266266
return err
267267
}
@@ -297,7 +297,7 @@ func (s *State) initializeResource(p *Provider, r *states.Resource) error {
297297

298298
multi := r.EachMode != states.NoEach
299299
for _, instance := range r.Instances {
300-
r := NewResource(name, typ, ResourceKind, schema.Block, p, p.Resource)
300+
r := NewResource(name, typ, ResourceKind, schema.Block, p, p.Resource, nil)
301301

302302
var val interface{}
303303
if err := json.Unmarshal(instance.Current.AttrsJSON, &val); err != nil {

starlark/types/collection.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ import (
5555
// Value to match in the given key.
5656
//
5757
type ResourceCollection struct {
58-
typ string
59-
kind Kind
60-
block *configschema.Block
61-
provider *Provider
62-
parent *Resource
58+
typ string
59+
kind Kind
60+
block *configschema.Block
61+
nestedblock *configschema.NestedBlock
62+
provider *Provider
63+
parent *Resource
64+
6365
*starlark.List
6466
}
6567

@@ -82,6 +84,21 @@ func NewResourceCollection(
8284
}
8385
}
8486

87+
// NewNestedResourceCollection returns
88+
func NewNestedResourceCollection(
89+
typ string, block *configschema.NestedBlock, provider *Provider, parent *Resource,
90+
) *ResourceCollection {
91+
return &ResourceCollection{
92+
typ: typ,
93+
kind: NestedKind,
94+
block: &block.Block,
95+
nestedblock: block,
96+
provider: provider,
97+
parent: parent,
98+
List: starlark.NewList(nil),
99+
}
100+
}
101+
85102
// LoadList loads a list of dicts on the collection. It clears the collection.
86103
func (c *ResourceCollection) LoadList(l *starlark.List) error {
87104
if err := c.List.Clear(); err != nil {
@@ -94,7 +111,7 @@ func (c *ResourceCollection) LoadList(l *starlark.List) error {
94111
return fmt.Errorf("%d: expected dict, got %s", i, l.Index(i).Type())
95112
}
96113

97-
r := NewResource("", c.typ, c.kind, c.block, c.provider, c.parent)
114+
r := NewResource("", c.typ, c.kind, c.block, c.provider, c.parent, nil)
98115
if dict != nil && dict.Len() != 0 {
99116
if err := r.loadDict(dict); err != nil {
100117
return err

starlark/types/provider.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func MakeProvider(
5050
}
5151

5252
pm := t.Local(PluginManagerLocal).(*terraform.PluginManager)
53-
p, err := NewProvider(pm, name.GoString(), version.GoString(), alias.GoString())
53+
p, err := NewProvider(pm, name.GoString(), version.GoString(), alias.GoString(), t.CallStack())
5454
if err != nil {
5555
return nil, err
5656
}
@@ -112,7 +112,7 @@ var _ starlark.HasAttrs = &Provider{}
112112
var _ starlark.Comparable = &Provider{}
113113

114114
// NewProvider returns a new Provider instance from a given type, version and name.
115-
func NewProvider(pm *terraform.PluginManager, typ, version, name string) (*Provider, error) {
115+
func NewProvider(pm *terraform.PluginManager, typ, version, name string, cs starlark.CallStack) (*Provider, error) {
116116
cli, meta, err := pm.Provider(typ, version, false)
117117
if err != nil {
118118
return nil, err
@@ -141,7 +141,7 @@ func NewProvider(pm *terraform.PluginManager, typ, version, name string) (*Provi
141141
meta: meta,
142142
}
143143

144-
p.Resource = NewResource(name, typ, ProviderKind, response.Provider.Block, p, nil)
144+
p.Resource = NewResource(name, typ, ProviderKind, response.Provider.Block, p, nil, cs)
145145
p.dataSources = NewResourceCollectionGroup(p, DataSourceKind, response.DataSources)
146146
p.resources = NewResourceCollectionGroup(p, ResourceKind, response.ResourceTypes)
147147

starlark/types/provider_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ func doTestPrint(t *testing.T, filename string, print func(*starlark.Thread, str
8181
"hcl": BuiltinHCL(),
8282
"fn": BuiltinFunctionAttribute(),
8383
"evaluate": BuiltinEvaluate(),
84+
"validate": BuiltinValidate(),
8485
"tf": NewTerraform(pm),
8586
}
8687

starlark/types/provisioner.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func MakeProvisioner(
4444
return nil, fmt.Errorf("unexpected positional arguments count")
4545
}
4646

47-
p, err := NewProvisioner(pm, name.GoString())
47+
p, err := NewProvisioner(pm, name.GoString(), t.CallStack())
4848
if err != nil {
4949
return nil, err
5050
}
@@ -79,7 +79,7 @@ type Provisioner struct {
7979
}
8080

8181
// NewProvisioner returns a new Provisioner for the given type.
82-
func NewProvisioner(pm *terraform.PluginManager, typ string) (*Provisioner, error) {
82+
func NewProvisioner(pm *terraform.PluginManager, typ string, cs starlark.CallStack) (*Provisioner, error) {
8383
cli, meta, err := pm.Provisioner(typ)
8484
if err != nil {
8585
return nil, err
@@ -103,7 +103,7 @@ func NewProvisioner(pm *terraform.PluginManager, typ string) (*Provisioner, erro
103103
provisioner: provisioner,
104104
meta: meta,
105105

106-
Resource: NewResource(NameGenerator(), typ, ProvisionerKind, response.Provisioner, nil, nil),
106+
Resource: NewResource(NameGenerator(), typ, ProvisionerKind, response.Provisioner, nil, nil, cs),
107107
}, nil
108108
}
109109

starlark/types/resource.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var NameGenerator = func() string {
2020
return fmt.Sprintf("id_%s", ulid.MustNew(ulid.Timestamp(t), entropy))
2121
}
2222

23-
// Kind describes what kind of resource is represented by a Resource isntance.
23+
// Kind describes what kind of resource is represented by a Resource instance.
2424
type Kind string
2525

2626
// IsNamed returns true if this kind of resources contains a name.
@@ -65,7 +65,7 @@ func MakeResource(
6565
name = NameGenerator()
6666
}
6767

68-
r := NewResource(name, c.typ, c.kind, c.block, c.provider, c.parent)
68+
r := NewResource(name, c.typ, c.kind, c.block, c.provider, c.parent, t.CallStack())
6969
if dict != nil && dict.Len() != 0 {
7070
if err := r.loadDict(dict); err != nil {
7171
return nil, err
@@ -208,6 +208,8 @@ type Resource struct {
208208
parent *Resource
209209
dependencies []*Resource
210210
provisioners []*Provisioner
211+
212+
cs starlark.CallStack
211213
}
212214

213215
var _ starlark.Value = &Resource{}
@@ -217,7 +219,11 @@ var _ starlark.Comparable = &Resource{}
217219

218220
// NewResource returns a new resource of the given kind, type based on the
219221
// given configschema.Block.
220-
func NewResource(name, typ string, k Kind, b *configschema.Block, provider *Provider, parent *Resource) *Resource {
222+
func NewResource(
223+
name, typ string, k Kind,
224+
b *configschema.Block, provider *Provider, parent *Resource,
225+
cs starlark.CallStack,
226+
) *Resource {
221227
return &Resource{
222228
name: name,
223229
typ: typ,
@@ -226,6 +232,7 @@ func NewResource(name, typ string, k Kind, b *configschema.Block, provider *Prov
226232
values: NewValues(),
227233
provider: provider,
228234
parent: parent,
235+
cs: cs,
229236
}
230237
}
231238

@@ -337,11 +344,14 @@ func (r *Resource) attrBlock(name string, b *configschema.NestedBlock) (starlark
337344
return v.Starlark(), nil
338345
}
339346

347+
var output starlark.Value
340348
if b.MaxItems != 1 {
341-
return r.values.Set(name, MustValue(NewResourceCollection(name, NestedKind, &b.Block, r.provider, r))).Starlark(), nil
349+
output = NewNestedResourceCollection(name, b, r.provider, r)
350+
} else {
351+
output = NewResource("", name, NestedKind, &b.Block, r.provider, r, nil)
342352
}
343353

344-
return r.values.Set(name, MustValue(NewResource("", name, NestedKind, &b.Block, r.provider, r))).Starlark(), nil
354+
return r.values.Set(name, MustValue(output)).Starlark(), nil
345355
}
346356

347357
func (r *Resource) attrValue(name string, attr *configschema.Attribute) (starlark.Value, error) {
@@ -559,3 +569,15 @@ func (r *Resource) doCompareSameType(y *Resource, depth int) (bool, error) {
559569

560570
return true, nil
561571
}
572+
573+
func (r *Resource) CallStack() starlark.CallStack {
574+
if r.cs != nil {
575+
return r.cs
576+
}
577+
578+
if r.parent != nil {
579+
return r.parent.CallStack()
580+
}
581+
582+
return nil
583+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
load("assert.star", "assert")
2+
3+
helm = tf.provider("helm", "1.0.0", "default")
4+
helm.kubernetes.token = "foo"
5+
6+
# require scalar arguments
7+
helm.resource.release()
8+
errors = validate(helm)
9+
assert.eq(len(errors), 2)
10+
assert.eq(errors[0].pos, "testdata/validate.star:7:22")
11+
assert.eq(errors[1].pos, "testdata/validate.star:7:22")
12+
13+
# require list arguments
14+
google = tf.provider("google")
15+
r = google.resource.organization_iam_custom_role(role_id="foo", org_id="bar", title="qux")
16+
r.permissions = ["foo"]
17+
assert.eq(len(validate(google)), 0)
18+
19+
r.permissions.pop()
20+
assert.eq(len(validate(google)), 1)
21+
22+
# require blocks
23+
google = tf.provider("google")
24+
r = google.resource.compute_global_forwarding_rule(target="foo", name="bar")
25+
r.metadata_filters()
26+
assert.eq(len(validate(google)), 2)
27+
28+
errors = validate(google)
29+
for e in errors: print(e.pos, e.msg)

0 commit comments

Comments
 (0)