I've looked high and low for how to do this. I don't think I have the right terminology. Using Pulumi with Golang how can I reference the ID of some resource in a string.
For example, I create a bucket then I want to reference that bucket's ID in an IAM policy. This seems impossible.
bucket, err := s3.NewBucket(
ctx,
photosBucketName,
&s3.BucketArgs{})
tmpJSON, err := json.Marshal(map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Effect": "Allow",
"Principal": "*",
"Action": []string{"s3:GetObject"},
"Resource": []string{fmt.Sprintf("arn:aws:s3:::%s/*", bucket.ID())},
},
},
})
Output being:
Sprintf format %s has arg bucket.ID() of wrong type github.com/pulumi/pulumi/sdk/v2/go/pulumi.IDOutput
Using photosBucketName
results in a malformed document because of the generated suffix on the bucket name.
Appreciate the time and help.
Pulumi resources return Outputs, which are values that are not known by Pulumi until the upstream cloud provider API (in this case, the AWS S3 API) until the resource is created.
What that means is that if you want to access the raw output value as a standard Go string, you'll need to somehow tell the Pulumi engine to wait until that resource has been created. You do this using Pulumi's apply
So in your particular example, we want to build a JSON string for our IAM policy (IAM policies only take strings, they can't take other Pulumi outputs).
bucket, err := s3.NewBucket(
ctx,
photosBucketName,
&s3.BucketArgs{})
// notice how we're using the apply function to wrap the building of the JSON string
bucketPolicy := bucket.Arn.ApplyT(func (arn string) (string, error) {
policyJSON, err := json.Marshal(map[string]interface{}{
"Version": "2012-10-17",
"Statement": []map[string]interface{}{
{
"Effect": "Allow",
"Principal": "*",
"Action": []string{"s3:GetObject"},
"Resource": []string{
arn, // I can now pass the arn directy
},
},
},
})
if err != nil {
return "", err
}
return string(policyJSON), nil
})