// Copyright 2016-2024, Pulumi Corporation. All rights reserved. import * as pulumi from "@pulumi/pulumi"; import { Component, Random, TestProvider} from "./random"; class MyComponent extends pulumi.ComponentResource { child: Random; constructor(name: string, opts?: pulumi.ComponentResourceOptions) { super("my:component:MyComponent", name, {}, opts); this.child = new Random(`${name}-child`, { length: 5 }, { parent: this, additionalSecretOutputs: ["length"], }); this.registerOutputs({}); } } // Scenario #1 - apply a transform to a CustomResource const res1 = new Random("res1", { length: 5 }, { transforms: [ async ({ props, opts }) => { console.log("res1 transform"); return { props: props, opts: pulumi.mergeOptions(opts, { additionalSecretOutputs: ["result"] }), }; }, ], }); // Scenario #2 - apply a transform to a Component to transform it's children const res2 = new MyComponent("res2", { transforms: [ async ({ type, props, opts }) => { console.log("res2 transform"); if (type === "testprovider:index:Random") { return { props: { prefix: "newDefault", ...props }, opts: pulumi.mergeOptions(opts, { additionalSecretOutputs: ["result"] }), }; } }, ], }); // Scenario #3 - apply a transform to the Stack to transform all (future) resources in the stack pulumi.runtime.registerStackTransform(async ({ type, props, opts }) => { console.log("stack transform"); if (type === "testprovider:index:Random") { return { props: { ...props, prefix: "stackDefault" }, opts: pulumi.mergeOptions(opts, { additionalSecretOutputs: ["result"] }), }; } }); const res3 = new Random("res3", { length: pulumi.secret(5) }); // Scenario #4 - transforms are applied in order of decreasing specificity // 1. (not in this example) Child transform // 2. First parent transform // 3. Second parent transform // 4. Stack transform const res4 = new MyComponent("res4", { transforms: [ async ({ type, props, opts }) => { console.log("res4 transform"); if (type === "testprovider:index:Random") { return { props: { ...props, prefix: "default1" }, opts, }; } }, async ({ type, props, opts }) => { console.log("res4 transform 2"); if (type === "testprovider:index:Random") { return { props: { ...props, prefix: "default2" }, opts, }; } }, ], }); // Scenario #5 - mutate the properties of a resource const res5 = new Random("res5", { length: 10 }, { transforms: [ async ({ type, props, opts }) => { console.log("res5 transform"); if (type === "testprovider:index:Random") { const length = props["length"]; props["length"] = length * 2; return { props: props, opts: opts, }; } }, ], }); // Scenario #6 - mutate the provider on a custom resource const provider1 = new TestProvider("provider1"); const provider2 = new TestProvider("provider2"); const res6 = new Random("res6", { length: 10 }, { provider: provider1, transforms: [ async ({ type, props, opts }) => { console.log("res6 transform"); return { props: props, opts: pulumi.mergeOptions(opts, { provider: provider2 }), }; }, ], }); // Scenario #7 - mutate the provider on a component resource const res7 = new Component("res7", { length: 10 }, { provider: provider1, transforms: [ async ({ type, props, opts }) => { console.log("res7 transform"); return { props: props, opts: pulumi.mergeOptions(opts, { provider: provider2 }), }; }, ], }); pulumi.runtime.registerInvokeTransform(async ({ token, args, opts }) => { return { args: { ...args, length: 11 }, opts: opts, }; }); const res8 = new Random("res8", { length: pulumi.secret(5) }); const args = { length: 10, prefix: "test", }; async () => { const result = await res8.randomInvoke(args); if (result.length !== 11) { throw new Error(`expected length to be 11, got ${result.length}`); } if (result.prefix !== "test") { throw new Error(`expected prefix to be test, got ${result.prefix}`); } };