When it comes to string interpolation vs me, strin...
# typescript
c
When it comes to string interpolation vs me, string interpolation is undefeated 😅. I have a
Component Resource
I have created for the cluster autoscaler role. I want to pass a few args and use them within the IAM policy and role. I have it configured as below, but when I run a preview, the location where the string should be inserted is blank. I get no error and I've also tried using
pulumi.interpolate
Copy code
constructor(name: string, args: { clusterName: string, oidcArn: string, oidcUrl: string }, opts?: pulumi.ComponentResourceOptions) {
    super("pkg:iam:clusterAutoscalerRole", name, args, opts);
    
    this.policy = new aws.iam.Policy(name, {
      path: "/",
      description: "Amazon EKS - Cluster autoscaler policy",
      policy: `{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "autoscaling:SetDesiredCapacity",
                "autoscaling:TerminateInstanceInAutoScalingGroup"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/k8s.io/cluster-autoscaler/${args.clusterName}": "owned"
                }
            }
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeAutoScalingGroups",
                "ec2:DescribeLaunchTemplateVersions",
                "autoscaling:DescribeTags",
                "autoscaling:DescribeLaunchConfigurations",
                "ec2:DescribeInstanceTypes"
            ],
            "Resource": "*"
        }
    ]
}`
    }, { parent: this });
b
pulumi.jsonStringify
is a helper method to make this easier
c
Thanks @billowy-army-68599 I’ll give that a try when I’m back on my machine
I've gotten a bit closer to my desired outcome but I think my issue revolves around Output<T> and building the statement with
apply
. TypeScript is new to me and I feel this is largely where my issues have revolved around. If I do the following:
Copy code
constructor(name: string, args: { clusterName: string, oidcArn: string, oidcUrl: string }, opts?: pulumi.ComponentResourceOptions) {
    super("pkg:iam:clusterAutoscalerRole", name, args, opts);
    let clusterName: string = args.clusterName;
    let clusterTag: string = `aws:ResourceTag/k8s.io/cluster-autoscaler/${clusterName}`;

    this.policy = new aws.iam.Policy(name, {
      path: "/",
      description: "Amazon EKS - Cluster autoscaler policy",
      policy: pulumi.jsonStringify({
    Version: "2012-10-17",
    Statement: [
        {
            Sid: "VisualEditor0",
            Effect: "Allow",
            Action: [
                "autoscaling:SetDesiredCapacity",
                "autoscaling:TerminateInstanceInAutoScalingGroup"
            ],
            Resource: "*",
            Condition: {
                StringEquals: {
                    [clusterTag]: "owned"
                }
            }
        },
        {
            Sid: "VisualEditor1",
            Effect: "Allow",
            Action: [
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeAutoScalingGroups",
                "ec2:DescribeLaunchTemplateVersions",
                "autoscaling:DescribeTags",
                "autoscaling:DescribeLaunchConfigurations",
                "ec2:DescribeInstanceTypes"
            ],
            Resource: "*"
        }
    ]
})
    }, { parent: this });
I get this in preview:
Copy code
policy     : "{"Version":"2012-10-17","Statement":[{"Sid":"VisualEditor0","Effect":"Allow","Action":["autoscaling:SetDesiredCapacity","autoscaling:TerminateInstanceInAutoScalingGroup"],"Resource":"*","Condition":{"StringEquals":{"aws:ResourceTag/k8s.io/cluster-autoscaler/":"owned"}}},{"Sid":"VisualEditor1","Effect":"Allow","Action":["autoscaling:DescribeAutoScalingInstances","autoscaling:DescribeAutoScalingGroups","ec2:DescribeLaunchTemplateVersions","autoscaling:DescribeTags","autoscaling:DescribeLaunchConfigurations","ec2:DescribeInstanceTypes"],"Resource":"*"}]}"
Where part of the key is populated but I am still missing the cluster name portion.
Even tried this:
Copy code
constructor(name: string, args: { clusterName: string, oidcArn: string, oidcUrl: string }, opts?: pulumi.ComponentResourceOptions) {
    super("pkg:iam:clusterAutoscalerRole", name, args, opts);
    let tags = {};
    let clusterTag = pulumi.interpolate `aws:ResourceTag/k8s.io/cluster-autoscaler/${args.clusterName}`;
    clusterTag.apply(s => tags[s] = "owned");

    this.policy = new aws.iam.Policy(name, {
      path: "/",
      description: "Amazon EKS - Cluster autoscaler policy",
      policy: pulumi.jsonStringify({
    Version: "2012-10-17",
    Statement: [
        {
            Sid: "VisualEditor0",
            Effect: "Allow",
            Action: [
                "autoscaling:SetDesiredCapacity",
                "autoscaling:TerminateInstanceInAutoScalingGroup"
            ],
            Resource: "*",
            Condition: {
                StringEquals: tags
            }
        },
        {
            Sid: "VisualEditor1",
            Effect: "Allow",
            Action: [
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeAutoScalingGroups",
                "ec2:DescribeLaunchTemplateVersions",
                "autoscaling:DescribeTags",
                "autoscaling:DescribeLaunchConfigurations",
                "ec2:DescribeInstanceTypes"
            ],
            Resource: "*"
        }
    ]
})
    }, { parent: this });
But ended up with:
Copy code
policy     : "{"Version":"2012-10-17","Statement":[{"Sid":"VisualEditor0","Effect":"Allow","Action":["autoscaling:SetDesiredCapacity","autoscaling:TerminateInstanceInAutoScalingGroup"],"Resource":"*","Condition":{"StringEquals":{}}},{"Sid":"VisualEditor1","Effect":"Allow","Action":["autoscaling:DescribeAutoScalingInstances","autoscaling:DescribeAutoScalingGroups","ec2:DescribeLaunchTemplateVersions","autoscaling:DescribeTags","autoscaling:DescribeLaunchConfigurations","ec2:DescribeInstanceTypes"],"Resource":"*"}]}"
Where
StringEquals
gets set to an empty
{}
b
@cuddly-flower-91328 There’s a few errors here:
Copy code
oidcArn: string, oidcUrl: string
They are probably an
Output<str>
There’s an EKS OIDC example here you can use as a reference, fwiw: https://github.com/jaxxstorm/pulumi-examples/blob/378ddb65c6ae2fa018d34f7f57edd871ab9af994/typescript/aws/eks-platform/external-dns/index.ts#L9
c
Thanks! I’ll give that a look in a bit.
Ok, this is great. For context, the above resides in a file named
iam.ts
which is imported into
index.ts
within the project. Below is what exists in
index.ts
as it relates to the code in question:
Copy code
const clusterOidcProvider = cluster.core.oidcProvider;
export const clusterOidcProviderUrl = clusterOidcProvider.url;
export const clusterOidcProviderArn = clusterOidcProvider.arn;
let clusterName = cluster.core.cluster.name;
let args = {
  clusterName: "",
  oidcArn: "", 
  oidcUrl: "",
}
clusterName.apply(s => args["clusterName"] = s);
clusterOidcProviderArn.apply(s => args["oidcArn"] = s);
clusterOidcProviderUrl.apply(s => args["oidcUrl"] = s);
export const clusterAutoscalerRole = new iam.clusterAutoscalerRole(`${projectName}-${stackName}`, args);
The intent here was to package what is required to create the necessary role into a single Component Resource. My next step was going to be creating the policy document like you did in that example as well as what I had seen here. I figured I would include this additional bit of info in case I am just way off the mark, but I see that you're using
all()
here which I haven't done and maybe that will be helpful 🤞
b
this won’t work like you expect:
Copy code
clusterName.apply(s => args["clusterName"] = s);
clusterOidcProviderArn.apply(s => args["oidcArn"] = s);
clusterOidcProviderUrl.apply(s => args["oidcUrl"] = s);
You can’t assign a value inside an apply, you can only perform that operation inside an apply see https://leebriggs.co.uk/blog/2021/05/09/pulumi-apply for more info
c
Ok I will read that. I think the confusion comes from being able to do the following:
Copy code
let clusterName = cluster.core.cluster.name;
let clusterTag = pulumi.interpolate `<http://k8s.io/cluster-autoscaler/${clusterName}`;|k8s.io/cluster-autoscaler/${clusterName}`;>
let tags = {
      "org": "something",
      "<http://k8s.io/cluster-autoscaler/enabled|k8s.io/cluster-autoscaler/enabled>": "true",
}
clusterTag.apply(s => tags[s] = "owned");
So it seemed fitting that maybe something similar may also work. I appreciate your help on this!
Got this all buttoned up. Thanks again @billowy-army-68599!