important-elephant-42212
02/13/2025, 5:48 AMOutput<string>
question again, but I don't get how to get the actual string when needed.
The use case is generating a Tailscale key to by used in the UserData of an ec2 instance.
import * as tailscale from "@pulumi/tailscale";
import * as aws from "@pulumi/aws";
const tn_key = new tailscale.TailnetKey("tailnet-key", {
ephemeral: true,
expiry: 3600,
preauthorized: true,
recreateIfInvalid: "always",
reusable: false,
});
new aws.ec2.Instance("instance", {
tags: {
Name: "slartibartfast"
},
instanceType: "t3.micro",
ami: "ami-01e2093820bf84df1",
userData: `
curl -fsSL <https://tailscale.com/install.sh> | sh
tailscale up --auth-key=${tn_key.key.apply(v => v)}
`
})
From pulumi up
details, the text in the UserData is the dredged OutputImpl
toString
response.
Calling [toString] on an [Output<T>] is not supported.\n\nTo get the value of an Output<T> as an Output<string> consider either:\n1: o.apply(v => `prefix${v}suffix`)\n2: pulumi.interpolate `prefix${v}suffix`\n\nSee <https://www.pulumi.com/docs/concepts/inputs-outputs> for more details.\n\nOr use ESLint with <https://github.com/pulumi/eslint-plugin-pulumi> to warn or\nerror lint on using Output<T> in template literals.\nThis function may throw in a future version of @pulumi/pulumi.\n
Running pulumi up --debug
outputs the following
debug: Ignoring error in loadCompilerOptions(tsconfig.json}): Error: ENOENT: no such file or directory, open 'tsconfig.json'
debug: Found typescript version 5.5.4 at /Users/garymiller/devel/nettex/workspace/nettex/iac/node_modules/.pnpm/typescript@5.5.4/node_modules/typescript/lib/typescript.js
debug: Using vendored ts-node@7.0.1
debug: Registering resource: t=pulumi:pulumi:Stack, name=nettex-preinfra, custom=false, remote=false
debug: RegisterResource RPC prepared: t=pulumi:pulumi:Stack, name=nettex-preinfra
debug: RegisterResource RPC finished: resource:nettex-preinfra[pulumi:pulumi:Stack]; err: null, resp: urn:pulumi:preinfra::nettex::pulumi:pulumi:Stack::nettex-preinfra,,,,
debug: Running program '/Users/garymiller/devel/nettex/workspace/nettex/iac/stacks/preinfra' in pwd '/Users/garymiller/devel/nettex/workspace/nettex/iac/stacks/preinfra' w/ args:
debug: Registering resource: t=tailscale:index/tailnetKey:TailnetKey, name=tailnet-key, custom=true, remote=false
debug: RegisterResource RPC prepared: t=tailscale:index/tailnetKey:TailnetKey, name=tailnet-key
debug: Registering resource: t=aws:ec2/instance:Instance, name=instance, custom=true, remote=false
debug: RegisterResource RPC prepared: t=aws:ec2/instance:Instance, name=instance
debug: RegisterResourceOutputs RPC prepared: urn=urn:pulumi:preinfra::nettex::pulumi:pulumi:Stack::nettex-preinfra
debug: RegisterResourceOutputs RPC finished: urn=urn:pulumi:preinfra::nettex::pulumi:pulumi:Stack::nettex-preinfra; err: null, resp:
debug: RegisterResourceOutputs RPC finished: urn=urn:pulumi:preinfra::nettex::pulumi:pulumi:Stack::nettex-preinfra; err: null, resp:
debug: [INFO] pulumi-aws: starting to validate credentials. Disable this by AWS_SKIP_CREDENTIALS_VALIDATION or skipCredentialsValidation option
debug: [INFO] pulumi-aws: credentials are valid
debug: RegisterResource RPC finished: resource:instance[aws:ec2/instance:Instance]; err: null, resp: urn:pulumi:preinfra::nettex::aws:ec2/instance:Instance::instance,,ami,,,ami-01e2093820bf84df1,getPasswordData,,,,false,id,,,,instanceType,,,t3.micro,sourceDestCheck,,,,true,tags,,,,,Name,,,slartibartfast,tagsAll,,,,,Name,,,slartibartfast,userData,,,
apt-get update -y
apt-get install -y ec2-instance-connect
curl -fsSL <https://tailscale.com/install.sh> | sh
tailscale up --auth-key=Calling [toString] on an [Output<T>] is not supported.
To get the value of an Output<T> as an Output<string> consider either:
1: o.apply(v => `prefix${v}suffix`)
2: pulumi.interpolate `prefix${v}suffix`
See <https://www.pulumi.com/docs/concepts/inputs-outputs> for more details.
Or use ESLint with <https://github.com/pulumi/eslint-plugin-pulumi> to warn or
error lint on using Output<T> in template literals.
This function may throw in a future version of @pulumi/pulumi.
,userDataReplaceOnChange,,,,false,,
debug: RegisterResource RPC finished: resource:tailnet-key[tailscale:index/tailnetKey:TailnetKey]; err: null, resp: urn:pulumi:preinfra::nettex::tailscale:index/tailnetKey:TailnetKey::tailnet-key,,createdAt,,,xxx,description,0,ephemeral,,,,true,expiresAt,,,xxx,expiry,,3600,id,,,xxx,invalid,,,xxx,key,,,,,xxx,preauthorized,,,,true,recreateIfInvalid,,,always,reusable,,,,false,tags,0,,
important-elephant-42212
02/13/2025, 6:55 AMconst userData = tn_key.key.apply(v =>`
curl -fsSL <https://tailscale.com/install.sh> | sh
tailscale up --auth-key=${v}
`)
new aws.ec2.Instance("instance2", {
tags: {
Name: "slartibartfast"
},
instanceType: "t3.small",
ami: "ami-01e2093820bf84df1",
userData,
})
But this leads me to my next question, why doesn't the following work?
import * as tailscale from "@pulumi/tailscale";
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";
function makeinstance(key: pulumi.Input<string>) {
new aws.ec2.Instance("instance", {
tags: {
Name: "slartibartfast2"
},
instanceType: "t3.small",
ami: "ami-01e2093820bf84df1",
userData: `
curl -fsSL <https://tailscale.com/install.sh> | sh
tailscale up --auth-key=${key}
`
})
}
const tn2_key = new tailscale.TailnetKey("tailnet-key", {
ephemeral: true,
expiry: 3600,
preauthorized: true,
recreateIfInvalid: "always",
reusable: false,
});
makeinstance(tn2_key.key.apply(v => v))
important-elephant-42212
02/13/2025, 7:19 AMpulumi.ComponentResource
(ie. class MyInstance extends pulumi.ComponentResource
), with an Input<string>
, but it didn't help ðŸ˜
also tried
class MyInstance extends pulumi.ComponentResource {
constructor(
name: string,
params: {
tn_key: tailscale.TailnetKey,
key: pulumi.Input<string>,
},
opts?: pulumi.ComponentResourceOptions,
) {
super("MyInstance", name, {}, opts);
new aws.ec2.Instance(`${name}-instance`, {
tags: {
Name: "slartibartfast"
},
instanceType: "t3.small",
ami: "ami-01e2093820bf84df1",
userData: `
curl -fsSL <https://tailscale.com/install.sh> | sh
tailscale up --auth-key=${params.key}
`
}, {
dependsOn: [params.tn_key],
parent: this
})
}
}
not working 😡little-cartoon-10569
02/13/2025, 9:11 AMapply
. That code runs later, when the value of the output is known. The correct value is available to the logic.
The value returned from the apply
is just a promise (output). The value it generates will be correct in the future, but not at the time your code is running. However, because you're passing that output to a constrictor of a Pulumi resource, Pulumi knows what to do with that future value, and uses it when it is eventually available.quick-house-41860
02/13/2025, 9:33 AMpulumi.interpolate`
curl -fsSL <https://tailscale.com/install.sh> | sh
tailscale up --auth-key=${tn_key}
`
little-cartoon-10569
02/13/2025, 6:53 PMlittle-cartoon-10569
02/13/2025, 6:55 PM