2020-04-25 07:04:24 +02:00
|
|
|
package hcl2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
2021-03-17 14:20:05 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/model"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/syntax"
|
2020-04-25 07:04:24 +02:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
type nameInfo int
|
|
|
|
|
|
|
|
func (nameInfo) Format(name string) string {
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
2020-05-07 21:15:40 +02:00
|
|
|
//nolint: lll
|
2020-04-25 07:04:24 +02:00
|
|
|
func TestApplyRewriter(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
input, output string
|
2020-07-14 21:07:35 +02:00
|
|
|
skipPromises bool
|
2020-04-25 07:04:24 +02:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
input: `"v: ${resource.foo.bar}"`,
|
|
|
|
output: `__apply(resource.foo,eval(foo, "v: ${foo.bar}"))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"v: ${resource.baz[0]}"`,
|
|
|
|
output: `__apply(resource.baz,eval(baz, "v: ${baz[0]}"))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"v: ${resources[0].foo.bar}"`,
|
|
|
|
output: `__apply(resources[0].foo,eval(foo, "v: ${foo.bar}"))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"v: ${resources.*.id[0]}"`,
|
|
|
|
output: `__apply(resources.*.id[0],eval(id, "v: ${id}"))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"v: ${element(resources.*.id, 0)}"`,
|
|
|
|
output: `__apply(element(resources.*.id, 0),eval(ids, "v: ${ids}"))`,
|
|
|
|
},
|
2020-05-07 21:15:40 +02:00
|
|
|
{
|
|
|
|
input: `"v: ${[for r in resources: r.id][0]}"`,
|
|
|
|
output: `__apply([for r in resources: r.id][0],eval(id, "v: ${id}"))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"v: ${element([for r in resources: r.id], 0)}"`,
|
|
|
|
output: `__apply(element([for r in resources: r.id], 0),eval(ids, "v: ${ids}"))`,
|
|
|
|
},
|
2020-04-25 07:04:24 +02:00
|
|
|
{
|
|
|
|
input: `"v: ${resource[key]}"`,
|
|
|
|
output: `__apply(resource[key],eval(key, "v: ${key}"))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"v: ${resource[resource.id]}"`,
|
|
|
|
output: `__apply(__apply(resource.id,eval(id, resource[id])),eval(id, "v: ${id}"))`,
|
|
|
|
},
|
2020-05-07 21:15:40 +02:00
|
|
|
{
|
|
|
|
input: `resourcesPromise.*.id`,
|
|
|
|
output: `__apply(resourcesPromise, eval(resourcesPromise, resourcesPromise.*.id))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `[for r in resourcesPromise: r.id]`,
|
|
|
|
output: `__apply(resourcesPromise,eval(resourcesPromise, [for r in resourcesPromise: r.id]))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `resourcesOutput.*.id`,
|
|
|
|
output: `__apply(resourcesOutput, eval(resourcesOutput, resourcesOutput.*.id))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `[for r in resourcesOutput: r.id]`,
|
|
|
|
output: `__apply(resourcesOutput,eval(resourcesOutput, [for r in resourcesOutput: r.id]))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"v: ${[for r in resourcesPromise: r.id]}"`,
|
|
|
|
output: `__apply(__apply(resourcesPromise,eval(resourcesPromise, [for r in resourcesPromise: r.id])),eval(ids, "v: ${ids}"))`,
|
|
|
|
},
|
2020-04-25 07:04:24 +02:00
|
|
|
{
|
|
|
|
input: `toJSON({
|
2020-07-16 19:26:10 +02:00
|
|
|
Version = "2012-10-17"
|
|
|
|
Statement = [{
|
|
|
|
Effect = "Allow"
|
|
|
|
Principal = "*"
|
|
|
|
Action = [ "s3:GetObject" ]
|
|
|
|
Resource = [ "arn:aws:s3:::${resource.id}/*" ]
|
|
|
|
}]
|
|
|
|
})`,
|
2020-04-25 07:04:24 +02:00
|
|
|
output: `__apply(resource.id,eval(id, toJSON({
|
2020-07-16 19:26:10 +02:00
|
|
|
Version = "2012-10-17"
|
|
|
|
Statement = [{
|
|
|
|
Effect = "Allow"
|
|
|
|
Principal = "*"
|
|
|
|
Action = [ "s3:GetObject" ]
|
|
|
|
Resource = [ "arn:aws:s3:::${id}/*" ]
|
|
|
|
}]
|
|
|
|
})))`,
|
2020-04-25 07:04:24 +02:00
|
|
|
},
|
2020-07-14 21:07:35 +02:00
|
|
|
{
|
|
|
|
input: `getPromise().property`,
|
|
|
|
output: `__apply(getPromise(), eval(getPromise, getPromise.property))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `getPromise().object.foo`,
|
|
|
|
output: `__apply(getPromise(), eval(getPromise, getPromise.object.foo))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `getPromise().property`,
|
|
|
|
output: `getPromise().property`,
|
|
|
|
skipPromises: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `getPromise().object.foo`,
|
|
|
|
output: `getPromise().object.foo`,
|
|
|
|
skipPromises: true,
|
|
|
|
},
|
2020-07-16 19:26:10 +02:00
|
|
|
{
|
|
|
|
input: `getPromise(resource.id).property`,
|
|
|
|
output: `__apply(__apply(resource.id,eval(id, getPromise(id))), eval(getPromise, getPromise.property))`,
|
|
|
|
},
|
2020-04-25 07:04:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
resourceType := model.NewObjectType(map[string]model.Type{
|
|
|
|
"id": model.NewOutputType(model.StringType),
|
|
|
|
"foo": model.NewOutputType(model.NewObjectType(map[string]model.Type{
|
|
|
|
"bar": model.StringType,
|
|
|
|
})),
|
|
|
|
"baz": model.NewOutputType(model.NewListType(model.StringType)),
|
|
|
|
})
|
|
|
|
|
|
|
|
scope := model.NewRootScope(syntax.None)
|
|
|
|
scope.Define("key", &model.Variable{
|
|
|
|
Name: "key",
|
|
|
|
VariableType: model.StringType,
|
|
|
|
})
|
|
|
|
scope.Define("resource", &model.Variable{
|
|
|
|
Name: "resource",
|
|
|
|
VariableType: resourceType,
|
|
|
|
})
|
|
|
|
scope.Define("resources", &model.Variable{
|
|
|
|
Name: "resources",
|
|
|
|
VariableType: model.NewListType(resourceType),
|
|
|
|
})
|
2020-05-07 21:15:40 +02:00
|
|
|
scope.Define("resourcesPromise", &model.Variable{
|
|
|
|
Name: "resourcesPromise",
|
|
|
|
VariableType: model.NewPromiseType(model.NewListType(resourceType)),
|
|
|
|
})
|
|
|
|
scope.Define("resourcesOutput", &model.Variable{
|
|
|
|
Name: "resourcesOutput",
|
|
|
|
VariableType: model.NewOutputType(model.NewListType(resourceType)),
|
|
|
|
})
|
2020-04-25 07:04:24 +02:00
|
|
|
scope.DefineFunction("element", pulumiBuiltins["element"])
|
|
|
|
scope.DefineFunction("toJSON", pulumiBuiltins["toJSON"])
|
2020-07-14 21:07:35 +02:00
|
|
|
scope.DefineFunction("getPromise", model.NewFunction(model.StaticFunctionSignature{
|
2020-07-16 19:26:10 +02:00
|
|
|
Parameters: []model.Parameter{{
|
|
|
|
Name: "p",
|
|
|
|
Type: model.NewOptionalType(model.StringType),
|
|
|
|
}},
|
2020-07-14 21:07:35 +02:00
|
|
|
ReturnType: model.NewPromiseType(model.NewObjectType(map[string]model.Type{
|
|
|
|
"property": model.StringType,
|
|
|
|
"object": model.NewObjectType(map[string]model.Type{
|
|
|
|
"foo": model.StringType,
|
|
|
|
}),
|
|
|
|
})),
|
|
|
|
}))
|
2020-04-25 07:04:24 +02:00
|
|
|
|
|
|
|
for _, c := range cases {
|
2020-07-14 21:07:35 +02:00
|
|
|
t.Run(c.input, func(t *testing.T) {
|
|
|
|
expr, diags := model.BindExpressionText(c.input, scope, hcl.Pos{})
|
|
|
|
assert.Len(t, diags, 0)
|
2020-04-25 07:04:24 +02:00
|
|
|
|
2020-07-14 21:07:35 +02:00
|
|
|
expr, diags = RewriteApplies(expr, nameInfo(0), !c.skipPromises)
|
|
|
|
assert.Len(t, diags, 0)
|
2020-04-25 07:04:24 +02:00
|
|
|
|
2020-07-14 21:07:35 +02:00
|
|
|
assert.Equal(t, c.output, fmt.Sprintf("%v", expr))
|
|
|
|
})
|
2020-04-25 07:04:24 +02:00
|
|
|
}
|
|
|
|
}
|