Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert Pulumi Output<t> to string?

Tags:

output

pulumi

I am dealing with creating AWS API Gateway. I am trying to create CloudWatch Log group and name it API-Gateway-Execution-Logs_${restApiId}/${stageName}. I have no problem in Rest API creation.
My issue is in converting restApi.id which is of type pulumi.Outout to string.

I have tried these 2 versions which are proposed in their PR#2496

  1. const restApiId = apiGatewayToSqsQueueRestApi.id.apply((v) => `${v}`);
  2. const restApiId = pulumi.interpolate `${apiGatewayToSqsQueueRestApi.id}`

here is the code where it is used

const cloudWatchLogGroup = new aws.cloudwatch.LogGroup(
  `API-Gateway-Execution-Logs_${restApiId}/${stageName}`,
  {},
);

stageName is just a string.

I have also tried to apply again like
const restApiIdStrign = restApiId.apply((v) => v);

I always got this error from pulumi up
aws:cloudwatch:LogGroup API-Gateway-Execution-Logs_Calling [toString] on an [Output<T>] is not supported.

Please help me convert Output to string

like image 935
Tigran Sahakyan Avatar asked Jun 24 '20 18:06

Tigran Sahakyan


2 Answers

So long as the Output is resolvable while the Pulumi script is still running, you can use an approach like the below:

import {Output} from "@pulumi/pulumi";
import * as fs from "fs";

// create a GCP registry
const registry = new gcp.container.Registry("my-registry");
const registryUrl = registry.id.apply(_=>gcp.container.getRegistryRepository().then(reg=>reg.repositoryUrl));

// create a GCP storage bucket
const bucket = new gcp.storage.Bucket("my-bucket");
const bucketURL = bucket.url;

function GetValue<T>(output: Output<T>) {
    return new Promise<T>((resolve, reject)=>{
        output.apply(value=>{
            resolve(value);
        });
    });
}

(async()=>{
    fs.writeFileSync("./PulumiOutput_Public.json", JSON.stringify({
        registryURL: await GetValue(registryUrl),
        bucketURL: await GetValue(bucketURL),
    }, null, "\t"));
})();

To clarify, this approach only works when you're doing an actual deployment (ie. pulumi up), not merely a preview. (as explained here)

That's good enough for my use-case though, as I just want a way to store the registry-url and such after each deployment, for other scripts in my project to know where to find the latest version.

like image 171
Venryx Avatar answered Oct 20 '22 18:10

Venryx


Short Answer

You can specify the physical name of your LogGroup by specifying the name input and you can construct this from the API Gateway id output using pulumi.interpolate. You must use a static string as the first argument to your resource. I would recommend using the same name you're providing to your API Gateway resource as the name for your Log Group. Here's an example:

const apiGatewayToSqsQueueRestApi = new aws.apigateway.RestApi("API-Gateway-Execution");

const cloudWatchLogGroup = new aws.cloudwatch.LogGroup(
  "API-Gateway-Execution", // this is the logical name and must be a static string
  {
    name: pulumi.interpolate`API-Gateway-Execution-Logs_${apiGatewayToSqsQueueRestApi.id}/${stageName}` // this the physical name and can be constructed from other resource outputs
  },
);

Longer Answer

The first argument to every resource type in Pulumi is the logical name and is used for Pulumi to track the resource internally from one deployment to the next. By default, Pulumi auto-names the physical resources from this logical name. You can override this behavior by specifying your own physical name, typically via a name input to the resource. More information on resource names and auto-naming is here.

The specific issue here is that logical names cannot be constructed from other resource outputs. They must be static strings. Resource inputs (such as name) can be constructed from other resource outputs.

like image 28
Cameron Avatar answered Oct 20 '22 16:10

Cameron