```const region = pulumi.output(aws.getRegion()) ...
# general
b
Copy code
const region = pulumi.output(aws.getRegion())

const policy = {
	Version: '2012-10-17',
	Statement: [{
		Action: [
			'logs:*'
		],
		Effect: 'Allow',
		Resource: [
			pulumi.interpolate`arn:aws:logs:${region.name}:*:*`
		]
	}]
}

export const cloudwatchLogsPolicy = new aws.iam.Policy('cloudwatchLogsPolicy', {
	policy: JSON.stringify(policy)
})
@handsome-actor-1155 in the same vein, albeit with intra-stack dependencies, I am finding out using an output with interpolate (or apply) doesn’t work with JSON.stringify. Probably different from your problem, but I just came across this issue and saw your post. From my reading of the docs, the way you’re defining it appears to be the cleanest way. Seems to be some gotchas with pulumi.interpolate that I’m not seeing?
h
I also use
const kubeconfig = infraStack.getOutput("kubeconfig").apply(JSON.stringify);
Which returns type
Output<string>
I’m then able to pass it to a
new k8s.Provider
which accepts that type. A little different than your issue as well but similar?
What issue are you seeing exactly?
b
Copy code
policy    : "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"logs:*\"],\"Effect\":\"Allow\",\"Resource\":[\"Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee <https://pulumi.io/help/outputs> for more details.\\nThis function may throw in a future version of @pulumi/pulumi.\"]}]}"
appears it’s an uncaught exception that gets injected in the string for resource
Copy code
const region = pulumi.output(aws.getRegion())

const policy = pulumi.interpolate`{
	"Version": "2012-10-17",
	"Statement": [{
		"Action": [
			"logs:*"
		],
		"Effect": "Allow",
		"Resource": [
			"${region.apply((region) => `arn:aws:logs:${region.name}:*:*`)}"
		]
	}]
}`

export const cloudwatchLogsPolicy = new aws.iam.Policy('cloudwatchLogsPolicy', {
	policy
})
this works, but it’s obviously less than ideal. would be much cleaner, not to mention lint-compatible, if i could use JSON.stringify
h
Can you use JSON.stringify if you perform the ${region.apply…} and don’t use pulumi.interpolate at the top?
b
same issue unfortunately
Copy code
const region = pulumi.output(aws.getRegion())

const policy = {
	Version: '2012-10-17',
	Statement: [{
		Action: [
			'logs:*'
		],
		Effect: 'Allow',
		Resource: [
			region.apply((region) => `arn:aws:logs:${region.name}:*:*`)
		]
	}]
}

export const cloudwatchLogsPolicy = new aws.iam.Policy('cloudwatchLogsPolicy', {
	policy: JSON.stringify(policy)
})
h
So, I'm still having issues actually getting an output of a stackReference as a string. Everything I've tried ALWAYS results in an
Output<string>
, no matter what Output transformation I apply to it. Is there something I'm missing?
g
h
Unfortunately not. Maybe I’m just going about this the wrong way. I have 2 stacks: 1. An infra stack which exports a bucketName as well as the entire bucket object 2. A services stack which needs to reference the bucket I am able to get away with:
Copy code
pulumi.interpolate `${bucketName}`
in my ReplicaSet since it is able to accept an
OutputInstance<string>
as a value. The issue is arising when I’m trying to
get
the bucket for use in a Lambda in my service stack. Here:
Copy code
const bucket = aws.s3.Bucket.get(bucketName, "aws");
bucketName
can only be a string, not an
Output<string>
or anythings else but a string. Is there a better way of getting a bucket from a different stack? In reference to the code that you shared, I wrote:
Copy code
const name = pulumi.all([thing]).apply(([aName]) => {
        return aName
    });
where
thing
is of type
Output<any>
(I tried it where
thing
is of type
Output<string>
as well). It only returned the same type as
thing
.
w
And that?
Copy code
pulumi.all([thing]).apply(([aName]) => {
        const bucket = aws.s3.Bucket.get(aName, "aws");
    });
g
Ah, resource names cannot be interpolated from outputs. They must be regular strings.
Well, for a
get
that might not be true. Hmm.
This is doable. I’ll spend some time with it this morning.
h
@witty-alarm-17249 That got me a closer:
Copy code
const bucket = bucketName.apply((name) => {
        return aws.s3.Bucket.get(name, "aws");
    });;
That returns a type:
pulumi.OutputInstance<aws.s3.bucket>
And unfortunately I cannot call
.onObjectCreate
from that. From there it looks like I need to perform another apply on
bucket
to get access to the bucket’s methods, which is doable but seems unnecessarily tedious.
Actually that still doesn’t seem to work. Yes,
bucket
is an
Output<bucket>
but when running
pulumi update
, it’s not actually getting the bucket properly:
Copy code
aws:s3:Bucket (stream-demo-kafka-bucket-339079d):
    error: Preview failed: importing aws: Error importing AWS S3 bucket policy: BucketRegionError: incorrect region, the bucket is not in 'us-west-2' region at endpoint ''
        status code: 301, request id: , host id:
But the bucket is indeed in
us-west-2
Ok, looks like I finally got things looking good:
Copy code
export function create(bucketInput: Output<any>) {

    const bucket = bucketInput.apply((buck) => {
        return aws.s3.Bucket.get(buck.bucket, buck.bucketArn);
    });
    bucket.apply(liftedBucket => liftedBucket.onObjectCreated("anomalyEventMessage", async(e) => {
        //do stuff
        }
    }));
}
For closure, my final code ended up being:
Copy code
const bucketOutput = infraStack.getOutput("bucket");
bucketOutput.apply(bucket => {
    const actualBucket = aws.s3.Bucket.get(bucket.bucket, bucket.id);
    slackLambda.create(actualBucket)
});
where the parameter type for
create
is
Bucket
. Good to know that you need to perform your operations inside an
.apply()
instead of expecting it to return data to use in your operations.
g
I think there's still a better way to do this. Can you share your full code? Private/DM is fine if necessary.