Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support (logical) name for resources and config variables #546

Merged
merged 1 commit into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### Improvements

- Support (logical) name for resources and config variables
[#546](https://github.com/pulumi/pulumi-yaml/pull/546)

### Bug Fixes
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ variables:
arguments:
filters:
- name: name
values: ["amzn-ami-hvm-*-x86_64-ebs"]
values: ["amzn2-ami-hvm-2.0.20231218.0-x86_64-ebs"]
owners: ["137112412989"]
mostRecent: true
return: id
Expand Down
2 changes: 1 addition & 1 deletion examples/webserver-json/Main.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"function": "aws:getAmi",
"arguments": {
"filters": [
{ "name": "name", "values": ["amzn-ami-hvm-*-x86_64-ebs"] }
{ "name": "name", "values": ["amzn2-ami-hvm-2.0.20231218.0-x86_64-ebs"] }
],
"owners": ["137112412989"],
"mostRecent": true
Expand Down
2 changes: 1 addition & 1 deletion examples/webserver/Pulumi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ variables:
arguments:
filters:
- name: name
values: ["amzn-ami-hvm-*-x86_64-ebs"]
values: ["amzn2-ami-hvm-2.0.20231218.0-x86_64-ebs"]
owners: ["137112412989"]
mostRecent: true
return: id
Expand Down
24 changes: 17 additions & 7 deletions pkg/pulumiyaml/ast/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ type ConfigParamDecl struct {
declNode

Type *StringExpr
Name *StringExpr
Secret *BooleanExpr
Default Expr
Value Expr
Expand All @@ -281,19 +282,20 @@ func (d *ConfigParamDecl) recordSyntax() *syntax.Node {
return &d.syntax
}

func ConfigParamSyntax(node *syntax.ObjectNode, typ *StringExpr,
func ConfigParamSyntax(node *syntax.ObjectNode, typ *StringExpr, name *StringExpr,
secret *BooleanExpr, defaultValue Expr) *ConfigParamDecl {

return &ConfigParamDecl{
declNode: decl(node),
Type: typ,
Name: name,
Secret: secret,
Default: defaultValue,
}
}

func ConfigParam(typ *StringExpr, defaultValue Expr, secret *BooleanExpr) *ConfigParamDecl {
return ConfigParamSyntax(nil, typ, secret, defaultValue)
func ConfigParam(typ *StringExpr, name *StringExpr, defaultValue Expr, secret *BooleanExpr) *ConfigParamDecl {
return ConfigParamSyntax(nil, typ, name, secret, defaultValue)
}

type ResourceOptionsDecl struct {
Expand Down Expand Up @@ -411,6 +413,7 @@ type ResourceDecl struct {
declNode

Type *StringExpr
Name *StringExpr
DefaultProvider *BooleanExpr
Properties PropertyMapDecl
Options ResourceOptionsDecl
Expand All @@ -423,23 +426,30 @@ func (d *ResourceDecl) recordSyntax() *syntax.Node {

// The names of exported fields.
func (*ResourceDecl) Fields() []string {
return []string{"type", "defaultprovider", "properties", "options", "get"}
return []string{"type", "name", "defaultprovider", "properties", "options", "get"}
}

func ResourceSyntax(node *syntax.ObjectNode, typ *StringExpr, defaultProvider *BooleanExpr,
func ResourceSyntax(node *syntax.ObjectNode, typ *StringExpr, name *StringExpr, defaultProvider *BooleanExpr,
properties PropertyMapDecl, options ResourceOptionsDecl, get GetResourceDecl) *ResourceDecl {
return &ResourceDecl{
declNode: decl(node),
Type: typ,
Name: name,
DefaultProvider: defaultProvider,
Properties: properties,
Options: options,
Get: get,
}
}

func Resource(typ *StringExpr, defaultProvider *BooleanExpr, properties PropertyMapDecl, options ResourceOptionsDecl, get GetResourceDecl) *ResourceDecl {
return ResourceSyntax(nil, typ, defaultProvider, properties, options, get)
func Resource(
typ *StringExpr,
name *StringExpr,
defaultProvider *BooleanExpr,
properties PropertyMapDecl,
options ResourceOptionsDecl,
get GetResourceDecl) *ResourceDecl {
return ResourceSyntax(nil, typ, name, defaultProvider, properties, options, get)
}

type CustomTimeoutsDecl struct {
Expand Down
25 changes: 10 additions & 15 deletions pkg/pulumiyaml/codegen/gen_program.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,6 @@ import (
func GenerateProgram(program *pcl.Program) (map[string][]byte, hcl.Diagnostics, error) {
g := generator{}

g.logicalNames = map[string]string{}
for _, n := range program.Nodes {
switch n := n.(type) {
case *pcl.Resource:
g.logicalNames[n.Name()] = n.LogicalName()
case *pcl.OutputVariable:
g.logicalNames[n.Name()] = n.LogicalName()
}
}

for _, n := range program.Nodes {
g.genNode(n)
}
Expand Down Expand Up @@ -96,7 +86,6 @@ func GenerateProject(directory string, project workspace.Project, program *pcl.P
type generator struct {
diags hcl.Diagnostics

logicalNames map[string]string
// These values can be assembled into a template
config []syn.ObjectPropertyDef
resources []syn.ObjectPropertyDef
Expand Down Expand Up @@ -239,6 +228,11 @@ func (g *generator) genResource(n *pcl.Resource) {
entries := []syn.ObjectPropertyDef{
g.TypeProperty(collapseToken(n.Token)),
}

if n.Name() != n.LogicalName() {
entries = append(entries, syn.ObjectProperty(syn.String("name"), syn.String(n.LogicalName())))
}

if len(properties) > 0 {
entries = append(entries, syn.ObjectProperty(syn.String("properties"), syn.Object(properties...)))
}
Expand All @@ -248,7 +242,7 @@ func (g *generator) genResource(n *pcl.Resource) {
r := syn.Object(entries...)

g.resources = append(g.resources, syn.ObjectProperty(
syn.StringSyntax(trivia(n.Definition), n.LogicalName()), r))
syn.StringSyntax(trivia(n.Definition), n.Name()), r))
}

func (g *generator) genOutputVariable(n *pcl.OutputVariable) {
Expand Down Expand Up @@ -561,9 +555,6 @@ func (g *generator) expr(e model.Expression) syn.Node {

case *model.ScopeTraversalExpression:
rootName := e.RootName
if logicalName, found := g.logicalNames[rootName]; found {
rootName = logicalName
}
traversal := g.Traversal(e.Traversal).WithRoot(rootName, e.Tokens.Root.Range().Ptr())
s := fmt.Sprintf("${%s}", traversal)
return syn.String(s)
Expand Down Expand Up @@ -640,6 +631,10 @@ func (g *generator) genConfigVariable(n *pcl.ConfigVariable) {
entries := []syn.ObjectPropertyDef{
g.TypeProperty(n.Type().String()),
}

if n.Name() != n.LogicalName() {
entries = append(entries, syn.ObjectProperty(syn.String("name"), syn.String(n.LogicalName())))
}
if n.DefaultValue != nil {
prop := syn.ObjectProperty(syn.String("default"), g.expr(n.DefaultValue))
entries = append(entries, prop)
Expand Down
4 changes: 2 additions & 2 deletions pkg/pulumiyaml/codegen/gen_program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,6 @@ func TestGenerateProgram(t *testing.T) {
// But the actual error is that it is using a Splat operator.
case "components":
// https://github.com/pulumi/pulumi-yaml/issues/476
case "logical-name":
// https://github.com/pulumi/pulumi-yaml/issues/477
case "unknown-resource":
// https://github.com/pulumi/pulumi-yaml/issues/478
case "optional-complex-config":
Expand Down Expand Up @@ -201,6 +199,7 @@ func TestGenerateProgram(t *testing.T) {
case "regress-node-12507":
// https://github.com/pulumi/pulumi-yaml/issues/494
case "config-variables":
case "logical-name":
// Needs config set in order to compile/run.
tt.SkipCompile = codegen.NewStringSet("yaml")
l = append(l, tt)
Expand All @@ -218,6 +217,7 @@ func TestGenerateProgram(t *testing.T) {
assert.NoError(t, err)
assert.Falsef(t, diags.HasErrors(), "%s", diags.Error())
err = pulumi.RunErr(func(ctx *pulumi.Context) error {

return pulumiyaml.RunTemplate(ctx, templateDecl, nil, nil, testPackageLoader{t})
}, pulumi.WithMocks("test", "gen", &testMonitor{}), func(ri *pulumi.RunInfo) { ri.DryRun = true })
assert.NoError(t, err)
Expand Down
24 changes: 19 additions & 5 deletions pkg/pulumiyaml/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,9 @@ func (e *programEvaluator) registerConfig(intm configNode) (interface{}, bool) {
case configNodeYaml:
k, intmKey = intm.Key.Value, intm.Key
c := intm.Value
if c.Name != nil && c.Name.Value != "" {
k = c.Name.Value
}
// If we implement global type checking, the type of configuration variables
// can be inferred and this requirement relaxed.
if c.Type == nil && c.Default == nil {
Expand Down Expand Up @@ -1216,6 +1219,11 @@ func (e *programEvaluator) registerResource(kvp resourceNode) (lateboundResource

// Create either a latebound custom resource or latebound provider resource depending on
// whether the type token indicates a special provider type.
resourceName := k
if v.Name != nil && v.Name.Value != "" {
resourceName = v.Name.Value
}

var state lateboundResource
var res pulumi.Resource
var resourceSchema *schema.Resource
Expand All @@ -1224,12 +1232,12 @@ func (e *programEvaluator) registerResource(kvp resourceNode) (lateboundResource
}
isProvider := false
if strings.HasPrefix(v.Type.Value, "pulumi:providers:") {
r := lateboundProviderResourceState{name: k, resourceSchema: resourceSchema}
r := lateboundProviderResourceState{name: resourceName, resourceSchema: resourceSchema}
state = &r
res = &r
isProvider = true
} else {
r := lateboundCustomResourceState{name: k, resourceSchema: resourceSchema}
r := lateboundCustomResourceState{name: resourceName, resourceSchema: resourceSchema}
state = &r
res = &r
}
Expand Down Expand Up @@ -1296,7 +1304,7 @@ func (e *programEvaluator) registerResource(kvp resourceNode) (lateboundResource

// Now register the resulting resource with the engine.
if isComponent {
err = e.pulumiCtx.RegisterRemoteComponentResource(string(typ), k, untypedArgs(props), res, opts...)
err = e.pulumiCtx.RegisterRemoteComponentResource(string(typ), resourceName, untypedArgs(props), res, opts...)
} else if isRead {
s, ok := e.evaluateExpr(v.Get.Id)
if !ok {
Expand All @@ -1311,9 +1319,15 @@ func (e *programEvaluator) registerResource(kvp resourceNode) (lateboundResource
e.errorf(v.Get.Id, "get.id must be a prompt string, instead got type %T", s)
return nil, false
}
err = e.pulumiCtx.ReadResource(string(typ), k, pulumi.ID(id), untypedArgs(props), res.(pulumi.CustomResource), opts...)
err = e.pulumiCtx.ReadResource(
string(typ),
resourceName,
pulumi.ID(id),
untypedArgs(props),
res.(pulumi.CustomResource),
opts...)
} else {
err = e.pulumiCtx.RegisterResource(string(typ), k, untypedArgs(props), res, opts...)
err = e.pulumiCtx.RegisterResource(string(typ), resourceName, untypedArgs(props), res, opts...)
}
if err != nil {
e.error(kvp.Key, err.Error())
Expand Down
2 changes: 1 addition & 1 deletion pkg/pulumiyaml/run_plugin_version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ resources:
arguments:
filters:
- name: name
values: ["amzn-ami-hvm-*-x86_64-ebs"]
values: ["amzn2-ami-hvm-2.0.20231218.0-x86_64-ebs"]
owners: ["137112412989"]
mostRecent: true
Return: id
Expand Down
73 changes: 73 additions & 0 deletions pkg/pulumiyaml/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,37 @@ configuration:
assert.False(t, found, "We should not get any errors: '%s'", diags)
}

func TestConfigNames(t *testing.T) { //nolint:paralleltest
const text = `name: test-yaml
runtime: yaml
configuration:
foo:
type: String
name: logicalFoo
bar:
type: String
`

tmpl := yamlTemplate(t, text)
fooValue := "value from logicalName"
barValue := "value from config"
setConfig(t,
resource.PropertyMap{
projectConfigKey("logicalFoo"): resource.NewStringProperty(fooValue),
projectConfigKey("bar"): resource.NewStringProperty(barValue),
})
testRan := false
err := testTemplateDiags(t, tmpl, func(e *programEvaluator) {
assert.Equal(t, fooValue, e.config["foo"])
assert.Equal(t, barValue, e.config["bar"])

testRan = true
})
assert.True(t, testRan, "Our tests didn't run")
diags, found := HasDiagnostics(err)
assert.False(t, found, "We should not get any errors: '%s'", diags)
}

func TestConflictingConfigSecrets(t *testing.T) { //nolint:paralleltest
const text = `name: test-yaml
runtime: yaml
Expand Down Expand Up @@ -1944,6 +1975,48 @@ resources:
assert.NoError(t, err)
}

func TestResourceWithLogicalName(t *testing.T) {
t.Parallel()

text := `
name: test-logical-name
runtime: yaml
resources:
sourceName:
type: test:resource:UsingLogicalName
name: actual-registered-name

sourceNameOnly:
type: test:resource:WithoutLogicalName
`
tmpl := yamlTemplate(t, strings.TrimSpace(text))
mocks := &testMonitor{
NewResourceF: func(args pulumi.MockResourceArgs) (string, resource.PropertyMap, error) {
t.Logf("args: %+v", args)
if args.TypeToken == "test:resource:UsingLogicalName" {
registeredName := "actual-registered-name"
assert.Equal(t, registeredName, args.Name)
assert.Equal(t, registeredName, args.RegisterRPC.GetName())
} else if args.TypeToken == "test:resource:WithoutLogicalName" {
assert.Equal(t, "sourceNameOnly", args.Name)
assert.Equal(t, "sourceNameOnly", args.RegisterRPC.GetName())
} else {
t.Fatalf("unexpected type token: %s", args.TypeToken)
}

return args.Name, args.Inputs, nil
},
}
err := pulumi.RunErr(func(ctx *pulumi.Context) error {
runner := newRunner(tmpl, newMockPackageMap())
err := runner.Evaluate(ctx)
assert.Len(t, err, 0)
assert.Equal(t, err.Error(), "no diagnostics")
return nil
}, pulumi.WithMocks("project", "stack", mocks))
assert.NoError(t, err)
}

func TestGetConfNodesFromMap(t *testing.T) {
t.Parallel()
tests := []struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
ami = invoke("aws:index:getAmi", {
filters = [{
name = "name"
values = ["amzn-ami-hvm-*-x86_64-ebs"]
values = ["amzn2-ami-hvm-2.0.20231218.0-x86_64-ebs"]
}]
owners = ["137112412989"] // Amazon
mostRecent = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ variables:
filters:
- name: name
values:
- amzn-ami-hvm-*-x86_64-ebs
- amzn2-ami-hvm-2.0.20231218.0-x86_64-ebs
owners:
- '137112412989'
mostRecent: true
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
configuration:
configLexicalName:
type: string
name: "cC-Charlie_charlie.\U0001F603⁉️"
resources:
"aA-Alpha_alpha.\U0001F92F⁉️":
resourceLexicalName:
type: random:RandomPet
name: "aA-Alpha_alpha.\U0001F92F⁉️"
properties:
prefix: ${configLexicalName}
outputs:
"bB-Beta_beta.\U0001F49C⁉": "${[\"aA-Alpha_alpha.\U0001F92F⁉️\"].id}"
"bB-Beta_beta.\U0001F49C⁉": ${resourceLexicalName.id}
Loading
Loading