pulumi / pulumi-yaml

YAML language provider for Pulumi
Apache License 2.0
38 stars 11 forks source link

Nested variable resolution #506

Open aureq opened 10 months ago

aureq commented 10 months ago

Hello!

Issue details

Currently, pulumi YAML is unable to resolve nested variables such as this example. The important line here being project: ${projectDescription.${selector}} where the project description could be fet

name: example-yaml-app
runtime: yaml
description: A minimal AWS Pulumi YAML program
outputs:
  bucketName: ${my-bucket.id}

variables:
    projectDescription:
        projectA: "This is project A"
        projectB: "This is project B"

config:
    selector: "projectA"

resources:
  # Create an AWS resource (S3 Bucket)
  my-bucket:
    type: aws:s3:Bucket
    properties:
      tags:
        project: ${projectDescription.${selector}}

The pulumi pre --diff shows

+ pulumi:pulumi:Stack: (create)
    [urn=urn:pulumi:dev::delete-me::pulumi:pulumi:Stack::delete-me-dev]
    + aws:s3/bucket:Bucket: (create)
        [urn=urn:pulumi:dev::delete-me::aws:s3/bucket:Bucket::my-bucket]
        acl         : "private"
        bucket      : "my-bucket-849a90c"
        forceDestroy: false
        tags        : {
            project   : "<nil> }"
        }
    --outputs:--
    bucketName: output<string>

I've also tried using project: ${projectDescription}.${selector} but this returns:

+ pulumi:pulumi:Stack: (create)
    [urn=urn:pulumi:dev::delete-me::pulumi:pulumi:Stack::delete-me-dev]
    + aws:s3/bucket:Bucket: (create)
        [urn=urn:pulumi:dev::delete-me::aws:s3/bucket:Bucket::my-bucket]
        acl         : "private"
        bucket      : "my-bucket-bd16986"
        forceDestroy: false
        tags        : {
            project   : "map[projectA:This is project A projectB:This is project B].projectA"
        }
    --outputs:--
    bucketName: output<string>

Affected area/feature

AaronFriel commented 10 months ago

As an alternative, would fn::select supporting maps and object types meet the user's needs?

(This is a straw proposal, but I think this would be a lower lift than changing the expression syntax similar to how you've described.)

# all other keys identical to example

resources:
  # Create an AWS resource (S3 Bucket)
  my-bucket:
    type: aws:s3:Bucket
    properties:
      tags:
        project: 
          fn::select:
            - ${selector}
            - ${projectDescription}
grantbeattie commented 10 months ago

fn::select would be an option.. but how would it work for multi-level objects? eg.

variables:
  projectDescription:
    regionA:
      projectA: "This is region A, project A"
      projectB: "This is region A, project B"
    regionB:
      projectA: "This is region B, project A"
      projectB: "This is region B, project B"

config:
  regionSelector: "regionA"
  projectSelector: "projectA"

projectDescription.${regionSelector}.${projectSelector} would read fairly well and is obvious what is happening.

Frassle commented 10 months ago

Why not ${projectDescription[selector]}?

grantbeattie commented 10 months ago

Why not ${projectDescription[selector]}?

yep, that works too.

AaronFriel commented 10 months ago

@Frassle changing the substitution parsing requires more significant changes, changing or adding a built-in is lower lift.

However I'm wondering if std already has this?

It looks like fn::std:lookup has the right shape.