Skip to content

Commit

Permalink
feat(sdk/nodejs): delegates alias computation to the engine
Browse files Browse the repository at this point in the history
  • Loading branch information
kpitzen committed Nov 3, 2022
1 parent 77d72ad commit eb756a3
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 15 deletions.
@@ -0,0 +1,4 @@
changes:
- type: feat
scope: sdk/nodejs
description: Delegates alias computation to engine for Node SDK
8 changes: 6 additions & 2 deletions sdk/nodejs/resource.ts
Expand Up @@ -15,7 +15,7 @@
import { ResourceError } from "./errors";
import { Input, Inputs, interpolate, Output, output } from "./output";
import { getResource, readResource, registerResource, registerResourceOutputs } from "./runtime/resource";
import { getProject, getStack } from "./runtime/settings";
import { getProject, getStack, monitorSupportsAliasSpecs } from "./runtime/settings";
import { getStackResource } from "./runtime/state";
import * as stacklib from "./runtime/stack";
import { unknownValue } from "./runtime/rpc";
Expand Down Expand Up @@ -334,7 +334,11 @@ export abstract class Resource {
}

// Update aliases to include the full set of aliases implied by the child and parent aliases.
opts.aliases = allAliases(opts.aliases || [], name, t, parent, parent.__name!);
monitorSupportsAliasSpecs().then(supportsAliasSpecs => {
if (!supportsAliasSpecs) {
opts.aliases = allAliases(opts.aliases || [], name, t, parent, parent.__name!);
}
});

this.__providers = parent.__providers;
}
Expand Down
39 changes: 35 additions & 4 deletions sdk/nodejs/runtime/resource.ts
Expand Up @@ -20,6 +20,7 @@ import * as utils from "../utils";
import { getAllResources, Input, Inputs, Output, output } from "../output";
import { ResolvedResource } from "../queryable";
import {
Alias,
ComponentResource,
ComponentResourceOptions,
createUrn,
Expand Down Expand Up @@ -52,13 +53,15 @@ import {
getStack,
isDryRun,
isLegacyApplyEnabled,
monitorSupportsAliasSpecs,
rpcKeepAlive,
serialize,
terminateRpcs,
} from "./settings";

const gstruct = require("google-protobuf/google/protobuf/struct_pb.js");
const resproto = require("../proto/resource_pb.js");
const aliasproto = require("../proto/alias_pb.js");

interface ResourceResolverOperation {
// A resolver for a resource's URN.
Expand All @@ -83,7 +86,7 @@ interface ResourceResolverOperation {
// all be URNs of custom resources, not component resources.
propertyToDirectDependencyURNs: Map<string, Set<URN>>;
// A list of aliases applied to this resource.
aliases: URN[];
aliases: (Alias | URN)[];
// An ID to import, if any.
import: ID | undefined;
}
Expand Down Expand Up @@ -272,6 +275,28 @@ export function readResource(res: Resource, parent: Resource | undefined, t: str
}), label);
}

function mapAliasesForRequest(aliases: (string | Alias)[] | undefined) {
if (aliases === undefined) {
return [];
}

return aliases.map(a => {
const newAlias = new aliasproto.Alias();
if (typeof a === "string") {
newAlias.setUrn(a);
} else {
const newAliasSpec = new aliasproto.Alias.Spec();
newAliasSpec.setName(a.name);
newAliasSpec.setType(a.type);
newAliasSpec.setStack(a.stack);
newAliasSpec.setProject(a.project);
newAliasSpec.setParenturn(a.parent);
newAlias.setSpec(newAliasSpec);
}
return newAlias;
});
}

/**
* registerResource registers a new resource object with a given type t and name. It returns the auto-generated
* URN and the ID that will resolve after the deployment has completed. All properties will be initialized to property
Expand Down Expand Up @@ -310,7 +335,13 @@ export function registerResource(res: Resource, parent: Resource | undefined, t:
req.setAcceptsecrets(true);
req.setAcceptresources(!utils.disableResourceReferences);
req.setAdditionalsecretoutputsList((<any>opts).additionalSecretOutputs || []);
req.setAliasurnsList(resop.aliases);
monitorSupportsAliasSpecs().then(supportsAliasSpecs => {
if (supportsAliasSpecs) {
req.setAliasesList(mapAliasesForRequest(resop.aliases));
} else {
req.setAliasurnsList(resop.aliases);
}
});
req.setImportid(resop.import || "");
req.setSupportspartialvalues(true);
req.setRemote(remote);
Expand Down Expand Up @@ -579,8 +610,8 @@ async function prepareResource(label: string, res: Resource, parent: Resource |
// in the Resource constructor prior to calling `registerResource` - both adding new inherited aliases and
// simplifying aliases down to URNs.
const aliases = [];
const uniqueAliases = new Set<string>();
for (const alias of (res.__aliases || [])) {
const uniqueAliases = new Set<Alias | URN>();
for (const alias of (opts.aliases || [])) {
const aliasVal = await output(alias).promise();
if (!uniqueAliases.has(aliasVal)) {
uniqueAliases.add(aliasVal);
Expand Down
9 changes: 9 additions & 0 deletions sdk/nodejs/runtime/settings.ts
Expand Up @@ -510,6 +510,15 @@ export async function monitorSupportsOutputValues(): Promise<boolean> {
return monitorSupportsFeature("outputValues");
}

/**
* monitorSupportsAliasSpecs returns a promise that when resolved tells you if the resource monitor we are
* connected to is able to support alias specs across its RPC interface. When it does, we marshal aliases
* in a special way.
*/
export async function monitorSupportsAliasSpecs(): Promise<boolean> {
return monitorSupportsFeature("aliasSpecs");
}

// sxsRandomIdentifier is a module level global that is transfered to process.env.
// the goal is to detect side by side (sxs) pulumi/pulumi situations for inline programs
// and fail fast. See https://github.com/pulumi/pulumi/issues/7333 for details.
Expand Down
Expand Up @@ -18,10 +18,39 @@ class MyResource extends pulumi.CustomResource {
}
}

class MyOtherResource extends pulumi.CustomResource {
constructor(name, aliases, parent) {
super(
"test:index:MyOtherResource",
name,
{},
{
aliases: aliases,
parent
}
);
}
}

const resource1Aliases = Array.from(new Array(1000).keys()).map(key => `my-alias-name-${key}`);
const resource1 = new MyResource("testResource1", resource1Aliases);
resource1.__aliases.map(alias => alias.apply(aliasName => assert(resource1Aliases.includes(aliasName))));
assert.equal(resource1.__aliases.length, 1000);

const resource2Aliases = Array.from(new Array(1000).keys()).map(key => `my-other-alias-name-${key}`);
const resource2 = new MyResource("testResource2", resource2Aliases, resource1)
resource2.__aliases.map(alias => alias.apply(aliasName => assert(resource2Aliases.includes(aliasName))));
assert.equal(resource2.__aliases.length, 1000);

const resource3Aliases = Array.from(new Array(1000).keys()).map(key => {
return {
name: `my-alias-${key}`,
stack: "my-stack",
project: "my-project",
type: "test:index:MyOtherResource",
}
});
const resource3 = new MyOtherResource("testResource2", resource3Aliases, resource2)
assert.equal(resource3.__aliases.length, 1000);
// We want to ensure that the parent's type is included in computed aliases from the engine
resource3.__aliases[0].apply(aliasName => assert(aliasName.includes("test:index:MyResource")));
17 changes: 8 additions & 9 deletions sdk/nodejs/tests/runtime/langhost/run.spec.ts
Expand Up @@ -1249,14 +1249,13 @@ describe("rpc", () => {
return { urn: makeUrn(t, name), id: undefined, props: undefined };
},
},
/** Skipping this test case as it requires limiting the alias multiplication which occurs */
// "large_alias_lineage_chains": {
// program: path.join(base, "072.large_alias_lineage_chains"),
// expectResourceCount: 1,
// registerResource: (ctx: any, dryrun: boolean, t: string, name: string, res: any, ...args: any) => {
// return { urn: makeUrn(t, name), id: undefined, props: undefined };
// },
// }
"large_alias_lineage_chains": {
program: path.join(base, "072.large_alias_lineage_chains"),
expectResourceCount: 3,
registerResource: (ctx: any, dryrun: boolean, t: string, name: string, res: any, ...args: any) => {
return { urn: makeUrn(t, name), id: undefined, props: undefined };
},
},
};

for (const casename of Object.keys(cases)) {
Expand Down Expand Up @@ -1418,7 +1417,7 @@ describe("rpc", () => {
// SupportsFeature callback
(call: any, callback: any) => {
const resp = new resproto.SupportsFeatureResponse();
resp.setHassupport(false);
resp.setHassupport(true);
callback(undefined, resp);
},
);
Expand Down

0 comments on commit eb756a3

Please sign in to comment.