// Copyright 2016-2018, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import * as assert from "assert"; import * as pulumi from "../index"; import { CustomResourceOptions } from "../resource"; import { MockCallArgs, MockCallResult, MockResourceArgs, MockResourceResult } from "../runtime"; const callMock = (args: MockCallArgs): MockCallResult => { switch (args.token) { case "test:index:MyFunction": return { out_value: 59 }; default: return {}; } }; const asyncCallMock = (args: MockCallArgs) => Promise.resolve(callMock(args)); const newResourceMock = (args: MockResourceArgs): MockResourceResult => { switch (args.type) { case "aws:ec2/instance:Instance": assert.strictEqual(args.custom, true); const state = { arn: "arn:aws:ec2:us-west-2:123456789012:instance/i-1234567890abcdef0", instanceState: "running", primaryNetworkInterfaceId: "eni-12345678", privateDns: "ip-10-0-1-17.ec2.internal", publicDns: "ec2-203-0-113-12.compute-1.amazonaws.com", publicIP: "203.0.113.12", }; return { id: "i-1234567890abcdef0", state: { ...args.inputs, ...state } }; case "pkg:index:MyCustom": assert.strictEqual(args.custom, true); return { id: args.name + "_id", state: args.inputs }; case "pkg:index:MyRemoteComponent": return { id: `${args.name}_id`, state: { ...args.inputs, outprop: `output: ${args.inputs["inprop"]}`, }, }; default: assert.strictEqual(args.custom, false); return { id: "", state: {} }; } }; const asyncNewResourceMock = (args: MockResourceArgs) => Promise.resolve(newResourceMock(args)); class MyComponent extends pulumi.ComponentResource { outprop: pulumi.Output<string>; constructor(name: string, inprop: pulumi.Input<string>, opts?: pulumi.ComponentResourceOptions) { super("pkg:index:MyComponent", name, {}, opts); this.outprop = pulumi.output(inprop).apply((x) => `output: ${x}`); } } class MyRemoteComponent extends pulumi.ComponentResource { outprop!: pulumi.Output<string>; constructor(name: string, inprop: pulumi.Input<string>, opts?: pulumi.ComponentResourceOptions) { super("pkg:index:MyRemoteComponent", name, { inprop, outprop: undefined }, opts, true); } } class Instance extends pulumi.CustomResource { publicIP!: pulumi.Output<string>; constructor(name: string, opts?: CustomResourceOptions) { const props = { publicIP: undefined }; super("aws:ec2/instance:Instance", name, props, opts); } } class MyCustom extends pulumi.CustomResource { instance!: pulumi.Output<Instance>; constructor(name: string, props?: Record<string, any>, opts?: CustomResourceOptions) { super("pkg:index:MyCustom", name, props, opts); } } async function invoke(): Promise<number> { const value = await pulumi.runtime.invoke("test:index:MyFunction", { value: 41 }); return value["out_value"]; } const setups: [string, boolean, boolean][] = [ ["mocks: newResource sync, call sync", false, false], ["mocks: newResource sync, call async", false, true], ["mocks: newResource async, call sync", true, false], ["mocks: newResource async, call async", true, true], ]; setups.forEach(([test, isAsyncNewResource, isAsyncCall]) => { describe(test, function () { let component: MyComponent; let instance: Instance; let custom: MyCustom; let invokeResult: Promise<number>; let remoteComponent: MyRemoteComponent; before(() => { pulumi.runtime.setMocks({ call: isAsyncCall ? asyncCallMock : callMock, newResource: isAsyncNewResource ? asyncNewResourceMock : newResourceMock, }); pulumi.runtime.registerResourceModule("aws", "ec2/instance", { construct: (name: string, type: string, urn: string): pulumi.Resource => { switch (type) { case "aws:ec2/instance:Instance": return new Instance(name, { urn }); default: throw new Error(`unknown resource type ${type}`); } }, }); component = new MyComponent("mycomponent", "hello"); instance = new Instance("instance"); custom = new MyCustom("mycustom", { instance: instance }); invokeResult = invoke(); remoteComponent = new MyRemoteComponent("myremotecomponent", pulumi.interpolate`hello: ${instance.id}`); }); describe("component", function () { it("has expected output value", (done) => { component.outprop.apply((outprop) => { assert.strictEqual(outprop, "output: hello"); done(); }); }); }); describe("remote component", function () { it("has expected output value", (done) => { remoteComponent.outprop.apply((outprop) => { assert.strictEqual(outprop.startsWith("output: hello: "), true); done(); }); }); }); describe("custom", function () { it("instance has expected output value", (done) => { instance.publicIP.apply((ip) => { assert.strictEqual(ip, "203.0.113.12"); done(); }); }); it("mycustom has expected output value", (done) => { custom.instance.apply((_) => { done(); }); }); }); describe("invoke", function () { it("has expected result", (done) => { invokeResult.then((value) => { assert.strictEqual(value, 59); done(); }); }); }); }); });