[sdk/nodejs] Skip re-registrations of same package+version (#6387)

It is possible for the same version of the same provider SDK to be loaded multiple times in Node.js.  In this case, we might legitimately get mutliple registrations of the same resource.  It should not matter which we use, so we can just skip re-registering.  De-serialized resources will always be instances of classes from the first registered package.

Example layout this addresses.  Registrations of resources in `package3` at the same verrsion.

`node_modules`
  `@pulumi/pulumi`
  `package1`
    `node_modules`
      `package3`
  `package2`
    `node_modules`
      `package3`

Fixes #6258.
This commit is contained in:
Luke Hoban 2021-02-20 10:06:32 +11:00 committed by GitHub
parent 47a43dc862
commit f7397bb798
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 7 deletions

View file

@ -3,12 +3,19 @@ CHANGELOG
## HEAD (Unreleased)
### Improvements
- [sdk/dotnet] C# Automation API.
[#5761](https://github.com/pulumi/pulumi/pull/5761)
- [sdk/dotnet] F# API to specify stack options.
[#5077](https://github.com/pulumi/pulumi/pull/5077)
### Bug Fixes
- [sdk/nodejs] Don't error when loading multiple copies of the same version of a Node.js
component package. [#6387](https://github.com/pulumi/pulumi/pull/6387)
## 2.21.1 (2021-02-18)
### Bug Fixes
@ -16,6 +23,8 @@ CHANGELOG
- [sdk/python] Fixed a change to `Output.all()` that raised an error if no inputs are passed in.
[#6381](https://github.com/pulumi/pulumi/pull/6381)
### Bug Fixes
## 2.21.0 (2021-02-17)
### Improvements

View file

@ -599,12 +599,17 @@ function checkVersion(want?: semver.SemVer, have?: semver.SemVer): boolean {
}
/** @internal */
export function register<T extends { readonly version?: string }>(source: Map<string, T[]>, registrationType: string, key: string, item: T): void {
export function register<T extends { readonly version?: string }>(source: Map<string, T[]>, registrationType: string, key: string, item: T): boolean {
let items = source.get(key);
if (items) {
for (const existing of items) {
if (sameVersion(existing.version, item.version)) {
throw new Error(`Cannot re-register ${registrationType} ${key}@${item.version}. Previous registration was ${existing}, new registration was ${item}.`);
// It is possible for the same version of the same provider SDK to be loaded multiple times in Node.js.
// In this case, we might legitimately get mutliple registrations of the same resource. It should not
// matter which we use, so we can just skip re-registering. De-serialized resources will always be
// instances of classes from the first registered package.
log.debug(`skip re-registering already registered ${registrationType} ${key}@${item.version}.`);
return false;
}
}
} else {
@ -614,6 +619,7 @@ export function register<T extends { readonly version?: string }>(source: Map<st
log.debug(`registering ${registrationType} ${key}@${item.version}`);
items.push(item);
return true
}
/** @internal */

View file

@ -28,15 +28,14 @@ describe("runtime", () => {
describe("register", () => {
const tests = [
{ name: "wildcard version", version: undefined },
{ name: "blank version", version: "" },
{ name: "version", version: "1.2.3" },
{ name: "alpha version", version: "1.0.0-alpha1" },
];
for (const { name, version } of tests) {
it(`throws on same ${name}`, () => {
it(`ignores registration on same ${name}`, () => {
const source = new Map<string, runtime.ResourceModule[]>();
runtime.register(source, rt, "test", { version, construct });
assert.throws(() => runtime.register(source, rt, "test", { version, construct }));
assert.strictEqual(runtime.register(source, rt, "test", { version, construct }), true);
assert.strictEqual(runtime.register(source, rt, "test", { version, construct }), false);
});
}
});