From 635cee7b4e892e8feab61e2e539dd9ac60c1fc63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BB=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Fri, 24 Aug 2018 15:00:43 -0700 Subject: [PATCH] De-duplicate environments before bootstrap If not de-duplicating, multiple-stack applications that involve several stacks in the same account and region will attempt to bootstrap in parallel, and fail miserably. De-duplicating should make this... just work. --- packages/@aws-cdk/cdk/package-lock.json | 12 ++++++------ packages/aws-cdk/bin/cdk.ts | 22 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/packages/@aws-cdk/cdk/package-lock.json b/packages/@aws-cdk/cdk/package-lock.json index 59b67394eae31..5d9a20916b9c9 100644 --- a/packages/@aws-cdk/cdk/package-lock.json +++ b/packages/@aws-cdk/cdk/package-lock.json @@ -12,7 +12,7 @@ "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.1.7.tgz", "integrity": "sha1-rcMgD6RxzCEbDaf1ZrcemLnWc0c=", "requires": { - "es5-ext": "0.8.2" + "es5-ext": "0.8.x" } }, "difflib": { @@ -20,7 +20,7 @@ "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", "requires": { - "heap": "0.2.6" + "heap": ">= 0.2.0" } }, "dreamopt": { @@ -28,7 +28,7 @@ "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.6.0.tgz", "integrity": "sha1-2BPM2sjTnYrVJndVFKE92mZNa0s=", "requires": { - "wordwrap": "1.0.0" + "wordwrap": ">=0.0.2" } }, "es5-ext": { @@ -51,9 +51,9 @@ "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.3.1.tgz", "integrity": "sha1-bbw64tJeB1p/1xvNmHRFhmb7aBs=", "requires": { - "cli-color": "0.1.7", - "difflib": "0.2.4", - "dreamopt": "0.6.0" + "cli-color": "~0.1.6", + "difflib": "~0.2.1", + "dreamopt": "~0.6.0" } }, "wordwrap": { diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index 9aaaa73f05721..2fd6f28632b1e 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -264,8 +264,8 @@ async function initCommandLine() { environmentGlobs = [ '**' ]; // default to ALL } const stackInfos = await selectStacks(); - const availableEnvironments = stackInfos.map(stack => stack.environment) - .filter(env => env !== undefined); + const availableEnvironments = distinct(stackInfos.map(stack => stack.environment) + .filter(env => env !== undefined) as cxapi.Environment[]); const environments = availableEnvironments.filter(env => environmentGlobs.find(glob => minimatch(env!.name, glob))); if (environments.length === 0) { const globs = JSON.stringify(environmentGlobs); @@ -284,6 +284,24 @@ async function initCommandLine() { throw e; } })); + + /** + * De-duplicates a list of environments, such that a given account and region is only represented exactly once + * in the result. + * + * @param envs the possibly full-of-duplicates list of environments. + * + * @return a de-duplicated list of environments. + */ + function distinct(envs: cxapi.Environment[]): cxapi.Environment[] { + const unique: { [id: string]: cxapi.Environment } = {}; + for (const env of envs) { + const id = `${env.account || 'default'}/${env.region || 'default'}`; + if (id in unique) { continue; } + unique[id] = env; + } + return Object.values(unique); + } } /**