From 0620818abcf7b87122a5d6bdc8c777c748f532b4 Mon Sep 17 00:00:00 2001 From: Leonardo Gama Date: Thu, 1 May 2025 11:11:09 -0700 Subject: [PATCH 01/31] Add drift detection to cdk diff --- .../cloudformation-diff/lib/format.ts | 78 +++++++++- .../src/api/aws-auth/sdk.ts | 24 ++++ .../src/api/deployments/cfn-api.ts | 82 +++++++++++ .../src/api/diff/diff-formatter.ts | 68 ++++++++- .../test/api/diff/diff.test.ts | 136 ++++++++++++++++++ packages/aws-cdk/lib/cli/cdk-toolkit.ts | 36 ++++- packages/aws-cdk/lib/cli/cli-config.ts | 1 + packages/aws-cdk/lib/cli/cli.ts | 1 + .../aws-cdk/lib/cli/convert-to-user-input.ts | 2 + .../lib/cli/parse-command-line-arguments.ts | 5 + packages/aws-cdk/lib/cli/user-input.ts | 7 + 11 files changed, 435 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-diff/lib/format.ts b/packages/@aws-cdk/cloudformation-diff/lib/format.ts index bbfd621df..0390bdf93 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/format.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/format.ts @@ -1,9 +1,10 @@ import { format } from 'util'; +import type { DescribeStackResourceDriftsCommandOutput } from '@aws-sdk/client-cloudformation'; import * as chalk from 'chalk'; import type { DifferenceCollection, TemplateDiff } from './diff/types'; import { deepEqual } from './diff/util'; -import type { Difference, ResourceDifference } from './diff-template'; -import { isPropertyDifference, ResourceImpact } from './diff-template'; +import type { ResourceDifference } from './diff-template'; +import { isPropertyDifference, ResourceImpact, Difference } from './diff-template'; import { formatTable } from './format-table'; import type { IamChanges } from './iam/iam-changes'; import type { SecurityGroupChanges } from './network/security-group-changes'; @@ -19,6 +20,16 @@ export interface FormatStream extends NodeJS.WritableStream { columns?: number; } +/** + * Resource drift status types from CloudFormation + */ +export enum ResourceDriftStatus { + MODIFIED = 'MODIFIED', + DELETED = 'DELETED', + NOT_CHECKED = 'NOT_CHECKED', + IN_SYNC = 'IN_SYNC', +} + /** * Renders template differences to the process' console. * @@ -67,6 +78,69 @@ export function formatSecurityChanges( formatSecurityChangesWithBanner(formatter, templateDiff); } +/** + * Renders stack drift information to the given stream + * + * @param stream The stream to write the formatted drift to + * @param driftResults The stack resource drifts from CloudFormation + * @param logicalToPathMap A map from logical ID to construct path + */ +export function formatStackDriftChanges( + stream: FormatStream, + driftResults: DescribeStackResourceDriftsCommandOutput, + logicalToPathMap: { [logicalId: string]: string } = {}) { + const formatter = new Formatter(stream, logicalToPathMap); + + if (!driftResults.StackResourceDrifts || driftResults.StackResourceDrifts.length === 0) { + return; + } + + const drifts = driftResults.StackResourceDrifts; + + // Process modified resources + const modifiedResources = drifts.filter(d => d.StackResourceDriftStatus === ResourceDriftStatus.MODIFIED); + if (modifiedResources.length > 0) { + formatter.printSectionHeader('Modified Resources'); + + for (const drift of modifiedResources) { + if (!drift.LogicalResourceId || !drift.ResourceType) continue; + + // Print the resource header + formatter.print(`${UPDATE} ${formatter.formatValue(drift.ResourceType, chalk.cyan)} ${formatter.formatLogicalId(drift.LogicalResourceId)}`); + + // Format property differences using formatTreeDiff + if (drift.PropertyDifferences) { + const propDiffs = drift.PropertyDifferences; + for (let i = 0; i < propDiffs.length; i++) { + const diff = propDiffs[i]; + if (!diff.PropertyPath) continue; + + // Create a simple Difference object that formatTreeDiff can handle + const difference = new Difference(diff.ExpectedValue, diff.ActualValue); + + // Use formatTreeDiff to format the property difference + formatter.formatTreeDiff(diff.PropertyPath, difference, i === propDiffs.length - 1); + } + } + } + formatter.printSectionFooter(); + } + + // Process deleted resources + const deletedResources = drifts.filter(d => d.StackResourceDriftStatus === ResourceDriftStatus.DELETED); + if (deletedResources.length > 0) { + formatter.printSectionHeader('Deleted Resources'); + + for (const drift of deletedResources) { + if (!drift.LogicalResourceId || !drift.ResourceType) continue; + + // Use formatter's print method for consistent output + formatter.print(`${REMOVAL} ${formatter.formatValue(drift.ResourceType, chalk.cyan)} ${formatter.formatLogicalId(drift.LogicalResourceId)}`); + } + formatter.printSectionFooter(); + } +} + function formatSecurityChangesWithBanner(formatter: Formatter, templateDiff: TemplateDiff) { if (!templateDiff.iamChanges.hasChanges && !templateDiff.securityGroupChanges.hasChanges) { return; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/aws-auth/sdk.ts b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/aws-auth/sdk.ts index 0c6fd1fb0..11a845fd9 100644 --- a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/aws-auth/sdk.ts +++ b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/aws-auth/sdk.ts @@ -88,6 +88,14 @@ import type { UpdateTerminationProtectionCommandInput, UpdateTerminationProtectionCommandOutput, StackSummary, + DescribeStackDriftDetectionStatusCommandInput, + DescribeStackDriftDetectionStatusCommandOutput, + DescribeStackResourceDriftsCommandOutput, + DetectStackDriftCommandInput, + DetectStackDriftCommandOutput, + DetectStackResourceDriftCommandInput, + DetectStackResourceDriftCommandOutput, + DescribeStackResourceDriftsCommandInput, } from '@aws-sdk/client-cloudformation'; import { paginateListStacks, @@ -119,6 +127,10 @@ import { StartResourceScanCommand, UpdateStackCommand, UpdateTerminationProtectionCommand, + DescribeStackDriftDetectionStatusCommand, + DescribeStackResourceDriftsCommand, + DetectStackDriftCommand, + DetectStackResourceDriftCommand, } from '@aws-sdk/client-cloudformation'; import type { FilterLogEventsCommandInput, @@ -418,8 +430,12 @@ export interface ICloudFormationClient { input: DescribeGeneratedTemplateCommandInput, ): Promise; describeResourceScan(input: DescribeResourceScanCommandInput): Promise; + describeStackDriftDetectionStatus(input: DescribeStackDriftDetectionStatusCommandInput): Promise; describeStacks(input: DescribeStacksCommandInput): Promise; + describeStackResourceDrifts(input: DescribeStackResourceDriftsCommandInput): Promise; describeStackResources(input: DescribeStackResourcesCommandInput): Promise; + detectStackDrift(input: DetectStackDriftCommandInput): Promise; + detectStackResourceDrift(input: DetectStackResourceDriftCommandInput): Promise; executeChangeSet(input: ExecuteChangeSetCommandInput): Promise; getGeneratedTemplate(input: GetGeneratedTemplateCommandInput): Promise; getTemplate(input: GetTemplateCommandInput): Promise; @@ -680,6 +696,10 @@ export class SDK { ): Promise => client.send(new DeleteGeneratedTemplateCommand(input)), deleteStack: (input: DeleteStackCommandInput): Promise => client.send(new DeleteStackCommand(input)), + detectStackDrift: (input: DetectStackDriftCommandInput): Promise => + client.send(new DetectStackDriftCommand(input)), + detectStackResourceDrift: (input: DetectStackResourceDriftCommandInput): Promise => + client.send(new DetectStackResourceDriftCommand(input)), describeChangeSet: (input: DescribeChangeSetCommandInput): Promise => client.send(new DescribeChangeSetCommand(input)), describeGeneratedTemplate: ( @@ -687,6 +707,10 @@ export class SDK { ): Promise => client.send(new DescribeGeneratedTemplateCommand(input)), describeResourceScan: (input: DescribeResourceScanCommandInput): Promise => client.send(new DescribeResourceScanCommand(input)), + describeStackDriftDetectionStatus: (input: DescribeStackDriftDetectionStatusCommandInput): + Promise => client.send(new DescribeStackDriftDetectionStatusCommand(input)), + describeStackResourceDrifts: (input: DescribeStackResourceDriftsCommandInput): Promise => + client.send(new DescribeStackResourceDriftsCommand(input)), describeStacks: (input: DescribeStacksCommandInput): Promise => client.send(new DescribeStacksCommand(input)), describeStackResources: (input: DescribeStackResourcesCommandInput): Promise => diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/cfn-api.ts b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/cfn-api.ts index 82453f361..92b5bca9f 100644 --- a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/cfn-api.ts +++ b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/deployments/cfn-api.ts @@ -3,6 +3,8 @@ import * as cxapi from '@aws-cdk/cx-api'; import { SSMPARAM_NO_INVALIDATE } from '@aws-cdk/cx-api'; import type { DescribeChangeSetCommandOutput, + DescribeStackDriftDetectionStatusCommandOutput, + DescribeStackResourceDriftsCommandOutput, Parameter, ResourceToImport, Tag, @@ -466,6 +468,86 @@ export async function stabilizeStack( }); } +/** + * Detect drift for a CloudFormation stack and wait for the detection to complete + * + * @param cfn a CloudFormation client + * @param ioHelper helper for IO operations + * @param stackName the name of the stack to check for drift + * + * @returns the CloudFormation description of the drift detection results + */ +export async function detectStackDrift( + cfn: ICloudFormationClient, + ioHelper: IoHelper, + stackName: string, +): Promise { + await ioHelper.notify(IO.DEFAULT_TOOLKIT_DEBUG.msg(format('Starting drift detection for stack %s...', stackName))); + + // Start drift detection + const driftDetection = await cfn.detectStackDrift({ + StackName: stackName, + }); + + // Wait for drift detection to complete + const driftStatus = await waitForDriftDetection(cfn, ioHelper, driftDetection.StackDriftDetectionId!); + + if (!driftStatus) { + throw new ToolkitError('Drift detection took too long to complete. Aborting'); + } + + if (driftStatus?.DetectionStatus === 'DETECTION_FAILED') { + throw new ToolkitError( + `Failed to detect drift for stack ${stackName}: ${driftStatus.DetectionStatusReason || 'No reason provided'}`, + ); + } + + // Get the drift results + return cfn.describeStackResourceDrifts({ + StackName: stackName, + }); +} + +/** + * Wait for a drift detection operation to complete + */ +async function waitForDriftDetection( + cfn: ICloudFormationClient, + ioHelper: IoHelper, + driftDetectionId: string, +): Promise { + await ioHelper.notify(IO.DEFAULT_TOOLKIT_DEBUG.msg(format('Waiting for drift detection %s to complete...', driftDetectionId))); + + const maxDelay = 30_000; // 30 seconds max delay + let baseDelay = 1_000; // Start with 1 second + let attempts = 0; + + while (true) { + const response = await cfn.describeStackDriftDetectionStatus({ + StackDriftDetectionId: driftDetectionId, + }); + + if (response.DetectionStatus === 'DETECTION_COMPLETE') { + return response; + } + + if (response.DetectionStatus === 'DETECTION_FAILED') { + throw new ToolkitError(`Drift detection failed: ${response.DetectionStatusReason}`); + } + + if (attempts++ > 30) { + throw new ToolkitError('Drift detection timed out after 30 attempts'); + } + + // Calculate backoff with jitter + const jitter = Math.random() * 1000; + const delay = Math.min(baseDelay + jitter, maxDelay); + await new Promise(resolve => setTimeout(resolve, delay)); + baseDelay *= 2; + attempts++; + } +} + /** * The set of (formal) parameters that have been declared in a template */ diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts index 3a90e521d..3731fac8c 100644 --- a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts +++ b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts @@ -6,8 +6,10 @@ import { fullDiff, mangleLikeCloudFormation, type TemplateDiff, + formatStackDriftChanges, } from '@aws-cdk/cloudformation-diff'; import type * as cxapi from '@aws-cdk/cx-api'; +import type { DescribeStackResourceDriftsCommandOutput } from '@aws-sdk/client-cloudformation'; import * as chalk from 'chalk'; import type { NestedStackTemplates } from '../cloudformation'; import type { IoHelper } from '../io/private'; @@ -41,6 +43,21 @@ interface FormatStackDiffOutput { readonly formattedDiff: string; } +/** + * Output of formatStackDrift + */ +interface FormatStackDriftOutput { + /** + * Number of stacks with drift + */ + readonly numResourcesWithDrift: number; + + /** + * Complete formatted drift + */ + readonly formattedDrift: string; +} + /** * Props for the Diff Formatter */ @@ -55,6 +72,11 @@ interface DiffFormatterProps { * Includes the old/current state of the stack as well as the new state. */ readonly templateInfo: TemplateInfo; + + /** + * The results of stack drift + */ + readonly driftResults?: DescribeStackResourceDriftsCommandOutput; } /** @@ -68,7 +90,7 @@ interface FormatSecurityDiffOptions { } /** - * PRoperties specific to formatting the stack diff + * Properties specific to formatting the stack diff */ interface FormatStackDiffOptions { /** @@ -93,6 +115,16 @@ interface FormatStackDiffOptions { readonly quiet?: boolean; } +/** + * Properties specific to formatting the stack drift diff + */ +interface FormatStackDriftOptions { + /** + * Silences 'There were no differences' messages + */ + readonly quiet?: boolean; +} + interface ReusableStackDiffOptions extends FormatStackDiffOptions { readonly ioDefaultHelper: IoDefaultMessages; } @@ -147,6 +179,7 @@ export class DiffFormatter { private readonly stackName: string; private readonly changeSet?: any; private readonly nestedStacks: { [nestedStackLogicalId: string]: NestedStackTemplates } | undefined; + private readonly driftResults?: DescribeStackResourceDriftsCommandOutput; private readonly isImport: boolean; /** @@ -162,6 +195,7 @@ export class DiffFormatter { this.stackName = props.templateInfo.newTemplate.stackName; this.changeSet = props.templateInfo.changeSet; this.nestedStacks = props.templateInfo.nestedStacks; + this.driftResults = props.driftResults; this.isImport = props.templateInfo.isImport ?? false; } @@ -308,6 +342,38 @@ export class DiffFormatter { } return {}; } + + public formatStackDrift(options: FormatStackDriftOptions): FormatStackDriftOutput { + const stream = new StringWriteStream(); + let driftCount = 0; + + if (!this.driftResults?.StackResourceDrifts) { + return { formattedDrift: '', numResourcesWithDrift: 0 }; + } + + const drifts = this.driftResults.StackResourceDrifts; + + if (drifts.length === 0 && !options.quiet) { + stream.write(chalk.green('No drift detected\n')); + stream.end(); + return { formattedDrift: stream.toString(), numResourcesWithDrift: 0 }; + } + + // Count resources with drift + driftCount = drifts.filter(d => + d.StackResourceDriftStatus === 'MODIFIED' || + d.StackResourceDriftStatus === 'DELETED', + ).length; + + formatStackDriftChanges(stream, this.driftResults, buildLogicalToPathMap(this.newTemplate)); + stream.write(chalk.yellow(`\n${driftCount} resource${driftCount === 1 ? '' : 's'} ${driftCount === 1 ? 'has' : 'have'} drifted from their expected configuration\n`)); + stream.end(); + + return { + formattedDrift: stream.toString(), + numResourcesWithDrift: driftCount, + }; + } } /** diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/test/api/diff/diff.test.ts b/packages/@aws-cdk/tmp-toolkit-helpers/test/api/diff/diff.test.ts index bfe0bcd66..fbcc90e87 100644 --- a/packages/@aws-cdk/tmp-toolkit-helpers/test/api/diff/diff.test.ts +++ b/packages/@aws-cdk/tmp-toolkit-helpers/test/api/diff/diff.test.ts @@ -1,4 +1,5 @@ import type * as cxapi from '@aws-cdk/cx-api'; +import type { DescribeStackResourceDriftsCommandOutput } from '@aws-sdk/client-cloudformation'; import * as chalk from 'chalk'; import { DiffFormatter } from '../../../src/api/diff/diff-formatter'; import { IoHelper, IoDefaultMessages } from '../../../src/api/io/private'; @@ -321,3 +322,138 @@ describe('formatSecurityDiff', () => { expect(mockIoDefaultMessages.warning).not.toHaveBeenCalled(); }); }); + +describe('formatStackDrift', () => { + let mockIoHelper: IoHelper; + let mockNewTemplate: cxapi.CloudFormationStackArtifact; + let mockIoDefaultMessages: any; + + beforeEach(() => { + const mockNotify = jest.fn().mockResolvedValue(undefined); + const mockRequestResponse = jest.fn().mockResolvedValue(undefined); + + mockIoHelper = IoHelper.fromIoHost( + { notify: mockNotify, requestResponse: mockRequestResponse }, + 'diff', + ); + + mockIoDefaultMessages = { + info: jest.fn(), + warning: jest.fn(), + error: jest.fn(), + }; + + jest.spyOn(mockIoHelper, 'notify').mockImplementation(() => Promise.resolve()); + jest.spyOn(mockIoHelper, 'requestResponse').mockImplementation(() => Promise.resolve()); + + (IoDefaultMessages as jest.Mock).mockImplementation(() => mockIoDefaultMessages); + + mockNewTemplate = { + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + S3Bucket: 'BuckChuckets', + S3Key: 'some-key', + }, + Handler: 'index.handler', + Runtime: 'nodejs20.x', + Description: 'Some description', + }, + }, + }, + }, + templateFile: 'template.json', + stackName: 'test-stack', + findMetadataByType: () => [], + } as any; + }); + + test('detects drift', () => { + // GIVEN + const mockDriftedResources: DescribeStackResourceDriftsCommandOutput = { + StackResourceDrifts: [{ + StackId: 'some:stack:arn', + StackResourceDriftStatus: 'MODIFIED', + LogicalResourceId: 'GiveUpTheFunc', + PhysicalResourceId: 'gotta-have-that-func', + ResourceType: 'AWS::Lambda::Function', + PropertyDifferences: [{ + PropertyPath: '/Description', + ExpectedValue: 'Some description', + ActualValue: 'Tear the Roof Off the Sucker', + DifferenceType: 'NOT_EQUAL', + }], + Timestamp: new Date(2024, 5, 3, 13, 0, 0), + }], + $metadata: {}, + }; + + // WHEN + const formatter = new DiffFormatter({ + ioHelper: mockIoHelper, + templateInfo: { + oldTemplate: mockNewTemplate.template, + newTemplate: mockNewTemplate, + }, + driftResults: mockDriftedResources, + }); + const result = formatter.formatStackDrift({}); + + // THEN + expect(result.numResourcesWithDrift).toBe(1); + const expectedStringsInOutput = [ + 'Modified Resources', + 'AWS::Lambda::Function', + 'GiveUpTheFunc', + 'Description', + 'Some description', + 'Tear the Roof Off the Sucker', + '1 resource has drifted', + ]; + for (const expectedStringInOutput of expectedStringsInOutput) { + expect(result.formattedDrift).toContain(expectedStringInOutput); + } + }); + + test('no drift detected', () => { + // GIVEN + const mockDriftResults: DescribeStackResourceDriftsCommandOutput = { + StackResourceDrifts: [], + $metadata: {}, + }; + + // WHEN + const formatter = new DiffFormatter({ + ioHelper: mockIoHelper, + templateInfo: { + oldTemplate: mockNewTemplate.template, + newTemplate: mockNewTemplate, + }, + driftResults: mockDriftResults, + }); + const result = formatter.formatStackDrift({}); + + // THEN + expect(result.numResourcesWithDrift).toBe(0); + expect(result.formattedDrift).toContain('No drift detected'); + }); + + test('if detect drift is false, no output', () => { + // WHEN + const formatter = new DiffFormatter({ + ioHelper: mockIoHelper, + templateInfo: { + oldTemplate: mockNewTemplate.template, + newTemplate: mockNewTemplate, + }, + }); + const result = formatter.formatStackDrift({}); + + // THEN + expect(result.numResourcesWithDrift).toBe(0); + expect(result.formattedDrift).toBeFalsy(); + }); +}); diff --git a/packages/aws-cdk/lib/cli/cdk-toolkit.ts b/packages/aws-cdk/lib/cli/cdk-toolkit.ts index 1a4e198dc..a1d3d8bdb 100644 --- a/packages/aws-cdk/lib/cli/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cli/cdk-toolkit.ts @@ -14,9 +14,11 @@ import type { ToolkitAction } from '../../../@aws-cdk/tmp-toolkit-helpers/src/ap import { ambiguousMovements, findResourceMovements, + Mode, resourceMappings, ToolkitError, } from '../../../@aws-cdk/tmp-toolkit-helpers/src/api'; +import { detectStackDrift } from '../../../@aws-cdk/tmp-toolkit-helpers/src/api/deployments/cfn-api'; import { asIoHelper } from '../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private'; import { AmbiguityError } from '../../../@aws-cdk/tmp-toolkit-helpers/src/api/refactoring'; import type { ToolkitOptions } from '../../../@aws-cdk/toolkit-lib/lib/toolkit'; @@ -213,6 +215,7 @@ export class CdkToolkit { const quiet = options.quiet || false; let diffs = 0; + let drifts = 0; const parameterMap = buildParameterMap(options.parameters); if (options.templatePath !== undefined) { @@ -263,6 +266,19 @@ export class CdkToolkit { const currentTemplate = templateWithNestedStacks.deployedRootTemplate; const nestedStacks = templateWithNestedStacks.nestedStacks; + let driftResults = undefined; + + if (options.detectDrift) { + const env = await this.props.deployments.resolveEnvironment(stack); + const cfn = (await this.props.sdkProvider.forEnvironment(env, Mode.ForReading)).sdk.cloudFormation(); + + driftResults = await detectStackDrift( + cfn, + asIoHelper(this.ioHost, 'diff'), + stack.stackName, + ); + } + const migrator = new ResourceMigrator({ deployments: this.props.deployments, ioHelper: asIoHelper(this.ioHost, 'diff'), @@ -318,6 +334,7 @@ export class CdkToolkit { isImport: !!resourcesToImport, nestedStacks, }, + driftResults, }); if (options.securityOnly) { @@ -334,13 +351,21 @@ export class CdkToolkit { context: contextLines, quiet, }); - info(diff.formattedDiff); + const drift = formatter.formatStackDrift({ + quiet, + }); + info(diff.formattedDiff + '\n' + drift.formattedDrift); diffs += diff.numStacksWithChanges; + drifts = drift.numResourcesWithDrift; } } } - info(format('\n✨ Number of stacks with differences: %s\n', diffs)); + if (options.detectDrift) { + info(format('\n✨ Number of stacks with differences: %s\n✨ Number of resources with drift: %s\n', diffs, drifts)); + } else { + info(format('\n✨ Number of stacks with differences: %s\n', diffs)); + } return diffs && options.fail ? 1 : 0; } @@ -1472,6 +1497,13 @@ export interface DiffOptions { */ readonly securityOnly?: boolean; + /** + * Run drift detection on the stack as well + * + * @default false + */ + readonly detectDrift?: boolean; + /** * Whether to run the diff against the template after the CloudFormation Transforms inside it have been executed * (as opposed to the original template, the default, which contains the unprocessed Transforms). diff --git a/packages/aws-cdk/lib/cli/cli-config.ts b/packages/aws-cdk/lib/cli/cli-config.ts index e8cea579c..a5af8a46b 100644 --- a/packages/aws-cdk/lib/cli/cli-config.ts +++ b/packages/aws-cdk/lib/cli/cli-config.ts @@ -308,6 +308,7 @@ export async function makeConfig(): Promise { 'template': { type: 'string', desc: 'The path to the CloudFormation template to compare with', requiresArg: true }, 'strict': { type: 'boolean', desc: 'Do not filter out AWS::CDK::Metadata resources, mangled non-ASCII characters, or the CheckBootstrapVersionRule', default: false }, 'security-only': { type: 'boolean', desc: 'Only diff for broadened security changes', default: false }, + 'detect-drift': { type: 'boolean', desc: 'Whether or not to also run CloudFormation drift detection', default: false }, 'fail': { type: 'boolean', desc: 'Fail with exit code 1 in case of diff' }, 'processed': { type: 'boolean', desc: 'Whether to compare against the template with Transforms already processed', default: false }, 'quiet': { type: 'boolean', alias: 'q', desc: 'Do not print stack name and default message when there is no diff to stdout', default: false }, diff --git a/packages/aws-cdk/lib/cli/cli.ts b/packages/aws-cdk/lib/cli/cli.ts index fd15044af..c3f00cf3d 100644 --- a/packages/aws-cdk/lib/cli/cli.ts +++ b/packages/aws-cdk/lib/cli/cli.ts @@ -256,6 +256,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise): any { type: 'boolean', desc: 'Only diff for broadened security changes', }) + .option('detect-drift', { + default: false, + type: 'boolean', + desc: 'Whether or not to also run CloudFormation drift detection', + }) .option('fail', { default: undefined, type: 'boolean', diff --git a/packages/aws-cdk/lib/cli/user-input.ts b/packages/aws-cdk/lib/cli/user-input.ts index 3083eb626..dd03c3646 100644 --- a/packages/aws-cdk/lib/cli/user-input.ts +++ b/packages/aws-cdk/lib/cli/user-input.ts @@ -1073,6 +1073,13 @@ export interface DiffOptions { */ readonly securityOnly?: boolean; + /** + * Whether or not to also run CloudFormation drift detection + * + * @default - false + */ + readonly detectDrift?: boolean; + /** * Fail with exit code 1 in case of diff * From 7c4e1fcda3af7763ec913def983f9edbc554709c Mon Sep 17 00:00:00 2001 From: Leonardo Gama Date: Thu, 1 May 2025 11:23:12 -0700 Subject: [PATCH 02/31] Fix output for no drifts --- .../src/api/diff/diff-formatter.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts index 3731fac8c..fce80b52e 100644 --- a/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts +++ b/packages/@aws-cdk/tmp-toolkit-helpers/src/api/diff/diff-formatter.ts @@ -351,7 +351,10 @@ export class DiffFormatter { return { formattedDrift: '', numResourcesWithDrift: 0 }; } - const drifts = this.driftResults.StackResourceDrifts; + const drifts = this.driftResults.StackResourceDrifts.filter(d => + d.StackResourceDriftStatus === 'MODIFIED' || + d.StackResourceDriftStatus === 'DELETED', + ); if (drifts.length === 0 && !options.quiet) { stream.write(chalk.green('No drift detected\n')); @@ -359,12 +362,7 @@ export class DiffFormatter { return { formattedDrift: stream.toString(), numResourcesWithDrift: 0 }; } - // Count resources with drift - driftCount = drifts.filter(d => - d.StackResourceDriftStatus === 'MODIFIED' || - d.StackResourceDriftStatus === 'DELETED', - ).length; - + driftCount = drifts.length; formatStackDriftChanges(stream, this.driftResults, buildLogicalToPathMap(this.newTemplate)); stream.write(chalk.yellow(`\n${driftCount} resource${driftCount === 1 ? '' : 's'} ${driftCount === 1 ? 'has' : 'have'} drifted from their expected configuration\n`)); stream.end(); From 3caf9c985e7062308522e9af3df3d939bc8085a2 Mon Sep 17 00:00:00 2001 From: Leonardo Gama Date: Thu, 1 May 2025 11:11:09 -0700 Subject: [PATCH 03/31] Add drift detection to cdk diff --- .../cloudformation-diff/lib/format.ts | 78 +++++++++- .../toolkit-lib/lib/api/aws-auth/sdk.ts | 24 ++++ .../lib/api/deployments/cfn-api.ts | 82 +++++++++++ .../lib/api/diff/diff-formatter.ts | 83 +++++++++++ .../toolkit-lib/test/api/diff/diff.test.ts | 136 ++++++++++++++++++ packages/aws-cdk/lib/cli/cdk-toolkit.ts | 51 +++++-- packages/aws-cdk/lib/cli/cli-config.ts | 1 + packages/aws-cdk/lib/cli/cli.ts | 1 + .../aws-cdk/lib/cli/convert-to-user-input.ts | 2 + .../lib/cli/parse-command-line-arguments.ts | 5 + packages/aws-cdk/lib/cli/user-input.ts | 7 + 11 files changed, 454 insertions(+), 16 deletions(-) diff --git a/packages/@aws-cdk/cloudformation-diff/lib/format.ts b/packages/@aws-cdk/cloudformation-diff/lib/format.ts index bbfd621df..0390bdf93 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/format.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/format.ts @@ -1,9 +1,10 @@ import { format } from 'util'; +import type { DescribeStackResourceDriftsCommandOutput } from '@aws-sdk/client-cloudformation'; import * as chalk from 'chalk'; import type { DifferenceCollection, TemplateDiff } from './diff/types'; import { deepEqual } from './diff/util'; -import type { Difference, ResourceDifference } from './diff-template'; -import { isPropertyDifference, ResourceImpact } from './diff-template'; +import type { ResourceDifference } from './diff-template'; +import { isPropertyDifference, ResourceImpact, Difference } from './diff-template'; import { formatTable } from './format-table'; import type { IamChanges } from './iam/iam-changes'; import type { SecurityGroupChanges } from './network/security-group-changes'; @@ -19,6 +20,16 @@ export interface FormatStream extends NodeJS.WritableStream { columns?: number; } +/** + * Resource drift status types from CloudFormation + */ +export enum ResourceDriftStatus { + MODIFIED = 'MODIFIED', + DELETED = 'DELETED', + NOT_CHECKED = 'NOT_CHECKED', + IN_SYNC = 'IN_SYNC', +} + /** * Renders template differences to the process' console. * @@ -67,6 +78,69 @@ export function formatSecurityChanges( formatSecurityChangesWithBanner(formatter, templateDiff); } +/** + * Renders stack drift information to the given stream + * + * @param stream The stream to write the formatted drift to + * @param driftResults The stack resource drifts from CloudFormation + * @param logicalToPathMap A map from logical ID to construct path + */ +export function formatStackDriftChanges( + stream: FormatStream, + driftResults: DescribeStackResourceDriftsCommandOutput, + logicalToPathMap: { [logicalId: string]: string } = {}) { + const formatter = new Formatter(stream, logicalToPathMap); + + if (!driftResults.StackResourceDrifts || driftResults.StackResourceDrifts.length === 0) { + return; + } + + const drifts = driftResults.StackResourceDrifts; + + // Process modified resources + const modifiedResources = drifts.filter(d => d.StackResourceDriftStatus === ResourceDriftStatus.MODIFIED); + if (modifiedResources.length > 0) { + formatter.printSectionHeader('Modified Resources'); + + for (const drift of modifiedResources) { + if (!drift.LogicalResourceId || !drift.ResourceType) continue; + + // Print the resource header + formatter.print(`${UPDATE} ${formatter.formatValue(drift.ResourceType, chalk.cyan)} ${formatter.formatLogicalId(drift.LogicalResourceId)}`); + + // Format property differences using formatTreeDiff + if (drift.PropertyDifferences) { + const propDiffs = drift.PropertyDifferences; + for (let i = 0; i < propDiffs.length; i++) { + const diff = propDiffs[i]; + if (!diff.PropertyPath) continue; + + // Create a simple Difference object that formatTreeDiff can handle + const difference = new Difference(diff.ExpectedValue, diff.ActualValue); + + // Use formatTreeDiff to format the property difference + formatter.formatTreeDiff(diff.PropertyPath, difference, i === propDiffs.length - 1); + } + } + } + formatter.printSectionFooter(); + } + + // Process deleted resources + const deletedResources = drifts.filter(d => d.StackResourceDriftStatus === ResourceDriftStatus.DELETED); + if (deletedResources.length > 0) { + formatter.printSectionHeader('Deleted Resources'); + + for (const drift of deletedResources) { + if (!drift.LogicalResourceId || !drift.ResourceType) continue; + + // Use formatter's print method for consistent output + formatter.print(`${REMOVAL} ${formatter.formatValue(drift.ResourceType, chalk.cyan)} ${formatter.formatLogicalId(drift.LogicalResourceId)}`); + } + formatter.printSectionFooter(); + } +} + function formatSecurityChangesWithBanner(formatter: Formatter, templateDiff: TemplateDiff) { if (!templateDiff.iamChanges.hasChanges && !templateDiff.securityGroupChanges.hasChanges) { return; diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/aws-auth/sdk.ts b/packages/@aws-cdk/toolkit-lib/lib/api/aws-auth/sdk.ts index 0c6fd1fb0..11a845fd9 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/aws-auth/sdk.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/aws-auth/sdk.ts @@ -88,6 +88,14 @@ import type { UpdateTerminationProtectionCommandInput, UpdateTerminationProtectionCommandOutput, StackSummary, + DescribeStackDriftDetectionStatusCommandInput, + DescribeStackDriftDetectionStatusCommandOutput, + DescribeStackResourceDriftsCommandOutput, + DetectStackDriftCommandInput, + DetectStackDriftCommandOutput, + DetectStackResourceDriftCommandInput, + DetectStackResourceDriftCommandOutput, + DescribeStackResourceDriftsCommandInput, } from '@aws-sdk/client-cloudformation'; import { paginateListStacks, @@ -119,6 +127,10 @@ import { StartResourceScanCommand, UpdateStackCommand, UpdateTerminationProtectionCommand, + DescribeStackDriftDetectionStatusCommand, + DescribeStackResourceDriftsCommand, + DetectStackDriftCommand, + DetectStackResourceDriftCommand, } from '@aws-sdk/client-cloudformation'; import type { FilterLogEventsCommandInput, @@ -418,8 +430,12 @@ export interface ICloudFormationClient { input: DescribeGeneratedTemplateCommandInput, ): Promise; describeResourceScan(input: DescribeResourceScanCommandInput): Promise; + describeStackDriftDetectionStatus(input: DescribeStackDriftDetectionStatusCommandInput): Promise; describeStacks(input: DescribeStacksCommandInput): Promise; + describeStackResourceDrifts(input: DescribeStackResourceDriftsCommandInput): Promise; describeStackResources(input: DescribeStackResourcesCommandInput): Promise; + detectStackDrift(input: DetectStackDriftCommandInput): Promise; + detectStackResourceDrift(input: DetectStackResourceDriftCommandInput): Promise; executeChangeSet(input: ExecuteChangeSetCommandInput): Promise; getGeneratedTemplate(input: GetGeneratedTemplateCommandInput): Promise; getTemplate(input: GetTemplateCommandInput): Promise; @@ -680,6 +696,10 @@ export class SDK { ): Promise => client.send(new DeleteGeneratedTemplateCommand(input)), deleteStack: (input: DeleteStackCommandInput): Promise => client.send(new DeleteStackCommand(input)), + detectStackDrift: (input: DetectStackDriftCommandInput): Promise => + client.send(new DetectStackDriftCommand(input)), + detectStackResourceDrift: (input: DetectStackResourceDriftCommandInput): Promise => + client.send(new DetectStackResourceDriftCommand(input)), describeChangeSet: (input: DescribeChangeSetCommandInput): Promise => client.send(new DescribeChangeSetCommand(input)), describeGeneratedTemplate: ( @@ -687,6 +707,10 @@ export class SDK { ): Promise => client.send(new DescribeGeneratedTemplateCommand(input)), describeResourceScan: (input: DescribeResourceScanCommandInput): Promise => client.send(new DescribeResourceScanCommand(input)), + describeStackDriftDetectionStatus: (input: DescribeStackDriftDetectionStatusCommandInput): + Promise => client.send(new DescribeStackDriftDetectionStatusCommand(input)), + describeStackResourceDrifts: (input: DescribeStackResourceDriftsCommandInput): Promise => + client.send(new DescribeStackResourceDriftsCommand(input)), describeStacks: (input: DescribeStacksCommandInput): Promise => client.send(new DescribeStacksCommand(input)), describeStackResources: (input: DescribeStackResourcesCommandInput): Promise => diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/deployments/cfn-api.ts b/packages/@aws-cdk/toolkit-lib/lib/api/deployments/cfn-api.ts index 972a7d11a..138c560e4 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/deployments/cfn-api.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/deployments/cfn-api.ts @@ -3,6 +3,8 @@ import * as cxapi from '@aws-cdk/cx-api'; import { SSMPARAM_NO_INVALIDATE } from '@aws-cdk/cx-api'; import type { DescribeChangeSetCommandOutput, + DescribeStackDriftDetectionStatusCommandOutput, + DescribeStackResourceDriftsCommandOutput, Parameter, ResourceToImport, Tag, @@ -466,6 +468,86 @@ export async function stabilizeStack( }); } +/** + * Detect drift for a CloudFormation stack and wait for the detection to complete + * + * @param cfn a CloudFormation client + * @param ioHelper helper for IO operations + * @param stackName the name of the stack to check for drift + * + * @returns the CloudFormation description of the drift detection results + */ +export async function detectStackDrift( + cfn: ICloudFormationClient, + ioHelper: IoHelper, + stackName: string, +): Promise { + await ioHelper.notify(IO.DEFAULT_TOOLKIT_DEBUG.msg(format('Starting drift detection for stack %s...', stackName))); + + // Start drift detection + const driftDetection = await cfn.detectStackDrift({ + StackName: stackName, + }); + + // Wait for drift detection to complete + const driftStatus = await waitForDriftDetection(cfn, ioHelper, driftDetection.StackDriftDetectionId!); + + if (!driftStatus) { + throw new ToolkitError('Drift detection took too long to complete. Aborting'); + } + + if (driftStatus?.DetectionStatus === 'DETECTION_FAILED') { + throw new ToolkitError( + `Failed to detect drift for stack ${stackName}: ${driftStatus.DetectionStatusReason || 'No reason provided'}`, + ); + } + + // Get the drift results + return cfn.describeStackResourceDrifts({ + StackName: stackName, + }); +} + +/** + * Wait for a drift detection operation to complete + */ +async function waitForDriftDetection( + cfn: ICloudFormationClient, + ioHelper: IoHelper, + driftDetectionId: string, +): Promise { + await ioHelper.notify(IO.DEFAULT_TOOLKIT_DEBUG.msg(format('Waiting for drift detection %s to complete...', driftDetectionId))); + + const maxDelay = 30_000; // 30 seconds max delay + let baseDelay = 1_000; // Start with 1 second + let attempts = 0; + + while (true) { + const response = await cfn.describeStackDriftDetectionStatus({ + StackDriftDetectionId: driftDetectionId, + }); + + if (response.DetectionStatus === 'DETECTION_COMPLETE') { + return response; + } + + if (response.DetectionStatus === 'DETECTION_FAILED') { + throw new ToolkitError(`Drift detection failed: ${response.DetectionStatusReason}`); + } + + if (attempts++ > 30) { + throw new ToolkitError('Drift detection timed out after 30 attempts'); + } + + // Calculate backoff with jitter + const jitter = Math.random() * 1000; + const delay = Math.min(baseDelay + jitter, maxDelay); + await new Promise(resolve => setTimeout(resolve, delay)); + baseDelay *= 2; + attempts++; + } +} + /** * The set of (formal) parameters that have been declared in a template */ diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts b/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts index 9d6e8905a..f19fc0890 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts @@ -6,14 +6,18 @@ import { fullDiff, mangleLikeCloudFormation, type TemplateDiff, + formatStackDriftChanges, } from '@aws-cdk/cloudformation-diff'; import type * as cxapi from '@aws-cdk/cx-api'; +import type { DescribeStackResourceDriftsCommandOutput } from '@aws-sdk/client-cloudformation'; import * as chalk from 'chalk'; import { PermissionChangeType } from '../../payloads'; import type { NestedStackTemplates } from '../cloudformation'; import type { IoHelper } from '../io/private'; import { IoDefaultMessages } from '../io/private'; import { StringWriteStream } from '../streams'; +import { RequireApproval } from '../require-approval'; +import { ToolkitError } from '../toolkit-error'; /** * Output of formatSecurityDiff @@ -46,6 +50,21 @@ interface FormatStackDiffOutput { readonly formattedDiff: string; } +/** + * Output of formatStackDrift + */ +interface FormatStackDriftOutput { + /** + * Number of stacks with drift + */ + readonly numResourcesWithDrift: number; + + /** + * Complete formatted drift + */ + readonly formattedDrift: string; +} + /** * Props for the Diff Formatter */ @@ -60,6 +79,11 @@ interface DiffFormatterProps { * Includes the old/current state of the stack as well as the new state. */ readonly templateInfo: TemplateInfo; + + /** + * The results of stack drift + */ + readonly driftResults?: DescribeStackResourceDriftsCommandOutput; } /** @@ -88,6 +112,16 @@ interface FormatStackDiffOptions { readonly quiet?: boolean; } +/** + * Properties specific to formatting the stack drift diff + */ +interface FormatStackDriftOptions { + /** + * Silences 'There were no differences' messages + */ + readonly quiet?: boolean; +} + interface ReusableStackDiffOptions extends FormatStackDiffOptions { readonly ioDefaultHelper: IoDefaultMessages; } @@ -142,6 +176,7 @@ export class DiffFormatter { private readonly stackName: string; private readonly changeSet?: any; private readonly nestedStacks: { [nestedStackLogicalId: string]: NestedStackTemplates } | undefined; + private readonly driftResults?: DescribeStackResourceDriftsCommandOutput; private readonly isImport: boolean; /** @@ -157,6 +192,7 @@ export class DiffFormatter { this.stackName = props.templateInfo.newTemplate.stackName; this.changeSet = props.templateInfo.changeSet; this.nestedStacks = props.templateInfo.nestedStacks; + this.driftResults = props.driftResults; this.isImport = props.templateInfo.isImport ?? false; } @@ -329,6 +365,53 @@ export class DiffFormatter { const formattedDiff = stream.toString(); return { formattedDiff, permissionChangeType: this.permissionType() }; } + + public formatStackDrift(options: FormatStackDriftOptions): FormatStackDriftOutput { + const stream = new StringWriteStream(); + let driftCount = 0; + + if (!this.driftResults?.StackResourceDrifts) { + return { formattedDrift: '', numResourcesWithDrift: 0 }; + } + + const drifts = this.driftResults.StackResourceDrifts; + + if (drifts.length === 0 && !options.quiet) { + stream.write(chalk.green('No drift detected\n')); + stream.end(); + return { formattedDrift: stream.toString(), numResourcesWithDrift: 0 }; + } + + // Count resources with drift + driftCount = drifts.filter(d => + d.StackResourceDriftStatus === 'MODIFIED' || + d.StackResourceDriftStatus === 'DELETED', + ).length; + + formatStackDriftChanges(stream, this.driftResults, buildLogicalToPathMap(this.newTemplate)); + stream.write(chalk.yellow(`\n${driftCount} resource${driftCount === 1 ? '' : 's'} ${driftCount === 1 ? 'has' : 'have'} drifted from their expected configuration\n`)); + stream.end(); + + return { + formattedDrift: stream.toString(), + numResourcesWithDrift: driftCount, + }; + } +} + +/** + * Return whether the diff has security-impacting changes that need confirmation + * + * TODO: Filter the security impact determination based off of an enum that allows + * us to pick minimum "severities" to alert on. + */ +function diffRequiresApproval(diff: TemplateDiff, requireApproval: RequireApproval) { + switch (requireApproval) { + case RequireApproval.NEVER: return false; + case RequireApproval.ANY_CHANGE: return diff.permissionsAnyChanges; + case RequireApproval.BROADENING: return diff.permissionsBroadened; + default: throw new ToolkitError(`Unrecognized approval level: ${requireApproval}`); + } } function buildLogicalToPathMap(stack: cxapi.CloudFormationStackArtifact) { diff --git a/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts index 79de4e448..90536dd9f 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts @@ -1,4 +1,5 @@ import type * as cxapi from '@aws-cdk/cx-api'; +import type { DescribeStackResourceDriftsCommandOutput } from '@aws-sdk/client-cloudformation'; import * as chalk from 'chalk'; import { DiffFormatter } from '../../../lib/api/diff/diff-formatter'; import { IoHelper, IoDefaultMessages } from '../../../lib/api/io/private'; @@ -261,3 +262,138 @@ describe('formatSecurityDiff', () => { ); }); }); + +describe('formatStackDrift', () => { + let mockIoHelper: IoHelper; + let mockNewTemplate: cxapi.CloudFormationStackArtifact; + let mockIoDefaultMessages: any; + + beforeEach(() => { + const mockNotify = jest.fn().mockResolvedValue(undefined); + const mockRequestResponse = jest.fn().mockResolvedValue(undefined); + + mockIoHelper = IoHelper.fromIoHost( + { notify: mockNotify, requestResponse: mockRequestResponse }, + 'diff', + ); + + mockIoDefaultMessages = { + info: jest.fn(), + warning: jest.fn(), + error: jest.fn(), + }; + + jest.spyOn(mockIoHelper, 'notify').mockImplementation(() => Promise.resolve()); + jest.spyOn(mockIoHelper, 'requestResponse').mockImplementation(() => Promise.resolve()); + + (IoDefaultMessages as jest.Mock).mockImplementation(() => mockIoDefaultMessages); + + mockNewTemplate = { + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + S3Bucket: 'BuckChuckets', + S3Key: 'some-key', + }, + Handler: 'index.handler', + Runtime: 'nodejs20.x', + Description: 'Some description', + }, + }, + }, + }, + templateFile: 'template.json', + stackName: 'test-stack', + findMetadataByType: () => [], + } as any; + }); + + test('detects drift', () => { + // GIVEN + const mockDriftedResources: DescribeStackResourceDriftsCommandOutput = { + StackResourceDrifts: [{ + StackId: 'some:stack:arn', + StackResourceDriftStatus: 'MODIFIED', + LogicalResourceId: 'GiveUpTheFunc', + PhysicalResourceId: 'gotta-have-that-func', + ResourceType: 'AWS::Lambda::Function', + PropertyDifferences: [{ + PropertyPath: '/Description', + ExpectedValue: 'Some description', + ActualValue: 'Tear the Roof Off the Sucker', + DifferenceType: 'NOT_EQUAL', + }], + Timestamp: new Date(2024, 5, 3, 13, 0, 0), + }], + $metadata: {}, + }; + + // WHEN + const formatter = new DiffFormatter({ + ioHelper: mockIoHelper, + templateInfo: { + oldTemplate: mockNewTemplate.template, + newTemplate: mockNewTemplate, + }, + driftResults: mockDriftedResources, + }); + const result = formatter.formatStackDrift({}); + + // THEN + expect(result.numResourcesWithDrift).toBe(1); + const expectedStringsInOutput = [ + 'Modified Resources', + 'AWS::Lambda::Function', + 'GiveUpTheFunc', + 'Description', + 'Some description', + 'Tear the Roof Off the Sucker', + '1 resource has drifted', + ]; + for (const expectedStringInOutput of expectedStringsInOutput) { + expect(result.formattedDrift).toContain(expectedStringInOutput); + } + }); + + test('no drift detected', () => { + // GIVEN + const mockDriftResults: DescribeStackResourceDriftsCommandOutput = { + StackResourceDrifts: [], + $metadata: {}, + }; + + // WHEN + const formatter = new DiffFormatter({ + ioHelper: mockIoHelper, + templateInfo: { + oldTemplate: mockNewTemplate.template, + newTemplate: mockNewTemplate, + }, + driftResults: mockDriftResults, + }); + const result = formatter.formatStackDrift({}); + + // THEN + expect(result.numResourcesWithDrift).toBe(0); + expect(result.formattedDrift).toContain('No drift detected'); + }); + + test('if detect drift is false, no output', () => { + // WHEN + const formatter = new DiffFormatter({ + ioHelper: mockIoHelper, + templateInfo: { + oldTemplate: mockNewTemplate.template, + newTemplate: mockNewTemplate, + }, + }); + const result = formatter.formatStackDrift({}); + + // THEN + expect(result.numResourcesWithDrift).toBe(0); + expect(result.formattedDrift).toBeFalsy(); + }); +}); diff --git a/packages/aws-cdk/lib/cli/cdk-toolkit.ts b/packages/aws-cdk/lib/cli/cdk-toolkit.ts index 992045476..d2d0af93d 100644 --- a/packages/aws-cdk/lib/cli/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cli/cdk-toolkit.ts @@ -10,19 +10,10 @@ import * as uuid from 'uuid'; import { CliIoHost } from './io-host'; import type { Configuration } from './user-configuration'; import { PROJECT_CONFIG } from './user-configuration'; -import type { ToolkitAction } from '../../../@aws-cdk/toolkit-lib/lib/api'; -import { - ambiguousMovements, - findResourceMovements, - resourceMappings, - ToolkitError, -} from '../../../@aws-cdk/toolkit-lib/lib/api'; -import { asIoHelper } from '../../../@aws-cdk/toolkit-lib/lib/api/io/private'; -import { AmbiguityError } from '../../../@aws-cdk/toolkit-lib/lib/api/refactoring'; -import { PermissionChangeType } from '../../../@aws-cdk/toolkit-lib/lib/payloads'; +import { AmbiguityError, ambiguousMovements, findResourceMovements, resourceMappings, type ToolkitAction } from '../../../@aws-cdk/toolkit-lib/lib/api'; import type { ToolkitOptions } from '../../../@aws-cdk/toolkit-lib/lib/toolkit'; import { Toolkit } from '../../../@aws-cdk/toolkit-lib/lib/toolkit'; -import { DEFAULT_TOOLKIT_STACK_NAME } from '../api'; +import { DEFAULT_TOOLKIT_STACK_NAME, Mode, ToolkitError } from '../api'; import type { SdkProvider } from '../api/aws-auth'; import type { BootstrapEnvironmentOptions } from '../api/bootstrap'; import { Bootstrapper } from '../api/bootstrap'; @@ -35,7 +26,7 @@ import { removeNonImportResources, ResourceImporter, ResourceMigrator } from '.. import { type Tag, tagsForStack } from '../api/tags'; import type { AssetBuildNode, AssetPublishNode, Concurrency, StackNode, WorkGraph } from '../api/work-graph'; import { WorkGraphBuilder } from '../api/work-graph'; -import { cfnApi } from '../api-private'; +import { asIoHelper, cfnApi } from '../api-private'; import { StackActivityProgress } from '../commands/deploy'; import { DiffFormatter, RequireApproval } from '../commands/diff'; import { listStacks } from '../commands/list-stacks'; @@ -68,6 +59,8 @@ import { serializeStructure, validateSnsTopicArn, } from '../util'; +import { PermissionChangeType } from '../../../@aws-cdk/toolkit-lib/lib/payloads'; +import { detectStackDrift } from '../../../@aws-cdk/toolkit-lib/lib/api/deployments/cfn-api'; // Must use a require() otherwise esbuild complains about calling a namespace // eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/consistent-type-imports @@ -214,6 +207,7 @@ export class CdkToolkit { const quiet = options.quiet || false; let diffs = 0; + let drifts = 0; const parameterMap = buildParameterMap(options.parameters); if (options.templatePath !== undefined) { @@ -264,6 +258,19 @@ export class CdkToolkit { const currentTemplate = templateWithNestedStacks.deployedRootTemplate; const nestedStacks = templateWithNestedStacks.nestedStacks; + let driftResults = undefined; + + if (options.detectDrift) { + const env = await this.props.deployments.resolveEnvironment(stack); + const cfn = (await this.props.sdkProvider.forEnvironment(env, Mode.ForReading)).sdk.cloudFormation(); + + driftResults = await detectStackDrift( + cfn, + asIoHelper(this.ioHost, 'diff'), + stack.stackName, + ); + } + const migrator = new ResourceMigrator({ deployments: this.props.deployments, ioHelper: asIoHelper(this.ioHost, 'diff'), @@ -319,6 +326,7 @@ export class CdkToolkit { isImport: !!resourcesToImport, nestedStacks, }, + driftResults, }); if (options.securityOnly) { @@ -335,13 +343,21 @@ export class CdkToolkit { context: contextLines, quiet, }); - info(diff.formattedDiff); + const drift = formatter.formatStackDrift({ + quiet, + }); + info(diff.formattedDiff + '\n' + drift.formattedDrift); diffs += diff.numStacksWithChanges; + drifts = drift.numResourcesWithDrift; } } } - info(format('\n✨ Number of stacks with differences: %s\n', diffs)); + if (options.detectDrift) { + info(format('\n✨ Number of stacks with differences: %s\n✨ Number of resources with drift: %s\n', diffs, drifts)); + } else { + info(format('\n✨ Number of stacks with differences: %s\n', diffs)); + } return diffs && options.fail ? 1 : 0; } @@ -1476,6 +1492,13 @@ export interface DiffOptions { */ readonly securityOnly?: boolean; + /** + * Run drift detection on the stack as well + * + * @default false + */ + readonly detectDrift?: boolean; + /** * Whether to run the diff against the template after the CloudFormation Transforms inside it have been executed * (as opposed to the original template, the default, which contains the unprocessed Transforms). diff --git a/packages/aws-cdk/lib/cli/cli-config.ts b/packages/aws-cdk/lib/cli/cli-config.ts index 183b511be..ab00c5abb 100644 --- a/packages/aws-cdk/lib/cli/cli-config.ts +++ b/packages/aws-cdk/lib/cli/cli-config.ts @@ -308,6 +308,7 @@ export async function makeConfig(): Promise { 'template': { type: 'string', desc: 'The path to the CloudFormation template to compare with', requiresArg: true }, 'strict': { type: 'boolean', desc: 'Do not filter out AWS::CDK::Metadata resources, mangled non-ASCII characters, or the CheckBootstrapVersionRule', default: false }, 'security-only': { type: 'boolean', desc: 'Only diff for broadened security changes', default: false }, + 'detect-drift': { type: 'boolean', desc: 'Whether or not to also run CloudFormation drift detection', default: false }, 'fail': { type: 'boolean', desc: 'Fail with exit code 1 in case of diff' }, 'processed': { type: 'boolean', desc: 'Whether to compare against the template with Transforms already processed', default: false }, 'quiet': { type: 'boolean', alias: 'q', desc: 'Do not print stack name and default message when there is no diff to stdout', default: false }, diff --git a/packages/aws-cdk/lib/cli/cli.ts b/packages/aws-cdk/lib/cli/cli.ts index 08ee2f0bf..cbeafd699 100644 --- a/packages/aws-cdk/lib/cli/cli.ts +++ b/packages/aws-cdk/lib/cli/cli.ts @@ -256,6 +256,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise): any { type: 'boolean', desc: 'Only diff for broadened security changes', }) + .option('detect-drift', { + default: false, + type: 'boolean', + desc: 'Whether or not to also run CloudFormation drift detection', + }) .option('fail', { default: undefined, type: 'boolean', diff --git a/packages/aws-cdk/lib/cli/user-input.ts b/packages/aws-cdk/lib/cli/user-input.ts index 4bfc9c3c7..3f4ac388e 100644 --- a/packages/aws-cdk/lib/cli/user-input.ts +++ b/packages/aws-cdk/lib/cli/user-input.ts @@ -1078,6 +1078,13 @@ export interface DiffOptions { */ readonly securityOnly?: boolean; + /** + * Whether or not to also run CloudFormation drift detection + * + * @default - false + */ + readonly detectDrift?: boolean; + /** * Fail with exit code 1 in case of diff * From 87cf1f399e57483dca4198a804323c7659518a96 Mon Sep 17 00:00:00 2001 From: Leonardo Gama Date: Thu, 1 May 2025 11:23:12 -0700 Subject: [PATCH 04/31] Fix output for no drifts --- .../toolkit-lib/lib/api/diff/diff-formatter.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts b/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts index f19fc0890..235dd0114 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts @@ -374,7 +374,10 @@ export class DiffFormatter { return { formattedDrift: '', numResourcesWithDrift: 0 }; } - const drifts = this.driftResults.StackResourceDrifts; + const drifts = this.driftResults.StackResourceDrifts.filter(d => + d.StackResourceDriftStatus === 'MODIFIED' || + d.StackResourceDriftStatus === 'DELETED', + ); if (drifts.length === 0 && !options.quiet) { stream.write(chalk.green('No drift detected\n')); @@ -382,12 +385,7 @@ export class DiffFormatter { return { formattedDrift: stream.toString(), numResourcesWithDrift: 0 }; } - // Count resources with drift - driftCount = drifts.filter(d => - d.StackResourceDriftStatus === 'MODIFIED' || - d.StackResourceDriftStatus === 'DELETED', - ).length; - + driftCount = drifts.length; formatStackDriftChanges(stream, this.driftResults, buildLogicalToPathMap(this.newTemplate)); stream.write(chalk.yellow(`\n${driftCount} resource${driftCount === 1 ? '' : 's'} ${driftCount === 1 ? 'has' : 'have'} drifted from their expected configuration\n`)); stream.end(); From 004fcab97432e848b68c41da5c0466c7167dd5c2 Mon Sep 17 00:00:00 2001 From: Leonardo Gama Date: Thu, 1 May 2025 11:32:34 -0700 Subject: [PATCH 05/31] Merge --- .../lib/api/aws-auth/account-cache.d.ts | 41 + .../lib/api/aws-auth/account-cache.js | 108 +++ .../lib/api/aws-auth/awscli-compatible.d.ts | 70 ++ .../lib/api/aws-auth/awscli-compatible.js | 250 +++++++ .../lib/api/aws-auth/cached.d.ts | 11 + .../lib/api/aws-auth/cached.js | 26 + .../lib/api/aws-auth/credential-plugins.d.ts | 38 + .../lib/api/aws-auth/credential-plugins.js | 154 ++++ .../lib/api/aws-auth/index.d.ts | 11 + .../lib/api/aws-auth/index.js | 37 + .../lib/api/aws-auth/provider-caching.d.ts | 13 + .../lib/api/aws-auth/provider-caching.js | 24 + .../lib/api/aws-auth/proxy-agent.d.ts | 13 + .../lib/api/aws-auth/proxy-agent.js | 54 ++ .../lib/api/aws-auth/sdk-logger.d.ts | 69 ++ .../lib/api/aws-auth/sdk-logger.js | 128 ++++ .../lib/api/aws-auth/sdk-provider.d.ts | 229 ++++++ .../lib/api/aws-auth/sdk-provider.js | 373 +++++++++ .../lib/api/aws-auth/sdk.d.ts | 239 ++++++ .../lib/api/aws-auth/sdk.js | 395 ++++++++++ .../lib/api/aws-auth/tracing.d.ts | 11 + .../lib/api/aws-auth/tracing.js | 60 ++ .../lib/api/aws-auth/user-agent.d.ts | 7 + .../lib/api/aws-auth/user-agent.js | 20 + .../lib/api/aws-auth/util.d.ts | 6 + .../lib/api/aws-auth/util.js | 21 + .../api/bootstrap/bootstrap-environment.d.ts | 35 + .../api/bootstrap/bootstrap-environment.js | 323 ++++++++ .../lib/api/bootstrap/bootstrap-props.d.ts | 130 ++++ .../lib/api/bootstrap/bootstrap-props.js | 14 + .../lib/api/bootstrap/bootstrap-template.yaml | 707 ++++++++++++++++++ .../lib/api/bootstrap/deploy-bootstrap.d.ts | 39 + .../lib/api/bootstrap/deploy-bootstrap.js | 147 ++++ .../lib/api/bootstrap/index.d.ts | 3 + .../lib/api/bootstrap/index.js | 23 + .../lib/api/bootstrap/legacy-template.d.ts | 2 + .../lib/api/bootstrap/legacy-template.js | 82 ++ .../lib/api/cloud-assembly/environment.d.ts | 43 ++ .../lib/api/cloud-assembly/environment.js | 127 ++++ .../lib/api/cloud-assembly/index.d.ts | 4 + .../lib/api/cloud-assembly/index.js | 21 + .../api/cloud-assembly/stack-assembly.d.ts | 55 ++ .../lib/api/cloud-assembly/stack-assembly.js | 139 ++++ .../api/cloud-assembly/stack-collection.d.ts | 27 + .../api/cloud-assembly/stack-collection.js | 112 +++ .../api/cloud-assembly/stack-selector.d.ts | 81 ++ .../lib/api/cloud-assembly/stack-selector.js | 64 ++ .../evaluate-cloudformation-template.d.ts | 85 +++ .../evaluate-cloudformation-template.js | 456 +++++++++++ .../lib/api/cloudformation/index.d.ts | 4 + .../lib/api/cloudformation/index.js | 21 + .../cloudformation/nested-stack-helpers.d.ts | 25 + .../cloudformation/nested-stack-helpers.js | 86 +++ .../lib/api/cloudformation/stack-helpers.d.ts | 96 +++ .../lib/api/cloudformation/stack-helpers.js | 163 ++++ .../template-body-parameter.d.ts | 22 + .../cloudformation/template-body-parameter.js | 104 +++ .../tmp-toolkit-helpers/lib/api/context.d.ts | 40 + .../tmp-toolkit-helpers/lib/api/context.js | 84 +++ .../deployments/asset-manifest-builder.d.ts | 8 + .../api/deployments/asset-manifest-builder.js | 33 + .../lib/api/deployments/asset-publishing.d.ts | 60 ++ .../lib/api/deployments/asset-publishing.js | 144 ++++ .../lib/api/deployments/assets.d.ts | 11 + .../lib/api/deployments/assets.js | 109 +++ .../lib/api/deployments/cfn-api.d.ts | 155 ++++ .../lib/api/deployments/cfn-api.js | 502 +++++++++++++ .../lib/api/deployments/checks.d.ts | 9 + .../lib/api/deployments/checks.js | 72 ++ .../lib/api/deployments/deploy-stack.d.ts | 164 ++++ .../lib/api/deployments/deploy-stack.js | 490 ++++++++++++ .../api/deployments/deployment-method.d.ts | 24 + .../lib/api/deployments/deployment-method.js | 3 + .../api/deployments/deployment-result.d.ts | 21 + .../lib/api/deployments/deployment-result.js | 10 + .../lib/api/deployments/deployments.d.ts | 289 +++++++ .../lib/api/deployments/deployments.js | 355 +++++++++ .../lib/api/deployments/index.d.ts | 6 + .../lib/api/deployments/index.js | 27 + .../lib/api/diff/diff-formatter.d.ts | 168 +++++ .../lib/api/diff/diff-formatter.js | 244 ++++++ .../lib/api/diff/index.d.ts | 1 + .../tmp-toolkit-helpers/lib/api/diff/index.js | 18 + .../api/environment/environment-access.d.ts | 139 ++++ .../lib/api/environment/environment-access.js | 205 +++++ .../environment/environment-resources.d.ts | 75 ++ .../api/environment/environment-resources.js | 213 ++++++ .../lib/api/environment/index.d.ts | 3 + .../lib/api/environment/index.js | 20 + .../lib/api/environment/placeholders.d.ts | 10 + .../lib/api/environment/placeholders.js | 23 + .../garbage-collection/garbage-collector.d.ts | 158 ++++ .../garbage-collection/garbage-collector.js | 614 +++++++++++++++ .../lib/api/garbage-collection/index.d.ts | 3 + .../lib/api/garbage-collection/index.js | 21 + .../garbage-collection/progress-printer.d.ts | 23 + .../garbage-collection/progress-printer.js | 80 ++ .../api/garbage-collection/stack-refresh.d.ts | 49 ++ .../api/garbage-collection/stack-refresh.js | 152 ++++ .../hotswap/appsync-mapping-templates.d.ts | 4 + .../api/hotswap/appsync-mapping-templates.js | 162 ++++ .../lib/api/hotswap/code-build-projects.d.ts | 4 + .../lib/api/hotswap/code-build-projects.js | 62 ++ .../lib/api/hotswap/common.d.ts | 89 +++ .../lib/api/hotswap/common.js | 137 ++++ .../lib/api/hotswap/ecs-services.d.ts | 4 + .../lib/api/hotswap/ecs-services.js | 159 ++++ .../lib/api/hotswap/hotswap-deployments.d.ts | 17 + .../lib/api/hotswap/hotswap-deployments.js | 441 +++++++++++ .../lib/api/hotswap/index.d.ts | 2 + .../lib/api/hotswap/index.js | 19 + .../lib/api/hotswap/lambda-functions.d.ts | 4 + .../lib/api/hotswap/lambda-functions.js | 297 ++++++++ .../api/hotswap/s3-bucket-deployments.d.ts | 5 + .../lib/api/hotswap/s3-bucket-deployments.js | 117 +++ .../hotswap/stepfunctions-state-machines.d.ts | 4 + .../hotswap/stepfunctions-state-machines.js | 48 ++ .../tmp-toolkit-helpers/lib/api/index.d.ts | 25 + .../tmp-toolkit-helpers/lib/api/index.js | 42 ++ .../tmp-toolkit-helpers/lib/api/io/index.d.ts | 3 + .../tmp-toolkit-helpers/lib/api/io/index.js | 20 + .../lib/api/io/io-host.d.ts | 15 + .../tmp-toolkit-helpers/lib/api/io/io-host.js | 3 + .../lib/api/io/io-message.d.ts | 76 ++ .../lib/api/io/io-message.js | 3 + .../lib/api/io/private/index.d.ts | 7 + .../lib/api/io/private/index.js | 24 + .../api/io/private/io-default-messages.d.ts | 21 + .../lib/api/io/private/io-default-messages.js | 59 ++ .../lib/api/io/private/io-helper.d.ts | 32 + .../lib/api/io/private/io-helper.js | 51 ++ .../lib/api/io/private/level-priority.d.ts | 11 + .../lib/api/io/private/level-priority.js | 33 + .../lib/api/io/private/message-maker.d.ts | 89 +++ .../lib/api/io/private/message-maker.js | 60 ++ .../lib/api/io/private/messages.d.ts | 178 +++++ .../lib/api/io/private/messages.js | 534 +++++++++++++ .../lib/api/io/private/span.d.ts | 93 +++ .../lib/api/io/private/span.js | 87 +++ .../api/io/private/testing/fake-io-host.d.ts | 28 + .../api/io/private/testing/fake-io-host.js | 41 + .../lib/api/io/private/testing/index.d.ts | 2 + .../lib/api/io/private/testing/index.js | 19 + .../api/io/private/testing/test-io-host.d.ts | 27 + .../api/io/private/testing/test-io-host.js | 61 ++ .../lib/api/io/private/types.d.ts | 4 + .../lib/api/io/private/types.js | 3 + .../lib/api/io/toolkit-action.d.ts | 4 + .../lib/api/io/toolkit-action.js | 3 + .../logs-monitor/find-cloudwatch-logs.d.ts | 25 + .../api/logs-monitor/find-cloudwatch-logs.js | 95 +++ .../lib/api/logs-monitor/index.d.ts | 2 + .../lib/api/logs-monitor/index.js | 19 + .../lib/api/logs-monitor/logs-monitor.d.ts | 76 ++ .../lib/api/logs-monitor/logs-monitor.js | 194 +++++ .../tmp-toolkit-helpers/lib/api/notices.d.ts | 210 ++++++ .../tmp-toolkit-helpers/lib/api/notices.js | 430 +++++++++++ .../api/plugin/context-provider-plugin.d.ts | 6 + .../lib/api/plugin/context-provider-plugin.js | 7 + .../lib/api/plugin/index.d.ts | 3 + .../lib/api/plugin/index.js | 20 + .../lib/api/plugin/mode.d.ts | 4 + .../lib/api/plugin/mode.js | 9 + .../lib/api/plugin/plugin.d.ts | 78 ++ .../lib/api/plugin/plugin.js | 132 ++++ .../tmp-toolkit-helpers/lib/api/private.d.ts | 1 + .../tmp-toolkit-helpers/lib/api/private.js | 18 + .../lib/api/refactoring/cloudformation.d.ts | 15 + .../lib/api/refactoring/cloudformation.js | 3 + .../lib/api/refactoring/digest.d.ts | 26 + .../lib/api/refactoring/digest.js | 175 +++++ .../lib/api/refactoring/index.d.ts | 51 ++ .../lib/api/refactoring/index.js | 214 ++++++ .../lib/api/require-approval.d.ts | 17 + .../lib/api/require-approval.js | 22 + .../lib/api/resource-import/importer.d.ts | 216 ++++++ .../lib/api/resource-import/importer.js | 331 ++++++++ .../lib/api/resource-import/index.d.ts | 2 + .../lib/api/resource-import/index.js | 19 + .../lib/api/resource-import/migrator.d.ts | 26 + .../lib/api/resource-import/migrator.js | 73 ++ .../lib/api/resource-metadata/index.d.ts | 1 + .../lib/api/resource-metadata/index.js | 18 + .../resource-metadata/resource-metadata.d.ts | 24 + .../resource-metadata/resource-metadata.js | 42 ++ .../tmp-toolkit-helpers/lib/api/rwlock.d.ts | 76 ++ .../tmp-toolkit-helpers/lib/api/rwlock.js | 204 +++++ .../tmp-toolkit-helpers/lib/api/settings.d.ts | 26 + .../tmp-toolkit-helpers/lib/api/settings.js | 107 +++ .../lib/api/stack-events/index.d.ts | 4 + .../lib/api/stack-events/index.js | 23 + .../stack-events/stack-activity-monitor.d.ts | 100 +++ .../stack-events/stack-activity-monitor.js | 164 ++++ .../api/stack-events/stack-event-poller.d.ts | 69 ++ .../api/stack-events/stack-event-poller.js | 130 ++++ .../stack-events/stack-progress-monitor.d.ts | 48 ++ .../stack-events/stack-progress-monitor.js | 98 +++ .../lib/api/stack-events/stack-status.d.ts | 42 ++ .../lib/api/stack-events/stack-status.js | 90 +++ .../tmp-toolkit-helpers/lib/api/streams.d.ts | 7 + .../tmp-toolkit-helpers/lib/api/streams.js | 24 + .../tmp-toolkit-helpers/lib/api/tags.d.ts | 9 + .../tmp-toolkit-helpers/lib/api/tags.js | 10 + .../lib/api/toolkit-error.d.ts | 86 +++ .../lib/api/toolkit-error.js | 132 ++++ .../lib/api/toolkit-info.d.ts | 52 ++ .../lib/api/toolkit-info.js | 157 ++++ .../tmp-toolkit-helpers/lib/api/tree.d.ts | 31 + .../tmp-toolkit-helpers/lib/api/tree.js | 37 + .../lib/api/work-graph/index.d.ts | 3 + .../lib/api/work-graph/index.js | 20 + .../api/work-graph/work-graph-builder.d.ts | 34 + .../lib/api/work-graph/work-graph-builder.js | 172 +++++ .../lib/api/work-graph/work-graph-types.d.ts | 50 ++ .../lib/api/work-graph/work-graph-types.js | 13 + .../lib/api/work-graph/work-graph.d.ts | 72 ++ .../lib/api/work-graph/work-graph.js | 349 +++++++++ .../lib/context-providers/ami.d.ts | 13 + .../lib/context-providers/ami.js | 52 ++ .../context-providers/availability-zones.d.ts | 13 + .../context-providers/availability-zones.js | 29 + .../context-providers/cc-api-provider.d.ts | 30 + .../lib/context-providers/cc-api-provider.js | 145 ++++ .../endpoint-service-availability-zones.d.ts | 13 + .../endpoint-service-availability-zones.js | 35 + .../lib/context-providers/hosted-zones.d.ts | 12 + .../lib/context-providers/hosted-zones.js | 69 ++ .../lib/context-providers/index.d.ts | 44 ++ .../lib/context-providers/index.js | 128 ++++ .../lib/context-providers/keys.d.ts | 13 + .../lib/context-providers/keys.js | 54 ++ .../lib/context-providers/load-balancers.d.ts | 20 + .../lib/context-providers/load-balancers.js | 161 ++++ .../context-providers/security-groups.d.ts | 14 + .../lib/context-providers/security-groups.js | 69 ++ .../lib/context-providers/ssm-parameters.d.ts | 25 + .../lib/context-providers/ssm-parameters.js | 61 ++ .../lib/context-providers/vpcs.d.ts | 13 + .../lib/context-providers/vpcs.js | 291 +++++++ .../tmp-toolkit-helpers/lib/index.d.ts | 3 + .../@aws-cdk/tmp-toolkit-helpers/lib/index.js | 20 + .../bootstrap-environment-progress.d.ts | 17 + .../bootstrap-environment-progress.js | 3 + .../lib/payloads/context.d.ts | 9 + .../lib/payloads/context.js | 3 + .../lib/payloads/deploy.d.ts | 69 ++ .../lib/payloads/deploy.js | 3 + .../lib/payloads/destroy.d.ts | 23 + .../lib/payloads/destroy.js | 3 + .../lib/payloads/diff.d.ts | 31 + .../tmp-toolkit-helpers/lib/payloads/diff.js | 22 + .../lib/payloads/hotswap.d.ts | 211 ++++++ .../lib/payloads/hotswap.js | 43 ++ .../lib/payloads/index.d.ts | 17 + .../tmp-toolkit-helpers/lib/payloads/index.js | 34 + .../lib/payloads/list.d.ts | 4 + .../tmp-toolkit-helpers/lib/payloads/list.js | 3 + .../lib/payloads/logs-monitor.d.ts | 33 + .../lib/payloads/logs-monitor.js | 3 + .../lib/payloads/progress.d.ts | 14 + .../lib/payloads/progress.js | 3 + .../lib/payloads/refactor.d.ts | 14 + .../lib/payloads/refactor.js | 3 + .../lib/payloads/rollback.d.ts | 17 + .../lib/payloads/rollback.js | 3 + .../lib/payloads/sdk-trace.d.ts | 20 + .../lib/payloads/sdk-trace.js | 3 + .../lib/payloads/stack-activity.d.ts | 53 ++ .../lib/payloads/stack-activity.js | 3 + .../lib/payloads/stack-details.d.ts | 17 + .../lib/payloads/stack-details.js | 3 + .../lib/payloads/synth.d.ts | 7 + .../tmp-toolkit-helpers/lib/payloads/synth.js | 3 + .../lib/payloads/types.d.ts | 95 +++ .../tmp-toolkit-helpers/lib/payloads/types.js | 3 + .../lib/payloads/watch.d.ts | 27 + .../tmp-toolkit-helpers/lib/payloads/watch.js | 3 + .../lib/private/activity-printer/base.d.ts | 50 ++ .../lib/private/activity-printer/base.js | 120 +++ .../lib/private/activity-printer/current.d.ts | 26 + .../lib/private/activity-printer/current.js | 122 +++ .../lib/private/activity-printer/display.d.ts | 13 + .../lib/private/activity-printer/display.js | 81 ++ .../lib/private/activity-printer/history.d.ts | 32 + .../lib/private/activity-printer/history.js | 109 +++ .../lib/private/activity-printer/index.d.ts | 3 + .../lib/private/activity-printer/index.js | 20 + .../lib/private/index.d.ts | 1 + .../tmp-toolkit-helpers/lib/private/index.js | 18 + .../tmp-toolkit-helpers/lib/util/archive.d.ts | 1 + .../tmp-toolkit-helpers/lib/util/archive.js | 86 +++ .../tmp-toolkit-helpers/lib/util/arrays.d.ts | 14 + .../tmp-toolkit-helpers/lib/util/arrays.js | 36 + .../tmp-toolkit-helpers/lib/util/bool.d.ts | 7 + .../tmp-toolkit-helpers/lib/util/bool.js | 13 + .../tmp-toolkit-helpers/lib/util/bytes.d.ts | 8 + .../tmp-toolkit-helpers/lib/util/bytes.js | 21 + .../lib/util/cloudformation.d.ts | 16 + .../lib/util/cloudformation.js | 36 + .../lib/util/content-hash.d.ts | 5 + .../lib/util/content-hash.js | 43 ++ .../lib/util/directories.d.ts | 22 + .../lib/util/directories.js | 59 ++ .../lib/util/format-error.d.ts | 9 + .../lib/util/format-error.js | 22 + .../tmp-toolkit-helpers/lib/util/index.d.ts | 18 + .../tmp-toolkit-helpers/lib/util/index.js | 35 + .../tmp-toolkit-helpers/lib/util/json.d.ts | 48 ++ .../tmp-toolkit-helpers/lib/util/json.js | 68 ++ .../tmp-toolkit-helpers/lib/util/objects.d.ts | 65 ++ .../tmp-toolkit-helpers/lib/util/objects.js | 230 ++++++ .../lib/util/package-info.d.ts | 3 + .../lib/util/package-info.js | 22 + .../lib/util/parallel.d.ts | 6 + .../tmp-toolkit-helpers/lib/util/parallel.js | 48 ++ .../lib/util/serialize.d.ts | 27 + .../tmp-toolkit-helpers/lib/util/serialize.js | 86 +++ .../lib/util/string-manipulation.d.ts | 18 + .../lib/util/string-manipulation.js | 46 ++ .../lib/util/type-brands.d.ts | 39 + .../lib/util/type-brands.js | 39 + .../tmp-toolkit-helpers/lib/util/types.d.ts | 27 + .../tmp-toolkit-helpers/lib/util/types.js | 25 + .../lib/util/version-range.d.ts | 2 + .../lib/util/version-range.js | 36 + .../lib/util/yaml-cfn.d.ts | 15 + .../tmp-toolkit-helpers/lib/util/yaml-cfn.js | 58 ++ 327 files changed, 22862 insertions(+) create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-template.yaml create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/nested-stack-helpers.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/nested-stack-helpers.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/stack-helpers.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/stack-helpers.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/template-body-parameter.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/template-body-parameter.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/context.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/context.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/asset-manifest-builder.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/asset-manifest-builder.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/asset-publishing.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/asset-publishing.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/assets.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/assets.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/cfn-api.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/cfn-api.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/checks.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/checks.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deploy-stack.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deploy-stack.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deployment-method.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deployment-method.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deployment-result.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deployment-result.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deployments.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/deployments.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/deployments/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/diff/diff-formatter.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/diff/diff-formatter.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/diff/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/diff/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/environment-access.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/environment-access.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/environment-resources.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/environment-resources.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/placeholders.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/environment/placeholders.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/garbage-collector.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/garbage-collector.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/progress-printer.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/progress-printer.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/stack-refresh.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/garbage-collection/stack-refresh.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/appsync-mapping-templates.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/appsync-mapping-templates.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/code-build-projects.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/code-build-projects.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/common.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/common.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/ecs-services.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/ecs-services.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/hotswap-deployments.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/hotswap-deployments.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/lambda-functions.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/lambda-functions.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/s3-bucket-deployments.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/s3-bucket-deployments.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/stepfunctions-state-machines.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/hotswap/stepfunctions-state-machines.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/io-host.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/io-host.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/io-message.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/io-message.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/io-default-messages.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/io-default-messages.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/io-helper.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/io-helper.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/level-priority.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/level-priority.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/message-maker.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/message-maker.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/messages.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/messages.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/span.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/span.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/testing/fake-io-host.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/testing/fake-io-host.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/testing/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/testing/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/testing/test-io-host.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/testing/test-io-host.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/types.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/private/types.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/toolkit-action.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/io/toolkit-action.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/logs-monitor/find-cloudwatch-logs.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/logs-monitor/find-cloudwatch-logs.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/logs-monitor/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/logs-monitor/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/logs-monitor/logs-monitor.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/logs-monitor/logs-monitor.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/notices.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/notices.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/context-provider-plugin.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/context-provider-plugin.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/mode.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/mode.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/plugin.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/plugin/plugin.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/private.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/private.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/refactoring/cloudformation.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/refactoring/cloudformation.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/refactoring/digest.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/refactoring/digest.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/refactoring/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/refactoring/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/require-approval.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/require-approval.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-import/importer.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-import/importer.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-import/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-import/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-import/migrator.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-import/migrator.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-metadata/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-metadata/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-metadata/resource-metadata.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/resource-metadata/resource-metadata.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/rwlock.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/rwlock.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/settings.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/settings.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-activity-monitor.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-activity-monitor.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-event-poller.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-event-poller.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-progress-monitor.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-progress-monitor.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-status.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/stack-events/stack-status.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/streams.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/streams.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/tags.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/tags.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/toolkit-error.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/toolkit-error.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/toolkit-info.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/toolkit-info.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/tree.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/tree.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/work-graph-builder.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/work-graph-builder.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/work-graph-types.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/work-graph-types.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/work-graph.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/api/work-graph/work-graph.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/ami.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/ami.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/availability-zones.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/availability-zones.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/cc-api-provider.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/cc-api-provider.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/endpoint-service-availability-zones.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/endpoint-service-availability-zones.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/hosted-zones.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/hosted-zones.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/keys.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/keys.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/load-balancers.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/load-balancers.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/security-groups.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/security-groups.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/ssm-parameters.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/ssm-parameters.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/vpcs.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/context-providers/vpcs.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/bootstrap-environment-progress.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/bootstrap-environment-progress.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/context.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/context.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/deploy.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/deploy.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/destroy.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/destroy.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/diff.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/diff.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/hotswap.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/hotswap.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/list.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/list.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/logs-monitor.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/logs-monitor.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/progress.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/progress.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/refactor.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/refactor.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/rollback.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/rollback.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/sdk-trace.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/sdk-trace.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/stack-activity.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/stack-activity.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/stack-details.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/stack-details.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/synth.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/synth.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/types.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/types.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/watch.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/payloads/watch.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/base.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/base.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/current.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/current.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/display.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/display.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/history.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/history.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/activity-printer/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/private/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/archive.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/archive.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/arrays.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/arrays.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/bool.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/bool.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/bytes.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/bytes.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/cloudformation.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/cloudformation.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/content-hash.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/content-hash.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/directories.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/directories.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/format-error.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/format-error.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/index.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/index.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/json.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/json.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/objects.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/objects.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/package-info.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/package-info.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/parallel.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/parallel.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/serialize.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/serialize.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/string-manipulation.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/string-manipulation.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/type-brands.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/type-brands.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/types.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/types.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/version-range.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/version-range.js create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/yaml-cfn.d.ts create mode 100644 packages/@aws-cdk/tmp-toolkit-helpers/lib/util/yaml-cfn.js diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.d.ts new file mode 100644 index 000000000..2a04f7d4e --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.d.ts @@ -0,0 +1,41 @@ +import type { Account } from './sdk-provider'; +/** + * Disk cache which maps access key IDs to account IDs. + * Usage: + * cache.get(accessKey) => accountId | undefined + * cache.put(accessKey, accountId) + */ +export declare class AccountAccessKeyCache { + /** + * Max number of entries in the cache, after which the cache will be reset. + */ + static readonly MAX_ENTRIES = 1000; + /** + * The default path used for the accounts access key cache + */ + static get DEFAULT_PATH(): string; + private readonly cacheFile; + private readonly debug; + /** + * @param filePath Path to the cache file + */ + constructor(filePath: string | undefined, debugFn: (msg: string) => Promise); + /** + * Tries to fetch the account ID from cache. If it's not in the cache, invokes + * the resolver function which should retrieve the account ID and return it. + * Then, it will be stored into disk cache returned. + * + * Example: + * + * const accountId = cache.fetch(accessKey, async () => { + * return await fetchAccountIdFromSomewhere(accessKey); + * }); + */ + fetch(accessKeyId: string, resolver: () => Promise): Promise; + /** Get the account ID from an access key or undefined if not in cache */ + get(accessKeyId: string): Promise; + /** Put a mapping between access key and account ID */ + put(accessKeyId: string, account: Account): Promise; + private loadMap; + private saveMap; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.js new file mode 100644 index 000000000..2780f2167 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/account-cache.js @@ -0,0 +1,108 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AccountAccessKeyCache = void 0; +const path = require("path"); +const fs = require("fs-extra"); +const util_1 = require("../../util"); +/** + * Disk cache which maps access key IDs to account IDs. + * Usage: + * cache.get(accessKey) => accountId | undefined + * cache.put(accessKey, accountId) + */ +class AccountAccessKeyCache { + /** + * Max number of entries in the cache, after which the cache will be reset. + */ + static MAX_ENTRIES = 1000; + /** + * The default path used for the accounts access key cache + */ + static get DEFAULT_PATH() { + // needs to be a getter because cdkCacheDir can be set via env variable and might change + return path.join((0, util_1.cdkCacheDir)(), 'accounts_partitions.json'); + } + cacheFile; + debug; + /** + * @param filePath Path to the cache file + */ + constructor(filePath = AccountAccessKeyCache.DEFAULT_PATH, debugFn) { + this.cacheFile = filePath; + this.debug = debugFn; + } + /** + * Tries to fetch the account ID from cache. If it's not in the cache, invokes + * the resolver function which should retrieve the account ID and return it. + * Then, it will be stored into disk cache returned. + * + * Example: + * + * const accountId = cache.fetch(accessKey, async () => { + * return await fetchAccountIdFromSomewhere(accessKey); + * }); + */ + async fetch(accessKeyId, resolver) { + // try to get account ID based on this access key ID from disk. + const cached = await this.get(accessKeyId); + if (cached) { + await this.debug(`Retrieved account ID ${cached.accountId} from disk cache`); + return cached; + } + // if it's not in the cache, resolve and put in cache. + const account = await resolver(); + if (account) { + await this.put(accessKeyId, account); + } + return account; + } + /** Get the account ID from an access key or undefined if not in cache */ + async get(accessKeyId) { + const map = await this.loadMap(); + return map[accessKeyId]; + } + /** Put a mapping between access key and account ID */ + async put(accessKeyId, account) { + let map = await this.loadMap(); + // nuke cache if it's too big. + if (Object.keys(map).length >= AccountAccessKeyCache.MAX_ENTRIES) { + map = {}; + } + map[accessKeyId] = account; + await this.saveMap(map); + } + async loadMap() { + try { + return await fs.readJson(this.cacheFile); + } + catch (e) { + // File doesn't exist or is not readable. This is a cache, + // pretend we successfully loaded an empty map. + if (e.code === 'ENOENT' || e.code === 'EACCES') { + return {}; + } + // File is not JSON, could be corrupted because of concurrent writes. + // Again, an empty cache is fine. + if (e instanceof SyntaxError) { + return {}; + } + throw e; + } + } + async saveMap(map) { + try { + await fs.ensureFile(this.cacheFile); + await fs.writeJson(this.cacheFile, map, { spaces: 2 }); + } + catch (e) { + // File doesn't exist or file/dir isn't writable. This is a cache, + // if we can't write it then too bad. + if (e.code === 'ENOENT' || e.code === 'EACCES' || e.code === 'EROFS') { + return; + } + throw e; + } + } +} +exports.AccountAccessKeyCache = AccountAccessKeyCache; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3VudC1jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvYXdzLWF1dGgvYWNjb3VudC1jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2QkFBNkI7QUFDN0IsK0JBQStCO0FBRS9CLHFDQUF5QztBQUV6Qzs7Ozs7R0FLRztBQUNILE1BQWEscUJBQXFCO0lBQ2hDOztPQUVHO0lBQ0ksTUFBTSxDQUFVLFdBQVcsR0FBRyxJQUFJLENBQUM7SUFFMUM7O09BRUc7SUFDSSxNQUFNLEtBQUssWUFBWTtRQUM1Qix3RkFBd0Y7UUFDeEYsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUEsa0JBQVcsR0FBRSxFQUFFLDBCQUEwQixDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVnQixTQUFTLENBQVM7SUFFbEIsS0FBSyxDQUFpQztJQUV2RDs7T0FFRztJQUNILFlBQVksV0FBbUIscUJBQXFCLENBQUMsWUFBWSxFQUFFLE9BQXVDO1FBQ3hHLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDO1FBQzFCLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0ksS0FBSyxDQUFDLEtBQUssQ0FBb0IsV0FBbUIsRUFBRSxRQUEwQjtRQUNuRiwrREFBK0Q7UUFDL0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzNDLElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsd0JBQXdCLE1BQU0sQ0FBQyxTQUFTLGtCQUFrQixDQUFDLENBQUM7WUFDN0UsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQztRQUVELHNEQUFzRDtRQUN0RCxNQUFNLE9BQU8sR0FBRyxNQUFNLFFBQVEsRUFBRSxDQUFDO1FBQ2pDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFFRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQseUVBQXlFO0lBQ2xFLEtBQUssQ0FBQyxHQUFHLENBQUMsV0FBbUI7UUFDbEMsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDakMsT0FBTyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVELHNEQUFzRDtJQUMvQyxLQUFLLENBQUMsR0FBRyxDQUFDLFdBQW1CLEVBQUUsT0FBZ0I7UUFDcEQsSUFBSSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFL0IsOEJBQThCO1FBQzlCLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLElBQUkscUJBQXFCLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakUsR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNYLENBQUM7UUFFRCxHQUFHLENBQUMsV0FBVyxDQUFDLEdBQUcsT0FBTyxDQUFDO1FBQzNCLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRU8sS0FBSyxDQUFDLE9BQU87UUFDbkIsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2hCLDBEQUEwRDtZQUMxRCwrQ0FBK0M7WUFDL0MsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUMvQyxPQUFPLEVBQUUsQ0FBQztZQUNaLENBQUM7WUFDRCxxRUFBcUU7WUFDckUsaUNBQWlDO1lBQ2pDLElBQUksQ0FBQyxZQUFZLFdBQVcsRUFBRSxDQUFDO2dCQUM3QixPQUFPLEVBQUUsQ0FBQztZQUNaLENBQUM7WUFDRCxNQUFNLENBQUMsQ0FBQztRQUNWLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUF1QztRQUMzRCxJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3BDLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3pELENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2hCLGtFQUFrRTtZQUNsRSxxQ0FBcUM7WUFDckMsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO2dCQUNyRSxPQUFPO1lBQ1QsQ0FBQztZQUNELE1BQU0sQ0FBQyxDQUFDO1FBQ1YsQ0FBQztJQUNILENBQUM7O0FBdkdILHNEQXdHQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgdHlwZSB7IEFjY291bnQgfSBmcm9tICcuL3Nkay1wcm92aWRlcic7XG5pbXBvcnQgeyBjZGtDYWNoZURpciB9IGZyb20gJy4uLy4uL3V0aWwnO1xuXG4vKipcbiAqIERpc2sgY2FjaGUgd2hpY2ggbWFwcyBhY2Nlc3Mga2V5IElEcyB0byBhY2NvdW50IElEcy5cbiAqIFVzYWdlOlxuICogICBjYWNoZS5nZXQoYWNjZXNzS2V5KSA9PiBhY2NvdW50SWQgfCB1bmRlZmluZWRcbiAqICAgY2FjaGUucHV0KGFjY2Vzc0tleSwgYWNjb3VudElkKVxuICovXG5leHBvcnQgY2xhc3MgQWNjb3VudEFjY2Vzc0tleUNhY2hlIHtcbiAgLyoqXG4gICAqIE1heCBudW1iZXIgb2YgZW50cmllcyBpbiB0aGUgY2FjaGUsIGFmdGVyIHdoaWNoIHRoZSBjYWNoZSB3aWxsIGJlIHJlc2V0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBNQVhfRU5UUklFUyA9IDEwMDA7XG5cbiAgLyoqXG4gICAqIFRoZSBkZWZhdWx0IHBhdGggdXNlZCBmb3IgdGhlIGFjY291bnRzIGFjY2VzcyBrZXkgY2FjaGVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ2V0IERFRkFVTFRfUEFUSCgpOiBzdHJpbmcge1xuICAgIC8vIG5lZWRzIHRvIGJlIGEgZ2V0dGVyIGJlY2F1c2UgY2RrQ2FjaGVEaXIgY2FuIGJlIHNldCB2aWEgZW52IHZhcmlhYmxlIGFuZCBtaWdodCBjaGFuZ2VcbiAgICByZXR1cm4gcGF0aC5qb2luKGNka0NhY2hlRGlyKCksICdhY2NvdW50c19wYXJ0aXRpb25zLmpzb24nKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGVGaWxlOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0gZmlsZVBhdGggUGF0aCB0byB0aGUgY2FjaGUgZmlsZVxuICAgKi9cbiAgY29uc3RydWN0b3IoZmlsZVBhdGg6IHN0cmluZyA9IEFjY291bnRBY2Nlc3NLZXlDYWNoZS5ERUZBVUxUX1BBVEgsIGRlYnVnRm46IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPikge1xuICAgIHRoaXMuY2FjaGVGaWxlID0gZmlsZVBhdGg7XG4gICAgdGhpcy5kZWJ1ZyA9IGRlYnVnRm47XG4gIH1cblxuICAvKipcbiAgICogVHJpZXMgdG8gZmV0Y2ggdGhlIGFjY291bnQgSUQgZnJvbSBjYWNoZS4gSWYgaXQncyBub3QgaW4gdGhlIGNhY2hlLCBpbnZva2VzXG4gICAqIHRoZSByZXNvbHZlciBmdW5jdGlvbiB3aGljaCBzaG91bGQgcmV0cmlldmUgdGhlIGFjY291bnQgSUQgYW5kIHJldHVybiBpdC5cbiAgICogVGhlbiwgaXQgd2lsbCBiZSBzdG9yZWQgaW50byBkaXNrIGNhY2hlIHJldHVybmVkLlxuICAgKlxuICAgKiBFeGFtcGxlOlxuICAgKlxuICAgKiAgICBjb25zdCBhY2NvdW50SWQgPSBjYWNoZS5mZXRjaChhY2Nlc3NLZXksIGFzeW5jICgpID0+IHtcbiAgICogICAgICByZXR1cm4gYXdhaXQgZmV0Y2hBY2NvdW50SWRGcm9tU29tZXdoZXJlKGFjY2Vzc0tleSk7XG4gICAqICAgIH0pO1xuICAgKi9cbiAgcHVibGljIGFzeW5jIGZldGNoPEEgZXh0ZW5kcyBBY2NvdW50PihhY2Nlc3NLZXlJZDogc3RyaW5nLCByZXNvbHZlcjogKCkgPT4gUHJvbWlzZTxBPikge1xuICAgIC8vIHRyeSB0byBnZXQgYWNjb3VudCBJRCBiYXNlZCBvbiB0aGlzIGFjY2VzcyBrZXkgSUQgZnJvbSBkaXNrLlxuICAgIGNvbnN0IGNhY2hlZCA9IGF3YWl0IHRoaXMuZ2V0KGFjY2Vzc0tleUlkKTtcbiAgICBpZiAoY2FjaGVkKSB7XG4gICAgICBhd2FpdCB0aGlzLmRlYnVnKGBSZXRyaWV2ZWQgYWNjb3VudCBJRCAke2NhY2hlZC5hY2NvdW50SWR9IGZyb20gZGlzayBjYWNoZWApO1xuICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG5cbiAgICAvLyBpZiBpdCdzIG5vdCBpbiB0aGUgY2FjaGUsIHJlc29sdmUgYW5kIHB1dCBpbiBjYWNoZS5cbiAgICBjb25zdCBhY2NvdW50ID0gYXdhaXQgcmVzb2x2ZXIoKTtcbiAgICBpZiAoYWNjb3VudCkge1xuICAgICAgYXdhaXQgdGhpcy5wdXQoYWNjZXNzS2V5SWQsIGFjY291bnQpO1xuICAgIH1cblxuICAgIHJldHVybiBhY2NvdW50O1xuICB9XG5cbiAgLyoqIEdldCB0aGUgYWNjb3VudCBJRCBmcm9tIGFuIGFjY2VzcyBrZXkgb3IgdW5kZWZpbmVkIGlmIG5vdCBpbiBjYWNoZSAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0KGFjY2Vzc0tleUlkOiBzdHJpbmcpOiBQcm9taXNlPEFjY291bnQgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBtYXAgPSBhd2FpdCB0aGlzLmxvYWRNYXAoKTtcbiAgICByZXR1cm4gbWFwW2FjY2Vzc0tleUlkXTtcbiAgfVxuXG4gIC8qKiBQdXQgYSBtYXBwaW5nIGJldHdlZW4gYWNjZXNzIGtleSBhbmQgYWNjb3VudCBJRCAqL1xuICBwdWJsaWMgYXN5bmMgcHV0KGFjY2Vzc0tleUlkOiBzdHJpbmcsIGFjY291bnQ6IEFjY291bnQpIHtcbiAgICBsZXQgbWFwID0gYXdhaXQgdGhpcy5sb2FkTWFwKCk7XG5cbiAgICAvLyBudWtlIGNhY2hlIGlmIGl0J3MgdG9vIGJpZy5cbiAgICBpZiAoT2JqZWN0LmtleXMobWFwKS5sZW5ndGggPj0gQWNjb3VudEFjY2Vzc0tleUNhY2hlLk1BWF9FTlRSSUVTKSB7XG4gICAgICBtYXAgPSB7fTtcbiAgICB9XG5cbiAgICBtYXBbYWNjZXNzS2V5SWRdID0gYWNjb3VudDtcbiAgICBhd2FpdCB0aGlzLnNhdmVNYXAobWFwKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZE1hcCgpOiBQcm9taXNlPHsgW2FjY2Vzc0tleUlkOiBzdHJpbmddOiBBY2NvdW50IH0+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGZzLnJlYWRKc29uKHRoaXMuY2FjaGVGaWxlKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIC8vIEZpbGUgZG9lc24ndCBleGlzdCBvciBpcyBub3QgcmVhZGFibGUuIFRoaXMgaXMgYSBjYWNoZSxcbiAgICAgIC8vIHByZXRlbmQgd2Ugc3VjY2Vzc2Z1bGx5IGxvYWRlZCBhbiBlbXB0eSBtYXAuXG4gICAgICBpZiAoZS5jb2RlID09PSAnRU5PRU5UJyB8fCBlLmNvZGUgPT09ICdFQUNDRVMnKSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH1cbiAgICAgIC8vIEZpbGUgaXMgbm90IEpTT04sIGNvdWxkIGJlIGNvcnJ1cHRlZCBiZWNhdXNlIG9mIGNvbmN1cnJlbnQgd3JpdGVzLlxuICAgICAgLy8gQWdhaW4sIGFuIGVtcHR5IGNhY2hlIGlzIGZpbmUuXG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIFN5bnRheEVycm9yKSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzYXZlTWFwKG1hcDogeyBbYWNjZXNzS2V5SWQ6IHN0cmluZ106IEFjY291bnQgfSkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmcy5lbnN1cmVGaWxlKHRoaXMuY2FjaGVGaWxlKTtcbiAgICAgIGF3YWl0IGZzLndyaXRlSnNvbih0aGlzLmNhY2hlRmlsZSwgbWFwLCB7IHNwYWNlczogMiB9KTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIC8vIEZpbGUgZG9lc24ndCBleGlzdCBvciBmaWxlL2RpciBpc24ndCB3cml0YWJsZS4gVGhpcyBpcyBhIGNhY2hlLFxuICAgICAgLy8gaWYgd2UgY2FuJ3Qgd3JpdGUgaXQgdGhlbiB0b28gYmFkLlxuICAgICAgaWYgKGUuY29kZSA9PT0gJ0VOT0VOVCcgfHwgZS5jb2RlID09PSAnRUFDQ0VTJyB8fCBlLmNvZGUgPT09ICdFUk9GUycpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.d.ts new file mode 100644 index 000000000..dca462d34 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.d.ts @@ -0,0 +1,70 @@ +import type { NodeHttpHandlerOptions } from '@smithy/node-http-handler'; +import type { AwsCredentialIdentityProvider, Logger } from '@smithy/types'; +import type { SdkHttpOptions } from './sdk-provider'; +import { type IoHelper } from '../io/private'; +/** + * Behaviors to match AWS CLI + * + * See these links: + * + * https://docs.aws.amazon.com/cli/latest/topic/config-vars.html + * https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html + */ +export declare class AwsCliCompatible { + private readonly ioHelper; + private readonly requestHandler; + private readonly logger?; + constructor(ioHelper: IoHelper, requestHandler: NodeHttpHandlerOptions, logger?: Logger); + baseConfig(profile?: string): Promise<{ + credentialProvider: AwsCredentialIdentityProvider; + defaultRegion: string; + }>; + /** + * Build an AWS CLI-compatible credential chain provider + * + * The credential chain returned by this function is always caching. + */ + credentialChainBuilder(options?: CredentialChainOptions): Promise; + /** + * Attempts to get the region from a number of sources and falls back to us-east-1 if no region can be found, + * as is done in the AWS CLI. + * + * The order of priority is the following: + * + * 1. Environment variables specifying region, with both an AWS prefix and AMAZON prefix + * to maintain backwards compatibility, and without `DEFAULT` in the name because + * Lambda and CodeBuild set the $AWS_REGION variable. + * 2. Regions listed in the Shared Ini Files - First checking for the profile provided + * and then checking for the default profile. + * 3. IMDS instance identity region from the Metadata Service. + * 4. us-east-1 + */ + region(maybeProfile?: string): Promise; + /** + * The MetadataService class will attempt to fetch the instance identity document from + * IMDSv2 first, and then will attempt v1 as a fallback. + * + * If this fails, we will use us-east-1 as the region so no error should be thrown. + * @returns The region for the instance identity + */ + private regionFromMetadataService; + /** + * Looks up the region of the provided profile. If no region is present, + * it will attempt to lookup the default region. + * @param profile The profile to use to lookup the region + * @returns The region for the profile or default profile, if present. Otherwise returns undefined. + */ + private getRegionFromIni; + private getRegionFromIniFile; + /** + * Ask user for MFA token for given serial + * + * Result is send to callback function for SDK to authorize the request + */ + private tokenCodeFn; +} +export interface CredentialChainOptions { + readonly profile?: string; + readonly logger?: Logger; +} +export declare function makeRequestHandler(ioHelper: IoHelper, options?: SdkHttpOptions): Promise; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.js new file mode 100644 index 000000000..0edd7e1b5 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/awscli-compatible.js @@ -0,0 +1,250 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AwsCliCompatible = void 0; +exports.makeRequestHandler = makeRequestHandler; +const node_util_1 = require("node:util"); +const credential_providers_1 = require("@aws-sdk/credential-providers"); +const ec2_metadata_service_1 = require("@aws-sdk/ec2-metadata-service"); +const shared_ini_file_loader_1 = require("@smithy/shared-ini-file-loader"); +const promptly = require("promptly"); +const provider_caching_1 = require("./provider-caching"); +const proxy_agent_1 = require("./proxy-agent"); +const private_1 = require("../io/private"); +const toolkit_error_1 = require("../toolkit-error"); +const DEFAULT_CONNECTION_TIMEOUT = 10000; +const DEFAULT_TIMEOUT = 300000; +/** + * Behaviors to match AWS CLI + * + * See these links: + * + * https://docs.aws.amazon.com/cli/latest/topic/config-vars.html + * https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html + */ +class AwsCliCompatible { + ioHelper; + requestHandler; + logger; + constructor(ioHelper, requestHandler, logger) { + this.ioHelper = ioHelper; + this.requestHandler = requestHandler; + this.logger = logger; + } + async baseConfig(profile) { + const credentialProvider = await this.credentialChainBuilder({ + profile, + logger: this.logger, + }); + const defaultRegion = await this.region(profile); + return { credentialProvider, defaultRegion }; + } + /** + * Build an AWS CLI-compatible credential chain provider + * + * The credential chain returned by this function is always caching. + */ + async credentialChainBuilder(options = {}) { + const clientConfig = { + requestHandler: this.requestHandler, + customUserAgent: 'aws-cdk', + logger: options.logger, + }; + // Super hacky solution to https://github.com/aws/aws-cdk/issues/32510, proposed by the SDK team. + // + // Summary of the problem: we were reading the region from the config file and passing it to + // the credential providers. However, in the case of SSO, this makes the credential provider + // use that region to do the SSO flow, which is incorrect. The region that should be used for + // that is the one set in the sso_session section of the config file. + // + // The idea here: the "clientConfig" is for configuring the inner auth client directly, + // and has the highest priority, whereas "parentClientConfig" is the upper data client + // and has lower priority than the sso_region but still higher priority than STS global region. + const parentClientConfig = { + region: await this.region(options.profile), + }; + /** + * The previous implementation matched AWS CLI behavior: + * + * If a profile is explicitly set using `--profile`, + * we use that to the exclusion of everything else. + * + * Note: this does not apply to AWS_PROFILE, + * environment credentials still take precedence over AWS_PROFILE + */ + if (options.profile) { + return (0, provider_caching_1.makeCachingProvider)((0, credential_providers_1.fromIni)({ + profile: options.profile, + ignoreCache: true, + mfaCodeProvider: this.tokenCodeFn.bind(this), + clientConfig, + parentClientConfig, + logger: options.logger, + })); + } + const envProfile = process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE; + /** + * Env AWS - EnvironmentCredentials with string AWS + * Env Amazon - EnvironmentCredentials with string AMAZON + * Profile Credentials - PatchedSharedIniFileCredentials with implicit profile, credentials file, http options, and token fn + * SSO with implicit profile only + * SharedIniFileCredentials with implicit profile and preferStaticCredentials true (profile with source_profile) + * Shared Credential file that points to Environment Credentials with AWS prefix + * Shared Credential file that points to EC2 Metadata + * Shared Credential file that points to ECS Credentials + * SSO Credentials - SsoCredentials with implicit profile and http options + * ProcessCredentials with implicit profile + * ECS Credentials - ECSCredentials with no input OR Web Identity - TokenFileWebIdentityCredentials with no input OR EC2 Metadata - EC2MetadataCredentials with no input + * + * These translate to: + * fromEnv() + * fromSSO()/fromIni() + * fromProcess() + * fromContainerMetadata() + * fromTokenFile() + * fromInstanceMetadata() + * + * The NodeProviderChain is already cached. + */ + const nodeProviderChain = (0, credential_providers_1.fromNodeProviderChain)({ + profile: envProfile, + clientConfig, + parentClientConfig, + logger: options.logger, + mfaCodeProvider: this.tokenCodeFn.bind(this), + ignoreCache: true, + }); + return shouldPrioritizeEnv() + ? (0, credential_providers_1.createCredentialChain)((0, credential_providers_1.fromEnv)(), nodeProviderChain).expireAfter(60 * 60_000) + : nodeProviderChain; + } + /** + * Attempts to get the region from a number of sources and falls back to us-east-1 if no region can be found, + * as is done in the AWS CLI. + * + * The order of priority is the following: + * + * 1. Environment variables specifying region, with both an AWS prefix and AMAZON prefix + * to maintain backwards compatibility, and without `DEFAULT` in the name because + * Lambda and CodeBuild set the $AWS_REGION variable. + * 2. Regions listed in the Shared Ini Files - First checking for the profile provided + * and then checking for the default profile. + * 3. IMDS instance identity region from the Metadata Service. + * 4. us-east-1 + */ + async region(maybeProfile) { + const defaultRegion = 'us-east-1'; + const profile = maybeProfile || process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE || 'default'; + const region = process.env.AWS_REGION || + process.env.AMAZON_REGION || + process.env.AWS_DEFAULT_REGION || + process.env.AMAZON_DEFAULT_REGION || + (await this.getRegionFromIni(profile)) || + (await this.regionFromMetadataService()); + if (!region) { + const usedProfile = !profile ? '' : ` (profile: "${profile}")`; + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(`Unable to determine AWS region from environment or AWS configuration${usedProfile}, defaulting to '${defaultRegion}'`)); + return defaultRegion; + } + return region; + } + /** + * The MetadataService class will attempt to fetch the instance identity document from + * IMDSv2 first, and then will attempt v1 as a fallback. + * + * If this fails, we will use us-east-1 as the region so no error should be thrown. + * @returns The region for the instance identity + */ + async regionFromMetadataService() { + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg('Looking up AWS region in the EC2 Instance Metadata Service (IMDS).')); + try { + const metadataService = new ec2_metadata_service_1.MetadataService({ + httpOptions: { + timeout: 1000, + }, + }); + await metadataService.fetchMetadataToken(); + const document = await metadataService.request('/latest/dynamic/instance-identity/document', {}); + return JSON.parse(document).region; + } + catch (e) { + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(`Unable to retrieve AWS region from IMDS: ${e}`)); + } + } + /** + * Looks up the region of the provided profile. If no region is present, + * it will attempt to lookup the default region. + * @param profile The profile to use to lookup the region + * @returns The region for the profile or default profile, if present. Otherwise returns undefined. + */ + async getRegionFromIni(profile) { + const sharedFiles = await (0, shared_ini_file_loader_1.loadSharedConfigFiles)({ ignoreCache: true }); + // Priority: + // + // credentials come before config because aws-cli v1 behaves like that. + // + // 1. profile-region-in-credentials + // 2. profile-region-in-config + // 3. default-region-in-credentials + // 4. default-region-in-config + return this.getRegionFromIniFile(profile, sharedFiles.credentialsFile) + ?? this.getRegionFromIniFile(profile, sharedFiles.configFile) + ?? this.getRegionFromIniFile('default', sharedFiles.credentialsFile) + ?? this.getRegionFromIniFile('default', sharedFiles.configFile); + } + getRegionFromIniFile(profile, data) { + return data?.[profile]?.region; + } + /** + * Ask user for MFA token for given serial + * + * Result is send to callback function for SDK to authorize the request + */ + async tokenCodeFn(serialArn) { + const debugFn = (msg, ...args) => this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg((0, node_util_1.format)(msg, ...args))); + await debugFn('Require MFA token for serial ARN', serialArn); + try { + const token = await promptly.prompt(`MFA token for ${serialArn}: `, { + trim: true, + default: '', + }); + await debugFn('Successfully got MFA token from user'); + return token; + } + catch (err) { + await debugFn('Failed to get MFA token', err); + const e = new toolkit_error_1.AuthenticationError(`Error fetching MFA token: ${err.message ?? err}`); + e.name = 'SharedIniFileCredentialsProviderFailure'; + throw e; + } + } +} +exports.AwsCliCompatible = AwsCliCompatible; +/** + * We used to support both AWS and AMAZON prefixes for these environment variables. + * + * Adding this for backward compatibility. + */ +function shouldPrioritizeEnv() { + const id = process.env.AWS_ACCESS_KEY_ID || process.env.AMAZON_ACCESS_KEY_ID; + const key = process.env.AWS_SECRET_ACCESS_KEY || process.env.AMAZON_SECRET_ACCESS_KEY; + if (!!id && !!key) { + process.env.AWS_ACCESS_KEY_ID = id; + process.env.AWS_SECRET_ACCESS_KEY = key; + const sessionToken = process.env.AWS_SESSION_TOKEN ?? process.env.AMAZON_SESSION_TOKEN; + if (sessionToken) { + process.env.AWS_SESSION_TOKEN = sessionToken; + } + return true; + } + return false; +} +async function makeRequestHandler(ioHelper, options = {}) { + const agent = await new proxy_agent_1.ProxyAgentProvider(ioHelper).create(options); + return { + connectionTimeout: DEFAULT_CONNECTION_TIMEOUT, + requestTimeout: DEFAULT_TIMEOUT, + httpsAgent: agent, + httpAgent: agent, + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzY2xpLWNvbXBhdGlibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2F3cy1hdXRoL2F3c2NsaS1jb21wYXRpYmxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWdSQSxnREFTQztBQXpSRCx5Q0FBbUM7QUFDbkMsd0VBQStHO0FBQy9HLHdFQUFnRTtBQUVoRSwyRUFBdUU7QUFFdkUscUNBQXFDO0FBQ3JDLHlEQUF5RDtBQUN6RCwrQ0FBbUQ7QUFFbkQsMkNBQWtEO0FBQ2xELG9EQUF1RDtBQUV2RCxNQUFNLDBCQUEwQixHQUFHLEtBQUssQ0FBQztBQUN6QyxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUM7QUFFL0I7Ozs7Ozs7R0FPRztBQUNILE1BQWEsZ0JBQWdCO0lBQ1YsUUFBUSxDQUFXO0lBQ25CLGNBQWMsQ0FBeUI7SUFDdkMsTUFBTSxDQUFVO0lBRWpDLFlBQW1CLFFBQWtCLEVBQUUsY0FBc0MsRUFBRSxNQUFlO1FBQzVGLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFTSxLQUFLLENBQUMsVUFBVSxDQUFDLE9BQWdCO1FBQ3RDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQUM7WUFDM0QsT0FBTztZQUNQLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtTQUNwQixDQUFDLENBQUM7UUFDSCxNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGFBQWEsRUFBRSxDQUFDO0lBQy9DLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLHNCQUFzQixDQUNqQyxVQUFrQyxFQUFFO1FBRXBDLE1BQU0sWUFBWSxH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LEtBQUs7S0FDakIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmb3JtYXQgfSBmcm9tICdub2RlOnV0aWwnO1xuaW1wb3J0IHsgY3JlYXRlQ3JlZGVudGlhbENoYWluLCBmcm9tRW52LCBmcm9tSW5pLCBmcm9tTm9kZVByb3ZpZGVyQ2hhaW4gfSBmcm9tICdAYXdzLXNkay9jcmVkZW50aWFsLXByb3ZpZGVycyc7XG5pbXBvcnQgeyBNZXRhZGF0YVNlcnZpY2UgfSBmcm9tICdAYXdzLXNkay9lYzItbWV0YWRhdGEtc2VydmljZSc7XG5pbXBvcnQgdHlwZSB7IE5vZGVIdHRwSGFuZGxlck9wdGlvbnMgfSBmcm9tICdAc21pdGh5L25vZGUtaHR0cC1oYW5kbGVyJztcbmltcG9ydCB7IGxvYWRTaGFyZWRDb25maWdGaWxlcyB9IGZyb20gJ0BzbWl0aHkvc2hhcmVkLWluaS1maWxlLWxvYWRlcic7XG5pbXBvcnQgdHlwZSB7IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyLCBMb2dnZXIgfSBmcm9tICdAc21pdGh5L3R5cGVzJztcbmltcG9ydCAqIGFzIHByb21wdGx5IGZyb20gJ3Byb21wdGx5JztcbmltcG9ydCB7IG1ha2VDYWNoaW5nUHJvdmlkZXIgfSBmcm9tICcuL3Byb3ZpZGVyLWNhY2hpbmcnO1xuaW1wb3J0IHsgUHJveHlBZ2VudFByb3ZpZGVyIH0gZnJvbSAnLi9wcm94eS1hZ2VudCc7XG5pbXBvcnQgdHlwZSB7IFNka0h0dHBPcHRpb25zIH0gZnJvbSAnLi9zZGstcHJvdmlkZXInO1xuaW1wb3J0IHsgSU8sIHR5cGUgSW9IZWxwZXIgfSBmcm9tICcuLi9pby9wcml2YXRlJztcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uRXJyb3IgfSBmcm9tICcuLi90b29sa2l0LWVycm9yJztcblxuY29uc3QgREVGQVVMVF9DT05ORUNUSU9OX1RJTUVPVVQgPSAxMDAwMDtcbmNvbnN0IERFRkFVTFRfVElNRU9VVCA9IDMwMDAwMDtcblxuLyoqXG4gKiBCZWhhdmlvcnMgdG8gbWF0Y2ggQVdTIENMSVxuICpcbiAqIFNlZSB0aGVzZSBsaW5rczpcbiAqXG4gKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2xpL2xhdGVzdC90b3BpYy9jb25maWctdmFycy5odG1sXG4gKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2xpL2xhdGVzdC91c2VyZ3VpZGUvY2xpLWNvbmZpZ3VyZS1lbnZ2YXJzLmh0bWxcbiAqL1xuZXhwb3J0IGNsYXNzIEF3c0NsaUNvbXBhdGlibGUge1xuICBwcml2YXRlIHJlYWRvbmx5IGlvSGVscGVyOiBJb0hlbHBlcjtcbiAgcHJpdmF0ZSByZWFkb25seSByZXF1ZXN0SGFuZGxlcjogTm9kZUh0dHBIYW5kbGVyT3B0aW9ucztcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI/OiBMb2dnZXI7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKGlvSGVscGVyOiBJb0hlbHBlciwgcmVxdWVzdEhhbmRsZXI6IE5vZGVIdHRwSGFuZGxlck9wdGlvbnMsIGxvZ2dlcj86IExvZ2dlcikge1xuICAgIHRoaXMuaW9IZWxwZXIgPSBpb0hlbHBlcjtcbiAgICB0aGlzLnJlcXVlc3RIYW5kbGVyID0gcmVxdWVzdEhhbmRsZXI7XG4gICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgYmFzZUNvbmZpZyhwcm9maWxlPzogc3RyaW5nKTogUHJvbWlzZTx7IGNyZWRlbnRpYWxQcm92aWRlcjogQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXI7IGRlZmF1bHRSZWdpb246IHN0cmluZyB9PiB7XG4gICAgY29uc3QgY3JlZGVudGlhbFByb3ZpZGVyID0gYXdhaXQgdGhpcy5jcmVkZW50aWFsQ2hhaW5CdWlsZGVyKHtcbiAgICAgIHByb2ZpbGUsXG4gICAgICBsb2dnZXI6IHRoaXMubG9nZ2VyLFxuICAgIH0pO1xuICAgIGNvbnN0IGRlZmF1bHRSZWdpb24gPSBhd2FpdCB0aGlzLnJlZ2lvbihwcm9maWxlKTtcbiAgICByZXR1cm4geyBjcmVkZW50aWFsUHJvdmlkZXIsIGRlZmF1bHRSZWdpb24gfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhbiBBV1MgQ0xJLWNvbXBhdGlibGUgY3JlZGVudGlhbCBjaGFpbiBwcm92aWRlclxuICAgKlxuICAgKiBUaGUgY3JlZGVudGlhbCBjaGFpbiByZXR1cm5lZCBieSB0aGlzIGZ1bmN0aW9uIGlzIGFsd2F5cyBjYWNoaW5nLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGNyZWRlbnRpYWxDaGFpbkJ1aWxkZXIoXG4gICAgb3B0aW9uczogQ3JlZGVudGlhbENoYWluT3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyPiB7XG4gICAgY29uc3QgY2xpZW50Q29uZmlnID0ge1xuICAgICAgcmVxdWVzdEhhbmRsZXI6IHRoaXMucmVxdWVzdEhhbmRsZXIsXG4gICAgICBjdXN0b21Vc2VyQWdlbnQ6ICdhd3MtY2RrJyxcbiAgICAgIGxvZ2dlcjogb3B0aW9ucy5sb2dnZXIsXG4gICAgfTtcblxuICAgIC8vIFN1cGVyIGhhY2t5IHNvbHV0aW9uIHRvIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvMzI1MTAsIHByb3Bvc2VkIGJ5IHRoZSBTREsgdGVhbS5cbiAgICAvL1xuICAgIC8vIFN1bW1hcnkgb2YgdGhlIHByb2JsZW06IHdlIHdlcmUgcmVhZGluZyB0aGUgcmVnaW9uIGZyb20gdGhlIGNvbmZpZyBmaWxlIGFuZCBwYXNzaW5nIGl0IHRvXG4gICAgLy8gdGhlIGNyZWRlbnRpYWwgcHJvdmlkZXJzLiBIb3dldmVyLCBpbiB0aGUgY2FzZSBvZiBTU08sIHRoaXMgbWFrZXMgdGhlIGNyZWRlbnRpYWwgcHJvdmlkZXJcbiAgICAvLyB1c2UgdGhhdCByZWdpb24gdG8gZG8gdGhlIFNTTyBmbG93LCB3aGljaCBpcyBpbmNvcnJlY3QuIFRoZSByZWdpb24gdGhhdCBzaG91bGQgYmUgdXNlZCBmb3JcbiAgICAvLyB0aGF0IGlzIHRoZSBvbmUgc2V0IGluIHRoZSBzc29fc2Vzc2lvbiBzZWN0aW9uIG9mIHRoZSBjb25maWcgZmlsZS5cbiAgICAvL1xuICAgIC8vIFRoZSBpZGVhIGhlcmU6IHRoZSBcImNsaWVudENvbmZpZ1wiIGlzIGZvciBjb25maWd1cmluZyB0aGUgaW5uZXIgYXV0aCBjbGllbnQgZGlyZWN0bHksXG4gICAgLy8gYW5kIGhhcyB0aGUgaGlnaGVzdCBwcmlvcml0eSwgd2hlcmVhcyBcInBhcmVudENsaWVudENvbmZpZ1wiIGlzIHRoZSB1cHBlciBkYXRhIGNsaWVudFxuICAgIC8vIGFuZCBoYXMgbG93ZXIgcHJpb3JpdHkgdGhhbiB0aGUgc3NvX3JlZ2lvbiBidXQgc3RpbGwgaGlnaGVyIHByaW9yaXR5IHRoYW4gU1RTIGdsb2JhbCByZWdpb24uXG4gICAgY29uc3QgcGFyZW50Q2xpZW50Q29uZmlnID0ge1xuICAgICAgcmVnaW9uOiBhd2FpdCB0aGlzLnJlZ2lvbihvcHRpb25zLnByb2ZpbGUpLFxuICAgIH07XG4gICAgLyoqXG4gICAgICogVGhlIHByZXZpb3VzIGltcGxlbWVudGF0aW9uIG1hdGNoZWQgQVdTIENMSSBiZWhhdmlvcjpcbiAgICAgKlxuICAgICAqIElmIGEgcHJvZmlsZSBpcyBleHBsaWNpdGx5IHNldCB1c2luZyBgLS1wcm9maWxlYCxcbiAgICAgKiB3ZSB1c2UgdGhhdCB0byB0aGUgZXhjbHVzaW9uIG9mIGV2ZXJ5dGhpbmcgZWxzZS5cbiAgICAgKlxuICAgICAqIE5vdGU6IHRoaXMgZG9lcyBub3QgYXBwbHkgdG8gQVdTX1BST0ZJTEUsXG4gICAgICogZW52aXJvbm1lbnQgY3JlZGVudGlhbHMgc3RpbGwgdGFrZSBwcmVjZWRlbmNlIG92ZXIgQVdTX1BST0ZJTEVcbiAgICAgKi9cbiAgICBpZiAob3B0aW9ucy5wcm9maWxlKSB7XG4gICAgICByZXR1cm4gbWFrZUNhY2hpbmdQcm92aWRlcihmcm9tSW5pKHtcbiAgICAgICAgcHJvZmlsZTogb3B0aW9ucy5wcm9maWxlLFxuICAgICAgICBpZ25vcmVDYWNoZTogdHJ1ZSxcbiAgICAgICAgbWZhQ29kZVByb3ZpZGVyOiB0aGlzLnRva2VuQ29kZUZuLmJpbmQodGhpcyksXG4gICAgICAgIGNsaWVudENvbmZpZyxcbiAgICAgICAgcGFyZW50Q2xpZW50Q29uZmlnLFxuICAgICAgICBsb2dnZXI6IG9wdGlvbnMubG9nZ2VyLFxuICAgICAgfSkpO1xuICAgIH1cblxuICAgIGNvbnN0IGVudlByb2ZpbGUgPSBwcm9jZXNzLmVudi5BV1NfUFJPRklMRSB8fCBwcm9jZXNzLmVudi5BV1NfREVGQVVMVF9QUk9GSUxFO1xuXG4gICAgLyoqXG4gICAgICogRW52IEFXUyAtIEVudmlyb25tZW50Q3JlZGVudGlhbHMgd2l0aCBzdHJpbmcgQVdTXG4gICAgICogRW52IEFtYXpvbiAtIEVudmlyb25tZW50Q3JlZGVudGlhbHMgd2l0aCBzdHJpbmcgQU1BWk9OXG4gICAgICogUHJvZmlsZSBDcmVkZW50aWFscyAtIFBhdGNoZWRTaGFyZWRJbmlGaWxlQ3JlZGVudGlhbHMgd2l0aCBpbXBsaWNpdCBwcm9maWxlLCBjcmVkZW50aWFscyBmaWxlLCBodHRwIG9wdGlvbnMsIGFuZCB0b2tlbiBmblxuICAgICAqICAgIFNTTyB3aXRoIGltcGxpY2l0IHByb2ZpbGUgb25seVxuICAgICAqICAgIFNoYXJlZEluaUZpbGVDcmVkZW50aWFscyB3aXRoIGltcGxpY2l0IHByb2ZpbGUgYW5kIHByZWZlclN0YXRpY0NyZWRlbnRpYWxzIHRydWUgKHByb2ZpbGUgd2l0aCBzb3VyY2VfcHJvZmlsZSlcbiAgICAgKiAgICBTaGFyZWQgQ3JlZGVudGlhbCBmaWxlIHRoYXQgcG9pbnRzIHRvIEVudmlyb25tZW50IENyZWRlbnRpYWxzIHdpdGggQVdTIHByZWZpeFxuICAgICAqICAgIFNoYXJlZCBDcmVkZW50aWFsIGZpbGUgdGhhdCBwb2ludHMgdG8gRUMyIE1ldGFkYXRhXG4gICAgICogICAgU2hhcmVkIENyZWRlbnRpYWwgZmlsZSB0aGF0IHBvaW50cyB0byBFQ1MgQ3JlZGVudGlhbHNcbiAgICAgKiBTU08gQ3JlZGVudGlhbHMgLSBTc29DcmVkZW50aWFscyB3aXRoIGltcGxpY2l0IHByb2ZpbGUgYW5kIGh0dHAgb3B0aW9uc1xuICAgICAqIFByb2Nlc3NDcmVkZW50aWFscyB3aXRoIGltcGxpY2l0IHByb2ZpbGVcbiAgICAgKiBFQ1MgQ3JlZGVudGlhbHMgLSBFQ1NDcmVkZW50aWFscyB3aXRoIG5vIGlucHV0IE9SIFdlYiBJZGVudGl0eSAtIFRva2VuRmlsZVdlYklkZW50aXR5Q3JlZGVudGlhbHMgd2l0aCBubyBpbnB1dCBPUiBFQzIgTWV0YWRhdGEgLSBFQzJNZXRhZGF0YUNyZWRlbnRpYWxzIHdpdGggbm8gaW5wdXRcbiAgICAgKlxuICAgICAqIFRoZXNlIHRyYW5zbGF0ZSB0bzpcbiAgICAgKiBmcm9tRW52KClcbiAgICAgKiBmcm9tU1NPKCkvZnJvbUluaSgpXG4gICAgICogZnJvbVByb2Nlc3MoKVxuICAgICAqIGZyb21Db250YWluZXJNZXRhZGF0YSgpXG4gICAgICogZnJvbVRva2VuRmlsZSgpXG4gICAgICogZnJvbUluc3RhbmNlTWV0YWRhdGEoKVxuICAgICAqXG4gICAgICogVGhlIE5vZGVQcm92aWRlckNoYWluIGlzIGFscmVhZHkgY2FjaGVkLlxuICAgICAqL1xuICAgIGNvbnN0IG5vZGVQcm92aWRlckNoYWluID0gZnJvbU5vZGVQcm92aWRlckNoYWluKHtcbiAgICAgIHByb2ZpbGU6IGVudlByb2ZpbGUsXG4gICAgICBjbGllbnRDb25maWcsXG4gICAgICBwYXJlbnRDbGllbnRDb25maWcsXG4gICAgICBsb2dnZXI6IG9wdGlvbnMubG9nZ2VyLFxuICAgICAgbWZhQ29kZVByb3ZpZGVyOiB0aGlzLnRva2VuQ29kZUZuLmJpbmQodGhpcyksXG4gICAgICBpZ25vcmVDYWNoZTogdHJ1ZSxcbiAgICB9KTtcblxuICAgIHJldHVybiBzaG91bGRQcmlvcml0aXplRW52KClcbiAgICAgID8gY3JlYXRlQ3JlZGVudGlhbENoYWluKGZyb21FbnYoKSwgbm9kZVByb3ZpZGVyQ2hhaW4pLmV4cGlyZUFmdGVyKDYwICogNjBfMDAwKVxuICAgICAgOiBub2RlUHJvdmlkZXJDaGFpbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRlbXB0cyB0byBnZXQgdGhlIHJlZ2lvbiBmcm9tIGEgbnVtYmVyIG9mIHNvdXJjZXMgYW5kIGZhbGxzIGJhY2sgdG8gdXMtZWFzdC0xIGlmIG5vIHJlZ2lvbiBjYW4gYmUgZm91bmQsXG4gICAqIGFzIGlzIGRvbmUgaW4gdGhlIEFXUyBDTEkuXG4gICAqXG4gICAqIFRoZSBvcmRlciBvZiBwcmlvcml0eSBpcyB0aGUgZm9sbG93aW5nOlxuICAgKlxuICAgKiAxLiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgc3BlY2lmeWluZyByZWdpb24sIHdpdGggYm90aCBhbiBBV1MgcHJlZml4IGFuZCBBTUFaT04gcHJlZml4XG4gICAqICAgIHRvIG1haW50YWluIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LCBhbmQgd2l0aG91dCBgREVGQVVMVGAgaW4gdGhlIG5hbWUgYmVjYXVzZVxuICAgKiAgICBMYW1iZGEgYW5kIENvZGVCdWlsZCBzZXQgdGhlICRBV1NfUkVHSU9OIHZhcmlhYmxlLlxuICAgKiAyLiBSZWdpb25zIGxpc3RlZCBpbiB0aGUgU2hhcmVkIEluaSBGaWxlcyAtIEZpcnN0IGNoZWNraW5nIGZvciB0aGUgcHJvZmlsZSBwcm92aWRlZFxuICAgKiAgICBhbmQgdGhlbiBjaGVja2luZyBmb3IgdGhlIGRlZmF1bHQgcHJvZmlsZS5cbiAgICogMy4gSU1EUyBpbnN0YW5jZSBpZGVudGl0eSByZWdpb24gZnJvbSB0aGUgTWV0YWRhdGEgU2VydmljZS5cbiAgICogNC4gdXMtZWFzdC0xXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVnaW9uKG1heWJlUHJvZmlsZT86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgZGVmYXVsdFJlZ2lvbiA9ICd1cy1lYXN0LTEnO1xuICAgIGNvbnN0IHByb2ZpbGUgPSBtYXliZVByb2ZpbGUgfHwgcHJvY2Vzcy5lbnYuQVdTX1BST0ZJTEUgfHwgcHJvY2Vzcy5lbnYuQVdTX0RFRkFVTFRfUFJPRklMRSB8fCAnZGVmYXVsdCc7XG5cbiAgICBjb25zdCByZWdpb24gPVxuICAgICAgcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTiB8fFxuICAgICAgcHJvY2Vzcy5lbnYuQU1BWk9OX1JFR0lPTiB8fFxuICAgICAgcHJvY2Vzcy5lbnYuQVdTX0RFRkFVTFRfUkVHSU9OIHx8XG4gICAgICBwcm9jZXNzLmVudi5BTUFaT05fREVGQVVMVF9SRUdJT04gfHxcbiAgICAgIChhd2FpdCB0aGlzLmdldFJlZ2lvbkZyb21JbmkocHJvZmlsZSkpIHx8XG4gICAgICAoYXdhaXQgdGhpcy5yZWdpb25Gcm9tTWV0YWRhdGFTZXJ2aWNlKCkpO1xuXG4gICAgaWYgKCFyZWdpb24pIHtcbiAgICAgIGNvbnN0IHVzZWRQcm9maWxlID0gIXByb2ZpbGUgPyAnJyA6IGAgKHByb2ZpbGU6IFwiJHtwcm9maWxlfVwiKWA7XG4gICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1NES19ERUJVRy5tc2coXG4gICAgICAgIGBVbmFibGUgdG8gZGV0ZXJtaW5lIEFXUyByZWdpb24gZnJvbSBlbnZpcm9ubWVudCBvciBBV1MgY29uZmlndXJhdGlvbiR7dXNlZFByb2ZpbGV9LCBkZWZhdWx0aW5nIHRvICcke2RlZmF1bHRSZWdpb259J2AsXG4gICAgICApKTtcbiAgICAgIHJldHVybiBkZWZhdWx0UmVnaW9uO1xuICAgIH1cblxuICAgIHJldHVybiByZWdpb247XG4gIH1cblxuICAvKipcbiAgICogVGhlIE1ldGFkYXRhU2VydmljZSBjbGFzcyB3aWxsIGF0dGVtcHQgdG8gZmV0Y2ggdGhlIGluc3RhbmNlIGlkZW50aXR5IGRvY3VtZW50IGZyb21cbiAgICogSU1EU3YyIGZpcnN0LCBhbmQgdGhlbiB3aWxsIGF0dGVtcHQgdjEgYXMgYSBmYWxsYmFjay5cbiAgICpcbiAgICogSWYgdGhpcyBmYWlscywgd2Ugd2lsbCB1c2UgdXMtZWFzdC0xIGFzIHRoZSByZWdpb24gc28gbm8gZXJyb3Igc2hvdWxkIGJlIHRocm93bi5cbiAgICogQHJldHVybnMgVGhlIHJlZ2lvbiBmb3IgdGhlIGluc3RhbmNlIGlkZW50aXR5XG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlZ2lvbkZyb21NZXRhZGF0YVNlcnZpY2UoKSB7XG4gICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9TREtfREVCVUcubXNnKCdMb29raW5nIHVwIEFXUyByZWdpb24gaW4gdGhlIEVDMiBJbnN0YW5jZSBNZXRhZGF0YSBTZXJ2aWNlIChJTURTKS4nKSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhU2VydmljZSA9IG5ldyBNZXRhZGF0YVNlcnZpY2Uoe1xuICAgICAgICBodHRwT3B0aW9uczoge1xuICAgICAgICAgIHRpbWVvdXQ6IDEwMDAsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgbWV0YWRhdGFTZXJ2aWNlLmZldGNoTWV0YWRhdGFUb2tlbigpO1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBhd2FpdCBtZXRhZGF0YVNlcnZpY2UucmVxdWVzdCgnL2xhdGVzdC9keW5hbWljL2luc3RhbmNlLWlkZW50aXR5L2RvY3VtZW50Jywge30pO1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZG9jdW1lbnQpLnJlZ2lvbjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1NES19ERUJVRy5tc2coYFVuYWJsZSB0byByZXRyaWV2ZSBBV1MgcmVnaW9uIGZyb20gSU1EUzogJHtlfWApKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTG9va3MgdXAgdGhlIHJlZ2lvbiBvZiB0aGUgcHJvdmlkZWQgcHJvZmlsZS4gSWYgbm8gcmVnaW9uIGlzIHByZXNlbnQsXG4gICAqIGl0IHdpbGwgYXR0ZW1wdCB0byBsb29rdXAgdGhlIGRlZmF1bHQgcmVnaW9uLlxuICAgKiBAcGFyYW0gcHJvZmlsZSBUaGUgcHJvZmlsZSB0byB1c2UgdG8gbG9va3VwIHRoZSByZWdpb25cbiAgICogQHJldHVybnMgVGhlIHJlZ2lvbiBmb3IgdGhlIHByb2ZpbGUgb3IgZGVmYXVsdCBwcm9maWxlLCBpZiBwcmVzZW50LiBPdGhlcndpc2UgcmV0dXJucyB1bmRlZmluZWQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFJlZ2lvbkZyb21JbmkocHJvZmlsZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBzaGFyZWRGaWxlcyA9IGF3YWl0IGxvYWRTaGFyZWRDb25maWdGaWxlcyh7IGlnbm9yZUNhY2hlOiB0cnVlIH0pO1xuXG4gICAgLy8gUHJpb3JpdHk6XG4gICAgLy9cbiAgICAvLyBjcmVkZW50aWFscyBjb21lIGJlZm9yZSBjb25maWcgYmVjYXVzZSBhd3MtY2xpIHYxIGJlaGF2ZXMgbGlrZSB0aGF0LlxuICAgIC8vXG4gICAgLy8gMS4gcHJvZmlsZS1yZWdpb24taW4tY3JlZGVudGlhbHNcbiAgICAvLyAyLiBwcm9maWxlLXJlZ2lvbi1pbi1jb25maWdcbiAgICAvLyAzLiBkZWZhdWx0LXJlZ2lvbi1pbi1jcmVkZW50aWFsc1xuICAgIC8vIDQuIGRlZmF1bHQtcmVnaW9uLWluLWNvbmZpZ1xuXG4gICAgcmV0dXJuIHRoaXMuZ2V0UmVnaW9uRnJvbUluaUZpbGUocHJvZmlsZSwgc2hhcmVkRmlsZXMuY3JlZGVudGlhbHNGaWxlKVxuICAgID8/IHRoaXMuZ2V0UmVnaW9uRnJvbUluaUZpbGUocHJvZmlsZSwgc2hhcmVkRmlsZXMuY29uZmlnRmlsZSlcbiAgICA/PyB0aGlzLmdldFJlZ2lvbkZyb21JbmlGaWxlKCdkZWZhdWx0Jywgc2hhcmVkRmlsZXMuY3JlZGVudGlhbHNGaWxlKVxuICAgID8/IHRoaXMuZ2V0UmVnaW9uRnJvbUluaUZpbGUoJ2RlZmF1bHQnLCBzaGFyZWRGaWxlcy5jb25maWdGaWxlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UmVnaW9uRnJvbUluaUZpbGUocHJvZmlsZTogc3RyaW5nLCBkYXRhPzogYW55KSB7XG4gICAgcmV0dXJuIGRhdGE/Lltwcm9maWxlXT8ucmVnaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEFzayB1c2VyIGZvciBNRkEgdG9rZW4gZm9yIGdpdmVuIHNlcmlhbFxuICAgKlxuICAgKiBSZXN1bHQgaXMgc2VuZCB0byBjYWxsYmFjayBmdW5jdGlvbiBmb3IgU0RLIHRvIGF1dGhvcml6ZSB0aGUgcmVxdWVzdFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB0b2tlbkNvZGVGbihzZXJpYWxBcm46IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgZGVidWdGbiA9IChtc2c6IHN0cmluZywgLi4uYXJnczogYW55W10pID0+IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfU0RLX0RFQlVHLm1zZyhmb3JtYXQobXNnLCAuLi5hcmdzKSkpO1xuICAgIGF3YWl0IGRlYnVnRm4oJ1JlcXVpcmUgTUZBIHRva2VuIGZvciBzZXJpYWwgQVJOJywgc2VyaWFsQXJuKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdG9rZW46IHN0cmluZyA9IGF3YWl0IHByb21wdGx5LnByb21wdChgTUZBIHRva2VuIGZvciAke3NlcmlhbEFybn06IGAsIHtcbiAgICAgICAgdHJpbTogdHJ1ZSxcbiAgICAgICAgZGVmYXVsdDogJycsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IGRlYnVnRm4oJ1N1Y2Nlc3NmdWxseSBnb3QgTUZBIHRva2VuIGZyb20gdXNlcicpO1xuICAgICAgcmV0dXJuIHRva2VuO1xuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICBhd2FpdCBkZWJ1Z0ZuKCdGYWlsZWQgdG8gZ2V0IE1GQSB0b2tlbicsIGVycik7XG4gICAgICBjb25zdCBlID0gbmV3IEF1dGhlbnRpY2F0aW9uRXJyb3IoYEVycm9yIGZldGNoaW5nIE1GQSB0b2tlbjogJHtlcnIubWVzc2FnZSA/PyBlcnJ9YCk7XG4gICAgICBlLm5hbWUgPSAnU2hhcmVkSW5pRmlsZUNyZWRlbnRpYWxzUHJvdmlkZXJGYWlsdXJlJztcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogV2UgdXNlZCB0byBzdXBwb3J0IGJvdGggQVdTIGFuZCBBTUFaT04gcHJlZml4ZXMgZm9yIHRoZXNlIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAqXG4gKiBBZGRpbmcgdGhpcyBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eS5cbiAqL1xuZnVuY3Rpb24gc2hvdWxkUHJpb3JpdGl6ZUVudigpIHtcbiAgY29uc3QgaWQgPSBwcm9jZXNzLmVudi5BV1NfQUNDRVNTX0tFWV9JRCB8fCBwcm9jZXNzLmVudi5BTUFaT05fQUNDRVNTX0tFWV9JRDtcbiAgY29uc3Qga2V5ID0gcHJvY2Vzcy5lbnYuQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZIHx8IHByb2Nlc3MuZW52LkFNQVpPTl9TRUNSRVRfQUNDRVNTX0tFWTtcblxuICBpZiAoISFpZCAmJiAhIWtleSkge1xuICAgIHByb2Nlc3MuZW52LkFXU19BQ0NFU1NfS0VZX0lEID0gaWQ7XG4gICAgcHJvY2Vzcy5lbnYuQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZID0ga2V5O1xuXG4gICAgY29uc3Qgc2Vzc2lvblRva2VuID0gcHJvY2Vzcy5lbnYuQVdTX1NFU1NJT05fVE9LRU4gPz8gcHJvY2Vzcy5lbnYuQU1BWk9OX1NFU1NJT05fVE9LRU47XG4gICAgaWYgKHNlc3Npb25Ub2tlbikge1xuICAgICAgcHJvY2Vzcy5lbnYuQVdTX1NFU1NJT05fVE9LRU4gPSBzZXNzaW9uVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlZGVudGlhbENoYWluT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHByb2ZpbGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGxvZ2dlcj86IExvZ2dlcjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1ha2VSZXF1ZXN0SGFuZGxlcihpb0hlbHBlcjogSW9IZWxwZXIsIG9wdGlvbnM6IFNka0h0dHBPcHRpb25zID0ge30pOiBQcm9taXNlPE5vZGVIdHRwSGFuZGxlck9wdGlvbnM+IHtcbiAgY29uc3QgYWdlbnQgPSBhd2FpdCBuZXcgUHJveHlBZ2VudFByb3ZpZGVyKGlvSGVscGVyKS5jcmVhdGUob3B0aW9ucyk7XG5cbiAgcmV0dXJuIHtcbiAgICBjb25uZWN0aW9uVGltZW91dDogREVGQVVMVF9DT05ORUNUSU9OX1RJTUVPVVQsXG4gICAgcmVxdWVzdFRpbWVvdXQ6IERFRkFVTFRfVElNRU9VVCxcbiAgICBodHRwc0FnZW50OiBhZ2VudCxcbiAgICBodHRwQWdlbnQ6IGFnZW50LFxuICB9O1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.d.ts new file mode 100644 index 000000000..d2a9c2a27 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.d.ts @@ -0,0 +1,11 @@ +/** + * Cache the result of a function on an object + * + * We could have used @decorators to make this nicer but we don't use them anywhere yet, + * so let's keep it simple and readable. + */ +export declare function cached(obj: A, sym: symbol, fn: () => B): B; +/** + * Like 'cached', but async + */ +export declare function cachedAsync(obj: A, sym: symbol, fn: () => Promise): Promise; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.js new file mode 100644 index 000000000..3a006ab94 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/cached.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.cached = cached; +exports.cachedAsync = cachedAsync; +/** + * Cache the result of a function on an object + * + * We could have used @decorators to make this nicer but we don't use them anywhere yet, + * so let's keep it simple and readable. + */ +function cached(obj, sym, fn) { + if (!(sym in obj)) { + obj[sym] = fn(); + } + return obj[sym]; +} +/** + * Like 'cached', but async + */ +async function cachedAsync(obj, sym, fn) { + if (!(sym in obj)) { + obj[sym] = await fn(); + } + return obj[sym]; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9hd3MtYXV0aC9jYWNoZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFNQSx3QkFLQztBQUtELGtDQUtDO0FBckJEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsTUFBTSxDQUFzQixHQUFNLEVBQUUsR0FBVyxFQUFFLEVBQVc7SUFDMUUsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDakIsR0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFDRCxPQUFRLEdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMzQixDQUFDO0FBRUQ7O0dBRUc7QUFDSSxLQUFLLFVBQVUsV0FBVyxDQUFzQixHQUFNLEVBQUUsR0FBVyxFQUFFLEVBQW9CO0lBQzlGLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ2pCLEdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLEVBQUUsRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFDRCxPQUFRLEdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMzQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDYWNoZSB0aGUgcmVzdWx0IG9mIGEgZnVuY3Rpb24gb24gYW4gb2JqZWN0XG4gKlxuICogV2UgY291bGQgaGF2ZSB1c2VkIEBkZWNvcmF0b3JzIHRvIG1ha2UgdGhpcyBuaWNlciBidXQgd2UgZG9uJ3QgdXNlIHRoZW0gYW55d2hlcmUgeWV0LFxuICogc28gbGV0J3Mga2VlcCBpdCBzaW1wbGUgYW5kIHJlYWRhYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FjaGVkPEEgZXh0ZW5kcyBvYmplY3QsIEI+KG9iajogQSwgc3ltOiBzeW1ib2wsIGZuOiAoKSA9PiBCKTogQiB7XG4gIGlmICghKHN5bSBpbiBvYmopKSB7XG4gICAgKG9iaiBhcyBhbnkpW3N5bV0gPSBmbigpO1xuICB9XG4gIHJldHVybiAob2JqIGFzIGFueSlbc3ltXTtcbn1cblxuLyoqXG4gKiBMaWtlICdjYWNoZWQnLCBidXQgYXN5bmNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNhY2hlZEFzeW5jPEEgZXh0ZW5kcyBvYmplY3QsIEI+KG9iajogQSwgc3ltOiBzeW1ib2wsIGZuOiAoKSA9PiBQcm9taXNlPEI+KTogUHJvbWlzZTxCPiB7XG4gIGlmICghKHN5bSBpbiBvYmopKSB7XG4gICAgKG9iaiBhcyBhbnkpW3N5bV0gPSBhd2FpdCBmbigpO1xuICB9XG4gIHJldHVybiAob2JqIGFzIGFueSlbc3ltXTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.d.ts new file mode 100644 index 000000000..3f10b78f9 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.d.ts @@ -0,0 +1,38 @@ +import type { AwsCredentialIdentityProvider } from '@smithy/types'; +import { type IoHelper } from '../io/private'; +import type { PluginHost } from '../plugin'; +import type { Mode } from '../plugin/mode'; +/** + * Cache for credential providers. + * + * Given an account and an operating mode (read or write) will return an + * appropriate credential provider for credentials for the given account. The + * credential provider will be cached so that multiple AWS clients for the same + * environment will not make multiple network calls to obtain credentials. + * + * Will use default credentials if they are for the right account; otherwise, + * all loaded credential provider plugins will be tried to obtain credentials + * for the given account. + */ +export declare class CredentialPlugins { + private readonly host; + private readonly ioHelper; + private readonly cache; + constructor(host: PluginHost, ioHelper: IoHelper); + fetchCredentialsFor(awsAccountId: string, mode: Mode): Promise; + get availablePluginNames(): string[]; + private lookupCredentials; +} +/** + * Result from trying to fetch credentials from the Plugin host + */ +export interface PluginCredentialsFetchResult { + /** + * SDK-v3 compatible credential provider + */ + readonly credentials: AwsCredentialIdentityProvider; + /** + * Name of plugin that successfully provided credentials + */ + readonly pluginName: string; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.js new file mode 100644 index 000000000..756d2f7b2 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/credential-plugins.js @@ -0,0 +1,154 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CredentialPlugins = void 0; +const util_1 = require("util"); +const provider_caching_1 = require("./provider-caching"); +const util_2 = require("../../util"); +const private_1 = require("../io/private"); +const toolkit_error_1 = require("../toolkit-error"); +/** + * Cache for credential providers. + * + * Given an account and an operating mode (read or write) will return an + * appropriate credential provider for credentials for the given account. The + * credential provider will be cached so that multiple AWS clients for the same + * environment will not make multiple network calls to obtain credentials. + * + * Will use default credentials if they are for the right account; otherwise, + * all loaded credential provider plugins will be tried to obtain credentials + * for the given account. + */ +class CredentialPlugins { + host; + ioHelper; + cache = {}; + constructor(host, ioHelper) { + this.host = host; + this.ioHelper = ioHelper; + } + async fetchCredentialsFor(awsAccountId, mode) { + const key = `${awsAccountId}-${mode}`; + if (!(key in this.cache)) { + this.cache[key] = await this.lookupCredentials(awsAccountId, mode); + } + return this.cache[key]; + } + get availablePluginNames() { + return this.host.credentialProviderSources.map((s) => s.name); + } + async lookupCredentials(awsAccountId, mode) { + const triedSources = []; + // Otherwise, inspect the various credential sources we have + for (const source of this.host.credentialProviderSources) { + let available; + try { + available = await source.isAvailable(); + } + catch (e) { + // This shouldn't happen, but let's guard against it anyway + await this.ioHelper.notify(private_1.IO.CDK_TOOLKIT_W0100.msg(`Uncaught exception in ${source.name}: ${(0, util_2.formatErrorMessage)(e)}`)); + available = false; + } + if (!available) { + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Credentials source ${source.name} is not available, ignoring it.`)); + continue; + } + triedSources.push(source); + let canProvide; + try { + canProvide = await source.canProvideCredentials(awsAccountId); + } + catch (e) { + // This shouldn't happen, but let's guard against it anyway + await this.ioHelper.notify(private_1.IO.CDK_TOOLKIT_W0100.msg(`Uncaught exception in ${source.name}: ${(0, util_2.formatErrorMessage)(e)}`)); + canProvide = false; + } + if (!canProvide) { + continue; + } + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Using ${source.name} credentials for account ${awsAccountId}`)); + return { + credentials: await v3ProviderFromPlugin(() => source.getProvider(awsAccountId, mode, { + supportsV3Providers: true, + })), + pluginName: source.name, + }; + } + return undefined; + } +} +exports.CredentialPlugins = CredentialPlugins; +/** + * Take a function that calls the plugin, and turn it into an SDKv3-compatible credential provider. + * + * What we will do is the following: + * + * - Query the plugin and see what kind of result it gives us. + * - If the result is self-refreshing or doesn't need refreshing, we turn it into an SDKv3 provider + * and return it directly. + * * If the underlying return value is a provider, we will make it a caching provider + * (because we can't know if it will cache by itself or not). + * * If the underlying return value is a static credential, caching isn't relevant. + * * If the underlying return value is V2 credentials, those have caching built-in. + * - If the result is a static credential that expires, we will wrap it in an SDKv3 provider + * that will query the plugin again when the credential expires. + */ +async function v3ProviderFromPlugin(producer) { + const initial = await producer(); + if (isV3Provider(initial)) { + // Already a provider, make caching + return (0, provider_caching_1.makeCachingProvider)(initial); + } + else if (isV3Credentials(initial) && initial.expiration === undefined) { + // Static credentials that don't need refreshing nor caching + return () => Promise.resolve(initial); + } + else if (isV3Credentials(initial) && initial.expiration !== undefined) { + // Static credentials that do need refreshing and caching + return refreshFromPluginProvider(initial, producer); + } + else if (isV2Credentials(initial)) { + // V2 credentials that refresh and cache themselves + return v3ProviderFromV2Credentials(initial); + } + else { + throw new toolkit_error_1.AuthenticationError(`Plugin returned a value that doesn't resemble AWS credentials: ${(0, util_1.inspect)(initial)}`); + } +} +/** + * Converts a V2 credential into a V3-compatible provider + */ +function v3ProviderFromV2Credentials(x) { + return async () => { + // Get will fetch or refresh as necessary + await x.getPromise(); + return { + accessKeyId: x.accessKeyId, + secretAccessKey: x.secretAccessKey, + sessionToken: x.sessionToken, + expiration: x.expireTime ?? undefined, + }; + }; +} +function refreshFromPluginProvider(current, producer) { + return async () => { + if ((0, provider_caching_1.credentialsAboutToExpire)(current)) { + const newCreds = await producer(); + if (!isV3Credentials(newCreds)) { + throw new toolkit_error_1.AuthenticationError(`Plugin initially returned static V3 credentials but now returned something else: ${(0, util_1.inspect)(newCreds)}`); + } + current = newCreds; + } + return current; + }; +} +function isV3Provider(x) { + return typeof x === 'function'; +} +function isV2Credentials(x) { + return !!(x && typeof x === 'object' && x.getPromise); +} +function isV3Credentials(x) { + return !!(x && typeof x === 'object' && x.accessKeyId && !isV2Credentials(x)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlZGVudGlhbC1wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9hd3MtYXV0aC9jcmVkZW50aWFsLXBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0JBQStCO0FBRy9CLHlEQUFtRjtBQUNuRixxQ0FBZ0Q7QUFDaEQsMkNBQWtEO0FBR2xELG9EQUF1RDtBQUV2RDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQWEsaUJBQWlCO0lBR0M7SUFBbUM7SUFGL0MsS0FBSyxHQUFnRSxFQUFFLENBQUM7SUFFekYsWUFBNkIsSUFBZ0IsRUFBbUIsUUFBa0I7UUFBckQsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUFtQixhQUFRLEdBQVIsUUFBUSxDQUFVO0lBQ2xGLENBQUM7SUFFTSxLQUFLLENBQUMsbUJBQW1CLENBQUMsWUFBb0IsRUFBRSxJQUFVO1FBQy9ELE1BQU0sR0FBRyxHQUFHLEdBQUcsWUFBWSxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLENBQUM7SUFFRCxJQUFXLG9CQUFvQjtRQUM3QixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVPLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxZQUFvQixFQUFFLElBQVU7UUFDOUQsTUFBTSxZQUFZLEdBQStCLEVBQUUsQ0FB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QUFDO0lBQ2pCLENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLFlBQVksQ0FBQyxDQUF1QjtJQUMzQyxPQUFPLE9BQU8sQ0FBQyxLQUFLLFVBQVUsQ0FBQztBQUNqQyxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsQ0FBdUI7SUFDOUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFLLENBQWdDLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDeEYsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLENBQXVCO0lBQzlDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsV0FBVyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDaEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGluc3BlY3QgfSBmcm9tICd1dGlsJztcbmltcG9ydCB0eXBlIHsgQ3JlZGVudGlhbFByb3ZpZGVyU291cmNlLCBGb3JSZWFkaW5nLCBGb3JXcml0aW5nLCBQbHVnaW5Qcm92aWRlclJlc3VsdCwgU0RLdjJDb21wYXRpYmxlQ3JlZGVudGlhbHMsIFNES3YzQ29tcGF0aWJsZUNyZWRlbnRpYWxQcm92aWRlciwgU0RLdjNDb21wYXRpYmxlQ3JlZGVudGlhbHMgfSBmcm9tICdAYXdzLWNkay9jbGktcGx1Z2luLWNvbnRyYWN0JztcbmltcG9ydCB0eXBlIHsgQXdzQ3JlZGVudGlhbElkZW50aXR5LCBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlciB9IGZyb20gJ0BzbWl0aHkvdHlwZXMnO1xuaW1wb3J0IHsgY3JlZGVudGlhbHNBYm91dFRvRXhwaXJlLCBtYWtlQ2FjaGluZ1Byb3ZpZGVyIH0gZnJvbSAnLi9wcm92aWRlci1jYWNoaW5nJztcbmltcG9ydCB7IGZvcm1hdEVycm9yTWVzc2FnZSB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgSU8sIHR5cGUgSW9IZWxwZXIgfSBmcm9tICcuLi9pby9wcml2YXRlJztcbmltcG9ydCB0eXBlIHsgUGx1Z2luSG9zdCB9IGZyb20gJy4uL3BsdWdpbic7XG5pbXBvcnQgdHlwZSB7IE1vZGUgfSBmcm9tICcuLi9wbHVnaW4vbW9kZSc7XG5pbXBvcnQgeyBBdXRoZW50aWNhdGlvbkVycm9yIH0gZnJvbSAnLi4vdG9vbGtpdC1lcnJvcic7XG5cbi8qKlxuICogQ2FjaGUgZm9yIGNyZWRlbnRpYWwgcHJvdmlkZXJzLlxuICpcbiAqIEdpdmVuIGFuIGFjY291bnQgYW5kIGFuIG9wZXJhdGluZyBtb2RlIChyZWFkIG9yIHdyaXRlKSB3aWxsIHJldHVybiBhblxuICogYXBwcm9wcmlhdGUgY3JlZGVudGlhbCBwcm92aWRlciBmb3IgY3JlZGVudGlhbHMgZm9yIHRoZSBnaXZlbiBhY2NvdW50LiBUaGVcbiAqIGNyZWRlbnRpYWwgcHJvdmlkZXIgd2lsbCBiZSBjYWNoZWQgc28gdGhhdCBtdWx0aXBsZSBBV1MgY2xpZW50cyBmb3IgdGhlIHNhbWVcbiAqIGVudmlyb25tZW50IHdpbGwgbm90IG1ha2UgbXVsdGlwbGUgbmV0d29yayBjYWxscyB0byBvYnRhaW4gY3JlZGVudGlhbHMuXG4gKlxuICogV2lsbCB1c2UgZGVmYXVsdCBjcmVkZW50aWFscyBpZiB0aGV5IGFyZSBmb3IgdGhlIHJpZ2h0IGFjY291bnQ7IG90aGVyd2lzZSxcbiAqIGFsbCBsb2FkZWQgY3JlZGVudGlhbCBwcm92aWRlciBwbHVnaW5zIHdpbGwgYmUgdHJpZWQgdG8gb2J0YWluIGNyZWRlbnRpYWxzXG4gKiBmb3IgdGhlIGdpdmVuIGFjY291bnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBDcmVkZW50aWFsUGx1Z2lucyB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGU6IHsgW2tleTogc3RyaW5nXTogUGx1Z2luQ3JlZGVudGlhbHNGZXRjaFJlc3VsdCB8IHVuZGVmaW5lZCB9ID0ge307XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBob3N0OiBQbHVnaW5Ib3N0LCBwcml2YXRlIHJlYWRvbmx5IGlvSGVscGVyOiBJb0hlbHBlcikge1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGZldGNoQ3JlZGVudGlhbHNGb3IoYXdzQWNjb3VudElkOiBzdHJpbmcsIG1vZGU6IE1vZGUpOiBQcm9taXNlPFBsdWdpbkNyZWRlbnRpYWxzRmV0Y2hSZXN1bHQgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBrZXkgPSBgJHthd3NBY2NvdW50SWR9LSR7bW9kZX1gO1xuICAgIGlmICghKGtleSBpbiB0aGlzLmNhY2hlKSkge1xuICAgICAgdGhpcy5jYWNoZVtrZXldID0gYXdhaXQgdGhpcy5sb29rdXBDcmVkZW50aWFscyhhd3NBY2NvdW50SWQsIG1vZGUpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jYWNoZVtrZXldO1xuICB9XG5cbiAgcHVibGljIGdldCBhdmFpbGFibGVQbHVnaW5OYW1lcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuaG9zdC5jcmVkZW50aWFsUHJvdmlkZXJTb3VyY2VzLm1hcCgocykgPT4gcy5uYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9va3VwQ3JlZGVudGlhbHMoYXdzQWNjb3VudElkOiBzdHJpbmcsIG1vZGU6IE1vZGUpOiBQcm9taXNlPFBsdWdpbkNyZWRlbnRpYWxzRmV0Y2hSZXN1bHQgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCB0cmllZFNvdXJjZXM6IENyZWRlbnRpYWxQcm92aWRlclNvdXJjZVtdID0gW107XG4gICAgLy8gT3RoZXJ3aXNlLCBpbnNwZWN0IHRoZSB2YXJpb3VzIGNyZWRlbnRpYWwgc291cmNlcyB3ZSBoYXZlXG4gICAgZm9yIChjb25zdCBzb3VyY2Ugb2YgdGhpcy5ob3N0LmNyZWRlbnRpYWxQcm92aWRlclNvdXJjZXMpIHtcbiAgICAgIGxldCBhdmFpbGFibGU6IGJvb2xlYW47XG4gICAgICB0cnkge1xuICAgICAgICBhdmFpbGFibGUgPSBhd2FpdCBzb3VyY2UuaXNBdmFpbGFibGUoKTtcbiAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAvLyBUaGlzIHNob3VsZG4ndCBoYXBwZW4sIGJ1dCBsZXQncyBndWFyZCBhZ2FpbnN0IGl0IGFueXdheVxuICAgICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5DREtfVE9PTEtJVF9XMDEwMC5tc2coYFVuY2F1Z2h0IGV4Y2VwdGlvbiBpbiAke3NvdXJjZS5uYW1lfTogJHtmb3JtYXRFcnJvck1lc3NhZ2UoZSl9YCkpO1xuICAgICAgICBhdmFpbGFibGUgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFhdmFpbGFibGUpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgQ3JlZGVudGlhbHMgc291cmNlICR7c291cmNlLm5hbWV9IGlzIG5vdCBhdmFpbGFibGUsIGlnbm9yaW5nIGl0LmApKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICB0cmllZFNvdXJjZXMucHVzaChzb3VyY2UpO1xuICAgICAgbGV0IGNhblByb3ZpZGU6IGJvb2xlYW47XG4gICAgICB0cnkge1xuICAgICAgICBjYW5Qcm92aWRlID0gYXdhaXQgc291cmNlLmNhblByb3ZpZGVDcmVkZW50aWFscyhhd3NBY2NvdW50SWQpO1xuICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgIC8vIFRoaXMgc2hvdWxkbid0IGhhcHBlbiwgYnV0IGxldCdzIGd1YXJkIGFnYWluc3QgaXQgYW55d2F5XG4gICAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkNES19UT09MS0lUX1cwMTAwLm1zZyhgVW5jYXVnaHQgZXhjZXB0aW9uIGluICR7c291cmNlLm5hbWV9OiAke2Zvcm1hdEVycm9yTWVzc2FnZShlKX1gKSk7XG4gICAgICAgIGNhblByb3ZpZGUgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmICghY2FuUHJvdmlkZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYFVzaW5nICR7c291cmNlLm5hbWV9IGNyZWRlbnRpYWxzIGZvciBhY2NvdW50ICR7YXdzQWNjb3VudElkfWApKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY3JlZGVudGlhbHM6IGF3YWl0IHYzUHJvdmlkZXJGcm9tUGx1Z2luKCgpID0+IHNvdXJjZS5nZXRQcm92aWRlcihhd3NBY2NvdW50SWQsIG1vZGUgYXMgRm9yUmVhZGluZyB8IEZvcldyaXRpbmcsIHtcbiAgICAgICAgICBzdXBwb3J0c1YzUHJvdmlkZXJzOiB0cnVlLFxuICAgICAgICB9KSksXG4gICAgICAgIHBsdWdpbk5hbWU6IHNvdXJjZS5uYW1lLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFJlc3VsdCBmcm9tIHRyeWluZyB0byBmZXRjaCBjcmVkZW50aWFscyBmcm9tIHRoZSBQbHVnaW4gaG9zdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBsdWdpbkNyZWRlbnRpYWxzRmV0Y2hSZXN1bHQge1xuICAvKipcbiAgICogU0RLLXYzIGNvbXBhdGlibGUgY3JlZGVudGlhbCBwcm92aWRlclxuICAgKi9cbiAgcmVhZG9ubHkgY3JlZGVudGlhbHM6IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyO1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHBsdWdpbiB0aGF0IHN1Y2Nlc3NmdWxseSBwcm92aWRlZCBjcmVkZW50aWFsc1xuICAgKi9cbiAgcmVhZG9ubHkgcGx1Z2luTmFtZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRha2UgYSBmdW5jdGlvbiB0aGF0IGNhbGxzIHRoZSBwbHVnaW4sIGFuZCB0dXJuIGl0IGludG8gYW4gU0RLdjMtY29tcGF0aWJsZSBjcmVkZW50aWFsIHByb3ZpZGVyLlxuICpcbiAqIFdoYXQgd2Ugd2lsbCBkbyBpcyB0aGUgZm9sbG93aW5nOlxuICpcbiAqIC0gUXVlcnkgdGhlIHBsdWdpbiBhbmQgc2VlIHdoYXQga2luZCBvZiByZXN1bHQgaXQgZ2l2ZXMgdXMuXG4gKiAtIElmIHRoZSByZXN1bHQgaXMgc2VsZi1yZWZyZXNoaW5nIG9yIGRvZXNuJ3QgbmVlZCByZWZyZXNoaW5nLCB3ZSB0dXJuIGl0IGludG8gYW4gU0RLdjMgcHJvdmlkZXJcbiAqICAgYW5kIHJldHVybiBpdCBkaXJlY3RseS5cbiAqICAgKiBJZiB0aGUgdW5kZXJseWluZyByZXR1cm4gdmFsdWUgaXMgYSBwcm92aWRlciwgd2Ugd2lsbCBtYWtlIGl0IGEgY2FjaGluZyBwcm92aWRlclxuICogICAgIChiZWNhdXNlIHdlIGNhbid0IGtub3cgaWYgaXQgd2lsbCBjYWNoZSBieSBpdHNlbGYgb3Igbm90KS5cbiAqICAgKiBJZiB0aGUgdW5kZXJseWluZyByZXR1cm4gdmFsdWUgaXMgYSBzdGF0aWMgY3JlZGVudGlhbCwgY2FjaGluZyBpc24ndCByZWxldmFudC5cbiAqICAgKiBJZiB0aGUgdW5kZXJseWluZyByZXR1cm4gdmFsdWUgaXMgVjIgY3JlZGVudGlhbHMsIHRob3NlIGhhdmUgY2FjaGluZyBidWlsdC1pbi5cbiAqIC0gSWYgdGhlIHJlc3VsdCBpcyBhIHN0YXRpYyBjcmVkZW50aWFsIHRoYXQgZXhwaXJlcywgd2Ugd2lsbCB3cmFwIGl0IGluIGFuIFNES3YzIHByb3ZpZGVyXG4gKiAgIHRoYXQgd2lsbCBxdWVyeSB0aGUgcGx1Z2luIGFnYWluIHdoZW4gdGhlIGNyZWRlbnRpYWwgZXhwaXJlcy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdjNQcm92aWRlckZyb21QbHVnaW4ocHJvZHVjZXI6ICgpID0+IFByb21pc2U8UGx1Z2luUHJvdmlkZXJSZXN1bHQ+KTogUHJvbWlzZTxBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcj4ge1xuICBjb25zdCBpbml0aWFsID0gYXdhaXQgcHJvZHVjZXIoKTtcblxuICBpZiAoaXNWM1Byb3ZpZGVyKGluaXRpYWwpKSB7XG4gICAgLy8gQWxyZWFkeSBhIHByb3ZpZGVyLCBtYWtlIGNhY2hpbmdcbiAgICByZXR1cm4gbWFrZUNhY2hpbmdQcm92aWRlcihpbml0aWFsKTtcbiAgfSBlbHNlIGlmIChpc1YzQ3JlZGVudGlhbHMoaW5pdGlhbCkgJiYgaW5pdGlhbC5leHBpcmF0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBTdGF0aWMgY3JlZGVudGlhbHMgdGhhdCBkb24ndCBuZWVkIHJlZnJlc2hpbmcgbm9yIGNhY2hpbmdcbiAgICByZXR1cm4gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKGluaXRpYWwpO1xuICB9IGVsc2UgaWYgKGlzVjNDcmVkZW50aWFscyhpbml0aWFsKSAmJiBpbml0aWFsLmV4cGlyYXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgIC8vIFN0YXRpYyBjcmVkZW50aWFscyB0aGF0IGRvIG5lZWQgcmVmcmVzaGluZyBhbmQgY2FjaGluZ1xuICAgIHJldHVybiByZWZyZXNoRnJvbVBsdWdpblByb3ZpZGVyKGluaXRpYWwsIHByb2R1Y2VyKTtcbiAgfSBlbHNlIGlmIChpc1YyQ3JlZGVudGlhbHMoaW5pdGlhbCkpIHtcbiAgICAvLyBWMiBjcmVkZW50aWFscyB0aGF0IHJlZnJlc2ggYW5kIGNhY2hlIHRoZW1zZWx2ZXNcbiAgICByZXR1cm4gdjNQcm92aWRlckZyb21WMkNyZWRlbnRpYWxzKGluaXRpYWwpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBBdXRoZW50aWNhdGlvbkVycm9yKGBQbHVnaW4gcmV0dXJuZWQgYSB2YWx1ZSB0aGF0IGRvZXNuJ3QgcmVzZW1ibGUgQVdTIGNyZWRlbnRpYWxzOiAke2luc3BlY3QoaW5pdGlhbCl9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIFYyIGNyZWRlbnRpYWwgaW50byBhIFYzLWNvbXBhdGlibGUgcHJvdmlkZXJcbiAqL1xuZnVuY3Rpb24gdjNQcm92aWRlckZyb21WMkNyZWRlbnRpYWxzKHg6IFNES3YyQ29tcGF0aWJsZUNyZWRlbnRpYWxzKTogQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXIge1xuICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgIC8vIEdldCB3aWxsIGZldGNoIG9yIHJlZnJlc2ggYXMgbmVjZXNzYXJ5XG4gICAgYXdhaXQgeC5nZXRQcm9taXNlKCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWNjZXNzS2V5SWQ6IHguYWNjZXNzS2V5SWQsXG4gICAgICBzZWNyZXRBY2Nlc3NLZXk6IHguc2VjcmV0QWNjZXNzS2V5LFxuICAgICAgc2Vzc2lvblRva2VuOiB4LnNlc3Npb25Ub2tlbixcbiAgICAgIGV4cGlyYXRpb246IHguZXhwaXJlVGltZSA/PyB1bmRlZmluZWQsXG4gICAgfTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVmcmVzaEZyb21QbHVnaW5Qcm92aWRlcihjdXJyZW50OiBBd3NDcmVkZW50aWFsSWRlbnRpdHksIHByb2R1Y2VyOiAoKSA9PiBQcm9taXNlPFBsdWdpblByb3ZpZGVyUmVzdWx0Pik6IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyIHtcbiAgcmV0dXJuIGFzeW5jICgpID0+IHtcbiAgICBpZiAoY3JlZGVudGlhbHNBYm91dFRvRXhwaXJlKGN1cnJlbnQpKSB7XG4gICAgICBjb25zdCBuZXdDcmVkcyA9IGF3YWl0IHByb2R1Y2VyKCk7XG4gICAgICBpZiAoIWlzVjNDcmVkZW50aWFscyhuZXdDcmVkcykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEF1dGhlbnRpY2F0aW9uRXJyb3IoYFBsdWdpbiBpbml0aWFsbHkgcmV0dXJuZWQgc3RhdGljIFYzIGNyZWRlbnRpYWxzIGJ1dCBub3cgcmV0dXJuZWQgc29tZXRoaW5nIGVsc2U6ICR7aW5zcGVjdChuZXdDcmVkcyl9YCk7XG4gICAgICB9XG4gICAgICBjdXJyZW50ID0gbmV3Q3JlZHM7XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50O1xuICB9O1xufVxuXG5mdW5jdGlvbiBpc1YzUHJvdmlkZXIoeDogUGx1Z2luUHJvdmlkZXJSZXN1bHQpOiB4IGlzIFNES3YzQ29tcGF0aWJsZUNyZWRlbnRpYWxQcm92aWRlciB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNWMkNyZWRlbnRpYWxzKHg6IFBsdWdpblByb3ZpZGVyUmVzdWx0KTogeCBpcyBTREt2MkNvbXBhdGlibGVDcmVkZW50aWFscyB7XG4gIHJldHVybiAhISh4ICYmIHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiAoeCBhcyBTREt2MkNvbXBhdGlibGVDcmVkZW50aWFscykuZ2V0UHJvbWlzZSk7XG59XG5cbmZ1bmN0aW9uIGlzVjNDcmVkZW50aWFscyh4OiBQbHVnaW5Qcm92aWRlclJlc3VsdCk6IHggaXMgU0RLdjNDb21wYXRpYmxlQ3JlZGVudGlhbHMge1xuICByZXR1cm4gISEoeCAmJiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgJiYgeC5hY2Nlc3NLZXlJZCAmJiAhaXNWMkNyZWRlbnRpYWxzKHgpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.d.ts new file mode 100644 index 000000000..73dc4914e --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.d.ts @@ -0,0 +1,11 @@ +export * from './proxy-agent'; +export * from './sdk'; +export * from './sdk-provider'; +export * from './sdk-logger'; +export { AccountAccessKeyCache } from './account-cache'; +export { cached } from './cached'; +export { AwsCliCompatible } from './awscli-compatible'; +export { setSdkTracing } from './tracing'; +export { CredentialPlugins } from './credential-plugins'; +export { credentialsAboutToExpire } from './provider-caching'; +export { defaultCliUserAgent } from './user-agent'; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.js new file mode 100644 index 000000000..8570a0995 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/index.js @@ -0,0 +1,37 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.defaultCliUserAgent = exports.credentialsAboutToExpire = exports.CredentialPlugins = exports.setSdkTracing = exports.AwsCliCompatible = exports.cached = exports.AccountAccessKeyCache = void 0; +__exportStar(require("./proxy-agent"), exports); +__exportStar(require("./sdk"), exports); +__exportStar(require("./sdk-provider"), exports); +__exportStar(require("./sdk-logger"), exports); +// temporary testing exports +var account_cache_1 = require("./account-cache"); +Object.defineProperty(exports, "AccountAccessKeyCache", { enumerable: true, get: function () { return account_cache_1.AccountAccessKeyCache; } }); +var cached_1 = require("./cached"); +Object.defineProperty(exports, "cached", { enumerable: true, get: function () { return cached_1.cached; } }); +var awscli_compatible_1 = require("./awscli-compatible"); +Object.defineProperty(exports, "AwsCliCompatible", { enumerable: true, get: function () { return awscli_compatible_1.AwsCliCompatible; } }); +var tracing_1 = require("./tracing"); +Object.defineProperty(exports, "setSdkTracing", { enumerable: true, get: function () { return tracing_1.setSdkTracing; } }); +var credential_plugins_1 = require("./credential-plugins"); +Object.defineProperty(exports, "CredentialPlugins", { enumerable: true, get: function () { return credential_plugins_1.CredentialPlugins; } }); +var provider_caching_1 = require("./provider-caching"); +Object.defineProperty(exports, "credentialsAboutToExpire", { enumerable: true, get: function () { return provider_caching_1.credentialsAboutToExpire; } }); +var user_agent_1 = require("./user-agent"); +Object.defineProperty(exports, "defaultCliUserAgent", { enumerable: true, get: function () { return user_agent_1.defaultCliUserAgent; } }); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2F3cy1hdXRoL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0RBQThCO0FBQzlCLHdDQUFzQjtBQUN0QixpREFBK0I7QUFDL0IsK0NBQTZCO0FBRTdCLDRCQUE0QjtBQUM1QixpREFBd0Q7QUFBL0Msc0hBQUEscUJBQXFCLE9BQUE7QUFDOUIsbUNBQWtDO0FBQXpCLGdHQUFBLE1BQU0sT0FBQTtBQUNmLHlEQUF1RDtBQUE5QyxxSEFBQSxnQkFBZ0IsT0FBQTtBQUN6QixxQ0FBMEM7QUFBakMsd0dBQUEsYUFBYSxPQUFBO0FBQ3RCLDJEQUF5RDtBQUFoRCx1SEFBQSxpQkFBaUIsT0FBQTtBQUMxQix1REFBOEQ7QUFBckQsNEhBQUEsd0JBQXdCLE9BQUE7QUFDakMsMkNBQW1EO0FBQTFDLGlIQUFBLG1CQUFtQixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9wcm94eS1hZ2VudCc7XG5leHBvcnQgKiBmcm9tICcuL3Nkayc7XG5leHBvcnQgKiBmcm9tICcuL3Nkay1wcm92aWRlcic7XG5leHBvcnQgKiBmcm9tICcuL3Nkay1sb2dnZXInO1xuXG4vLyB0ZW1wb3JhcnkgdGVzdGluZyBleHBvcnRzXG5leHBvcnQgeyBBY2NvdW50QWNjZXNzS2V5Q2FjaGUgfSBmcm9tICcuL2FjY291bnQtY2FjaGUnO1xuZXhwb3J0IHsgY2FjaGVkIH0gZnJvbSAnLi9jYWNoZWQnO1xuZXhwb3J0IHsgQXdzQ2xpQ29tcGF0aWJsZSB9IGZyb20gJy4vYXdzY2xpLWNvbXBhdGlibGUnO1xuZXhwb3J0IHsgc2V0U2RrVHJhY2luZyB9IGZyb20gJy4vdHJhY2luZyc7XG5leHBvcnQgeyBDcmVkZW50aWFsUGx1Z2lucyB9IGZyb20gJy4vY3JlZGVudGlhbC1wbHVnaW5zJztcbmV4cG9ydCB7IGNyZWRlbnRpYWxzQWJvdXRUb0V4cGlyZSB9IGZyb20gJy4vcHJvdmlkZXItY2FjaGluZyc7XG5leHBvcnQgeyBkZWZhdWx0Q2xpVXNlckFnZW50IH0gZnJvbSAnLi91c2VyLWFnZW50JztcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.d.ts new file mode 100644 index 000000000..4ebe73b28 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.d.ts @@ -0,0 +1,13 @@ +import type { AwsCredentialIdentity, AwsCredentialIdentityProvider } from '@smithy/types'; +/** + * Wrap a credential provider in a cache + * + * Some credential providers in the SDKv3 are cached (the default Node + * chain, specifically) but most others are not. + * + * Since we want to avoid duplicate calls to `AssumeRole`, or duplicate + * MFA prompts or what have you, we are going to liberally wrap providers + * in caches which will return the cached value until it expires. + */ +export declare function makeCachingProvider(provider: AwsCredentialIdentityProvider): AwsCredentialIdentityProvider; +export declare function credentialsAboutToExpire(token: AwsCredentialIdentity): boolean; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.js new file mode 100644 index 000000000..5e3deb195 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/provider-caching.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.makeCachingProvider = makeCachingProvider; +exports.credentialsAboutToExpire = credentialsAboutToExpire; +const property_provider_1 = require("@smithy/property-provider"); +/** + * Wrap a credential provider in a cache + * + * Some credential providers in the SDKv3 are cached (the default Node + * chain, specifically) but most others are not. + * + * Since we want to avoid duplicate calls to `AssumeRole`, or duplicate + * MFA prompts or what have you, we are going to liberally wrap providers + * in caches which will return the cached value until it expires. + */ +function makeCachingProvider(provider) { + return (0, property_provider_1.memoize)(provider, credentialsAboutToExpire, (token) => !!token.expiration); +} +function credentialsAboutToExpire(token) { + const expiryMarginSecs = 5; + // token.expiration is sometimes null + return !!token.expiration && token.expiration.getTime() - Date.now() < expiryMarginSecs * 1000; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXItY2FjaGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvYXdzLWF1dGgvcHJvdmlkZXItY2FjaGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWFBLGtEQU1DO0FBRUQsNERBSUM7QUF6QkQsaUVBQW9EO0FBR3BEOzs7Ozs7Ozs7R0FTRztBQUNILFNBQWdCLG1CQUFtQixDQUFDLFFBQXVDO0lBQ3pFLE9BQU8sSUFBQSwyQkFBTyxFQUNaLFFBQVEsRUFDUix3QkFBd0IsRUFDeEIsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUM5QixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQWdCLHdCQUF3QixDQUFDLEtBQTRCO0lBQ25FLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLHFDQUFxQztJQUNyQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBVSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLGdCQUFnQixHQUFHLElBQUksQ0FBQztBQUNqRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbWVtb2l6ZSB9IGZyb20gJ0BzbWl0aHkvcHJvcGVydHktcHJvdmlkZXInO1xuaW1wb3J0IHR5cGUgeyBBd3NDcmVkZW50aWFsSWRlbnRpdHksIEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyIH0gZnJvbSAnQHNtaXRoeS90eXBlcyc7XG5cbi8qKlxuICogV3JhcCBhIGNyZWRlbnRpYWwgcHJvdmlkZXIgaW4gYSBjYWNoZVxuICpcbiAqIFNvbWUgY3JlZGVudGlhbCBwcm92aWRlcnMgaW4gdGhlIFNES3YzIGFyZSBjYWNoZWQgKHRoZSBkZWZhdWx0IE5vZGVcbiAqIGNoYWluLCBzcGVjaWZpY2FsbHkpIGJ1dCBtb3N0IG90aGVycyBhcmUgbm90LlxuICpcbiAqIFNpbmNlIHdlIHdhbnQgdG8gYXZvaWQgZHVwbGljYXRlIGNhbGxzIHRvIGBBc3N1bWVSb2xlYCwgb3IgZHVwbGljYXRlXG4gKiBNRkEgcHJvbXB0cyBvciB3aGF0IGhhdmUgeW91LCB3ZSBhcmUgZ29pbmcgdG8gbGliZXJhbGx5IHdyYXAgcHJvdmlkZXJzXG4gKiBpbiBjYWNoZXMgd2hpY2ggd2lsbCByZXR1cm4gdGhlIGNhY2hlZCB2YWx1ZSB1bnRpbCBpdCBleHBpcmVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbWFrZUNhY2hpbmdQcm92aWRlcihwcm92aWRlcjogQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXIpOiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlciB7XG4gIHJldHVybiBtZW1vaXplKFxuICAgIHByb3ZpZGVyLFxuICAgIGNyZWRlbnRpYWxzQWJvdXRUb0V4cGlyZSxcbiAgICAodG9rZW4pID0+ICEhdG9rZW4uZXhwaXJhdGlvbixcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWRlbnRpYWxzQWJvdXRUb0V4cGlyZSh0b2tlbjogQXdzQ3JlZGVudGlhbElkZW50aXR5KSB7XG4gIGNvbnN0IGV4cGlyeU1hcmdpblNlY3MgPSA1O1xuICAvLyB0b2tlbi5leHBpcmF0aW9uIGlzIHNvbWV0aW1lcyBudWxsXG4gIHJldHVybiAhIXRva2VuLmV4cGlyYXRpb24gJiYgdG9rZW4uZXhwaXJhdGlvbi5nZXRUaW1lKCkgLSBEYXRlLm5vdygpIDwgZXhwaXJ5TWFyZ2luU2VjcyAqIDEwMDA7XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.d.ts new file mode 100644 index 000000000..135969d05 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.d.ts @@ -0,0 +1,13 @@ +import { ProxyAgent } from 'proxy-agent'; +import type { SdkHttpOptions } from './sdk-provider'; +import { type IoHelper } from '../io/private'; +export declare class ProxyAgentProvider { + private readonly ioHelper; + constructor(ioHelper: IoHelper); + create(options: SdkHttpOptions): Promise; + private tryGetCACert; + /** + * Find and return a CA certificate bundle path to be passed into the SDK. + */ + private caBundlePathFromEnvironment; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.js new file mode 100644 index 000000000..01beda351 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/proxy-agent.js @@ -0,0 +1,54 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ProxyAgentProvider = void 0; +const fs = require("fs-extra"); +const proxy_agent_1 = require("proxy-agent"); +const private_1 = require("../io/private"); +class ProxyAgentProvider { + ioHelper; + constructor(ioHelper) { + this.ioHelper = ioHelper; + } + async create(options) { + // Force it to use the proxy provided through the command line. + // Otherwise, let the ProxyAgent auto-detect the proxy using environment variables. + const getProxyForUrl = options.proxyAddress != null + ? () => Promise.resolve(options.proxyAddress) + : undefined; + return new proxy_agent_1.ProxyAgent({ + ca: await this.tryGetCACert(options.caBundlePath), + getProxyForUrl, + }); + } + async tryGetCACert(bundlePath) { + const path = bundlePath || this.caBundlePathFromEnvironment(); + if (path) { + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(`Using CA bundle path: ${path}`)); + try { + if (!fs.pathExistsSync(path)) { + return undefined; + } + return fs.readFileSync(path, { encoding: 'utf-8' }); + } + catch (e) { + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(String(e))); + return undefined; + } + } + return undefined; + } + /** + * Find and return a CA certificate bundle path to be passed into the SDK. + */ + caBundlePathFromEnvironment() { + if (process.env.aws_ca_bundle) { + return process.env.aws_ca_bundle; + } + if (process.env.AWS_CA_BUNDLE) { + return process.env.AWS_CA_BUNDLE; + } + return undefined; + } +} +exports.ProxyAgentProvider = ProxyAgentProvider; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJveHktYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2F3cy1hdXRoL3Byb3h5LWFnZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtCQUErQjtBQUMvQiw2Q0FBeUM7QUFFekMsMkNBQWtEO0FBRWxELE1BQWEsa0JBQWtCO0lBQ1osUUFBUSxDQUFXO0lBRXBDLFlBQW1CLFFBQWtCO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzNCLENBQUM7SUFFTSxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQXVCO1FBQ3pDLCtEQUErRDtRQUMvRCxtRkFBbUY7UUFDbkYsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLFlBQVksSUFBSSxJQUFJO1lBQ2pELENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxZQUFhLENBQUM7WUFDOUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUVkLE9BQU8sSUFBSSx3QkFBVSxDQUFDO1lBQ3BCLEVBQUUsRUFBRSxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQztZQUNqRCxjQUFjO1NBQ2YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxZQUFZLENBQUMsVUFBbUI7UUFDNUMsTUFBTSxJQUFJLEdBQUcsVUFBVSxJQUFJLElBQUksQ0FBQywyQkFBMkIsRUFBRSxDQUFDO1FBQzlELElBQUksSUFBSSxFQUFFLENBQUM7WUFDVCxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFlBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMseUJBQXlCLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN0RixJQUFJLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDN0IsT0FBTyxTQUFTLENBQUM7Z0JBQ25CLENBQUM7Z0JBQ0QsT0FBTyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3RELENBQUM7WUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFlBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDaEUsT0FBTyxTQUFTLENBQUM7WUFDbkIsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQ7O09BRUc7SUFDSywyQkFBMkI7UUFDakMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzlCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7UUFDbkMsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM5QixPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO1FBQ25DLENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0NBQ0Y7QUFqREQsZ0RBaURDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IHsgUHJveHlBZ2VudCB9IGZyb20gJ3Byb3h5LWFnZW50JztcbmltcG9ydCB0eXBlIHsgU2RrSHR0cE9wdGlvbnMgfSBmcm9tICcuL3Nkay1wcm92aWRlcic7XG5pbXBvcnQgeyBJTywgdHlwZSBJb0hlbHBlciB9IGZyb20gJy4uL2lvL3ByaXZhdGUnO1xuXG5leHBvcnQgY2xhc3MgUHJveHlBZ2VudFByb3ZpZGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBpb0hlbHBlcjogSW9IZWxwZXI7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKGlvSGVscGVyOiBJb0hlbHBlcikge1xuICAgIHRoaXMuaW9IZWxwZXIgPSBpb0hlbHBlcjtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjcmVhdGUob3B0aW9uczogU2RrSHR0cE9wdGlvbnMpIHtcbiAgICAvLyBGb3JjZSBpdCB0byB1c2UgdGhlIHByb3h5IHByb3ZpZGVkIHRocm91Z2ggdGhlIGNvbW1hbmQgbGluZS5cbiAgICAvLyBPdGhlcndpc2UsIGxldCB0aGUgUHJveHlBZ2VudCBhdXRvLWRldGVjdCB0aGUgcHJveHkgdXNpbmcgZW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgIGNvbnN0IGdldFByb3h5Rm9yVXJsID0gb3B0aW9ucy5wcm94eUFkZHJlc3MgIT0gbnVsbFxuICAgICAgPyAoKSA9PiBQcm9taXNlLnJlc29sdmUob3B0aW9ucy5wcm94eUFkZHJlc3MhKVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gbmV3IFByb3h5QWdlbnQoe1xuICAgICAgY2E6IGF3YWl0IHRoaXMudHJ5R2V0Q0FDZXJ0KG9wdGlvbnMuY2FCdW5kbGVQYXRoKSxcbiAgICAgIGdldFByb3h5Rm9yVXJsLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB0cnlHZXRDQUNlcnQoYnVuZGxlUGF0aD86IHN0cmluZykge1xuICAgIGNvbnN0IHBhdGggPSBidW5kbGVQYXRoIHx8IHRoaXMuY2FCdW5kbGVQYXRoRnJvbUVudmlyb25tZW50KCk7XG4gICAgaWYgKHBhdGgpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfU0RLX0RFQlVHLm1zZyhgVXNpbmcgQ0EgYnVuZGxlIHBhdGg6ICR7cGF0aH1gKSk7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIWZzLnBhdGhFeGlzdHNTeW5jKHBhdGgpKSB7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnMucmVhZEZpbGVTeW5jKHBhdGgsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSk7XG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9TREtfREVCVUcubXNnKFN0cmluZyhlKSkpO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmQgYW5kIHJldHVybiBhIENBIGNlcnRpZmljYXRlIGJ1bmRsZSBwYXRoIHRvIGJlIHBhc3NlZCBpbnRvIHRoZSBTREsuXG4gICAqL1xuICBwcml2YXRlIGNhQnVuZGxlUGF0aEZyb21FbnZpcm9ubWVudCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmIChwcm9jZXNzLmVudi5hd3NfY2FfYnVuZGxlKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5lbnYuYXdzX2NhX2J1bmRsZTtcbiAgICB9XG4gICAgaWYgKHByb2Nlc3MuZW52LkFXU19DQV9CVU5ETEUpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmVudi5BV1NfQ0FfQlVORExFO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.d.ts new file mode 100644 index 000000000..6191f83c8 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.d.ts @@ -0,0 +1,69 @@ +import type { Logger } from '@smithy/types'; +import type { IoHelper } from '../io/private'; +export declare class SdkToCliLogger implements Logger { + private readonly ioHelper; + constructor(ioHelper: IoHelper); + private notify; + trace(..._content: any[]): void; + debug(..._content: any[]): void; + /** + * Info is called mostly (exclusively?) for successful API calls + * + * Payload: + * + * (Note the input contains entire CFN templates, for example) + * + * ``` + * { + * clientName: 'S3Client', + * commandName: 'GetBucketLocationCommand', + * input: { + * Bucket: '.....', + * ExpectedBucketOwner: undefined + * }, + * output: { LocationConstraint: 'eu-central-1' }, + * metadata: { + * httpStatusCode: 200, + * requestId: '....', + * extendedRequestId: '...', + * cfId: undefined, + * attempts: 1, + * totalRetryDelay: 0 + * } + * } + * ``` + */ + info(...content: any[]): void; + warn(...content: any[]): void; + /** + * Error is called mostly (exclusively?) for failing API calls + * + * Payload (input would be the entire API call arguments). + * + * ``` + * { + * clientName: 'STSClient', + * commandName: 'GetCallerIdentityCommand', + * input: {}, + * error: AggregateError [ECONNREFUSED]: + * at internalConnectMultiple (node:net:1121:18) + * at afterConnectMultiple (node:net:1688:7) { + * code: 'ECONNREFUSED', + * '$metadata': { attempts: 3, totalRetryDelay: 600 }, + * [errors]: [ [Error], [Error] ] + * }, + * metadata: { attempts: 3, totalRetryDelay: 600 } + * } + * ``` + */ + error(...content: any[]): void; +} +/** + * This can be anything. + * + * For debug, it seems to be mostly strings. + * For info, it seems to be objects. + * + * Stringify and join without separator. + */ +export declare function formatSdkLoggerContent(content: any[]): string; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.js new file mode 100644 index 000000000..463117416 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-logger.js @@ -0,0 +1,128 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SdkToCliLogger = void 0; +exports.formatSdkLoggerContent = formatSdkLoggerContent; +const util_1 = require("util"); +const util_2 = require("../../util"); +const private_1 = require("../io/private"); +class SdkToCliLogger { + ioHelper; + constructor(ioHelper) { + this.ioHelper = ioHelper; + } + notify(level, ...content) { + void this.ioHelper.notify(private_1.IO.CDK_SDK_I0100.msg((0, util_1.format)('[SDK %s] %s', level, formatSdkLoggerContent(content)), { + sdkLevel: level, + content, + })); + } + trace(..._content) { + // This is too much detail for our logs + // this.notify('trace', ...content); + } + debug(..._content) { + // This is too much detail for our logs + // this.notify('debug', ...content); + } + /** + * Info is called mostly (exclusively?) for successful API calls + * + * Payload: + * + * (Note the input contains entire CFN templates, for example) + * + * ``` + * { + * clientName: 'S3Client', + * commandName: 'GetBucketLocationCommand', + * input: { + * Bucket: '.....', + * ExpectedBucketOwner: undefined + * }, + * output: { LocationConstraint: 'eu-central-1' }, + * metadata: { + * httpStatusCode: 200, + * requestId: '....', + * extendedRequestId: '...', + * cfId: undefined, + * attempts: 1, + * totalRetryDelay: 0 + * } + * } + * ``` + */ + info(...content) { + this.notify('info', ...content); + } + warn(...content) { + this.notify('warn', ...content); + } + /** + * Error is called mostly (exclusively?) for failing API calls + * + * Payload (input would be the entire API call arguments). + * + * ``` + * { + * clientName: 'STSClient', + * commandName: 'GetCallerIdentityCommand', + * input: {}, + * error: AggregateError [ECONNREFUSED]: + * at internalConnectMultiple (node:net:1121:18) + * at afterConnectMultiple (node:net:1688:7) { + * code: 'ECONNREFUSED', + * '$metadata': { attempts: 3, totalRetryDelay: 600 }, + * [errors]: [ [Error], [Error] ] + * }, + * metadata: { attempts: 3, totalRetryDelay: 600 } + * } + * ``` + */ + error(...content) { + this.notify('error', ...content); + } +} +exports.SdkToCliLogger = SdkToCliLogger; +/** + * This can be anything. + * + * For debug, it seems to be mostly strings. + * For info, it seems to be objects. + * + * Stringify and join without separator. + */ +function formatSdkLoggerContent(content) { + if (content.length === 1) { + const apiFmt = formatApiCall(content[0]); + if (apiFmt) { + return apiFmt; + } + } + return content.map((x) => typeof x === 'string' ? x : (0, util_1.inspect)(x)).join(''); +} +function formatApiCall(content) { + if (!isSdkApiCallSuccess(content) && !isSdkApiCallError(content)) { + return undefined; + } + const service = content.clientName.replace(/Client$/, ''); + const api = content.commandName.replace(/Command$/, ''); + const parts = []; + if ((content.metadata?.attempts ?? 0) > 1) { + parts.push(`[${content.metadata?.attempts} attempts, ${content.metadata?.totalRetryDelay}ms retry]`); + } + parts.push(`${service}.${api}(${JSON.stringify(content.input, util_2.replacerBufferWithInfo)})`); + if (isSdkApiCallSuccess(content)) { + parts.push('-> OK'); + } + else { + parts.push(`-> ${content.error}`); + } + return parts.join(' '); +} +function isSdkApiCallSuccess(x) { + return x && typeof x === 'object' && x.commandName && x.output; +} +function isSdkApiCallError(x) { + return x && typeof x === 'object' && x.commandName && x.error; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2RrLWxvZ2dlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvYXdzLWF1dGgvc2RrLWxvZ2dlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFtR0Esd0RBUUM7QUEzR0QsK0JBQXVDO0FBRXZDLHFDQUFvRDtBQUVwRCwyQ0FBbUM7QUFFbkMsTUFBYSxjQUFjO0lBQ1IsUUFBUSxDQUFXO0lBRXBDLFlBQW1CLFFBQWtCO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzNCLENBQUM7SUFFTyxNQUFNLENBQUMsS0FBZ0MsRUFBRSxHQUFHLE9BQWM7UUFDaEUsS0FBSyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxZQUFFLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxJQUFBLGFBQU0sRUFBQyxhQUFhLEVBQUUsS0FBSyxFQUFFLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUU7WUFDNUcsUUFBUSxFQUFFLEtBQUs7WUFDZixPQUFPO1NBQ1IsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBRU0sS0FBSyxDQUFDLEdBQUcsUUFBZTtRQUM3Qix1Q0FBdUM7UUFDdkMsb0NBQW9DO0lBQ3RDLENBQUM7SUFFTSxLQUFLLENBQUMsR0FBRyxRQUFlO1FBQzdCLHVDQUF1QztRQUN2QyxvQ0FBb0M7SUFDdEMsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQTBCRztJQUNJLElBQUksQ0FBQyxHQUFHLE9BQWM7UUFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRU0sSUFBSSxDQUFDLEdBQUcsT0FBYztRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FvQkc7SUFDSSxLQUFLLENBQUMsR0FBRyxPQUFjO1FBQzVCLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLENBQUM7SUFDbkMsQ0FBQztDQUNGO0FBbkZELHdDQW1GQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixzQkFBc0IsQ0FBQyxPQUFjO0lBQ25ELElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN6QixNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekMsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNYLE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBQSxjQUFPLEVBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDN0UsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLE9BQVk7SUFDakMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNqRSxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzFELE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUV4RCxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDakIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFLFFBQVEsY0FBYyxPQUFPLENBQUMsUUFBUSxFQUFFLGVBQWUsV0FBVyxDQUFDLENBQUM7SUFDdkcsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxPQUFPLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSw2QkFBc0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUUxRixJQUFJLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDakMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0QixDQUFDO1NBQU0sQ0FBQztRQUNOLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3pCLENBQUM7QUFtQkQsU0FBUyxtQkFBbUIsQ0FBQyxDQUFNO0lBQ2pDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsV0FBVyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUM7QUFDakUsQ0FBQztBQUVELFNBQVMsaUJBQWlCLENBQUMsQ0FBTTtJQUMvQixPQUFPLENBQUMsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDO0FBQ2hFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbnNwZWN0LCBmb3JtYXQgfSBmcm9tICd1dGlsJztcbmltcG9ydCB0eXBlIHsgTG9nZ2VyIH0gZnJvbSAnQHNtaXRoeS90eXBlcyc7XG5pbXBvcnQgeyByZXBsYWNlckJ1ZmZlcldpdGhJbmZvIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgdHlwZSB7IElvSGVscGVyIH0gZnJvbSAnLi4vaW8vcHJpdmF0ZSc7XG5pbXBvcnQgeyBJTyB9IGZyb20gJy4uL2lvL3ByaXZhdGUnO1xuXG5leHBvcnQgY2xhc3MgU2RrVG9DbGlMb2dnZXIgaW1wbGVtZW50cyBMb2dnZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGlvSGVscGVyOiBJb0hlbHBlcjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoaW9IZWxwZXI6IElvSGVscGVyKSB7XG4gICAgdGhpcy5pb0hlbHBlciA9IGlvSGVscGVyO1xuICB9XG5cbiAgcHJpdmF0ZSBub3RpZnkobGV2ZWw6ICdpbmZvJyB8ICd3YXJuJyB8ICdlcnJvcicsIC4uLmNvbnRlbnQ6IGFueVtdKSB7XG4gICAgdm9pZCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5DREtfU0RLX0kwMTAwLm1zZyhmb3JtYXQoJ1tTREsgJXNdICVzJywgbGV2ZWwsIGZvcm1hdFNka0xvZ2dlckNvbnRlbnQoY29udGVudCkpLCB7XG4gICAgICBzZGtMZXZlbDogbGV2ZWwsXG4gICAgICBjb250ZW50LFxuICAgIH0pKTtcbiAgfVxuXG4gIHB1YmxpYyB0cmFjZSguLi5fY29udGVudDogYW55W10pIHtcbiAgICAvLyBUaGlzIGlzIHRvbyBtdWNoIGRldGFpbCBmb3Igb3VyIGxvZ3NcbiAgICAvLyB0aGlzLm5vdGlmeSgndHJhY2UnLCAuLi5jb250ZW50KTtcbiAgfVxuXG4gIHB1YmxpYyBkZWJ1ZyguLi5fY29udGVudDogYW55W10pIHtcbiAgICAvLyBUaGlzIGlzIHRvbyBtdWNoIGRldGFpbCBmb3Igb3VyIGxvZ3NcbiAgICAvLyB0aGlzLm5vdGlmeSgnZGVidWcnLCAuLi5jb250ZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbmZvIGlzIGNhbGxlZCBtb3N0bHkgKGV4Y2x1c2l2ZWx5PykgZm9yIHN1Y2Nlc3NmdWwgQVBJIGNhbGxzXG4gICAqXG4gICAqIFBheWxvYWQ6XG4gICAqXG4gICAqIChOb3RlIHRoZSBpbnB1dCBjb250YWlucyBlbnRpcmUgQ0ZOIHRlbXBsYXRlcywgZm9yIGV4YW1wbGUpXG4gICAqXG4gICAqIGBgYFxuICAgKiB7XG4gICAqICAgY2xpZW50TmFtZTogJ1MzQ2xpZW50JyxcbiAgICogICBjb21tYW5kTmFtZTogJ0dldEJ1Y2tldExvY2F0aW9uQ29tbWFuZCcsXG4gICAqICAgaW5wdXQ6IHtcbiAgICogICAgIEJ1Y2tldDogJy4uLi4uJyxcbiAgICogICAgIEV4cGVjdGVkQnVja2V0T3duZXI6IHVuZGVmaW5lZFxuICAgKiAgIH0sXG4gICAqICAgb3V0cHV0OiB7IExvY2F0aW9uQ29uc3RyYWludDogJ2V1LWNlbnRyYWwtMScgfSxcbiAgICogICBtZXRhZGF0YToge1xuICAgKiAgICAgaHR0cFN0YXR1c0NvZGU6IDIwMCxcbiAgICogICAgIHJlcXVlc3RJZDogJy4uLi4nLFxuICAgKiAgICAgZXh0ZW5kZWRSZXF1ZXN0SWQ6ICcuLi4nLFxuICAgKiAgICAgY2ZJZDogdW5kZWZpbmVkLFxuICAgKiAgICAgYXR0ZW1wdHM6IDEsXG4gICAqICAgICB0b3RhbFJldHJ5RGVsYXk6IDBcbiAgICogICB9XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBwdWJsaWMgaW5mbyguLi5jb250ZW50OiBhbnlbXSkge1xuICAgIHRoaXMubm90aWZ5KCdpbmZvJywgLi4uY29udGVudCk7XG4gIH1cblxuICBwdWJsaWMgd2FybiguLi5jb250ZW50OiBhbnlbXSkge1xuICAgIHRoaXMubm90aWZ5KCd3YXJuJywgLi4uY29udGVudCk7XG4gIH1cblxuICAvKipcbiAgICogRXJyb3IgaXMgY2FsbGVkIG1vc3RseSAoZXhjbHVzaXZlbHk/KSBmb3IgZmFpbGluZyBBUEkgY2FsbHNcbiAgICpcbiAgICogUGF5bG9hZCAoaW5wdXQgd291bGQgYmUgdGhlIGVudGlyZSBBUEkgY2FsbCBhcmd1bWVudHMpLlxuICAgKlxuICAgKiBgYGBcbiAgICoge1xuICAgKiAgIGNsaWVudE5hbWU6ICdTVFNDbGllbnQnLFxuICAgKiAgIGNvbW1hbmROYW1lOiAnR2V0Q2FsbGVySWRlbnRpdHlDb21tYW5kJyxcbiAgICogICBpbnB1dDoge30sXG4gICAqICAgZXJyb3I6IEFnZ3JlZ2F0ZUVycm9yIFtFQ09OTlJFRlVTRURdOlxuICAgKiAgICAgICBhdCBpbnRlcm5hbENvbm5lY3RNdWx0aXBsZSAobm9kZTpuZXQ6MTEyMToxOClcbiAgICogICAgICAgYXQgYWZ0ZXJDb25uZWN0TXVsdGlwbGUgKG5vZGU6bmV0OjE2ODg6Nykge1xuICAgKiAgICAgY29kZTogJ0VDT05OUkVGVVNFRCcsXG4gICAqICAgICAnJG1ldGFkYXRhJzogeyBhdHRlbXB0czogMywgdG90YWxSZXRyeURlbGF5OiA2MDAgfSxcbiAgICogICAgIFtlcnJvcnNdOiBbIFtFcnJvcl0sIFtFcnJvcl0gXVxuICAgKiAgIH0sXG4gICAqICAgbWV0YWRhdGE6IHsgYXR0ZW1wdHM6IDMsIHRvdGFsUmV0cnlEZWxheTogNjAwIH1cbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIHB1YmxpYyBlcnJvciguLi5jb250ZW50OiBhbnlbXSkge1xuICAgIHRoaXMubm90aWZ5KCdlcnJvcicsIC4uLmNvbnRlbnQpO1xuICB9XG59XG5cbi8qKlxuICogVGhpcyBjYW4gYmUgYW55dGhpbmcuXG4gKlxuICogRm9yIGRlYnVnLCBpdCBzZWVtcyB0byBiZSBtb3N0bHkgc3RyaW5ncy5cbiAqIEZvciBpbmZvLCBpdCBzZWVtcyB0byBiZSBvYmplY3RzLlxuICpcbiAqIFN0cmluZ2lmeSBhbmQgam9pbiB3aXRob3V0IHNlcGFyYXRvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFNka0xvZ2dlckNvbnRlbnQoY29udGVudDogYW55W10pIHtcbiAgaWYgKGNvbnRlbnQubGVuZ3RoID09PSAxKSB7XG4gICAgY29uc3QgYXBpRm10ID0gZm9ybWF0QXBpQ2FsbChjb250ZW50WzBdKTtcbiAgICBpZiAoYXBpRm10KSB7XG4gICAgICByZXR1cm4gYXBpRm10O1xuICAgIH1cbiAgfVxuICByZXR1cm4gY29udGVudC5tYXAoKHgpID0+IHR5cGVvZiB4ID09PSAnc3RyaW5nJyA/IHggOiBpbnNwZWN0KHgpKS5qb2luKCcnKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0QXBpQ2FsbChjb250ZW50OiBhbnkpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIWlzU2RrQXBpQ2FsbFN1Y2Nlc3MoY29udGVudCkgJiYgIWlzU2RrQXBpQ2FsbEVycm9yKGNvbnRlbnQpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IHNlcnZpY2UgPSBjb250ZW50LmNsaWVudE5hbWUucmVwbGFjZSgvQ2xpZW50JC8sICcnKTtcbiAgY29uc3QgYXBpID0gY29udGVudC5jb21tYW5kTmFtZS5yZXBsYWNlKC9Db21tYW5kJC8sICcnKTtcblxuICBjb25zdCBwYXJ0cyA9IFtdO1xuICBpZiAoKGNvbnRlbnQubWV0YWRhdGE/LmF0dGVtcHRzID8/IDApID4gMSkge1xuICAgIHBhcnRzLnB1c2goYFske2NvbnRlbnQubWV0YWRhdGE/LmF0dGVtcHRzfSBhdHRlbXB0cywgJHtjb250ZW50Lm1ldGFkYXRhPy50b3RhbFJldHJ5RGVsYXl9bXMgcmV0cnldYCk7XG4gIH1cblxuICBwYXJ0cy5wdXNoKGAke3NlcnZpY2V9LiR7YXBpfSgke0pTT04uc3RyaW5naWZ5KGNvbnRlbnQuaW5wdXQsIHJlcGxhY2VyQnVmZmVyV2l0aEluZm8pfSlgKTtcblxuICBpZiAoaXNTZGtBcGlDYWxsU3VjY2Vzcyhjb250ZW50KSkge1xuICAgIHBhcnRzLnB1c2goJy0+IE9LJyk7XG4gIH0gZWxzZSB7XG4gICAgcGFydHMucHVzaChgLT4gJHtjb250ZW50LmVycm9yfWApO1xuICB9XG5cbiAgcmV0dXJuIHBhcnRzLmpvaW4oJyAnKTtcbn1cblxuaW50ZXJmYWNlIFNka0FwaUNhbGxCYXNlIHtcbiAgY2xpZW50TmFtZTogc3RyaW5nO1xuICBjb21tYW5kTmFtZTogc3RyaW5nO1xuICBpbnB1dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIG1ldGFkYXRhPzoge1xuICAgIGh0dHBTdGF0dXNDb2RlPzogbnVtYmVyO1xuICAgIHJlcXVlc3RJZD86IHN0cmluZztcbiAgICBleHRlbmRlZFJlcXVlc3RJZD86IHN0cmluZztcbiAgICBjZklkPzogc3RyaW5nO1xuICAgIGF0dGVtcHRzPzogbnVtYmVyO1xuICAgIHRvdGFsUmV0cnlEZWxheT86IG51bWJlcjtcbiAgfTtcbn1cblxudHlwZSBTZGtBcGlDYWxsU3VjY2VzcyA9IFNka0FwaUNhbGxCYXNlICYgeyBvdXRwdXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH07XG50eXBlIFNka0FwaUNhbGxFcnJvciA9IFNka0FwaUNhbGxCYXNlICYgeyBlcnJvcjogRXJyb3IgfTtcblxuZnVuY3Rpb24gaXNTZGtBcGlDYWxsU3VjY2Vzcyh4OiBhbnkpOiB4IGlzIFNka0FwaUNhbGxTdWNjZXNzIHtcbiAgcmV0dXJuIHggJiYgdHlwZW9mIHggPT09ICdvYmplY3QnICYmIHguY29tbWFuZE5hbWUgJiYgeC5vdXRwdXQ7XG59XG5cbmZ1bmN0aW9uIGlzU2RrQXBpQ2FsbEVycm9yKHg6IGFueSk6IHggaXMgU2RrQXBpQ2FsbEVycm9yIHtcbiAgcmV0dXJuIHggJiYgdHlwZW9mIHggPT09ICdvYmplY3QnICYmIHguY29tbWFuZE5hbWUgJiYgeC5lcnJvcjtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.d.ts new file mode 100644 index 000000000..85030a43d --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.d.ts @@ -0,0 +1,229 @@ +import type { ContextLookupRoleOptions } from '@aws-cdk/cloud-assembly-schema'; +import type { Environment } from '@aws-cdk/cx-api'; +import type { AssumeRoleCommandInput } from '@aws-sdk/client-sts'; +import type { NodeHttpHandlerOptions } from '@smithy/node-http-handler'; +import type { AwsCredentialIdentityProvider, Logger } from '@smithy/types'; +import { SDK } from './sdk'; +import { type IoHelper } from '../io/private'; +import { PluginHost, Mode } from '../plugin'; +export type AssumeRoleAdditionalOptions = Partial>; +/** + * Options for the default SDK provider + */ +export interface SdkProviderOptions extends SdkProviderServices { + /** + * Profile to read from ~/.aws + * + * @default - No profile + */ + readonly profile?: string; +} +/** + * Options for individual SDKs + */ +export interface SdkHttpOptions { + /** + * Proxy address to use + * + * @default No proxy + */ + readonly proxyAddress?: string; + /** + * A path to a certificate bundle that contains a cert to be trusted. + * + * @default No certificate bundle + */ + readonly caBundlePath?: string; +} +/** + * SDK configuration for a given environment + * 'forEnvironment' will attempt to assume a role and if it + * is not successful, then it will either: + * 1. Check to see if the default credentials (local credentials the CLI was executed with) + * are for the given environment. If they are then return those. + * 2. If the default credentials are not for the given environment then + * throw an error + * + * 'didAssumeRole' allows callers to whether they are receiving the assume role + * credentials or the default credentials. + */ +export interface SdkForEnvironment { + /** + * The SDK for the given environment + */ + readonly sdk: SDK; + /** + * Whether or not the assume role was successful. + * If the assume role was not successful (false) + * then that means that the 'sdk' returned contains + * the default credentials (not the assume role credentials) + */ + readonly didAssumeRole: boolean; +} +/** + * Creates instances of the AWS SDK appropriate for a given account/region. + * + * Behavior is as follows: + * + * - First, a set of "base" credentials are established + * - If a target environment is given and the default ("current") SDK credentials are for + * that account, return those; otherwise + * - If a target environment is given, scan all credential provider plugins + * for credentials, and return those if found; otherwise + * - Return default ("current") SDK credentials, noting that they might be wrong. + * + * - Second, a role may optionally need to be assumed. Use the base credentials + * established in the previous process to assume that role. + * - If assuming the role fails and the base credentials are for the correct + * account, return those. This is a fallback for people who are trying to interact + * with a Default Synthesized stack and already have right credentials setup. + * + * Typical cases we see in the wild: + * - Credential plugin setup that, although not recommended, works for them + * - Seeded terminal with `ReadOnly` credentials in order to do `cdk diff`--the `ReadOnly` + * role doesn't have `sts:AssumeRole` and will fail for no real good reason. + */ +export declare class SdkProvider { + /** + * Create a new SdkProvider which gets its defaults in a way that behaves like the AWS CLI does + * + * The AWS SDK for JS behaves slightly differently from the AWS CLI in a number of ways; see the + * class `AwsCliCompatible` for the details. + */ + static withAwsCliCompatibleDefaults(options: SdkProviderOptions): Promise; + readonly defaultRegion: string; + private readonly defaultCredentialProvider; + private readonly plugins; + private readonly requestHandler; + private readonly ioHelper; + private readonly logger?; + constructor(defaultCredentialProvider: AwsCredentialIdentityProvider, defaultRegion: string | undefined, services: SdkProviderServices); + /** + * Return an SDK which can do operations in the given environment + * + * The `environment` parameter is resolved first (see `resolveEnvironment()`). + */ + forEnvironment(environment: Environment, mode: Mode, options?: CredentialsOptions, quiet?: boolean): Promise; + /** + * Return the partition that base credentials are for + * + * Returns `undefined` if there are no base credentials. + */ + baseCredentialsPartition(environment: Environment, mode: Mode): Promise; + /** + * Resolve the environment for a stack + * + * Replaces the magic values `UNKNOWN_REGION` and `UNKNOWN_ACCOUNT` + * with the defaults for the current SDK configuration (`~/.aws/config` or + * otherwise). + * + * It is an error if `UNKNOWN_ACCOUNT` is used but the user hasn't configured + * any SDK credentials. + */ + resolveEnvironment(env: Environment): Promise; + /** + * The account we'd auth into if we used default credentials. + * + * Default credentials are the set of ambiently configured credentials using + * one of the environment variables, or ~/.aws/credentials, or the *one* + * profile that was passed into the CLI. + * + * Might return undefined if there are no default/ambient credentials + * available (in which case the user should better hope they have + * credential plugins configured). + * + * Uses a cache to avoid STS calls if we don't need 'em. + */ + defaultAccount(): Promise; + /** + * Get credentials for the given account ID in the given mode + * + * 1. Use the default credentials if the destination account matches the + * current credentials' account. + * 2. Otherwise try all credential plugins. + * 3. Fail if neither of these yield any credentials. + * 4. Return a failure if any of them returned credentials + */ + private obtainBaseCredentials; + /** + * Return an SDK which uses assumed role credentials + * + * The base credentials used to retrieve the assumed role credentials will be the + * same credentials returned by obtainCredentials if an environment and mode is passed, + * otherwise it will be the current credentials. + */ + private withAssumedRole; + /** + * Factory function that creates a new SDK instance + * + * This is a function here, instead of all the places where this is used creating a `new SDK` + * instance, so that it is trivial to mock from tests. + * + * Use like this: + * + * ```ts + * const mockSdk = jest.spyOn(SdkProvider.prototype, '_makeSdk').mockReturnValue(new MockSdk()); + * // ... + * mockSdk.mockRestore(); + * ``` + * + * @internal + */ + _makeSdk(credProvider: AwsCredentialIdentityProvider, region: string): SDK; +} +/** + * An AWS account + * + * An AWS account always exists in only one partition. Usually we don't care about + * the partition, but when we need to form ARNs we do. + */ +export interface Account { + /** + * The account number + */ + readonly accountId: string; + /** + * The partition ('aws' or 'aws-cn' or otherwise) + */ + readonly partition: string; +} +/** + * Options for obtaining credentials for an environment + */ +export interface CredentialsOptions { + /** + * The ARN of the role that needs to be assumed, if any + */ + readonly assumeRoleArn?: string; + /** + * External ID required to assume the given role. + */ + readonly assumeRoleExternalId?: string; + /** + * Session tags required to assume the given role. + */ + readonly assumeRoleAdditionalOptions?: AssumeRoleAdditionalOptions; +} +/** + * Instantiate an SDK for context providers. This function ensures that all + * lookup assume role options are used when context providers perform lookups. + */ +export declare function initContextProviderSdk(aws: SdkProvider, options: ContextLookupRoleOptions): Promise; +export interface SdkProviderServices { + /** + * An IO helper for emitting messages + */ + readonly ioHelper: IoHelper; + /** + * The request handler settings + */ + readonly requestHandler?: NodeHttpHandlerOptions; + /** + * A plugin host + */ + readonly pluginHost?: PluginHost; + /** + * An SDK logger + */ + readonly logger?: Logger; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.js new file mode 100644 index 000000000..643ff189e --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk-provider.js @@ -0,0 +1,373 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var SdkProvider_1; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SdkProvider = void 0; +exports.initContextProviderSdk = initContextProviderSdk; +const os = require("os"); +const cx_api_1 = require("@aws-cdk/cx-api"); +const credential_providers_1 = require("@aws-sdk/credential-providers"); +const awscli_compatible_1 = require("./awscli-compatible"); +const cached_1 = require("./cached"); +const credential_plugins_1 = require("./credential-plugins"); +const provider_caching_1 = require("./provider-caching"); +const sdk_1 = require("./sdk"); +const tracing_1 = require("./tracing"); +const util_1 = require("../../util"); +const private_1 = require("../io/private"); +const plugin_1 = require("../plugin"); +const toolkit_error_1 = require("../toolkit-error"); +const CACHED_ACCOUNT = Symbol('cached_account'); +/** + * Creates instances of the AWS SDK appropriate for a given account/region. + * + * Behavior is as follows: + * + * - First, a set of "base" credentials are established + * - If a target environment is given and the default ("current") SDK credentials are for + * that account, return those; otherwise + * - If a target environment is given, scan all credential provider plugins + * for credentials, and return those if found; otherwise + * - Return default ("current") SDK credentials, noting that they might be wrong. + * + * - Second, a role may optionally need to be assumed. Use the base credentials + * established in the previous process to assume that role. + * - If assuming the role fails and the base credentials are for the correct + * account, return those. This is a fallback for people who are trying to interact + * with a Default Synthesized stack and already have right credentials setup. + * + * Typical cases we see in the wild: + * - Credential plugin setup that, although not recommended, works for them + * - Seeded terminal with `ReadOnly` credentials in order to do `cdk diff`--the `ReadOnly` + * role doesn't have `sts:AssumeRole` and will fail for no real good reason. + */ +let SdkProvider = SdkProvider_1 = class SdkProvider { + /** + * Create a new SdkProvider which gets its defaults in a way that behaves like the AWS CLI does + * + * The AWS SDK for JS behaves slightly differently from the AWS CLI in a number of ways; see the + * class `AwsCliCompatible` for the details. + */ + static async withAwsCliCompatibleDefaults(options) { + (0, tracing_1.callTrace)(SdkProvider_1.withAwsCliCompatibleDefaults.name, SdkProvider_1.constructor.name, options.logger); + const config = await new awscli_compatible_1.AwsCliCompatible(options.ioHelper, options.requestHandler ?? {}, options.logger).baseConfig(options.profile); + return new SdkProvider_1(config.credentialProvider, config.defaultRegion, options); + } + defaultRegion; + defaultCredentialProvider; + plugins; + requestHandler; + ioHelper; + logger; + constructor(defaultCredentialProvider, defaultRegion, services) { + this.defaultCredentialProvider = defaultCredentialProvider; + this.defaultRegion = defaultRegion ?? 'us-east-1'; + this.requestHandler = services.requestHandler ?? {}; + this.ioHelper = services.ioHelper; + this.logger = services.logger; + this.plugins = new credential_plugins_1.CredentialPlugins(services.pluginHost ?? new plugin_1.PluginHost(), this.ioHelper); + } + /** + * Return an SDK which can do operations in the given environment + * + * The `environment` parameter is resolved first (see `resolveEnvironment()`). + */ + async forEnvironment(environment, mode, options, quiet = false) { + const env = await this.resolveEnvironment(environment); + const baseCreds = await this.obtainBaseCredentials(env.account, mode); + // At this point, we need at least SOME credentials + if (baseCreds.source === 'none') { + throw new toolkit_error_1.AuthenticationError(fmtObtainCredentialsError(env.account, baseCreds)); + } + // Simple case is if we don't need to "assumeRole" here. If so, we must now have credentials for the right + // account. + if (options?.assumeRoleArn === undefined) { + if (baseCreds.source === 'incorrectDefault') { + throw new toolkit_error_1.AuthenticationError(fmtObtainCredentialsError(env.account, baseCreds)); + } + // Our current credentials must be valid and not expired. Confirm that before we get into doing + // actual CloudFormation calls, which might take a long time to hang. + const sdk = this._makeSdk(baseCreds.credentials, env.region); + await sdk.validateCredentials(); + return { sdk, didAssumeRole: false }; + } + try { + // We will proceed to AssumeRole using whatever we've been given. + const sdk = await this.withAssumedRole(baseCreds, options.assumeRoleArn, options.assumeRoleExternalId, options.assumeRoleAdditionalOptions, env.region); + return { sdk, didAssumeRole: true }; + } + catch (err) { + if (err.name === 'ExpiredToken') { + throw err; + } + // AssumeRole failed. Proceed and warn *if and only if* the baseCredentials were already for the right account + // or returned from a plugin. This is to cover some current setups for people using plugins or preferring to + // feed the CLI credentials which are sufficient by themselves. Prefer to assume the correct role if we can, + // but if we can't then let's just try with available credentials anyway. + if (baseCreds.source === 'correctDefault' || baseCreds.source === 'plugin') { + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(err.message)); + const maker = quiet ? private_1.IO.DEFAULT_SDK_DEBUG : private_1.IO.DEFAULT_SDK_WARN; + await this.ioHelper.notify(maker.msg(`${fmtObtainedCredentials(baseCreds)} could not be used to assume '${options.assumeRoleArn}', but are for the right account. Proceeding anyway.`)); + return { + sdk: this._makeSdk(baseCreds.credentials, env.region), + didAssumeRole: false, + }; + } + throw err; + } + } + /** + * Return the partition that base credentials are for + * + * Returns `undefined` if there are no base credentials. + */ + async baseCredentialsPartition(environment, mode) { + const env = await this.resolveEnvironment(environment); + const baseCreds = await this.obtainBaseCredentials(env.account, mode); + if (baseCreds.source === 'none') { + return undefined; + } + return (await this._makeSdk(baseCreds.credentials, env.region).currentAccount()).partition; + } + /** + * Resolve the environment for a stack + * + * Replaces the magic values `UNKNOWN_REGION` and `UNKNOWN_ACCOUNT` + * with the defaults for the current SDK configuration (`~/.aws/config` or + * otherwise). + * + * It is an error if `UNKNOWN_ACCOUNT` is used but the user hasn't configured + * any SDK credentials. + */ + async resolveEnvironment(env) { + const region = env.region !== cx_api_1.UNKNOWN_REGION ? env.region : this.defaultRegion; + const account = env.account !== cx_api_1.UNKNOWN_ACCOUNT ? env.account : (await this.defaultAccount())?.accountId; + if (!account) { + throw new toolkit_error_1.AuthenticationError('Unable to resolve AWS account to use. It must be either configured when you define your CDK Stack, or through the environment'); + } + return { + region, + account, + name: cx_api_1.EnvironmentUtils.format(account, region), + }; + } + /** + * The account we'd auth into if we used default credentials. + * + * Default credentials are the set of ambiently configured credentials using + * one of the environment variables, or ~/.aws/credentials, or the *one* + * profile that was passed into the CLI. + * + * Might return undefined if there are no default/ambient credentials + * available (in which case the user should better hope they have + * credential plugins configured). + * + * Uses a cache to avoid STS calls if we don't need 'em. + */ + async defaultAccount() { + return (0, cached_1.cached)(this, CACHED_ACCOUNT, async () => { + try { + return await this._makeSdk(this.defaultCredentialProvider, this.defaultRegion).currentAccount(); + } + catch (e) { + // Treat 'ExpiredToken' specially. This is a common situation that people may find themselves in, and + // they are complaining about if we fail 'cdk synth' on them. We loudly complain in order to show that + // the current situation is probably undesirable, but we don't fail. + if (e.name === 'ExpiredToken') { + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_WARN.msg('There are expired AWS credentials in your environment. The CDK app will synth without current account information.')); + return undefined; + } + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(`Unable to determine the default AWS account (${e.name}): ${(0, util_1.formatErrorMessage)(e)}`)); + return undefined; + } + }); + } + /** + * Get credentials for the given account ID in the given mode + * + * 1. Use the default credentials if the destination account matches the + * current credentials' account. + * 2. Otherwise try all credential plugins. + * 3. Fail if neither of these yield any credentials. + * 4. Return a failure if any of them returned credentials + */ + async obtainBaseCredentials(accountId, mode) { + // First try 'current' credentials + const defaultAccountId = (await this.defaultAccount())?.accountId; + if (defaultAccountId === accountId) { + return { + source: 'correctDefault', + credentials: await this.defaultCredentialProvider, + }; + } + // Then try the plugins + const pluginCreds = await this.plugins.fetchCredentialsFor(accountId, mode); + if (pluginCreds) { + return { source: 'plugin', ...pluginCreds }; + } + // Fall back to default credentials with a note that they're not the right ones yet + if (defaultAccountId !== undefined) { + return { + source: 'incorrectDefault', + accountId: defaultAccountId, + credentials: await this.defaultCredentialProvider, + unusedPlugins: this.plugins.availablePluginNames, + }; + } + // Apparently we didn't find any at all + return { + source: 'none', + unusedPlugins: this.plugins.availablePluginNames, + }; + } + /** + * Return an SDK which uses assumed role credentials + * + * The base credentials used to retrieve the assumed role credentials will be the + * same credentials returned by obtainCredentials if an environment and mode is passed, + * otherwise it will be the current credentials. + */ + async withAssumedRole(mainCredentials, roleArn, externalId, additionalOptions, region) { + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(`Assuming role '${roleArn}'.`)); + region = region ?? this.defaultRegion; + const sourceDescription = fmtObtainedCredentials(mainCredentials); + try { + const credentials = await (0, provider_caching_1.makeCachingProvider)((0, credential_providers_1.fromTemporaryCredentials)({ + masterCredentials: mainCredentials.credentials, + params: { + RoleArn: roleArn, + ExternalId: externalId, + RoleSessionName: `aws-cdk-${safeUsername()}`, + ...additionalOptions, + TransitiveTagKeys: additionalOptions?.Tags ? additionalOptions.Tags.map((t) => t.Key) : undefined, + }, + clientConfig: { + region, + requestHandler: this.requestHandler, + customUserAgent: 'aws-cdk', + logger: this.logger, + }, + logger: this.logger, + })); + // Call the provider at least once here, to catch an error if it occurs + await credentials(); + return this._makeSdk(credentials, region); + } + catch (err) { + if (err.name === 'ExpiredToken') { + throw err; + } + await this.ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(`Assuming role failed: ${err.message}`)); + throw new toolkit_error_1.AuthenticationError([ + 'Could not assume role in target account', + ...(sourceDescription ? [`using ${sourceDescription}`] : []), + err.message, + ". Please make sure that this role exists in the account. If it doesn't exist, (re)-bootstrap the environment " + + "with the right '--trust', using the latest version of the CDK CLI.", + ].join(' ')); + } + } + /** + * Factory function that creates a new SDK instance + * + * This is a function here, instead of all the places where this is used creating a `new SDK` + * instance, so that it is trivial to mock from tests. + * + * Use like this: + * + * ```ts + * const mockSdk = jest.spyOn(SdkProvider.prototype, '_makeSdk').mockReturnValue(new MockSdk()); + * // ... + * mockSdk.mockRestore(); + * ``` + * + * @internal + */ + _makeSdk(credProvider, region) { + return new sdk_1.SDK(credProvider, region, this.requestHandler, this.ioHelper, this.logger); + } +}; +exports.SdkProvider = SdkProvider; +exports.SdkProvider = SdkProvider = SdkProvider_1 = __decorate([ + tracing_1.traceMemberMethods +], SdkProvider); +/** + * Return the username with characters invalid for a RoleSessionName removed + * + * @see https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html#API_AssumeRole_RequestParameters + */ +function safeUsername() { + try { + return os.userInfo().username.replace(/[^\w+=,.@-]/g, '@'); + } + catch { + return 'noname'; + } +} +/** + * Isolating the code that translates calculation errors into human error messages + * + * We cover the following cases: + * + * - No credentials are available at all + * - Default credentials are for the wrong account + */ +function fmtObtainCredentialsError(targetAccountId, obtainResult) { + const msg = [`Need to perform AWS calls for account ${targetAccountId}`]; + switch (obtainResult.source) { + case 'incorrectDefault': + msg.push(`but the current credentials are for ${obtainResult.accountId}`); + break; + case 'none': + msg.push('but no credentials have been configured'); + } + if (obtainResult.unusedPlugins.length > 0) { + msg.push(`and none of these plugins found any: ${obtainResult.unusedPlugins.join(', ')}`); + } + return msg.join(', '); +} +/** + * Format a message indicating where we got base credentials for the assume role + * + * We cover the following cases: + * + * - Default credentials for the right account + * - Default credentials for the wrong account + * - Credentials returned from a plugin + */ +function fmtObtainedCredentials(obtainResult) { + switch (obtainResult.source) { + case 'correctDefault': + return 'current credentials'; + case 'plugin': + return `credentials returned by plugin '${obtainResult.pluginName}'`; + case 'incorrectDefault': + const msg = []; + msg.push(`current credentials (which are for account ${obtainResult.accountId}`); + if (obtainResult.unusedPlugins.length > 0) { + msg.push(`, and none of the following plugins provided credentials: ${obtainResult.unusedPlugins.join(', ')}`); + } + msg.push(')'); + return msg.join(''); + } +} +/** + * Instantiate an SDK for context providers. This function ensures that all + * lookup assume role options are used when context providers perform lookups. + */ +async function initContextProviderSdk(aws, options) { + const account = options.account; + const region = options.region; + const creds = { + assumeRoleArn: options.lookupRoleArn, + assumeRoleExternalId: options.lookupRoleExternalId, + assumeRoleAdditionalOptions: options.assumeRoleAdditionalOptions, + }; + return (await aws.forEnvironment(cx_api_1.EnvironmentUtils.make(account, region), plugin_1.Mode.ForReading, creds)).sdk; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2RrLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9hd3MtYXV0aC9zZGstcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQXdoQkEsd0RBV0M7QUFuaUJELHlCQUF5QjtBQUd6Qiw0Q0FBb0Y7QUFFcEYsd0VBQXlFO0FBR3pFLDJEQUF1RDtBQUN2RCxxQ0FBa0M7QUFDbEMsNkRBQXlEO0FBQ3pELHlEQUF5RDtBQUN6RCwrQkFBNEI7QUFDNUIsdUNBQTBEO0FBQzFELHFDQUFnRDtBQUNoRCwyQ0FBa0Q7QUFDbEQsc0NBQTZDO0FBQzdDLG9EQUF1RDtBQW1DdkQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUE2QmhEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBRUksSUFBTSxXQUFXLG1CQUFqQixNQUFNLFdBQVc7SUFDdEI7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLDRCQUE0QixDQUFDLE9BQTJCO1FBQzFFLElBQUEsbUJBQVMsRUFBQyxhQUFXLENBQUMsNEJBQTRCLENBQUMsSUFBSSxFQUFFLGFBQVcsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2RyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksb0NBQWdCLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsY0FBYyxJQUFJLEVBQUUsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0SSxPQUFPLElBQUksYUFBVyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ25GLENBQUM7SUFFZSxhQUFhLENBQVM7SUFDckIseUJBQXlCLENBQWdDO0lBQ3pELE9BQU8s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QUksQ0FBQyw4Q0FBOEMsWUFBWSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7WUFFakYsSUFBSSxZQUFZLENBQUMsYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDMUMsR0FBRyxDQUFDLElBQUksQ0FBQyw2REFBNkQsWUFBWSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2pILENBQUM7WUFDRCxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRWQsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hCLENBQUM7QUFDSCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0ksS0FBSyxVQUFVLHNCQUFzQixDQUFDLEdBQWdCLEVBQUUsT0FBaUM7SUFDOUYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztJQUNoQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBRTlCLE1BQU0sS0FBSyxHQUF1QjtRQUNoQyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWE7UUFDcEMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLG9CQUFvQjtRQUNsRCwyQkFBMkIsRUFBRSxPQUFPLENBQUMsMkJBQTJCO0tBQ2pFLENBQUM7SUFFRixPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsY0FBYyxDQUFDLHlCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLEVBQUUsYUFBSSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztBQUN4RyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0IHR5cGUgeyBDb250ZXh0TG9va3VwUm9sZU9wdGlvbnMgfSBmcm9tICdAYXdzLWNkay9jbG91ZC1hc3NlbWJseS1zY2hlbWEnO1xuaW1wb3J0IHR5cGUgeyBFbnZpcm9ubWVudCB9IGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBFbnZpcm9ubWVudFV0aWxzLCBVTktOT1dOX0FDQ09VTlQsIFVOS05PV05fUkVHSU9OIH0gZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCB0eXBlIHsgQXNzdW1lUm9sZUNvbW1hbmRJbnB1dCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zdHMnO1xuaW1wb3J0IHsgZnJvbVRlbXBvcmFyeUNyZWRlbnRpYWxzIH0gZnJvbSAnQGF3cy1zZGsvY3JlZGVudGlhbC1wcm92aWRlcnMnO1xuaW1wb3J0IHR5cGUgeyBOb2RlSHR0cEhhbmRsZXJPcHRpb25zIH0gZnJvbSAnQHNtaXRoeS9ub2RlLWh0dHAtaGFuZGxlcic7XG5pbXBvcnQgdHlwZSB7IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyLCBMb2dnZXIgfSBmcm9tICdAc21pdGh5L3R5cGVzJztcbmltcG9ydCB7IEF3c0NsaUNvbXBhdGlibGUgfSBmcm9tICcuL2F3c2NsaS1jb21wYXRpYmxlJztcbmltcG9ydCB7IGNhY2hlZCB9IGZyb20gJy4vY2FjaGVkJztcbmltcG9ydCB7IENyZWRlbnRpYWxQbHVnaW5zIH0gZnJvbSAnLi9jcmVkZW50aWFsLXBsdWdpbnMnO1xuaW1wb3J0IHsgbWFrZUNhY2hpbmdQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXItY2FjaGluZyc7XG5pbXBvcnQgeyBTREsgfSBmcm9tICcuL3Nkayc7XG5pbXBvcnQgeyBjYWxsVHJhY2UsIHRyYWNlTWVtYmVyTWV0aG9kcyB9IGZyb20gJy4vdHJhY2luZyc7XG5pbXBvcnQgeyBmb3JtYXRFcnJvck1lc3NhZ2UgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IElPLCB0eXBlIElvSGVscGVyIH0gZnJvbSAnLi4vaW8vcHJpdmF0ZSc7XG5pbXBvcnQgeyBQbHVnaW5Ib3N0LCBNb2RlIH0gZnJvbSAnLi4vcGx1Z2luJztcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uRXJyb3IgfSBmcm9tICcuLi90b29sa2l0LWVycm9yJztcblxuZXhwb3J0IHR5cGUgQXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zID0gUGFydGlhbDxPbWl0PEFzc3VtZVJvbGVDb21tYW5kSW5wdXQsICdFeHRlcm5hbElkJyB8ICdSb2xlQXJuJz4+O1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIHRoZSBkZWZhdWx0IFNESyBwcm92aWRlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNka1Byb3ZpZGVyT3B0aW9ucyBleHRlbmRzIFNka1Byb3ZpZGVyU2VydmljZXMge1xuICAvKipcbiAgICogUHJvZmlsZSB0byByZWFkIGZyb20gfi8uYXdzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcHJvZmlsZVxuICAgKi9cbiAgcmVhZG9ubHkgcHJvZmlsZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBpbmRpdmlkdWFsIFNES3NcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZGtIdHRwT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBQcm94eSBhZGRyZXNzIHRvIHVzZVxuICAgKlxuICAgKiBAZGVmYXVsdCBObyBwcm94eVxuICAgKi9cbiAgcmVhZG9ubHkgcHJveHlBZGRyZXNzPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIHBhdGggdG8gYSBjZXJ0aWZpY2F0ZSBidW5kbGUgdGhhdCBjb250YWlucyBhIGNlcnQgdG8gYmUgdHJ1c3RlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgTm8gY2VydGlmaWNhdGUgYnVuZGxlXG4gICAqL1xuICByZWFkb25seSBjYUJ1bmRsZVBhdGg/OiBzdHJpbmc7XG59XG5cbmNvbnN0IENBQ0hFRF9BQ0NPVU5UID0gU3ltYm9sKCdjYWNoZWRfYWNjb3VudCcpO1xuXG4vKipcbiAqIFNESyBjb25maWd1cmF0aW9uIGZvciBhIGdpdmVuIGVudmlyb25tZW50XG4gKiAnZm9yRW52aXJvbm1lbnQnIHdpbGwgYXR0ZW1wdCB0byBhc3N1bWUgYSByb2xlIGFuZCBpZiBpdFxuICogaXMgbm90IHN1Y2Nlc3NmdWwsIHRoZW4gaXQgd2lsbCBlaXRoZXI6XG4gKiAgIDEuIENoZWNrIHRvIHNlZSBpZiB0aGUgZGVmYXVsdCBjcmVkZW50aWFscyAobG9jYWwgY3JlZGVudGlhbHMgdGhlIENMSSB3YXMgZXhlY3V0ZWQgd2l0aClcbiAqICAgICAgYXJlIGZvciB0aGUgZ2l2ZW4gZW52aXJvbm1lbnQuIElmIHRoZXkgYXJlIHRoZW4gcmV0dXJuIHRob3NlLlxuICogICAyLiBJZiB0aGUgZGVmYXVsdCBjcmVkZW50aWFscyBhcmUgbm90IGZvciB0aGUgZ2l2ZW4gZW52aXJvbm1lbnQgdGhlblxuICogICAgICB0aHJvdyBhbiBlcnJvclxuICpcbiAqICdkaWRBc3N1bWVSb2xlJyBhbGxvd3MgY2FsbGVycyB0byB3aGV0aGVyIHRoZXkgYXJlIHJlY2VpdmluZyB0aGUgYXNzdW1lIHJvbGVcbiAqIGNyZWRlbnRpYWxzIG9yIHRoZSBkZWZhdWx0IGNyZWRlbnRpYWxzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNka0ZvckVudmlyb25tZW50IHtcbiAgLyoqXG4gICAqIFRoZSBTREsgZm9yIHRoZSBnaXZlbiBlbnZpcm9ubWVudFxuICAgKi9cbiAgcmVhZG9ubHkgc2RrOiBTREs7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRoZSBhc3N1bWUgcm9sZSB3YXMgc3VjY2Vzc2Z1bC5cbiAgICogSWYgdGhlIGFzc3VtZSByb2xlIHdhcyBub3Qgc3VjY2Vzc2Z1bCAoZmFsc2UpXG4gICAqIHRoZW4gdGhhdCBtZWFucyB0aGF0IHRoZSAnc2RrJyByZXR1cm5lZCBjb250YWluc1xuICAgKiB0aGUgZGVmYXVsdCBjcmVkZW50aWFscyAobm90IHRoZSBhc3N1bWUgcm9sZSBjcmVkZW50aWFscylcbiAgICovXG4gIHJlYWRvbmx5IGRpZEFzc3VtZVJvbGU6IGJvb2xlYW47XG59XG5cbi8qKlxuICogQ3JlYXRlcyBpbnN0YW5jZXMgb2YgdGhlIEFXUyBTREsgYXBwcm9wcmlhdGUgZm9yIGEgZ2l2ZW4gYWNjb3VudC9yZWdpb24uXG4gKlxuICogQmVoYXZpb3IgaXMgYXMgZm9sbG93czpcbiAqXG4gKiAtIEZpcnN0LCBhIHNldCBvZiBcImJhc2VcIiBjcmVkZW50aWFscyBhcmUgZXN0YWJsaXNoZWRcbiAqICAgLSBJZiBhIHRhcmdldCBlbnZpcm9ubWVudCBpcyBnaXZlbiBhbmQgdGhlIGRlZmF1bHQgKFwiY3VycmVudFwiKSBTREsgY3JlZGVudGlhbHMgYXJlIGZvclxuICogICAgIHRoYXQgYWNjb3VudCwgcmV0dXJuIHRob3NlOyBvdGhlcndpc2VcbiAqICAgLSBJZiBhIHRhcmdldCBlbnZpcm9ubWVudCBpcyBnaXZlbiwgc2NhbiBhbGwgY3JlZGVudGlhbCBwcm92aWRlciBwbHVnaW5zXG4gKiAgICAgZm9yIGNyZWRlbnRpYWxzLCBhbmQgcmV0dXJuIHRob3NlIGlmIGZvdW5kOyBvdGhlcndpc2VcbiAqICAgLSBSZXR1cm4gZGVmYXVsdCAoXCJjdXJyZW50XCIpIFNESyBjcmVkZW50aWFscywgbm90aW5nIHRoYXQgdGhleSBtaWdodCBiZSB3cm9uZy5cbiAqXG4gKiAtIFNlY29uZCwgYSByb2xlIG1heSBvcHRpb25hbGx5IG5lZWQgdG8gYmUgYXNzdW1lZC4gVXNlIHRoZSBiYXNlIGNyZWRlbnRpYWxzXG4gKiAgIGVzdGFibGlzaGVkIGluIHRoZSBwcmV2aW91cyBwcm9jZXNzIHRvIGFzc3VtZSB0aGF0IHJvbGUuXG4gKiAgIC0gSWYgYXNzdW1pbmcgdGhlIHJvbGUgZmFpbHMgYW5kIHRoZSBiYXNlIGNyZWRlbnRpYWxzIGFyZSBmb3IgdGhlIGNvcnJlY3RcbiAqICAgICBhY2NvdW50LCByZXR1cm4gdGhvc2UuIFRoaXMgaXMgYSBmYWxsYmFjayBmb3IgcGVvcGxlIHdobyBhcmUgdHJ5aW5nIHRvIGludGVyYWN0XG4gKiAgICAgd2l0aCBhIERlZmF1bHQgU3ludGhlc2l6ZWQgc3RhY2sgYW5kIGFscmVhZHkgaGF2ZSByaWdodCBjcmVkZW50aWFscyBzZXR1cC5cbiAqXG4gKiAgICAgVHlwaWNhbCBjYXNlcyB3ZSBzZWUgaW4gdGhlIHdpbGQ6XG4gKiAgICAgLSBDcmVkZW50aWFsIHBsdWdpbiBzZXR1cCB0aGF0LCBhbHRob3VnaCBub3QgcmVjb21tZW5kZWQsIHdvcmtzIGZvciB0aGVtXG4gKiAgICAgLSBTZWVkZWQgdGVybWluYWwgd2l0aCBgUmVhZE9ubHlgIGNyZWRlbnRpYWxzIGluIG9yZGVyIHRvIGRvIGBjZGsgZGlmZmAtLXRoZSBgUmVhZE9ubHlgXG4gKiAgICAgICByb2xlIGRvZXNuJ3QgaGF2ZSBgc3RzOkFzc3VtZVJvbGVgIGFuZCB3aWxsIGZhaWwgZm9yIG5vIHJlYWwgZ29vZCByZWFzb24uXG4gKi9cbkB0cmFjZU1lbWJlck1ldGhvZHNcbmV4cG9ydCBjbGFzcyBTZGtQcm92aWRlciB7XG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgU2RrUHJvdmlkZXIgd2hpY2ggZ2V0cyBpdHMgZGVmYXVsdHMgaW4gYSB3YXkgdGhhdCBiZWhhdmVzIGxpa2UgdGhlIEFXUyBDTEkgZG9lc1xuICAgKlxuICAgKiBUaGUgQVdTIFNESyBmb3IgSlMgYmVoYXZlcyBzbGlnaHRseSBkaWZmZXJlbnRseSBmcm9tIHRoZSBBV1MgQ0xJIGluIGEgbnVtYmVyIG9mIHdheXM7IHNlZSB0aGVcbiAgICogY2xhc3MgYEF3c0NsaUNvbXBhdGlibGVgIGZvciB0aGUgZGV0YWlscy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgd2l0aEF3c0NsaUNvbXBhdGlibGVEZWZhdWx0cyhvcHRpb25zOiBTZGtQcm92aWRlck9wdGlvbnMpIHtcbiAgICBjYWxsVHJhY2UoU2RrUHJvdmlkZXIud2l0aEF3c0NsaUNvbXBhdGlibGVEZWZhdWx0cy5uYW1lLCBTZGtQcm92aWRlci5jb25zdHJ1Y3Rvci5uYW1lLCBvcHRpb25zLmxvZ2dlcik7XG4gICAgY29uc3QgY29uZmlnID0gYXdhaXQgbmV3IEF3c0NsaUNvbXBhdGlibGUob3B0aW9ucy5pb0hlbHBlciwgb3B0aW9ucy5yZXF1ZXN0SGFuZGxlciA/PyB7fSwgb3B0aW9ucy5sb2dnZXIpLmJhc2VDb25maWcob3B0aW9ucy5wcm9maWxlKTtcbiAgICByZXR1cm4gbmV3IFNka1Byb3ZpZGVyKGNvbmZpZy5jcmVkZW50aWFsUHJvdmlkZXIsIGNvbmZpZy5kZWZhdWx0UmVnaW9uLCBvcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBkZWZhdWx0UmVnaW9uOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdENyZWRlbnRpYWxQcm92aWRlcjogQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGx1Z2lucztcbiAgcHJpdmF0ZSByZWFkb25seSByZXF1ZXN0SGFuZGxlcjogTm9kZUh0dHBIYW5kbGVyT3B0aW9ucztcbiAgcHJpdmF0ZSByZWFkb25seSBpb0hlbHBlcjogSW9IZWxwZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyPzogTG9nZ2VyO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICBkZWZhdWx0Q3JlZGVudGlhbFByb3ZpZGVyOiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcixcbiAgICBkZWZhdWx0UmVnaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgc2VydmljZXM6IFNka1Byb3ZpZGVyU2VydmljZXMsXG4gICkge1xuICAgIHRoaXMuZGVmYXVsdENyZWRlbnRpYWxQcm92aWRlciA9IGRlZmF1bHRDcmVkZW50aWFsUHJvdmlkZXI7XG4gICAgdGhpcy5kZWZhdWx0UmVnaW9uID0gZGVmYXVsdFJlZ2lvbiA/PyAndXMtZWFzdC0xJztcbiAgICB0aGlzLnJlcXVlc3RIYW5kbGVyID0gc2VydmljZXMucmVxdWVzdEhhbmRsZXIgPz8ge307XG4gICAgdGhpcy5pb0hlbHBlciA9IHNlcnZpY2VzLmlvSGVscGVyO1xuICAgIHRoaXMubG9nZ2VyID0gc2VydmljZXMubG9nZ2VyO1xuICAgIHRoaXMucGx1Z2lucyA9IG5ldyBDcmVkZW50aWFsUGx1Z2lucyhzZXJ2aWNlcy5wbHVnaW5Ib3N0ID8/IG5ldyBQbHVnaW5Ib3N0KCksIHRoaXMuaW9IZWxwZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbiBTREsgd2hpY2ggY2FuIGRvIG9wZXJhdGlvbnMgaW4gdGhlIGdpdmVuIGVudmlyb25tZW50XG4gICAqXG4gICAqIFRoZSBgZW52aXJvbm1lbnRgIHBhcmFtZXRlciBpcyByZXNvbHZlZCBmaXJzdCAoc2VlIGByZXNvbHZlRW52aXJvbm1lbnQoKWApLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGZvckVudmlyb25tZW50KFxuICAgIGVudmlyb25tZW50OiBFbnZpcm9ubWVudCxcbiAgICBtb2RlOiBNb2RlLFxuICAgIG9wdGlvbnM/OiBDcmVkZW50aWFsc09wdGlvbnMsXG4gICAgcXVpZXQgPSBmYWxzZSxcbiAgKTogUHJvbWlzZTxTZGtGb3JFbnZpcm9ubWVudD4ge1xuICAgIGNvbnN0IGVudiA9IGF3YWl0IHRoaXMucmVzb2x2ZUVudmlyb25tZW50KGVudmlyb25tZW50KTtcblxuICAgIGNvbnN0IGJhc2VDcmVkcyA9IGF3YWl0IHRoaXMub2J0YWluQmFzZUNyZWRlbnRpYWxzKGVudi5hY2NvdW50LCBtb2RlKTtcblxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIG5lZWQgYXQgbGVhc3QgU09NRSBjcmVkZW50aWFsc1xuICAgIGlmIChiYXNlQ3JlZHMuc291cmNlID09PSAnbm9uZScpIHtcbiAgICAgIHRocm93IG5ldyBBdXRoZW50aWNhdGlvbkVycm9yKGZtdE9idGFpbkNyZWRlbnRpYWxzRXJyb3IoZW52LmFjY291bnQsIGJhc2VDcmVkcykpO1xuICAgIH1cblxuICAgIC8vIFNpbXBsZSBjYXNlIGlzIGlmIHdlIGRvbid0IG5lZWQgdG8gXCJhc3N1bWVSb2xlXCIgaGVyZS4gSWYgc28sIHdlIG11c3Qgbm93IGhhdmUgY3JlZGVudGlhbHMgZm9yIHRoZSByaWdodFxuICAgIC8vIGFjY291bnQuXG4gICAgaWYgKG9wdGlvbnM/LmFzc3VtZVJvbGVBcm4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGJhc2VDcmVkcy5zb3VyY2UgPT09ICdpbmNvcnJlY3REZWZhdWx0Jykge1xuICAgICAgICB0aHJvdyBuZXcgQXV0aGVudGljYXRpb25FcnJvcihmbXRPYnRhaW5DcmVkZW50aWFsc0Vycm9yKGVudi5hY2NvdW50LCBiYXNlQ3JlZHMpKTtcbiAgICAgIH1cblxuICAgICAgLy8gT3VyIGN1cnJlbnQgY3JlZGVudGlhbHMgbXVzdCBiZSB2YWxpZCBhbmQgbm90IGV4cGlyZWQuIENvbmZpcm0gdGhhdCBiZWZvcmUgd2UgZ2V0IGludG8gZG9pbmdcbiAgICAgIC8vIGFjdHVhbCBDbG91ZEZvcm1hdGlvbiBjYWxscywgd2hpY2ggbWlnaHQgdGFrZSBhIGxvbmcgdGltZSB0byBoYW5nLlxuICAgICAgY29uc3Qgc2RrID0gdGhpcy5fbWFrZVNkayhiYXNlQ3JlZHMuY3JlZGVudGlhbHMsIGVudi5yZWdpb24pO1xuICAgICAgYXdhaXQgc2RrLnZhbGlkYXRlQ3JlZGVudGlhbHMoKTtcbiAgICAgIHJldHVybiB7IHNkaywgZGlkQXNzdW1lUm9sZTogZmFsc2UgfTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLy8gV2Ugd2lsbCBwcm9jZWVkIHRvIEFzc3VtZVJvbGUgdXNpbmcgd2hhdGV2ZXIgd2UndmUgYmVlbiBnaXZlbi5cbiAgICAgIGNvbnN0IHNkayA9IGF3YWl0IHRoaXMud2l0aEFzc3VtZWRSb2xlKFxuICAgICAgICBiYXNlQ3JlZHMsXG4gICAgICAgIG9wdGlvbnMuYXNzdW1lUm9sZUFybixcbiAgICAgICAgb3B0aW9ucy5hc3N1bWVSb2xlRXh0ZXJuYWxJZCxcbiAgICAgICAgb3B0aW9ucy5hc3N1bWVSb2xlQWRkaXRpb25hbE9wdGlvbnMsXG4gICAgICAgIGVudi5yZWdpb24sXG4gICAgICApO1xuXG4gICAgICByZXR1cm4geyBzZGssIGRpZEFzc3VtZVJvbGU6IHRydWUgfTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgaWYgKGVyci5uYW1lID09PSAnRXhwaXJlZFRva2VuJykge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG5cbiAgICAgIC8vIEFzc3VtZVJvbGUgZmFpbGVkLiBQcm9jZWVkIGFuZCB3YXJuICppZiBhbmQgb25seSBpZiogdGhlIGJhc2VDcmVkZW50aWFscyB3ZXJlIGFscmVhZHkgZm9yIHRoZSByaWdodCBhY2NvdW50XG4gICAgICAvLyBvciByZXR1cm5lZCBmcm9tIGEgcGx1Z2luLiBUaGlzIGlzIHRvIGNvdmVyIHNvbWUgY3VycmVudCBzZXR1cHMgZm9yIHBlb3BsZSB1c2luZyBwbHVnaW5zIG9yIHByZWZlcnJpbmcgdG9cbiAgICAgIC8vIGZlZWQgdGhlIENMSSBjcmVkZW50aWFscyB3aGljaCBhcmUgc3VmZmljaWVudCBieSB0aGVtc2VsdmVzLiBQcmVmZXIgdG8gYXNzdW1lIHRoZSBjb3JyZWN0IHJvbGUgaWYgd2UgY2FuLFxuICAgICAgLy8gYnV0IGlmIHdlIGNhbid0IHRoZW4gbGV0J3MganVzdCB0cnkgd2l0aCBhdmFpbGFibGUgY3JlZGVudGlhbHMgYW55d2F5LlxuICAgICAgaWYgKGJhc2VDcmVkcy5zb3VyY2UgPT09ICdjb3JyZWN0RGVmYXVsdCcgfHwgYmFzZUNyZWRzLnNvdXJjZSA9PT0gJ3BsdWdpbicpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9TREtfREVCVUcubXNnKGVyci5tZXNzYWdlKSk7XG5cbiAgICAgICAgY29uc3QgbWFrZXIgPSBxdWlldCA/IElPLkRFRkFVTFRfU0RLX0RFQlVHIDogSU8uREVGQVVMVF9TREtfV0FSTjtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkobWFrZXIubXNnKFxuICAgICAgICAgIGAke2ZtdE9idGFpbmVkQ3JlZGVudGlhbHMoYmFzZUNyZWRzKX0gY291bGQgbm90IGJlIHVzZWQgdG8gYXNzdW1lICcke29wdGlvbnMuYXNzdW1lUm9sZUFybn0nLCBidXQgYXJlIGZvciB0aGUgcmlnaHQgYWNjb3VudC4gUHJvY2VlZGluZyBhbnl3YXkuYCxcbiAgICAgICAgKSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc2RrOiB0aGlzLl9tYWtlU2RrKGJhc2VDcmVkcy5jcmVkZW50aWFscywgZW52LnJlZ2lvbiksXG4gICAgICAgICAgZGlkQXNzdW1lUm9sZTogZmFsc2UsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBwYXJ0aXRpb24gdGhhdCBiYXNlIGNyZWRlbnRpYWxzIGFyZSBmb3JcbiAgICpcbiAgICogUmV0dXJucyBgdW5kZWZpbmVkYCBpZiB0aGVyZSBhcmUgbm8gYmFzZSBjcmVkZW50aWFscy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBiYXNlQ3JlZGVudGlhbHNQYXJ0aXRpb24oZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LCBtb2RlOiBNb2RlKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBlbnYgPSBhd2FpdCB0aGlzLnJlc29sdmVFbnZpcm9ubWVudChlbnZpcm9ubWVudCk7XG4gICAgY29uc3QgYmFzZUNyZWRzID0gYXdhaXQgdGhpcy5vYnRhaW5CYXNlQ3JlZGVudGlhbHMoZW52LmFjY291bnQsIG1vZGUpO1xuICAgIGlmIChiYXNlQ3JlZHMuc291cmNlID09PSAnbm9uZScpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiAoYXdhaXQgdGhpcy5fbWFrZVNkayhiYXNlQ3JlZHMuY3JlZGVudGlhbHMsIGVudi5yZWdpb24pLmN1cnJlbnRBY2NvdW50KCkpLnBhcnRpdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlIHRoZSBlbnZpcm9ubWVudCBmb3IgYSBzdGFja1xuICAgKlxuICAgKiBSZXBsYWNlcyB0aGUgbWFnaWMgdmFsdWVzIGBVTktOT1dOX1JFR0lPTmAgYW5kIGBVTktOT1dOX0FDQ09VTlRgXG4gICAqIHdpdGggdGhlIGRlZmF1bHRzIGZvciB0aGUgY3VycmVudCBTREsgY29uZmlndXJhdGlvbiAoYH4vLmF3cy9jb25maWdgIG9yXG4gICAqIG90aGVyd2lzZSkuXG4gICAqXG4gICAqIEl0IGlzIGFuIGVycm9yIGlmIGBVTktOT1dOX0FDQ09VTlRgIGlzIHVzZWQgYnV0IHRoZSB1c2VyIGhhc24ndCBjb25maWd1cmVkXG4gICAqIGFueSBTREsgY3JlZGVudGlhbHMuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVzb2x2ZUVudmlyb25tZW50KGVudjogRW52aXJvbm1lbnQpOiBQcm9taXNlPEVudmlyb25tZW50PiB7XG4gICAgY29uc3QgcmVnaW9uID0gZW52LnJlZ2lvbiAhPT0gVU5LTk9XTl9SRUdJT04gPyBlbnYucmVnaW9uIDogdGhpcy5kZWZhdWx0UmVnaW9uO1xuICAgIGNvbnN0IGFjY291bnQgPSBlbnYuYWNjb3VudCAhPT0gVU5LTk9XTl9BQ0NPVU5UID8gZW52LmFjY291bnQgOiAoYXdhaXQgdGhpcy5kZWZhdWx0QWNjb3VudCgpKT8uYWNjb3VudElkO1xuXG4gICAgaWYgKCFhY2NvdW50KSB7XG4gICAgICB0aHJvdyBuZXcgQXV0aGVudGljYXRpb25FcnJvcihcbiAgICAgICAgJ1VuYWJsZSB0byByZXNvbHZlIEFXUyBhY2NvdW50IHRvIHVzZS4gSXQgbXVzdCBiZSBlaXRoZXIgY29uZmlndXJlZCB3aGVuIHlvdSBkZWZpbmUgeW91ciBDREsgU3RhY2ssIG9yIHRocm91Z2ggdGhlIGVudmlyb25tZW50JyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlZ2lvbixcbiAgICAgIGFjY291bnQsXG4gICAgICBuYW1lOiBFbnZpcm9ubWVudFV0aWxzLmZvcm1hdChhY2NvdW50LCByZWdpb24pLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGFjY291bnQgd2UnZCBhdXRoIGludG8gaWYgd2UgdXNlZCBkZWZhdWx0IGNyZWRlbnRpYWxzLlxuICAgKlxuICAgKiBEZWZhdWx0IGNyZWRlbnRpYWxzIGFyZSB0aGUgc2V0IG9mIGFtYmllbnRseSBjb25maWd1cmVkIGNyZWRlbnRpYWxzIHVzaW5nXG4gICAqIG9uZSBvZiB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGVzLCBvciB+Ly5hd3MvY3JlZGVudGlhbHMsIG9yIHRoZSAqb25lKlxuICAgKiBwcm9maWxlIHRoYXQgd2FzIHBhc3NlZCBpbnRvIHRoZSBDTEkuXG4gICAqXG4gICAqIE1pZ2h0IHJldHVybiB1bmRlZmluZWQgaWYgdGhlcmUgYXJlIG5vIGRlZmF1bHQvYW1iaWVudCBjcmVkZW50aWFsc1xuICAgKiBhdmFpbGFibGUgKGluIHdoaWNoIGNhc2UgdGhlIHVzZXIgc2hvdWxkIGJldHRlciBob3BlIHRoZXkgaGF2ZVxuICAgKiBjcmVkZW50aWFsIHBsdWdpbnMgY29uZmlndXJlZCkuXG4gICAqXG4gICAqIFVzZXMgYSBjYWNoZSB0byBhdm9pZCBTVFMgY2FsbHMgaWYgd2UgZG9uJ3QgbmVlZCAnZW0uXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZGVmYXVsdEFjY291bnQoKTogUHJvbWlzZTxBY2NvdW50IHwgdW5kZWZpbmVkPiB7XG4gICAgcmV0dXJuIGNhY2hlZCh0aGlzLCBDQUNIRURfQUNDT1VOVCwgYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX21ha2VTZGsodGhpcy5kZWZhdWx0Q3JlZGVudGlhbFByb3ZpZGVyLCB0aGlzLmRlZmF1bHRSZWdpb24pLmN1cnJlbnRBY2NvdW50KCk7XG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgLy8gVHJlYXQgJ0V4cGlyZWRUb2tlbicgc3BlY2lhbGx5LiBUaGlzIGlzIGEgY29tbW9uIHNpdHVhdGlvbiB0aGF0IHBlb3BsZSBtYXkgZmluZCB0aGVtc2VsdmVzIGluLCBhbmRcbiAgICAgICAgLy8gdGhleSBhcmUgY29tcGxhaW5pbmcgYWJvdXQgaWYgd2UgZmFpbCAnY2RrIHN5bnRoJyBvbiB0aGVtLiBXZSBsb3VkbHkgY29tcGxhaW4gaW4gb3JkZXIgdG8gc2hvdyB0aGF0XG4gICAgICAgIC8vIHRoZSBjdXJyZW50IHNpdHVhdGlvbiBpcyBwcm9iYWJseSB1bmRlc2lyYWJsZSwgYnV0IHdlIGRvbid0IGZhaWwuXG4gICAgICAgIGlmIChlLm5hbWUgPT09ICdFeHBpcmVkVG9rZW4nKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9TREtfV0FSTi5tc2coXG4gICAgICAgICAgICAnVGhlcmUgYXJlIGV4cGlyZWQgQVdTIGNyZWRlbnRpYWxzIGluIHlvdXIgZW52aXJvbm1lbnQuIFRoZSBDREsgYXBwIHdpbGwgc3ludGggd2l0aG91dCBjdXJyZW50IGFjY291bnQgaW5mb3JtYXRpb24uJyxcbiAgICAgICAgICApKTtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9TREtfREVCVUcubXNnKGBVbmFibGUgdG8gZGV0ZXJtaW5lIHRoZSBkZWZhdWx0IEFXUyBhY2NvdW50ICgke2UubmFtZX0pOiAke2Zvcm1hdEVycm9yTWVzc2FnZShlKX1gKSk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNyZWRlbnRpYWxzIGZvciB0aGUgZ2l2ZW4gYWNjb3VudCBJRCBpbiB0aGUgZ2l2ZW4gbW9kZVxuICAgKlxuICAgKiAxLiBVc2UgdGhlIGRlZmF1bHQgY3JlZGVudGlhbHMgaWYgdGhlIGRlc3RpbmF0aW9uIGFjY291bnQgbWF0Y2hlcyB0aGVcbiAgICogICAgY3VycmVudCBjcmVkZW50aWFscycgYWNjb3VudC5cbiAgICogMi4gT3RoZXJ3aXNlIHRyeSBhbGwgY3JlZGVudGlhbCBwbHVnaW5zLlxuICAgKiAzLiBGYWlsIGlmIG5laXRoZXIgb2YgdGhlc2UgeWllbGQgYW55IGNyZWRlbnRpYWxzLlxuICAgKiA0LiBSZXR1cm4gYSBmYWlsdXJlIGlmIGFueSBvZiB0aGVtIHJldHVybmVkIGNyZWRlbnRpYWxzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIG9idGFpbkJhc2VDcmVkZW50aWFscyhhY2NvdW50SWQ6IHN0cmluZywgbW9kZTogTW9kZSk6IFByb21pc2U8T2J0YWluQmFzZUNyZWRlbnRpYWxzUmVzdWx0PiB7XG4gICAgLy8gRmlyc3QgdHJ5ICdjdXJyZW50JyBjcmVkZW50aWFsc1xuICAgIGNvbnN0IGRlZmF1bHRBY2NvdW50SWQgPSAoYXdhaXQgdGhpcy5kZWZhdWx0QWNjb3VudCgpKT8uYWNjb3VudElkO1xuICAgIGlmIChkZWZhdWx0QWNjb3VudElkID09PSBhY2NvdW50SWQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNvdXJjZTogJ2NvcnJlY3REZWZhdWx0JyxcbiAgICAgICAgY3JlZGVudGlhbHM6IGF3YWl0IHRoaXMuZGVmYXVsdENyZWRlbnRpYWxQcm92aWRlcixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVGhlbiB0cnkgdGhlIHBsdWdpbnNcbiAgICBjb25zdCBwbHVnaW5DcmVkcyA9IGF3YWl0IHRoaXMucGx1Z2lucy5mZXRjaENyZWRlbnRpYWxzRm9yKGFjY291bnRJZCwgbW9kZSk7XG4gICAgaWYgKHBsdWdpbkNyZWRzKSB7XG4gICAgICByZXR1cm4geyBzb3VyY2U6ICdwbHVnaW4nLCAuLi5wbHVnaW5DcmVkcyB9O1xuICAgIH1cblxuICAgIC8vIEZhbGwgYmFjayB0byBkZWZhdWx0IGNyZWRlbnRpYWxzIHdpdGggYSBub3RlIHRoYXQgdGhleSdyZSBub3QgdGhlIHJpZ2h0IG9uZXMgeWV0XG4gICAgaWYgKGRlZmF1bHRBY2NvdW50SWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc291cmNlOiAnaW5jb3JyZWN0RGVmYXVsdCcsXG4gICAgICAgIGFjY291bnRJZDogZGVmYXVsdEFjY291bnRJZCxcbiAgICAgICAgY3JlZGVudGlhbHM6IGF3YWl0IHRoaXMuZGVmYXVsdENyZWRlbnRpYWxQcm92aWRlcixcbiAgICAgICAgdW51c2VkUGx1Z2luczogdGhpcy5wbHVnaW5zLmF2YWlsYWJsZVBsdWdpbk5hbWVzLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBBcHBhcmVudGx5IHdlIGRpZG4ndCBmaW5kIGFueSBhdCBhbGxcbiAgICByZXR1cm4ge1xuICAgICAgc291cmNlOiAnbm9uZScsXG4gICAgICB1bnVzZWRQbHVnaW5zOiB0aGlzLnBsdWdpbnMuYXZhaWxhYmxlUGx1Z2luTmFtZXMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYW4gU0RLIHdoaWNoIHVzZXMgYXNzdW1lZCByb2xlIGNyZWRlbnRpYWxzXG4gICAqXG4gICAqIFRoZSBiYXNlIGNyZWRlbnRpYWxzIHVzZWQgdG8gcmV0cmlldmUgdGhlIGFzc3VtZWQgcm9sZSBjcmVkZW50aWFscyB3aWxsIGJlIHRoZVxuICAgKiBzYW1lIGNyZWRlbnRpYWxzIHJldHVybmVkIGJ5IG9idGFpbkNyZWRlbnRpYWxzIGlmIGFuIGVudmlyb25tZW50IGFuZCBtb2RlIGlzIHBhc3NlZCxcbiAgICogb3RoZXJ3aXNlIGl0IHdpbGwgYmUgdGhlIGN1cnJlbnQgY3JlZGVudGlhbHMuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdpdGhBc3N1bWVkUm9sZShcbiAgICBtYWluQ3JlZGVudGlhbHM6IEV4Y2x1ZGU8T2J0YWluQmFzZUNyZWRlbnRpYWxzUmVzdWx0LCB7IHNvdXJjZTogJ25vbmUnIH0+LFxuICAgIHJvbGVBcm46IHN0cmluZyxcbiAgICBleHRlcm5hbElkPzogc3RyaW5nLFxuICAgIGFkZGl0aW9uYWxPcHRpb25zPzogQXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zLFxuICAgIHJlZ2lvbj86IHN0cmluZyxcbiAgKTogUHJvbWlzZTxTREs+IHtcbiAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1NES19ERUJVRy5tc2coYEFzc3VtaW5nIHJvbGUgJyR7cm9sZUFybn0nLmApKTtcblxuICAgIHJlZ2lvbiA9IHJlZ2lvbiA/PyB0aGlzLmRlZmF1bHRSZWdpb247XG5cbiAgICBjb25zdCBzb3VyY2VEZXNjcmlwdGlvbiA9IGZtdE9idGFpbmVkQ3JlZGVudGlhbHMobWFpbkNyZWRlbnRpYWxzKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBjcmVkZW50aWFscyA9IGF3YWl0IG1ha2VDYWNoaW5nUHJvdmlkZXIoZnJvbVRlbXBvcmFyeUNyZWRlbnRpYWxzKHtcbiAgICAgICAgbWFzdGVyQ3JlZGVudGlhbHM6IG1haW5DcmVkZW50aWFscy5jcmVkZW50aWFscyxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgUm9sZUFybjogcm9sZUFybixcbiAgICAgICAgICBFeHRlcm5hbElkOiBleHRlcm5hbElkLFxuICAgICAgICAgIFJvbGVTZXNzaW9uTmFtZTogYGF3cy1jZGstJHtzYWZlVXNlcm5hbWUoKX1gLFxuICAgICAgICAgIC4uLmFkZGl0aW9uYWxPcHRpb25zLFxuICAgICAgICAgIFRyYW5zaXRpdmVUYWdLZXlzOiBhZGRpdGlvbmFsT3B0aW9ucz8uVGFncyA/IGFkZGl0aW9uYWxPcHRpb25zLlRhZ3MubWFwKCh0KSA9PiB0LktleSEpIDogdW5kZWZpbmVkLFxuICAgICAgICB9LFxuICAgICAgICBjbGllbnRDb25maWc6IHtcbiAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgcmVxdWVzdEhhbmRsZXI6IHRoaXMucmVxdWVzdEhhbmRsZXIsXG4gICAgICAgICAgY3VzdG9tVXNlckFnZW50OiAnYXdzLWNkaycsXG4gICAgICAgICAgbG9nZ2VyOiB0aGlzLmxvZ2dlcixcbiAgICAgICAgfSxcbiAgICAgICAgbG9nZ2VyOiB0aGlzLmxvZ2dlcixcbiAgICAgIH0pKTtcblxuICAgICAgLy8gQ2FsbCB0aGUgcHJvdmlkZXIgYXQgbGVhc3Qgb25jZSBoZXJlLCB0byBjYXRjaCBhbiBlcnJvciBpZiBpdCBvY2N1cnNcbiAgICAgIGF3YWl0IGNyZWRlbnRpYWxzKCk7XG5cbiAgICAgIHJldHVybiB0aGlzLl9tYWtlU2RrKGNyZWRlbnRpYWxzLCByZWdpb24pO1xuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICBpZiAoZXJyLm5hbWUgPT09ICdFeHBpcmVkVG9rZW4nKSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9TREtfREVCVUcubXNnKGBBc3N1bWluZyByb2xlIGZhaWxlZDogJHtlcnIubWVzc2FnZX1gKSk7XG4gICAgICB0aHJvdyBuZXcgQXV0aGVudGljYXRpb25FcnJvcihcbiAgICAgICAgW1xuICAgICAgICAgICdDb3VsZCBub3QgYXNzdW1lIHJvbGUgaW4gdGFyZ2V0IGFjY291bnQnLFxuICAgICAgICAgIC4uLihzb3VyY2VEZXNjcmlwdGlvbiA/IFtgdXNpbmcgJHtzb3VyY2VEZXNjcmlwdGlvbn1gXSA6IFtdKSxcbiAgICAgICAgICBlcnIubWVzc2FnZSxcbiAgICAgICAgICBcIi4gUGxlYXNlIG1ha2Ugc3VyZSB0aGF0IHRoaXMgcm9sZSBleGlzdHMgaW4gdGhlIGFjY291bnQuIElmIGl0IGRvZXNuJ3QgZXhpc3QsIChyZSktYm9vdHN0cmFwIHRoZSBlbnZpcm9ubWVudCBcIiArXG4gICAgICAgICAgICBcIndpdGggdGhlIHJpZ2h0ICctLXRydXN0JywgdXNpbmcgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIHRoZSBDREsgQ0xJLlwiLFxuICAgICAgICBdLmpvaW4oJyAnKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZhY3RvcnkgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIGEgbmV3IFNESyBpbnN0YW5jZVxuICAgKlxuICAgKiBUaGlzIGlzIGEgZnVuY3Rpb24gaGVyZSwgaW5zdGVhZCBvZiBhbGwgdGhlIHBsYWNlcyB3aGVyZSB0aGlzIGlzIHVzZWQgY3JlYXRpbmcgYSBgbmV3IFNES2BcbiAgICogaW5zdGFuY2UsIHNvIHRoYXQgaXQgaXMgdHJpdmlhbCB0byBtb2NrIGZyb20gdGVzdHMuXG4gICAqXG4gICAqIFVzZSBsaWtlIHRoaXM6XG4gICAqXG4gICAqIGBgYHRzXG4gICAqIGNvbnN0IG1vY2tTZGsgPSBqZXN0LnNweU9uKFNka1Byb3ZpZGVyLnByb3RvdHlwZSwgJ19tYWtlU2RrJykubW9ja1JldHVyblZhbHVlKG5ldyBNb2NrU2RrKCkpO1xuICAgKiAvLyAuLi5cbiAgICogbW9ja1Nkay5tb2NrUmVzdG9yZSgpO1xuICAgKiBgYGBcbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX21ha2VTZGsoXG4gICAgY3JlZFByb3ZpZGVyOiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcixcbiAgICByZWdpb246IHN0cmluZyxcbiAgKSB7XG4gICAgcmV0dXJuIG5ldyBTREsoY3JlZFByb3ZpZGVyLCByZWdpb24sIHRoaXMucmVxdWVzdEhhbmRsZXIsIHRoaXMuaW9IZWxwZXIsIHRoaXMubG9nZ2VyKTtcbiAgfVxufVxuXG4vKipcbiAqIEFuIEFXUyBhY2NvdW50XG4gKlxuICogQW4gQVdTIGFjY291bnQgYWx3YXlzIGV4aXN0cyBpbiBvbmx5IG9uZSBwYXJ0aXRpb24uIFVzdWFsbHkgd2UgZG9uJ3QgY2FyZSBhYm91dFxuICogdGhlIHBhcnRpdGlvbiwgYnV0IHdoZW4gd2UgbmVlZCB0byBmb3JtIEFSTnMgd2UgZG8uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWNjb3VudCB7XG4gIC8qKlxuICAgKiBUaGUgYWNjb3VudCBudW1iZXJcbiAgICovXG4gIHJlYWRvbmx5IGFjY291bnRJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgcGFydGl0aW9uICgnYXdzJyBvciAnYXdzLWNuJyBvciBvdGhlcndpc2UpXG4gICAqL1xuICByZWFkb25seSBwYXJ0aXRpb246IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXR1cm4gdGhlIHVzZXJuYW1lIHdpdGggY2hhcmFjdGVycyBpbnZhbGlkIGZvciBhIFJvbGVTZXNzaW9uTmFtZSByZW1vdmVkXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vU1RTL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0Fzc3VtZVJvbGUuaHRtbCNBUElfQXNzdW1lUm9sZV9SZXF1ZXN0UGFyYW1ldGVyc1xuICovXG5mdW5jdGlvbiBzYWZlVXNlcm5hbWUoKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG9zLnVzZXJJbmZvKCkudXNlcm5hbWUucmVwbGFjZSgvW15cXHcrPSwuQC1dL2csICdAJyk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiAnbm9uYW1lJztcbiAgfVxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIG9idGFpbmluZyBjcmVkZW50aWFscyBmb3IgYW4gZW52aXJvbm1lbnRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcmVkZW50aWFsc09wdGlvbnMge1xuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgcm9sZSB0aGF0IG5lZWRzIHRvIGJlIGFzc3VtZWQsIGlmIGFueVxuICAgKi9cbiAgcmVhZG9ubHkgYXNzdW1lUm9sZUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogRXh0ZXJuYWwgSUQgcmVxdWlyZWQgdG8gYXNzdW1lIHRoZSBnaXZlbiByb2xlLlxuICAgKi9cbiAgcmVhZG9ubHkgYXNzdW1lUm9sZUV4dGVybmFsSWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNlc3Npb24gdGFncyByZXF1aXJlZCB0byBhc3N1bWUgdGhlIGdpdmVuIHJvbGUuXG4gICAqL1xuICByZWFkb25seSBhc3N1bWVSb2xlQWRkaXRpb25hbE9wdGlvbnM/OiBBc3N1bWVSb2xlQWRkaXRpb25hbE9wdGlvbnM7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIG9idGFpbmluZyBiYXNlIGNyZWRlbnRpYWxzXG4gKi9cbnR5cGUgT2J0YWluQmFzZUNyZWRlbnRpYWxzUmVzdWx0ID1cbiAgfCB7IHNvdXJjZTogJ2NvcnJlY3REZWZhdWx0JzsgY3JlZGVudGlhbHM6IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyIH1cbiAgfCB7IHNvdXJjZTogJ3BsdWdpbic7IHBsdWdpbk5hbWU6IHN0cmluZzsgY3JlZGVudGlhbHM6IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyIH1cbiAgfCB7XG4gICAgc291cmNlOiAnaW5jb3JyZWN0RGVmYXVsdCc7XG4gICAgY3JlZGVudGlhbHM6IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyO1xuICAgIGFjY291bnRJZDogc3RyaW5nO1xuICAgIHVudXNlZFBsdWdpbnM6IHN0cmluZ1tdO1xuICB9XG4gIHwgeyBzb3VyY2U6ICdub25lJzsgdW51c2VkUGx1Z2luczogc3RyaW5nW10gfTtcblxuLyoqXG4gKiBJc29sYXRpbmcgdGhlIGNvZGUgdGhhdCB0cmFuc2xhdGVzIGNhbGN1bGF0aW9uIGVycm9ycyBpbnRvIGh1bWFuIGVycm9yIG1lc3NhZ2VzXG4gKlxuICogV2UgY292ZXIgdGhlIGZvbGxvd2luZyBjYXNlczpcbiAqXG4gKiAtIE5vIGNyZWRlbnRpYWxzIGFyZSBhdmFpbGFibGUgYXQgYWxsXG4gKiAtIERlZmF1bHQgY3JlZGVudGlhbHMgYXJlIGZvciB0aGUgd3JvbmcgYWNjb3VudFxuICovXG5mdW5jdGlvbiBmbXRPYnRhaW5DcmVkZW50aWFsc0Vycm9yKFxuICB0YXJnZXRBY2NvdW50SWQ6IHN0cmluZyxcbiAgb2J0YWluUmVzdWx0OiBPYnRhaW5CYXNlQ3JlZGVudGlhbHNSZXN1bHQgJiB7XG4gICAgc291cmNlOiAnbm9uZScgfCAnaW5jb3JyZWN0RGVmYXVsdCc7XG4gIH0sXG4pOiBzdHJpbmcge1xuICBjb25zdCBtc2cgPSBbYE5lZWQgdG8gcGVyZm9ybSBBV1MgY2FsbHMgZm9yIGFjY291bnQgJHt0YXJnZXRBY2NvdW50SWR9YF07XG4gIHN3aXRjaCAob2J0YWluUmVzdWx0LnNvdXJjZSkge1xuICAgIGNhc2UgJ2luY29ycmVjdERlZmF1bHQnOlxuICAgICAgbXNnLnB1c2goYGJ1dCB0aGUgY3VycmVudCBjcmVkZW50aWFscyBhcmUgZm9yICR7b2J0YWluUmVzdWx0LmFjY291bnRJZH1gKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ25vbmUnOlxuICAgICAgbXNnLnB1c2goJ2J1dCBubyBjcmVkZW50aWFscyBoYXZlIGJlZW4gY29uZmlndXJlZCcpO1xuICB9XG4gIGlmIChvYnRhaW5SZXN1bHQudW51c2VkUGx1Z2lucy5sZW5ndGggPiAwKSB7XG4gICAgbXNnLnB1c2goYGFuZCBub25lIG9mIHRoZXNlIHBsdWdpbnMgZm91bmQgYW55OiAke29idGFpblJlc3VsdC51bnVzZWRQbHVnaW5zLmpvaW4oJywgJyl9YCk7XG4gIH1cbiAgcmV0dXJuIG1zZy5qb2luKCcsICcpO1xufVxuXG4vKipcbiAqIEZvcm1hdCBhIG1lc3NhZ2UgaW5kaWNhdGluZyB3aGVyZSB3ZSBnb3QgYmFzZSBjcmVkZW50aWFscyBmb3IgdGhlIGFzc3VtZSByb2xlXG4gKlxuICogV2UgY292ZXIgdGhlIGZvbGxvd2luZyBjYXNlczpcbiAqXG4gKiAtIERlZmF1bHQgY3JlZGVudGlhbHMgZm9yIHRoZSByaWdodCBhY2NvdW50XG4gKiAtIERlZmF1bHQgY3JlZGVudGlhbHMgZm9yIHRoZSB3cm9uZyBhY2NvdW50XG4gKiAtIENyZWRlbnRpYWxzIHJldHVybmVkIGZyb20gYSBwbHVnaW5cbiAqL1xuZnVuY3Rpb24gZm10T2J0YWluZWRDcmVkZW50aWFscyhvYnRhaW5SZXN1bHQ6IEV4Y2x1ZGU8T2J0YWluQmFzZUNyZWRlbnRpYWxzUmVzdWx0LCB7IHNvdXJjZTogJ25vbmUnIH0+KTogc3RyaW5nIHtcbiAgc3dpdGNoIChvYnRhaW5SZXN1bHQuc291cmNlKSB7XG4gICAgY2FzZSAnY29ycmVjdERlZmF1bHQnOlxuICAgICAgcmV0dXJuICdjdXJyZW50IGNyZWRlbnRpYWxzJztcbiAgICBjYXNlICdwbHVnaW4nOlxuICAgICAgcmV0dXJuIGBjcmVkZW50aWFscyByZXR1cm5lZCBieSBwbHVnaW4gJyR7b2J0YWluUmVzdWx0LnBsdWdpbk5hbWV9J2A7XG4gICAgY2FzZSAnaW5jb3JyZWN0RGVmYXVsdCc6XG4gICAgICBjb25zdCBtc2cgPSBbXTtcbiAgICAgIG1zZy5wdXNoKGBjdXJyZW50IGNyZWRlbnRpYWxzICh3aGljaCBhcmUgZm9yIGFjY291bnQgJHtvYnRhaW5SZXN1bHQuYWNjb3VudElkfWApO1xuXG4gICAgICBpZiAob2J0YWluUmVzdWx0LnVudXNlZFBsdWdpbnMubGVuZ3RoID4gMCkge1xuICAgICAgICBtc2cucHVzaChgLCBhbmQgbm9uZSBvZiB0aGUgZm9sbG93aW5nIHBsdWdpbnMgcHJvdmlkZWQgY3JlZGVudGlhbHM6ICR7b2J0YWluUmVzdWx0LnVudXNlZFBsdWdpbnMuam9pbignLCAnKX1gKTtcbiAgICAgIH1cbiAgICAgIG1zZy5wdXNoKCcpJyk7XG5cbiAgICAgIHJldHVybiBtc2cuam9pbignJyk7XG4gIH1cbn1cblxuLyoqXG4gKiBJbnN0YW50aWF0ZSBhbiBTREsgZm9yIGNvbnRleHQgcHJvdmlkZXJzLiBUaGlzIGZ1bmN0aW9uIGVuc3VyZXMgdGhhdCBhbGxcbiAqIGxvb2t1cCBhc3N1bWUgcm9sZSBvcHRpb25zIGFyZSB1c2VkIHdoZW4gY29udGV4dCBwcm92aWRlcnMgcGVyZm9ybSBsb29rdXBzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5pdENvbnRleHRQcm92aWRlclNkayhhd3M6IFNka1Byb3ZpZGVyLCBvcHRpb25zOiBDb250ZXh0TG9va3VwUm9sZU9wdGlvbnMpOiBQcm9taXNlPFNESz4ge1xuICBjb25zdCBhY2NvdW50ID0gb3B0aW9ucy5hY2NvdW50O1xuICBjb25zdCByZWdpb24gPSBvcHRpb25zLnJlZ2lvbjtcblxuICBjb25zdCBjcmVkczogQ3JlZGVudGlhbHNPcHRpb25zID0ge1xuICAgIGFzc3VtZVJvbGVBcm46IG9wdGlvbnMubG9va3VwUm9sZUFybixcbiAgICBhc3N1bWVSb2xlRXh0ZXJuYWxJZDogb3B0aW9ucy5sb29rdXBSb2xlRXh0ZXJuYWxJZCxcbiAgICBhc3N1bWVSb2xlQWRkaXRpb25hbE9wdGlvbnM6IG9wdGlvbnMuYXNzdW1lUm9sZUFkZGl0aW9uYWxPcHRpb25zLFxuICB9O1xuXG4gIHJldHVybiAoYXdhaXQgYXdzLmZvckVudmlyb25tZW50KEVudmlyb25tZW50VXRpbHMubWFrZShhY2NvdW50LCByZWdpb24pLCBNb2RlLkZvclJlYWRpbmcsIGNyZWRzKSkuc2RrO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNka1Byb3ZpZGVyU2VydmljZXMge1xuICAvKipcbiAgICogQW4gSU8gaGVscGVyIGZvciBlbWl0dGluZyBtZXNzYWdlc1xuICAgKi9cbiAgcmVhZG9ubHkgaW9IZWxwZXI6IElvSGVscGVyO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVxdWVzdCBoYW5kbGVyIHNldHRpbmdzXG4gICAqL1xuICByZWFkb25seSByZXF1ZXN0SGFuZGxlcj86IE5vZGVIdHRwSGFuZGxlck9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIEEgcGx1Z2luIGhvc3RcbiAgICovXG4gIHJlYWRvbmx5IHBsdWdpbkhvc3Q/OiBQbHVnaW5Ib3N0O1xuXG4gIC8qKlxuICAgKiBBbiBTREsgbG9nZ2VyXG4gICAqL1xuICByZWFkb25seSBsb2dnZXI/OiBMb2dnZXI7XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.d.ts new file mode 100644 index 000000000..fad1bd30c --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.d.ts @@ -0,0 +1,239 @@ +import type { FunctionConfiguration, GetSchemaCreationStatusCommandInput, GetSchemaCreationStatusCommandOutput, ListFunctionsCommandInput, StartSchemaCreationCommandInput, StartSchemaCreationCommandOutput, UpdateApiKeyCommandInput, UpdateApiKeyCommandOutput, UpdateFunctionCommandInput, UpdateFunctionCommandOutput, UpdateResolverCommandInput, UpdateResolverCommandOutput } from '@aws-sdk/client-appsync'; +import type { GetResourceCommandInput, GetResourceCommandOutput, ListResourcesCommandInput, ListResourcesCommandOutput } from '@aws-sdk/client-cloudcontrol'; +import type { ContinueUpdateRollbackCommandInput, ContinueUpdateRollbackCommandOutput, DescribeStackEventsCommandOutput, DescribeStackResourcesCommandInput, DescribeStackResourcesCommandOutput, ListStacksCommandInput, ListStacksCommandOutput, RollbackStackCommandInput, RollbackStackCommandOutput, StackResourceSummary, CreateChangeSetCommandInput, CreateChangeSetCommandOutput, CreateGeneratedTemplateCommandInput, CreateGeneratedTemplateCommandOutput, CreateStackCommandInput, CreateStackCommandOutput, DeleteChangeSetCommandInput, DeleteChangeSetCommandOutput, DeleteGeneratedTemplateCommandInput, DeleteGeneratedTemplateCommandOutput, DeleteStackCommandInput, DeleteStackCommandOutput, DescribeChangeSetCommandInput, DescribeChangeSetCommandOutput, DescribeGeneratedTemplateCommandInput, DescribeGeneratedTemplateCommandOutput, DescribeResourceScanCommandInput, DescribeResourceScanCommandOutput, DescribeStackEventsCommandInput, DescribeStacksCommandInput, DescribeStacksCommandOutput, ExecuteChangeSetCommandInput, ExecuteChangeSetCommandOutput, GetGeneratedTemplateCommandInput, GetGeneratedTemplateCommandOutput, GetTemplateCommandInput, GetTemplateCommandOutput, GetTemplateSummaryCommandInput, GetTemplateSummaryCommandOutput, ListExportsCommandInput, ListExportsCommandOutput, ListResourceScanRelatedResourcesCommandInput, ListResourceScanRelatedResourcesCommandOutput, ListResourceScanResourcesCommandInput, ListResourceScanResourcesCommandOutput, ListResourceScansCommandInput, ListResourceScansCommandOutput, ListStackResourcesCommandInput, StartResourceScanCommandInput, StartResourceScanCommandOutput, UpdateStackCommandInput, UpdateStackCommandOutput, UpdateTerminationProtectionCommandInput, UpdateTerminationProtectionCommandOutput, StackSummary, DescribeStackDriftDetectionStatusCommandInput, DescribeStackDriftDetectionStatusCommandOutput, DescribeStackResourceDriftsCommandOutput, DetectStackDriftCommandInput, DetectStackDriftCommandOutput, DetectStackResourceDriftCommandInput, DetectStackResourceDriftCommandOutput, DescribeStackResourceDriftsCommandInput } from '@aws-sdk/client-cloudformation'; +import type { FilterLogEventsCommandInput, FilterLogEventsCommandOutput, DescribeLogGroupsCommandInput, DescribeLogGroupsCommandOutput } from '@aws-sdk/client-cloudwatch-logs'; +import { type UpdateProjectCommandInput, type UpdateProjectCommandOutput } from '@aws-sdk/client-codebuild'; +import { type DescribeAvailabilityZonesCommandInput, type DescribeAvailabilityZonesCommandOutput, type DescribeImagesCommandInput, type DescribeImagesCommandOutput, type DescribeInstancesCommandInput, type DescribeInstancesCommandOutput, type DescribeRouteTablesCommandInput, type DescribeRouteTablesCommandOutput, type DescribeSecurityGroupsCommandInput, type DescribeSecurityGroupsCommandOutput, type DescribeSubnetsCommandInput, type DescribeSubnetsCommandOutput, type DescribeVpcEndpointServicesCommandInput, type DescribeVpcEndpointServicesCommandOutput, type DescribeVpcsCommandInput, type DescribeVpcsCommandOutput, type DescribeVpnGatewaysCommandInput, type DescribeVpnGatewaysCommandOutput } from '@aws-sdk/client-ec2'; +import type { BatchDeleteImageCommandInput, BatchDeleteImageCommandOutput, ListImagesCommandInput, ListImagesCommandOutput, PutImageCommandInput, PutImageCommandOutput, BatchGetImageCommandInput, BatchGetImageCommandOutput, CreateRepositoryCommandInput, CreateRepositoryCommandOutput, DescribeImagesCommandInput as ECRDescribeImagesCommandInput, DescribeImagesCommandOutput as ECRDescribeImagesCommandOutput, DescribeRepositoriesCommandInput, DescribeRepositoriesCommandOutput, GetAuthorizationTokenCommandInput, GetAuthorizationTokenCommandOutput, PutImageScanningConfigurationCommandInput, PutImageScanningConfigurationCommandOutput } from '@aws-sdk/client-ecr'; +import type { DescribeServicesCommandInput, RegisterTaskDefinitionCommandInput, ListClustersCommandInput, ListClustersCommandOutput, RegisterTaskDefinitionCommandOutput, UpdateServiceCommandInput, UpdateServiceCommandOutput } from '@aws-sdk/client-ecs'; +import type { Listener, LoadBalancer, DescribeListenersCommandInput, DescribeListenersCommandOutput, DescribeLoadBalancersCommandInput, DescribeLoadBalancersCommandOutput, DescribeTagsCommandInput, DescribeTagsCommandOutput } from '@aws-sdk/client-elastic-load-balancing-v2'; +import { type CreatePolicyCommandInput, type CreatePolicyCommandOutput, type GetPolicyCommandInput, type GetPolicyCommandOutput, type GetRoleCommandInput, type GetRoleCommandOutput } from '@aws-sdk/client-iam'; +import { type DescribeKeyCommandInput, type DescribeKeyCommandOutput, type ListAliasesCommandInput, type ListAliasesCommandOutput } from '@aws-sdk/client-kms'; +import { type InvokeCommandInput, type InvokeCommandOutput, type PublishVersionCommandInput, type PublishVersionCommandOutput, type UpdateAliasCommandInput, type UpdateAliasCommandOutput, type UpdateFunctionCodeCommandInput, type UpdateFunctionCodeCommandOutput, type UpdateFunctionConfigurationCommandInput, type UpdateFunctionConfigurationCommandOutput } from '@aws-sdk/client-lambda'; +import { type GetHostedZoneCommandInput, type GetHostedZoneCommandOutput, type ListHostedZonesByNameCommandInput, type ListHostedZonesByNameCommandOutput, type ListHostedZonesCommandInput, type ListHostedZonesCommandOutput } from '@aws-sdk/client-route-53'; +import type { DeleteObjectsCommandInput, DeleteObjectsCommandOutput, DeleteObjectTaggingCommandInput, DeleteObjectTaggingCommandOutput, GetObjectTaggingCommandInput, GetObjectTaggingCommandOutput, PutObjectTaggingCommandInput, PutObjectTaggingCommandOutput, CompleteMultipartUploadCommandOutput, GetBucketEncryptionCommandInput, GetBucketEncryptionCommandOutput, GetBucketLocationCommandInput, GetBucketLocationCommandOutput, GetObjectCommandInput, GetObjectCommandOutput, ListObjectsV2CommandInput, ListObjectsV2CommandOutput, PutObjectCommandInput } from '@aws-sdk/client-s3'; +import { type GetSecretValueCommandInput, type GetSecretValueCommandOutput } from '@aws-sdk/client-secrets-manager'; +import type { UpdateStateMachineCommandInput, UpdateStateMachineCommandOutput } from '@aws-sdk/client-sfn'; +import { type GetParameterCommandInput, type GetParameterCommandOutput } from '@aws-sdk/client-ssm'; +import type { NodeHttpHandlerOptions } from '@smithy/node-http-handler'; +import type { AwsCredentialIdentityProvider, Logger } from '@smithy/types'; +import { ConfiguredRetryStrategy } from '@smithy/util-retry'; +import type { WaiterResult } from '@smithy/util-waiter'; +import type { Account } from './sdk-provider'; +import { type IoHelper } from '../io/private'; +export interface S3ClientOptions { + /** + * If APIs are used that require MD5 checksums. + * + * Some S3 APIs in SDKv2 have a bug that always requires them to use a MD5 checksum. + * These APIs are not going to be supported in a FIPS environment. + */ + needsMd5Checksums?: boolean; +} +/** + * Additional SDK configuration options + */ +export interface SdkOptions { + /** + * Additional descriptive strings that indicate where the "AssumeRole" credentials are coming from + * + * Will be printed in an error message to help users diagnose auth problems. + */ + readonly assumeRoleCredentialsSourceDescription?: string; +} +export interface ConfigurationOptions { + region: string; + credentials: AwsCredentialIdentityProvider; + requestHandler: NodeHttpHandlerOptions; + retryStrategy: ConfiguredRetryStrategy; + customUserAgent: string; + logger?: Logger; + s3DisableBodySigning?: boolean; + computeChecksums?: boolean; +} +export interface IAppSyncClient { + getSchemaCreationStatus(input: GetSchemaCreationStatusCommandInput): Promise; + startSchemaCreation(input: StartSchemaCreationCommandInput): Promise; + updateApiKey(input: UpdateApiKeyCommandInput): Promise; + updateFunction(input: UpdateFunctionCommandInput): Promise; + updateResolver(input: UpdateResolverCommandInput): Promise; + listFunctions(input: ListFunctionsCommandInput): Promise; +} +export interface ICloudControlClient { + listResources(input: ListResourcesCommandInput): Promise; + getResource(input: GetResourceCommandInput): Promise; +} +export interface ICloudFormationClient { + continueUpdateRollback(input: ContinueUpdateRollbackCommandInput): Promise; + createChangeSet(input: CreateChangeSetCommandInput): Promise; + createGeneratedTemplate(input: CreateGeneratedTemplateCommandInput): Promise; + createStack(input: CreateStackCommandInput): Promise; + deleteChangeSet(input: DeleteChangeSetCommandInput): Promise; + deleteGeneratedTemplate(input: DeleteGeneratedTemplateCommandInput): Promise; + deleteStack(input: DeleteStackCommandInput): Promise; + describeChangeSet(input: DescribeChangeSetCommandInput): Promise; + describeGeneratedTemplate(input: DescribeGeneratedTemplateCommandInput): Promise; + describeResourceScan(input: DescribeResourceScanCommandInput): Promise; + describeStackDriftDetectionStatus(input: DescribeStackDriftDetectionStatusCommandInput): Promise; + describeStacks(input: DescribeStacksCommandInput): Promise; + describeStackResourceDrifts(input: DescribeStackResourceDriftsCommandInput): Promise; + describeStackResources(input: DescribeStackResourcesCommandInput): Promise; + detectStackDrift(input: DetectStackDriftCommandInput): Promise; + detectStackResourceDrift(input: DetectStackResourceDriftCommandInput): Promise; + executeChangeSet(input: ExecuteChangeSetCommandInput): Promise; + getGeneratedTemplate(input: GetGeneratedTemplateCommandInput): Promise; + getTemplate(input: GetTemplateCommandInput): Promise; + getTemplateSummary(input: GetTemplateSummaryCommandInput): Promise; + listExports(input: ListExportsCommandInput): Promise; + listResourceScanRelatedResources(input: ListResourceScanRelatedResourcesCommandInput): Promise; + listResourceScanResources(input: ListResourceScanResourcesCommandInput): Promise; + listResourceScans(input?: ListResourceScansCommandInput): Promise; + listStacks(input: ListStacksCommandInput): Promise; + rollbackStack(input: RollbackStackCommandInput): Promise; + startResourceScan(input: StartResourceScanCommandInput): Promise; + updateStack(input: UpdateStackCommandInput): Promise; + updateTerminationProtection(input: UpdateTerminationProtectionCommandInput): Promise; + describeStackEvents(input: DescribeStackEventsCommandInput): Promise; + listStackResources(input: ListStackResourcesCommandInput): Promise; + paginatedListStacks(input: ListStacksCommandInput): Promise; +} +export interface ICloudWatchLogsClient { + describeLogGroups(input: DescribeLogGroupsCommandInput): Promise; + filterLogEvents(input: FilterLogEventsCommandInput): Promise; +} +export interface ICodeBuildClient { + updateProject(input: UpdateProjectCommandInput): Promise; +} +export interface IEC2Client { + describeAvailabilityZones(input: DescribeAvailabilityZonesCommandInput): Promise; + describeImages(input: DescribeImagesCommandInput): Promise; + describeInstances(input: DescribeInstancesCommandInput): Promise; + describeRouteTables(input: DescribeRouteTablesCommandInput): Promise; + describeSecurityGroups(input: DescribeSecurityGroupsCommandInput): Promise; + describeSubnets(input: DescribeSubnetsCommandInput): Promise; + describeVpcEndpointServices(input: DescribeVpcEndpointServicesCommandInput): Promise; + describeVpcs(input: DescribeVpcsCommandInput): Promise; + describeVpnGateways(input: DescribeVpnGatewaysCommandInput): Promise; +} +export interface IECRClient { + batchDeleteImage(input: BatchDeleteImageCommandInput): Promise; + batchGetImage(input: BatchGetImageCommandInput): Promise; + createRepository(input: CreateRepositoryCommandInput): Promise; + describeImages(input: ECRDescribeImagesCommandInput): Promise; + describeRepositories(input: DescribeRepositoriesCommandInput): Promise; + getAuthorizationToken(input: GetAuthorizationTokenCommandInput): Promise; + listImages(input: ListImagesCommandInput): Promise; + putImage(input: PutImageCommandInput): Promise; + putImageScanningConfiguration(input: PutImageScanningConfigurationCommandInput): Promise; +} +export interface IECSClient { + listClusters(input: ListClustersCommandInput): Promise; + registerTaskDefinition(input: RegisterTaskDefinitionCommandInput): Promise; + updateService(input: UpdateServiceCommandInput): Promise; + waitUntilServicesStable(input: DescribeServicesCommandInput): Promise; +} +export interface IElasticLoadBalancingV2Client { + describeListeners(input: DescribeListenersCommandInput): Promise; + describeLoadBalancers(input: DescribeLoadBalancersCommandInput): Promise; + describeTags(input: DescribeTagsCommandInput): Promise; + paginateDescribeListeners(input: DescribeListenersCommandInput): Promise; + paginateDescribeLoadBalancers(input: DescribeLoadBalancersCommandInput): Promise; +} +export interface IIAMClient { + createPolicy(input: CreatePolicyCommandInput): Promise; + getPolicy(input: GetPolicyCommandInput): Promise; + getRole(input: GetRoleCommandInput): Promise; +} +export interface IKMSClient { + describeKey(input: DescribeKeyCommandInput): Promise; + listAliases(input: ListAliasesCommandInput): Promise; +} +export interface ILambdaClient { + invokeCommand(input: InvokeCommandInput): Promise; + publishVersion(input: PublishVersionCommandInput): Promise; + updateAlias(input: UpdateAliasCommandInput): Promise; + updateFunctionCode(input: UpdateFunctionCodeCommandInput): Promise; + updateFunctionConfiguration(input: UpdateFunctionConfigurationCommandInput): Promise; + waitUntilFunctionUpdated(delaySeconds: number, input: UpdateFunctionConfigurationCommandInput): Promise; +} +export interface IRoute53Client { + getHostedZone(input: GetHostedZoneCommandInput): Promise; + listHostedZones(input: ListHostedZonesCommandInput): Promise; + listHostedZonesByName(input: ListHostedZonesByNameCommandInput): Promise; +} +export interface IS3Client { + deleteObjects(input: DeleteObjectsCommandInput): Promise; + deleteObjectTagging(input: DeleteObjectTaggingCommandInput): Promise; + getBucketEncryption(input: GetBucketEncryptionCommandInput): Promise; + getBucketLocation(input: GetBucketLocationCommandInput): Promise; + getObject(input: GetObjectCommandInput): Promise; + getObjectTagging(input: GetObjectTaggingCommandInput): Promise; + listObjectsV2(input: ListObjectsV2CommandInput): Promise; + putObjectTagging(input: PutObjectTaggingCommandInput): Promise; + upload(input: PutObjectCommandInput): Promise; +} +export interface ISecretsManagerClient { + getSecretValue(input: GetSecretValueCommandInput): Promise; +} +export interface ISSMClient { + getParameter(input: GetParameterCommandInput): Promise; +} +export interface IStepFunctionsClient { + updateStateMachine(input: UpdateStateMachineCommandInput): Promise; +} +/** + * Base functionality of SDK without credential fetching + */ +export declare class SDK { + private readonly credProvider; + readonly currentRegion: string; + readonly config: ConfigurationOptions; + protected readonly logger?: Logger; + private readonly accountCache; + /** + * STS is used to check credential validity, don't do too many retries. + */ + private readonly stsRetryStrategy; + /** + * Whether we have proof that the credentials have not expired + * + * We need to do some manual plumbing around this because the JS SDKv2 treats `ExpiredToken` + * as retriable and we have hefty retries on CFN calls making the CLI hang for a good 15 minutes + * if the credentials have expired. + */ + private _credentialsValidated; + /** + * A function to create debug messages + */ + private readonly debug; + constructor(credProvider: AwsCredentialIdentityProvider, region: string, requestHandler: NodeHttpHandlerOptions, ioHelper: IoHelper, logger?: Logger); + appendCustomUserAgent(userAgentData?: string): void; + removeCustomUserAgent(userAgentData: string): void; + appsync(): IAppSyncClient; + cloudControl(): ICloudControlClient; + cloudFormation(): ICloudFormationClient; + cloudWatchLogs(): ICloudWatchLogsClient; + codeBuild(): ICodeBuildClient; + ec2(): IEC2Client; + ecr(): IECRClient; + ecs(): IECSClient; + elbv2(): IElasticLoadBalancingV2Client; + iam(): IIAMClient; + kms(): IKMSClient; + lambda(): ILambdaClient; + route53(): IRoute53Client; + s3(): IS3Client; + secretsManager(): ISecretsManagerClient; + ssm(): ISSMClient; + stepFunctions(): IStepFunctionsClient; + /** + * The AWS SDK v3 requires a client config and a command in order to get an endpoint for + * any given service. + */ + getUrlSuffix(region: string): Promise; + currentAccount(): Promise; + /** + * Make sure the the current credentials are not expired + */ + validateCredentials(): Promise; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.js new file mode 100644 index 000000000..32320ce7e --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/sdk.js @@ -0,0 +1,395 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SDK = void 0; +const client_appsync_1 = require("@aws-sdk/client-appsync"); +const client_cloudcontrol_1 = require("@aws-sdk/client-cloudcontrol"); +const client_cloudformation_1 = require("@aws-sdk/client-cloudformation"); +const client_cloudwatch_logs_1 = require("@aws-sdk/client-cloudwatch-logs"); +const client_codebuild_1 = require("@aws-sdk/client-codebuild"); +const client_ec2_1 = require("@aws-sdk/client-ec2"); +const client_ecr_1 = require("@aws-sdk/client-ecr"); +const client_ecs_1 = require("@aws-sdk/client-ecs"); +const client_elastic_load_balancing_v2_1 = require("@aws-sdk/client-elastic-load-balancing-v2"); +const client_iam_1 = require("@aws-sdk/client-iam"); +const client_kms_1 = require("@aws-sdk/client-kms"); +const client_lambda_1 = require("@aws-sdk/client-lambda"); +const client_route_53_1 = require("@aws-sdk/client-route-53"); +const client_s3_1 = require("@aws-sdk/client-s3"); +const client_secrets_manager_1 = require("@aws-sdk/client-secrets-manager"); +const client_sfn_1 = require("@aws-sdk/client-sfn"); +const client_ssm_1 = require("@aws-sdk/client-ssm"); +const client_sts_1 = require("@aws-sdk/client-sts"); +const lib_storage_1 = require("@aws-sdk/lib-storage"); +const middleware_endpoint_1 = require("@smithy/middleware-endpoint"); +const util_retry_1 = require("@smithy/util-retry"); +const account_cache_1 = require("./account-cache"); +const cached_1 = require("./cached"); +const tracing_1 = require("./tracing"); +const user_agent_1 = require("./user-agent"); +const util_1 = require("../../util"); +const private_1 = require("../io/private"); +const toolkit_error_1 = require("../toolkit-error"); +/** + * Base functionality of SDK without credential fetching + */ +let SDK = class SDK { + credProvider; + currentRegion; + config; + logger; + accountCache; + /** + * STS is used to check credential validity, don't do too many retries. + */ + stsRetryStrategy = new util_retry_1.ConfiguredRetryStrategy(3, (attempt) => 100 * (2 ** attempt)); + /** + * Whether we have proof that the credentials have not expired + * + * We need to do some manual plumbing around this because the JS SDKv2 treats `ExpiredToken` + * as retriable and we have hefty retries on CFN calls making the CLI hang for a good 15 minutes + * if the credentials have expired. + */ + _credentialsValidated = false; + /** + * A function to create debug messages + */ + debug; + constructor(credProvider, region, requestHandler, ioHelper, logger) { + this.credProvider = credProvider; + const debugFn = async (msg) => ioHelper.notify(private_1.IO.DEFAULT_SDK_DEBUG.msg(msg)); + this.accountCache = new account_cache_1.AccountAccessKeyCache(account_cache_1.AccountAccessKeyCache.DEFAULT_PATH, debugFn); + this.debug = debugFn; + this.config = { + region, + credentials: credProvider, + requestHandler, + retryStrategy: new util_retry_1.ConfiguredRetryStrategy(7, (attempt) => 300 * (2 ** attempt)), + customUserAgent: (0, user_agent_1.defaultCliUserAgent)(), + logger, + }; + this.logger = logger; + this.currentRegion = region; + } + appendCustomUserAgent(userAgentData) { + if (!userAgentData) { + return; + } + const currentCustomUserAgent = this.config.customUserAgent; + this.config.customUserAgent = currentCustomUserAgent ? `${currentCustomUserAgent} ${userAgentData}` : userAgentData; + } + removeCustomUserAgent(userAgentData) { + this.config.customUserAgent = this.config.customUserAgent?.replace(userAgentData, ''); + } + appsync() { + const client = new client_appsync_1.AppSyncClient(this.config); + return { + getSchemaCreationStatus: (input) => client.send(new client_appsync_1.GetSchemaCreationStatusCommand(input)), + startSchemaCreation: (input) => client.send(new client_appsync_1.StartSchemaCreationCommand(input)), + updateApiKey: (input) => client.send(new client_appsync_1.UpdateApiKeyCommand(input)), + updateFunction: (input) => client.send(new client_appsync_1.UpdateFunctionCommand(input)), + updateResolver: (input) => client.send(new client_appsync_1.UpdateResolverCommand(input)), + // Pagination Functions + listFunctions: async (input) => { + const functions = Array(); + const paginator = (0, client_appsync_1.paginateListFunctions)({ client }, input); + for await (const page of paginator) { + functions.push(...(page.functions || [])); + } + return functions; + }, + }; + } + cloudControl() { + const client = new client_cloudcontrol_1.CloudControlClient(this.config); + return { + listResources: (input) => client.send(new client_cloudcontrol_1.ListResourcesCommand(input)), + getResource: (input) => client.send(new client_cloudcontrol_1.GetResourceCommand(input)), + }; + } + cloudFormation() { + const client = new client_cloudformation_1.CloudFormationClient({ + ...this.config, + retryStrategy: new util_retry_1.ConfiguredRetryStrategy(11, (attempt) => 1000 * (2 ** attempt)), + }); + return { + continueUpdateRollback: async (input) => client.send(new client_cloudformation_1.ContinueUpdateRollbackCommand(input)), + createChangeSet: (input) => client.send(new client_cloudformation_1.CreateChangeSetCommand(input)), + createGeneratedTemplate: (input) => client.send(new client_cloudformation_1.CreateGeneratedTemplateCommand(input)), + createStack: (input) => client.send(new client_cloudformation_1.CreateStackCommand(input)), + deleteChangeSet: (input) => client.send(new client_cloudformation_1.DeleteChangeSetCommand(input)), + deleteGeneratedTemplate: (input) => client.send(new client_cloudformation_1.DeleteGeneratedTemplateCommand(input)), + deleteStack: (input) => client.send(new client_cloudformation_1.DeleteStackCommand(input)), + detectStackDrift: (input) => client.send(new client_cloudformation_1.DetectStackDriftCommand(input)), + detectStackResourceDrift: (input) => client.send(new client_cloudformation_1.DetectStackResourceDriftCommand(input)), + describeChangeSet: (input) => client.send(new client_cloudformation_1.DescribeChangeSetCommand(input)), + describeGeneratedTemplate: (input) => client.send(new client_cloudformation_1.DescribeGeneratedTemplateCommand(input)), + describeResourceScan: (input) => client.send(new client_cloudformation_1.DescribeResourceScanCommand(input)), + describeStackDriftDetectionStatus: (input) => client.send(new client_cloudformation_1.DescribeStackDriftDetectionStatusCommand(input)), + describeStackResourceDrifts: (input) => client.send(new client_cloudformation_1.DescribeStackResourceDriftsCommand(input)), + describeStacks: (input) => client.send(new client_cloudformation_1.DescribeStacksCommand(input)), + describeStackResources: (input) => client.send(new client_cloudformation_1.DescribeStackResourcesCommand(input)), + executeChangeSet: (input) => client.send(new client_cloudformation_1.ExecuteChangeSetCommand(input)), + getGeneratedTemplate: (input) => client.send(new client_cloudformation_1.GetGeneratedTemplateCommand(input)), + getTemplate: (input) => client.send(new client_cloudformation_1.GetTemplateCommand(input)), + getTemplateSummary: (input) => client.send(new client_cloudformation_1.GetTemplateSummaryCommand(input)), + listExports: (input) => client.send(new client_cloudformation_1.ListExportsCommand(input)), + listResourceScanRelatedResources: (input) => client.send(new client_cloudformation_1.ListResourceScanRelatedResourcesCommand(input)), + listResourceScanResources: (input) => client.send(new client_cloudformation_1.ListResourceScanResourcesCommand(input)), + listResourceScans: (input) => client.send(new client_cloudformation_1.ListResourceScansCommand(input)), + listStacks: (input) => client.send(new client_cloudformation_1.ListStacksCommand(input)), + rollbackStack: (input) => client.send(new client_cloudformation_1.RollbackStackCommand(input)), + startResourceScan: (input) => client.send(new client_cloudformation_1.StartResourceScanCommand(input)), + updateStack: (input) => client.send(new client_cloudformation_1.UpdateStackCommand(input)), + updateTerminationProtection: (input) => client.send(new client_cloudformation_1.UpdateTerminationProtectionCommand(input)), + describeStackEvents: (input) => { + return client.send(new client_cloudformation_1.DescribeStackEventsCommand(input)); + }, + listStackResources: async (input) => { + const stackResources = Array(); + const paginator = (0, client_cloudformation_1.paginateListStackResources)({ client }, input); + for await (const page of paginator) { + stackResources.push(...(page?.StackResourceSummaries || [])); + } + return stackResources; + }, + paginatedListStacks: async (input) => { + const stackResources = Array(); + const paginator = (0, client_cloudformation_1.paginateListStacks)({ client }, input); + for await (const page of paginator) { + stackResources.push(...(page?.StackSummaries || [])); + } + return stackResources; + }, + }; + } + cloudWatchLogs() { + const client = new client_cloudwatch_logs_1.CloudWatchLogsClient(this.config); + return { + describeLogGroups: (input) => client.send(new client_cloudwatch_logs_1.DescribeLogGroupsCommand(input)), + filterLogEvents: (input) => client.send(new client_cloudwatch_logs_1.FilterLogEventsCommand(input)), + }; + } + codeBuild() { + const client = new client_codebuild_1.CodeBuildClient(this.config); + return { + updateProject: (input) => client.send(new client_codebuild_1.UpdateProjectCommand(input)), + }; + } + ec2() { + const client = new client_ec2_1.EC2Client(this.config); + return { + describeAvailabilityZones: (input) => client.send(new client_ec2_1.DescribeAvailabilityZonesCommand(input)), + describeImages: (input) => client.send(new client_ec2_1.DescribeImagesCommand(input)), + describeInstances: (input) => client.send(new client_ec2_1.DescribeInstancesCommand(input)), + describeRouteTables: (input) => client.send(new client_ec2_1.DescribeRouteTablesCommand(input)), + describeSecurityGroups: (input) => client.send(new client_ec2_1.DescribeSecurityGroupsCommand(input)), + describeSubnets: (input) => client.send(new client_ec2_1.DescribeSubnetsCommand(input)), + describeVpcEndpointServices: (input) => client.send(new client_ec2_1.DescribeVpcEndpointServicesCommand(input)), + describeVpcs: (input) => client.send(new client_ec2_1.DescribeVpcsCommand(input)), + describeVpnGateways: (input) => client.send(new client_ec2_1.DescribeVpnGatewaysCommand(input)), + }; + } + ecr() { + const client = new client_ecr_1.ECRClient(this.config); + return { + batchDeleteImage: (input) => client.send(new client_ecr_1.BatchDeleteImageCommand(input)), + batchGetImage: (input) => client.send(new client_ecr_1.BatchGetImageCommand(input)), + createRepository: (input) => client.send(new client_ecr_1.CreateRepositoryCommand(input)), + describeImages: (input) => client.send(new client_ecr_1.DescribeImagesCommand(input)), + describeRepositories: (input) => client.send(new client_ecr_1.DescribeRepositoriesCommand(input)), + getAuthorizationToken: (input) => client.send(new client_ecr_1.GetAuthorizationTokenCommand(input)), + listImages: (input) => client.send(new client_ecr_1.ListImagesCommand(input)), + putImage: (input) => client.send(new client_ecr_1.PutImageCommand(input)), + putImageScanningConfiguration: (input) => client.send(new client_ecr_1.PutImageScanningConfigurationCommand(input)), + }; + } + ecs() { + const client = new client_ecs_1.ECSClient(this.config); + return { + listClusters: (input) => client.send(new client_ecs_1.ListClustersCommand(input)), + registerTaskDefinition: (input) => client.send(new client_ecs_1.RegisterTaskDefinitionCommand(input)), + updateService: (input) => client.send(new client_ecs_1.UpdateServiceCommand(input)), + // Waiters + waitUntilServicesStable: (input) => { + return (0, client_ecs_1.waitUntilServicesStable)({ + client, + maxWaitTime: 600, + minDelay: 6, + maxDelay: 6, + }, input); + }, + }; + } + elbv2() { + const client = new client_elastic_load_balancing_v2_1.ElasticLoadBalancingV2Client(this.config); + return { + describeListeners: (input) => client.send(new client_elastic_load_balancing_v2_1.DescribeListenersCommand(input)), + describeLoadBalancers: (input) => client.send(new client_elastic_load_balancing_v2_1.DescribeLoadBalancersCommand(input)), + describeTags: (input) => client.send(new client_elastic_load_balancing_v2_1.DescribeTagsCommand(input)), + // Pagination Functions + paginateDescribeListeners: async (input) => { + const listeners = Array(); + const paginator = (0, client_elastic_load_balancing_v2_1.paginateDescribeListeners)({ client }, input); + for await (const page of paginator) { + listeners.push(...(page?.Listeners || [])); + } + return listeners; + }, + paginateDescribeLoadBalancers: async (input) => { + const loadBalancers = Array(); + const paginator = (0, client_elastic_load_balancing_v2_1.paginateDescribeLoadBalancers)({ client }, input); + for await (const page of paginator) { + loadBalancers.push(...(page?.LoadBalancers || [])); + } + return loadBalancers; + }, + }; + } + iam() { + const client = new client_iam_1.IAMClient(this.config); + return { + createPolicy: (input) => client.send(new client_iam_1.CreatePolicyCommand(input)), + getPolicy: (input) => client.send(new client_iam_1.GetPolicyCommand(input)), + getRole: (input) => client.send(new client_iam_1.GetRoleCommand(input)), + }; + } + kms() { + const client = new client_kms_1.KMSClient(this.config); + return { + describeKey: (input) => client.send(new client_kms_1.DescribeKeyCommand(input)), + listAliases: (input) => client.send(new client_kms_1.ListAliasesCommand(input)), + }; + } + lambda() { + const client = new client_lambda_1.LambdaClient(this.config); + return { + invokeCommand: (input) => client.send(new client_lambda_1.InvokeCommand(input)), + publishVersion: (input) => client.send(new client_lambda_1.PublishVersionCommand(input)), + updateAlias: (input) => client.send(new client_lambda_1.UpdateAliasCommand(input)), + updateFunctionCode: (input) => client.send(new client_lambda_1.UpdateFunctionCodeCommand(input)), + updateFunctionConfiguration: (input) => client.send(new client_lambda_1.UpdateFunctionConfigurationCommand(input)), + // Waiters + waitUntilFunctionUpdated: (delaySeconds, input) => { + return (0, client_lambda_1.waitUntilFunctionUpdatedV2)({ + client, + maxDelay: delaySeconds, + minDelay: delaySeconds, + maxWaitTime: delaySeconds * 60, + }, input); + }, + }; + } + route53() { + const client = new client_route_53_1.Route53Client(this.config); + return { + getHostedZone: (input) => client.send(new client_route_53_1.GetHostedZoneCommand(input)), + listHostedZones: (input) => client.send(new client_route_53_1.ListHostedZonesCommand(input)), + listHostedZonesByName: (input) => client.send(new client_route_53_1.ListHostedZonesByNameCommand(input)), + }; + } + s3() { + const client = new client_s3_1.S3Client(this.config); + return { + deleteObjects: (input) => client.send(new client_s3_1.DeleteObjectsCommand({ + ...input, + ChecksumAlgorithm: 'SHA256', + })), + deleteObjectTagging: (input) => client.send(new client_s3_1.DeleteObjectTaggingCommand(input)), + getBucketEncryption: (input) => client.send(new client_s3_1.GetBucketEncryptionCommand(input)), + getBucketLocation: (input) => client.send(new client_s3_1.GetBucketLocationCommand(input)), + getObject: (input) => client.send(new client_s3_1.GetObjectCommand(input)), + getObjectTagging: (input) => client.send(new client_s3_1.GetObjectTaggingCommand(input)), + listObjectsV2: (input) => client.send(new client_s3_1.ListObjectsV2Command(input)), + putObjectTagging: (input) => client.send(new client_s3_1.PutObjectTaggingCommand({ + ...input, + ChecksumAlgorithm: 'SHA256', + })), + upload: (input) => { + try { + const upload = new lib_storage_1.Upload({ + client, + params: { ...input, ChecksumAlgorithm: 'SHA256' }, + }); + return upload.done(); + } + catch (e) { + throw new toolkit_error_1.AuthenticationError(`Upload failed: ${(0, util_1.formatErrorMessage)(e)}`); + } + }, + }; + } + secretsManager() { + const client = new client_secrets_manager_1.SecretsManagerClient(this.config); + return { + getSecretValue: (input) => client.send(new client_secrets_manager_1.GetSecretValueCommand(input)), + }; + } + ssm() { + const client = new client_ssm_1.SSMClient(this.config); + return { + getParameter: (input) => client.send(new client_ssm_1.GetParameterCommand(input)), + }; + } + stepFunctions() { + const client = new client_sfn_1.SFNClient(this.config); + return { + updateStateMachine: (input) => client.send(new client_sfn_1.UpdateStateMachineCommand(input)), + }; + } + /** + * The AWS SDK v3 requires a client config and a command in order to get an endpoint for + * any given service. + */ + async getUrlSuffix(region) { + const cfn = new client_cloudformation_1.CloudFormationClient({ region }); + const endpoint = await (0, middleware_endpoint_1.getEndpointFromInstructions)({}, client_cloudformation_1.DescribeStackResourcesCommand, { ...cfn.config }); + return endpoint.url.hostname.split(`${region}.`).pop(); + } + async currentAccount() { + return (0, cached_1.cachedAsync)(this, CURRENT_ACCOUNT_KEY, async () => { + const creds = await this.credProvider(); + return this.accountCache.fetch(creds.accessKeyId, async () => { + // if we don't have one, resolve from STS and store in cache. + await this.debug('Looking up default account ID from STS'); + const client = new client_sts_1.STSClient({ + ...this.config, + retryStrategy: this.stsRetryStrategy, + }); + const command = new client_sts_1.GetCallerIdentityCommand({}); + const result = await client.send(command); + const accountId = result.Account; + const partition = result.Arn.split(':')[1]; + if (!accountId) { + throw new toolkit_error_1.AuthenticationError("STS didn't return an account ID"); + } + await this.debug(`Default account ID: ${accountId}`); + // Save another STS call later if this one already succeeded + this._credentialsValidated = true; + return { accountId, partition }; + }); + }); + } + /** + * Make sure the the current credentials are not expired + */ + async validateCredentials() { + if (this._credentialsValidated) { + return; + } + const client = new client_sts_1.STSClient({ ...this.config, retryStrategy: this.stsRetryStrategy }); + await client.send(new client_sts_1.GetCallerIdentityCommand({})); + this._credentialsValidated = true; + } +}; +exports.SDK = SDK; +exports.SDK = SDK = __decorate([ + tracing_1.traceMemberMethods +], SDK); +const CURRENT_ACCOUNT_KEY = Symbol('current_account_key'); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2RrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9hd3MtYXV0aC9zZGsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBY0EsNERBUWlDO0FBT2pDLHNFQUlzQztBQWtFdEMsMEVBa0N3QztBQU94Qyw0RUFJeUM7QUFDekMsZ0VBS21DO0FBQ25DLG9EQTZCNkI7QUFxQjdCLG9EQVc2QjtBQVU3QixvREFNNkI7QUFXN0IsZ0dBT21EO0FBQ25ELG9EQVc2QjtBQUM3QixvREFRNkI7QUFDN0IsMERBa0JnQztBQUNoQyw4REFXa0M7QUFxQmxDLGtEQVU0QjtBQUM1Qiw0RUFLeUM7QUFLekMsb0RBRzZCO0FBQzdCLG9EQUs2QjtBQUM3QixvREFBMEU7QUFDMUUsc0RBQThDO0FBQzlDLHFFQUEwRTtBQUcxRSxtREFBNkQ7QUFFN0QsbURBQXdEO0FBQ3hELHFDQUF1QztBQUV2Qyx1Q0FBK0M7QUFDL0MsNkNBQW1EO0FBQ25ELHFDQUFnRDtBQUNoRCwyQ0FBa0Q7QUFDbEQsb0RBQXVEO0FBK012RDs7R0FFRztBQUVJLElBQU0sR0FBRyxHQUFULE1BQU0sR0FBRztJQTZCSztJQTVCSCxhQUFhLENBQVM7SUFFdEIsTUFBTSxDQUF1QjtJQUUxQixNQUFNLENBQVU7SUFFbEIsWUFBWSxDQUFDO0lBRTlCOztPQUVHO0lBQ2MsZ0JBQWdCLEdBQUcsSUFBSSxvQ0FBdUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBRXRHOzs7Ozs7T0FNRztJQUNLLHFCQUFxQixHQUFHLEtBQUssQ0FBQztJQUV0Qzs7T0FFRztJQUNjLEtBQUssQ0FBaUM7SUFFdkQsWUFDbUIsWUFBMkMsRUFDNUQsTUFBYyxFQUNkLGNBQXNDLEVBQ3RDLFFBQWtCLEVBQ2xCLE1BQWU7UUFKRSxpQkFBWSxHQUFaLFlBQVksQ0FBK0I7UUFNNUQs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Q0FBQyxJQUFJLENBQUMsSUFBSSxxQ0FBd0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUM7SUFDcEMsQ0FBQztDQUNGLENBQUE7QUFsZlksa0JBQUc7Y0FBSCxHQUFHO0lBRGYsNEJBQWtCO0dBQ04sR0FBRyxDQWtmZjtBQUVELE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7XG4gIEZ1bmN0aW9uQ29uZmlndXJhdGlvbixcbiAgR2V0U2NoZW1hQ3JlYXRpb25TdGF0dXNDb21tYW5kSW5wdXQsXG4gIEdldFNjaGVtYUNyZWF0aW9uU3RhdHVzQ29tbWFuZE91dHB1dCxcbiAgTGlzdEZ1bmN0aW9uc0NvbW1hbmRJbnB1dCxcbiAgU3RhcnRTY2hlbWFDcmVhdGlvbkNvbW1hbmRJbnB1dCxcbiAgU3RhcnRTY2hlbWFDcmVhdGlvbkNvbW1hbmRPdXRwdXQsXG4gIFVwZGF0ZUFwaUtleUNvbW1hbmRJbnB1dCxcbiAgVXBkYXRlQXBpS2V5Q29tbWFuZE91dHB1dCxcbiAgVXBkYXRlRnVuY3Rpb25Db21tYW5kSW5wdXQsXG4gIFVwZGF0ZUZ1bmN0aW9uQ29tbWFuZE91dHB1dCxcbiAgVXBkYXRlUmVzb2x2ZXJDb21tYW5kSW5wdXQsXG4gIFVwZGF0ZVJlc29sdmVyQ29tbWFuZE91dHB1dCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWFwcHN5bmMnO1xuaW1wb3J0IHtcbiAgQXBwU3luY0NsaWVudCxcbiAgR2V0U2NoZW1hQ3JlYXRpb25TdGF0dXNDb21tYW5kLFxuICBwYWdpbmF0ZUxpc3RGdW5jdGlvbnMsXG4gIFN0YXJ0U2NoZW1hQ3JlYXRpb25Db21tYW5kLFxuICBVcGRhdGVBcGlLZXlDb21tYW5kLFxuICBVcGRhdGVGdW5jdGlvbkNvbW1hbmQsXG4gIFVwZGF0ZVJlc29sdmVyQ29tbWFuZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWFwcHN5bmMnO1xuaW1wb3J0IHR5cGUge1xuICBHZXRSZXNvdXJjZUNvbW1hbmRJbnB1dCxcbiAgR2V0UmVzb3VyY2VDb21tYW5kT3V0cHV0LFxuICBMaXN0UmVzb3VyY2VzQ29tbWFuZElucHV0LFxuICBMaXN0UmVzb3VyY2VzQ29tbWFuZE91dHB1dCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNsb3VkY29udHJvbCc7XG5pbXBvcnQge1xuICBDbG91ZENvbnRyb2xDbGllbnQsXG4gIEdldFJlc291cmNlQ29tbWFuZCxcbiAgTGlzdFJlc291cmNlc0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jbG91ZGNvbnRyb2wnO1xuaW1wb3J0IHR5cGUge1xuICBDb250aW51ZVVwZGF0ZVJvbGxiYWNrQ29tbWFuZElucHV0LFxuICBDb250aW51ZVVwZGF0ZVJvbGxiYWNrQ29tbWFuZE91dHB1dCxcbiAgRGVzY3JpYmVTdGFja0V2ZW50c0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlU3RhY2tSZXNvdXJjZXNDb21tYW5kSW5wdXQsXG4gIERlc2NyaWJlU3RhY2tSZXNvdXJjZXNDb21tYW5kT3V0cHV0LFxuICBMaXN0U3RhY2tzQ29tbWFuZElucHV0LFxuICBMaXN0U3RhY2tzQ29tbWFuZE91dHB1dCxcbiAgUm9sbGJhY2tTdGFja0NvbW1hbmRJbnB1dCxcbiAgUm9sbGJhY2tTdGFja0NvbW1hbmRPdXRwdXQsXG4gIFN0YWNrUmVzb3VyY2VTdW1tYXJ5LFxuICBDcmVhdGVDaGFuZ2VTZXRDb21tYW5kSW5wdXQsXG4gIENyZWF0ZUNoYW5nZVNldENvbW1hbmRPdXRwdXQsXG4gIENyZWF0ZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZElucHV0LFxuICBDcmVhdGVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRPdXRwdXQsXG4gIENyZWF0ZVN0YWNrQ29tbWFuZElucHV0LFxuICBDcmVhdGVTdGFja0NvbW1hbmRPdXRwdXQsXG4gIERlbGV0ZUNoYW5nZVNldENvbW1hbmRJbnB1dCxcbiAgRGVsZXRlQ2hhbmdlU2V0Q29tbWFuZE91dHB1dCxcbiAgRGVsZXRlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kSW5wdXQsXG4gIERlbGV0ZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dCxcbiAgRGVsZXRlU3RhY2tDb21tYW5kSW5wdXQsXG4gIERlbGV0ZVN0YWNrQ29tbWFuZE91dHB1dCxcbiAgRGVzY3JpYmVDaGFuZ2VTZXRDb21tYW5kSW5wdXQsXG4gIERlc2NyaWJlQ2hhbmdlU2V0Q29tbWFuZE91dHB1dCxcbiAgRGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRJbnB1dCxcbiAgRGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlUmVzb3VyY2VTY2FuQ29tbWFuZElucHV0LFxuICBEZXNjcmliZVJlc291cmNlU2NhbkNvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlU3RhY2tFdmVudHNDb21tYW5kSW5wdXQsXG4gIERlc2NyaWJlU3RhY2tzQ29tbWFuZElucHV0LFxuICBEZXNjcmliZVN0YWNrc0NvbW1hbmRPdXRwdXQsXG4gIEV4ZWN1dGVDaGFuZ2VTZXRDb21tYW5kSW5wdXQsXG4gIEV4ZWN1dGVDaGFuZ2VTZXRDb21tYW5kT3V0cHV0LFxuICBHZXRHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRJbnB1dCxcbiAgR2V0R2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kT3V0cHV0LFxuICBHZXRUZW1wbGF0ZUNvbW1hbmRJbnB1dCxcbiAgR2V0VGVtcGxhdGVDb21tYW5kT3V0cHV0LFxuICBHZXRUZW1wbGF0ZVN1bW1hcnlDb21tYW5kSW5wdXQsXG4gIEdldFRlbXBsYXRlU3VtbWFyeUNvbW1hbmRPdXRwdXQsXG4gIExpc3RFeHBvcnRzQ29tbWFuZElucHV0LFxuICBMaXN0RXhwb3J0c0NvbW1hbmRPdXRwdXQsXG4gIExpc3RSZXNvdXJjZVNjYW5SZWxhdGVkUmVzb3VyY2VzQ29tbWFuZElucHV0LFxuICBMaXN0UmVzb3VyY2VTY2FuUmVsYXRlZFJlc291cmNlc0NvbW1hbmRPdXRwdXQsXG4gIExpc3RSZXNvdXJjZVNjYW5SZXNvdXJjZXNDb21tYW5kSW5wdXQsXG4gIExpc3RSZXNvdXJjZVNjYW5SZXNvdXJjZXNDb21tYW5kT3V0cHV0LFxuICBMaXN0UmVzb3VyY2VTY2Fuc0NvbW1hbmRJbnB1dCxcbiAgTGlzdFJlc291cmNlU2NhbnNDb21tYW5kT3V0cHV0LFxuICBMaXN0U3RhY2tSZXNvdXJjZXNDb21tYW5kSW5wdXQsXG4gIFN0YXJ0UmVzb3VyY2VTY2FuQ29tbWFuZElucHV0LFxuICBTdGFydFJlc291cmNlU2NhbkNvbW1hbmRPdXRwdXQsXG4gIFVwZGF0ZVN0YWNrQ29tbWFuZElucHV0LFxuICBVcGRhdGVTdGFja0NvbW1hbmRPdXRwdXQsXG4gIFVwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbkNvbW1hbmRJbnB1dCxcbiAgVXBkYXRlVGVybWluYXRpb25Qcm90ZWN0aW9uQ29tbWFuZE91dHB1dCxcbiAgU3RhY2tTdW1tYXJ5LFxuICBEZXNjcmliZVN0YWNrRHJpZnREZXRlY3Rpb25TdGF0dXNDb21tYW5kSW5wdXQsXG4gIERlc2NyaWJlU3RhY2tEcmlmdERldGVjdGlvblN0YXR1c0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlU3RhY2tSZXNvdXJjZURyaWZ0c0NvbW1hbmRPdXRwdXQsXG4gIERldGVjdFN0YWNrRHJpZnRDb21tYW5kSW5wdXQsXG4gIERldGVjdFN0YWNrRHJpZnRDb21tYW5kT3V0cHV0LFxuICBEZXRlY3RTdGFja1Jlc291cmNlRHJpZnRDb21tYW5kSW5wdXQsXG4gIERldGVjdFN0YWNrUmVzb3VyY2VEcmlmdENvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlU3RhY2tSZXNvdXJjZURyaWZ0c0NvbW1hbmRJbnB1dCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNsb3VkZm9ybWF0aW9uJztcbmltcG9ydCB7XG4gIHBhZ2luYXRlTGlzdFN0YWNrcyxcbiAgQ2xvdWRGb3JtYXRpb25DbGllbnQsXG4gIENvbnRpbnVlVXBkYXRlUm9sbGJhY2tDb21tYW5kLFxuICBDcmVhdGVDaGFuZ2VTZXRDb21tYW5kLFxuICBDcmVhdGVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmQsXG4gIENyZWF0ZVN0YWNrQ29tbWFuZCxcbiAgRGVsZXRlQ2hhbmdlU2V0Q29tbWFuZCxcbiAgRGVsZXRlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kLFxuICBEZWxldGVTdGFja0NvbW1hbmQsXG4gIERlc2NyaWJlQ2hhbmdlU2V0Q29tbWFuZCxcbiAgRGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmQsXG4gIERlc2NyaWJlUmVzb3VyY2VTY2FuQ29tbWFuZCxcbiAgRGVzY3JpYmVTdGFja0V2ZW50c0NvbW1hbmQsXG4gIERlc2NyaWJlU3RhY2tSZXNvdXJjZXNDb21tYW5kLFxuICBEZXNjcmliZVN0YWNrc0NvbW1hbmQsXG4gIEV4ZWN1dGVDaGFuZ2VTZXRDb21tYW5kLFxuICBHZXRHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmQsXG4gIEdldFRlbXBsYXRlQ29tbWFuZCxcbiAgR2V0VGVtcGxhdGVTdW1tYXJ5Q29tbWFuZCxcbiAgTGlzdEV4cG9ydHNDb21tYW5kLFxuICBMaXN0UmVzb3VyY2VTY2FuUmVsYXRlZFJlc291cmNlc0NvbW1hbmQsXG4gIExpc3RSZXNvdXJjZVNjYW5SZXNvdXJjZXNDb21tYW5kLFxuICBMaXN0UmVzb3VyY2VTY2Fuc0NvbW1hbmQsXG4gIExpc3RTdGFja3NDb21tYW5kLFxuICBwYWdpbmF0ZUxpc3RTdGFja1Jlc291cmNlcyxcbiAgUm9sbGJhY2tTdGFja0NvbW1hbmQsXG4gIFN0YXJ0UmVzb3VyY2VTY2FuQ29tbWFuZCxcbiAgVXBkYXRlU3RhY2tDb21tYW5kLFxuICBVcGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb25Db21tYW5kLFxuICBEZXNjcmliZVN0YWNrRHJpZnREZXRlY3Rpb25TdGF0dXNDb21tYW5kLFxuICBEZXNjcmliZVN0YWNrUmVzb3VyY2VEcmlmdHNDb21tYW5kLFxuICBEZXRlY3RTdGFja0RyaWZ0Q29tbWFuZCxcbiAgRGV0ZWN0U3RhY2tSZXNvdXJjZURyaWZ0Q29tbWFuZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNsb3VkZm9ybWF0aW9uJztcbmltcG9ydCB0eXBlIHtcbiAgRmlsdGVyTG9nRXZlbnRzQ29tbWFuZElucHV0LFxuICBGaWx0ZXJMb2dFdmVudHNDb21tYW5kT3V0cHV0LFxuICBEZXNjcmliZUxvZ0dyb3Vwc0NvbW1hbmRJbnB1dCxcbiAgRGVzY3JpYmVMb2dHcm91cHNDb21tYW5kT3V0cHV0LFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtY2xvdWR3YXRjaC1sb2dzJztcbmltcG9ydCB7XG4gIENsb3VkV2F0Y2hMb2dzQ2xpZW50LFxuICBEZXNjcmliZUxvZ0dyb3Vwc0NvbW1hbmQsXG4gIEZpbHRlckxvZ0V2ZW50c0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jbG91ZHdhdGNoLWxvZ3MnO1xuaW1wb3J0IHtcbiAgQ29kZUJ1aWxkQ2xpZW50LFxuICBVcGRhdGVQcm9qZWN0Q29tbWFuZCxcbiAgdHlwZSBVcGRhdGVQcm9qZWN0Q29tbWFuZElucHV0LFxuICB0eXBlIFVwZGF0ZVByb2plY3RDb21tYW5kT3V0cHV0LFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtY29kZWJ1aWxkJztcbmltcG9ydCB7XG4gIERlc2NyaWJlQXZhaWxhYmlsaXR5Wm9uZXNDb21tYW5kLFxuICB0eXBlIERlc2NyaWJlQXZhaWxhYmlsaXR5Wm9uZXNDb21tYW5kSW5wdXQsXG4gIHR5cGUgRGVzY3JpYmVBdmFpbGFiaWxpdHlab25lc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlSW1hZ2VzQ29tbWFuZCxcbiAgdHlwZSBEZXNjcmliZUltYWdlc0NvbW1hbmRJbnB1dCxcbiAgdHlwZSBEZXNjcmliZUltYWdlc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlSW5zdGFuY2VzQ29tbWFuZCxcbiAgdHlwZSBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmRJbnB1dCxcbiAgdHlwZSBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlUm91dGVUYWJsZXNDb21tYW5kLFxuICB0eXBlIERlc2NyaWJlUm91dGVUYWJsZXNDb21tYW5kSW5wdXQsXG4gIHR5cGUgRGVzY3JpYmVSb3V0ZVRhYmxlc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlU2VjdXJpdHlHcm91cHNDb21tYW5kLFxuICB0eXBlIERlc2NyaWJlU2VjdXJpdHlHcm91cHNDb21tYW5kSW5wdXQsXG4gIHR5cGUgRGVzY3JpYmVTZWN1cml0eUdyb3Vwc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlU3VibmV0c0NvbW1hbmQsXG4gIHR5cGUgRGVzY3JpYmVTdWJuZXRzQ29tbWFuZElucHV0LFxuICB0eXBlIERlc2NyaWJlU3VibmV0c0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlVnBjRW5kcG9pbnRTZXJ2aWNlc0NvbW1hbmQsXG4gIHR5cGUgRGVzY3JpYmVWcGNFbmRwb2ludFNlcnZpY2VzQ29tbWFuZElucHV0LFxuICB0eXBlIERlc2NyaWJlVnBjRW5kcG9pbnRTZXJ2aWNlc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlVnBjc0NvbW1hbmQsXG4gIHR5cGUgRGVzY3JpYmVWcGNzQ29tbWFuZElucHV0LFxuICB0eXBlIERlc2NyaWJlVnBjc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlVnBuR2F0ZXdheXNDb21tYW5kLFxuICB0eXBlIERlc2NyaWJlVnBuR2F0ZXdheXNDb21tYW5kSW5wdXQsXG4gIHR5cGUgRGVzY3JpYmVWcG5HYXRld2F5c0NvbW1hbmRPdXRwdXQsXG4gIEVDMkNsaWVudCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVjMic7XG5pbXBvcnQgdHlwZSB7XG4gIEJhdGNoRGVsZXRlSW1hZ2VDb21tYW5kSW5wdXQsXG4gIEJhdGNoRGVsZXRlSW1hZ2VDb21tYW5kT3V0cHV0LFxuICBMaXN0SW1hZ2VzQ29tbWFuZElucHV0LFxuICBMaXN0SW1hZ2VzQ29tbWFuZE91dHB1dCxcbiAgUHV0SW1hZ2VDb21tYW5kSW5wdXQsXG4gIFB1dEltYWdlQ29tbWFuZE91dHB1dCxcbiAgQmF0Y2hHZXRJbWFnZUNvbW1hbmRJbnB1dCxcbiAgQmF0Y2hHZXRJbWFnZUNvbW1hbmRPdXRwdXQsXG4gIENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kSW5wdXQsXG4gIENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kT3V0cHV0LFxuICBEZXNjcmliZUltYWdlc0NvbW1hbmRJbnB1dCBhcyBFQ1JEZXNjcmliZUltYWdlc0NvbW1hbmRJbnB1dCxcbiAgRGVzY3JpYmVJbWFnZXNDb21tYW5kT3V0cHV0IGFzIEVDUkRlc2NyaWJlSW1hZ2VzQ29tbWFuZE91dHB1dCxcbiAgRGVzY3JpYmVSZXBvc2l0b3JpZXNDb21tYW5kSW5wdXQsXG4gIERlc2NyaWJlUmVwb3NpdG9yaWVzQ29tbWFuZE91dHB1dCxcbiAgR2V0QXV0aG9yaXphdGlvblRva2VuQ29tbWFuZElucHV0LFxuICBHZXRBdXRob3JpemF0aW9uVG9rZW5Db21tYW5kT3V0cHV0LFxuICBQdXRJbWFnZVNjYW5uaW5nQ29uZmlndXJhdGlvbkNvbW1hbmRJbnB1dCxcbiAgUHV0SW1hZ2VTY2FubmluZ0NvbmZpZ3VyYXRpb25Db21tYW5kT3V0cHV0LFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtZWNyJztcbmltcG9ydCB7XG4gIEJhdGNoRGVsZXRlSW1hZ2VDb21tYW5kLFxuICBDcmVhdGVSZXBvc2l0b3J5Q29tbWFuZCxcbiAgRGVzY3JpYmVJbWFnZXNDb21tYW5kIGFzIEVDUkRlc2NyaWJlSW1hZ2VzQ29tbWFuZCxcbiAgRGVzY3JpYmVSZXBvc2l0b3JpZXNDb21tYW5kLFxuICBFQ1JDbGllbnQsXG4gIEdldEF1dGhvcml6YXRpb25Ub2tlbkNvbW1hbmQsXG4gIExpc3RJbWFnZXNDb21tYW5kLFxuICBQdXRJbWFnZUNvbW1hbmQsXG4gIFB1dEltYWdlU2Nhbm5pbmdDb25maWd1cmF0aW9uQ29tbWFuZCxcbiAgQmF0Y2hHZXRJbWFnZUNvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lY3InO1xuaW1wb3J0IHR5cGUge1xuICBEZXNjcmliZVNlcnZpY2VzQ29tbWFuZElucHV0LFxuICBSZWdpc3RlclRhc2tEZWZpbml0aW9uQ29tbWFuZElucHV0LFxuICBMaXN0Q2x1c3RlcnNDb21tYW5kSW5wdXQsXG4gIExpc3RDbHVzdGVyc0NvbW1hbmRPdXRwdXQsXG4gIFJlZ2lzdGVyVGFza0RlZmluaXRpb25Db21tYW5kT3V0cHV0LFxuICBVcGRhdGVTZXJ2aWNlQ29tbWFuZElucHV0LFxuICBVcGRhdGVTZXJ2aWNlQ29tbWFuZE91dHB1dCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVjcyc7XG5pbXBvcnQge1xuICBFQ1NDbGllbnQsXG4gIExpc3RDbHVzdGVyc0NvbW1hbmQsXG4gIFJlZ2lzdGVyVGFza0RlZmluaXRpb25Db21tYW5kLFxuICBVcGRhdGVTZXJ2aWNlQ29tbWFuZCxcbiAgd2FpdFVudGlsU2VydmljZXNTdGFibGUsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lY3MnO1xuaW1wb3J0IHR5cGUge1xuICBMaXN0ZW5lcixcbiAgTG9hZEJhbGFuY2VyLFxuICBEZXNjcmliZUxpc3RlbmVyc0NvbW1hbmRJbnB1dCxcbiAgRGVzY3JpYmVMaXN0ZW5lcnNDb21tYW5kT3V0cHV0LFxuICBEZXNjcmliZUxvYWRCYWxhbmNlcnNDb21tYW5kSW5wdXQsXG4gIERlc2NyaWJlTG9hZEJhbGFuY2Vyc0NvbW1hbmRPdXRwdXQsXG4gIERlc2NyaWJlVGFnc0NvbW1hbmRJbnB1dCxcbiAgRGVzY3JpYmVUYWdzQ29tbWFuZE91dHB1dCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVsYXN0aWMtbG9hZC1iYWxhbmNpbmctdjInO1xuaW1wb3J0IHtcbiAgRGVzY3JpYmVMaXN0ZW5lcnNDb21tYW5kLFxuICBEZXNjcmliZUxvYWRCYWxhbmNlcnNDb21tYW5kLFxuICBEZXNjcmliZVRhZ3NDb21tYW5kLFxuICBFbGFzdGljTG9hZEJhbGFuY2luZ1YyQ2xpZW50LFxuICBwYWdpbmF0ZURlc2NyaWJlTGlzdGVuZXJzLFxuICBwYWdpbmF0ZURlc2NyaWJlTG9hZEJhbGFuY2Vycyxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVsYXN0aWMtbG9hZC1iYWxhbmNpbmctdjInO1xuaW1wb3J0IHtcbiAgQ3JlYXRlUG9saWN5Q29tbWFuZCxcbiAgdHlwZSBDcmVhdGVQb2xpY3lDb21tYW5kSW5wdXQsXG4gIHR5cGUgQ3JlYXRlUG9saWN5Q29tbWFuZE91dHB1dCxcbiAgR2V0UG9saWN5Q29tbWFuZCxcbiAgdHlwZSBHZXRQb2xpY3lDb21tYW5kSW5wdXQsXG4gIHR5cGUgR2V0UG9saWN5Q29tbWFuZE91dHB1dCxcbiAgR2V0Um9sZUNvbW1hbmQsXG4gIHR5cGUgR2V0Um9sZUNvbW1hbmRJbnB1dCxcbiAgdHlwZSBHZXRSb2xlQ29tbWFuZE91dHB1dCxcbiAgSUFNQ2xpZW50LFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtaWFtJztcbmltcG9ydCB7XG4gIERlc2NyaWJlS2V5Q29tbWFuZCxcbiAgdHlwZSBEZXNjcmliZUtleUNvbW1hbmRJbnB1dCxcbiAgdHlwZSBEZXNjcmliZUtleUNvbW1hbmRPdXRwdXQsXG4gIEtNU0NsaWVudCxcbiAgTGlzdEFsaWFzZXNDb21tYW5kLFxuICB0eXBlIExpc3RBbGlhc2VzQ29tbWFuZElucHV0LFxuICB0eXBlIExpc3RBbGlhc2VzQ29tbWFuZE91dHB1dCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWttcyc7XG5pbXBvcnQge1xuICBJbnZva2VDb21tYW5kLFxuICB0eXBlIEludm9rZUNvbW1hbmRJbnB1dCxcbiAgdHlwZSBJbnZva2VDb21tYW5kT3V0cHV0LFxuICBMYW1iZGFDbGllbnQsXG4gIFB1Ymxpc2hWZXJzaW9uQ29tbWFuZCxcbiAgdHlwZSBQdWJsaXNoVmVyc2lvbkNvbW1hbmRJbnB1dCxcbiAgdHlwZSBQdWJsaXNoVmVyc2lvbkNvbW1hbmRPdXRwdXQsXG4gIFVwZGF0ZUFsaWFzQ29tbWFuZCxcbiAgdHlwZSBVcGRhdGVBbGlhc0NvbW1hbmRJbnB1dCxcbiAgdHlwZSBVcGRhdGVBbGlhc0NvbW1hbmRPdXRwdXQsXG4gIFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmQsXG4gIHR5cGUgVXBkYXRlRnVuY3Rpb25Db2RlQ29tbWFuZElucHV0LFxuICB0eXBlIFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmRPdXRwdXQsXG4gIFVwZGF0ZUZ1bmN0aW9uQ29uZmlndXJhdGlvbkNvbW1hbmQsXG4gIHR5cGUgVXBkYXRlRnVuY3Rpb25Db25maWd1cmF0aW9uQ29tbWFuZElucHV0LFxuICB0eXBlIFVwZGF0ZUZ1bmN0aW9uQ29uZmlndXJhdGlvbkNvbW1hbmRPdXRwdXQsXG4gIHdhaXRVbnRpbEZ1bmN0aW9uVXBkYXRlZFYyLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtbGFtYmRhJztcbmltcG9ydCB7XG4gIEdldEhvc3RlZFpvbmVDb21tYW5kLFxuICB0eXBlIEdldEhvc3RlZFpvbmVDb21tYW5kSW5wdXQsXG4gIHR5cGUgR2V0SG9zdGVkWm9uZUNvbW1hbmRPdXRwdXQsXG4gIExpc3RIb3N0ZWRab25lc0J5TmFtZUNvbW1hbmQsXG4gIHR5cGUgTGlzdEhvc3RlZFpvbmVzQnlOYW1lQ29tbWFuZElucHV0LFxuICB0eXBlIExpc3RIb3N0ZWRab25lc0J5TmFtZUNvbW1hbmRPdXRwdXQsXG4gIExpc3RIb3N0ZWRab25lc0NvbW1hbmQsXG4gIHR5cGUgTGlzdEhvc3RlZFpvbmVzQ29tbWFuZElucHV0LFxuICB0eXBlIExpc3RIb3N0ZWRab25lc0NvbW1hbmRPdXRwdXQsXG4gIFJvdXRlNTNDbGllbnQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1yb3V0ZS01Myc7XG5pbXBvcnQgdHlwZSB7XG4gIERlbGV0ZU9iamVjdHNDb21tYW5kSW5wdXQsXG4gIERlbGV0ZU9iamVjdHNDb21tYW5kT3V0cHV0LFxuICBEZWxldGVPYmplY3RUYWdnaW5nQ29tbWFuZElucHV0LFxuICBEZWxldGVPYmplY3RUYWdnaW5nQ29tbWFuZE91dHB1dCxcbiAgR2V0T2JqZWN0VGFnZ2luZ0NvbW1hbmRJbnB1dCxcbiAgR2V0T2JqZWN0VGFnZ2luZ0NvbW1hbmRPdXRwdXQsXG4gIFB1dE9iamVjdFRhZ2dpbmdDb21tYW5kSW5wdXQsXG4gIFB1dE9iamVjdFRhZ2dpbmdDb21tYW5kT3V0cHV0LFxuICBDb21wbGV0ZU11bHRpcGFydFVwbG9hZENvbW1hbmRPdXRwdXQsXG4gIEdldEJ1Y2tldEVuY3J5cHRpb25Db21tYW5kSW5wdXQsXG4gIEdldEJ1Y2tldEVuY3J5cHRpb25Db21tYW5kT3V0cHV0LFxuICBHZXRCdWNrZXRMb2NhdGlvbkNvbW1hbmRJbnB1dCxcbiAgR2V0QnVja2V0TG9jYXRpb25Db21tYW5kT3V0cHV0LFxuICBHZXRPYmplY3RDb21tYW5kSW5wdXQsXG4gIEdldE9iamVjdENvbW1hbmRPdXRwdXQsXG4gIExpc3RPYmplY3RzVjJDb21tYW5kSW5wdXQsXG4gIExpc3RPYmplY3RzVjJDb21tYW5kT3V0cHV0LFxuICBQdXRPYmplY3RDb21tYW5kSW5wdXQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zMyc7XG5pbXBvcnQge1xuICBEZWxldGVPYmplY3RzQ29tbWFuZCxcbiAgRGVsZXRlT2JqZWN0VGFnZ2luZ0NvbW1hbmQsXG4gIEdldEJ1Y2tldEVuY3J5cHRpb25Db21tYW5kLFxuICBHZXRCdWNrZXRMb2NhdGlvbkNvbW1hbmQsXG4gIEdldE9iamVjdENvbW1hbmQsXG4gIEdldE9iamVjdFRhZ2dpbmdDb21tYW5kLFxuICBMaXN0T2JqZWN0c1YyQ29tbWFuZCxcbiAgUHV0T2JqZWN0VGFnZ2luZ0NvbW1hbmQsXG4gIFMzQ2xpZW50LFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtczMnO1xuaW1wb3J0IHtcbiAgR2V0U2VjcmV0VmFsdWVDb21tYW5kLFxuICB0eXBlIEdldFNlY3JldFZhbHVlQ29tbWFuZElucHV0LFxuICB0eXBlIEdldFNlY3JldFZhbHVlQ29tbWFuZE91dHB1dCxcbiAgU2VjcmV0c01hbmFnZXJDbGllbnQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zZWNyZXRzLW1hbmFnZXInO1xuaW1wb3J0IHR5cGUge1xuICBVcGRhdGVTdGF0ZU1hY2hpbmVDb21tYW5kSW5wdXQsXG4gIFVwZGF0ZVN0YXRlTWFjaGluZUNvbW1hbmRPdXRwdXQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zZm4nO1xuaW1wb3J0IHtcbiAgU0ZOQ2xpZW50LFxuICBVcGRhdGVTdGF0ZU1hY2hpbmVDb21tYW5kLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtc2ZuJztcbmltcG9ydCB7XG4gIEdldFBhcmFtZXRlckNvbW1hbmQsXG4gIHR5cGUgR2V0UGFyYW1ldGVyQ29tbWFuZElucHV0LFxuICB0eXBlIEdldFBhcmFtZXRlckNvbW1hbmRPdXRwdXQsXG4gIFNTTUNsaWVudCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXNzbSc7XG5pbXBvcnQgeyBHZXRDYWxsZXJJZGVudGl0eUNvbW1hbmQsIFNUU0NsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zdHMnO1xuaW1wb3J0IHsgVXBsb2FkIH0gZnJvbSAnQGF3cy1zZGsvbGliLXN0b3JhZ2UnO1xuaW1wb3J0IHsgZ2V0RW5kcG9pbnRGcm9tSW5zdHJ1Y3Rpb25zIH0gZnJvbSAnQHNtaXRoeS9taWRkbGV3YXJlLWVuZHBvaW50JztcbmltcG9ydCB0eXBlIHsgTm9kZUh0dHBIYW5kbGVyT3B0aW9ucyB9IGZyb20gJ0BzbWl0aHkvbm9kZS1odHRwLWhhbmRsZXInO1xuaW1wb3J0IHR5cGUgeyBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlciwgTG9nZ2VyIH0gZnJvbSAnQHNtaXRoeS90eXBlcyc7XG5pbXBvcnQgeyBDb25maWd1cmVkUmV0cnlTdHJhdGVneSB9IGZyb20gJ0BzbWl0aHkvdXRpbC1yZXRyeSc7XG5pbXBvcnQgdHlwZSB7IFdhaXRlclJlc3VsdCB9IGZyb20gJ0BzbWl0aHkvdXRpbC13YWl0ZXInO1xuaW1wb3J0IHsgQWNjb3VudEFjY2Vzc0tleUNhY2hlIH0gZnJvbSAnLi9hY2NvdW50LWNhY2hlJztcbmltcG9ydCB7IGNhY2hlZEFzeW5jIH0gZnJvbSAnLi9jYWNoZWQnO1xuaW1wb3J0IHR5cGUgeyBBY2NvdW50IH0gZnJvbSAnLi9zZGstcHJvdmlkZXInO1xuaW1wb3J0IHsgdHJhY2VNZW1iZXJNZXRob2RzIH0gZnJvbSAnLi90cmFjaW5nJztcbmltcG9ydCB7IGRlZmF1bHRDbGlVc2VyQWdlbnQgfSBmcm9tICcuL3VzZXItYWdlbnQnO1xuaW1wb3J0IHsgZm9ybWF0RXJyb3JNZXNzYWdlIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBJTywgdHlwZSBJb0hlbHBlciB9IGZyb20gJy4uL2lvL3ByaXZhdGUnO1xuaW1wb3J0IHsgQXV0aGVudGljYXRpb25FcnJvciB9IGZyb20gJy4uL3Rvb2xraXQtZXJyb3InO1xuXG5leHBvcnQgaW50ZXJmYWNlIFMzQ2xpZW50T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBJZiBBUElzIGFyZSB1c2VkIHRoYXQgcmVxdWlyZSBNRDUgY2hlY2tzdW1zLlxuICAgKlxuICAgKiBTb21lIFMzIEFQSXMgaW4gU0RLdjIgaGF2ZSBhIGJ1ZyB0aGF0IGFsd2F5cyByZXF1aXJlcyB0aGVtIHRvIHVzZSBhIE1ENSBjaGVja3N1bS5cbiAgICogVGhlc2UgQVBJcyBhcmUgbm90IGdvaW5nIHRvIGJlIHN1cHBvcnRlZCBpbiBhIEZJUFMgZW52aXJvbm1lbnQuXG4gICAqL1xuICBuZWVkc01kNUNoZWNrc3Vtcz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQWRkaXRpb25hbCBTREsgY29uZmlndXJhdGlvbiBvcHRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2RrT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGRlc2NyaXB0aXZlIHN0cmluZ3MgdGhhdCBpbmRpY2F0ZSB3aGVyZSB0aGUgXCJBc3N1bWVSb2xlXCIgY3JlZGVudGlhbHMgYXJlIGNvbWluZyBmcm9tXG4gICAqXG4gICAqIFdpbGwgYmUgcHJpbnRlZCBpbiBhbiBlcnJvciBtZXNzYWdlIHRvIGhlbHAgdXNlcnMgZGlhZ25vc2UgYXV0aCBwcm9ibGVtcy5cbiAgICovXG4gIHJlYWRvbmx5IGFzc3VtZVJvbGVDcmVkZW50aWFsc1NvdXJjZURlc2NyaXB0aW9uPzogc3RyaW5nO1xufVxuXG4vLyBUT0RPOiBzdGlsbCBzb21lIGNsZWFudXAgaGVyZS4gTWFrZSB0aGUgcGFnaW5hdGlvbiBmdW5jdGlvbnMgZG8gYWxsIHRoZSB3b3JrIGhlcmUgaW5zdGVhZCBvZiBpbiBpbmRpdmlkdWFsIHBhY2thZ2VzLlxuLy8gQWxzbyBhZGQgYXN5bmMvYXdhaXQuIERvZXMgdGhhdCBhY3R1YWxseSBtYXR0ZXIgaW4gdGhpcyBjb250ZXh0PyBGaW5kIG91dCBhbmQgdXBkYXRlIGFjY29yZGluZ2x5LlxuXG4vLyBBbHNvIGFkZCBub3RlcyB0byB0aGUgUFIgYWJvdXQgd2h5IHlvdSBpbXBvcnRlZCBldmVyeXRoaW5nIGluZGl2aWR1YWxseSBhbmQgdXNlZCAndHlwZScgc28gcmV2aWV3ZXJzIGRvbid0IGhhdmUgdG8gYXNrLlxuXG5leHBvcnQgaW50ZXJmYWNlIENvbmZpZ3VyYXRpb25PcHRpb25zIHtcbiAgcmVnaW9uOiBzdHJpbmc7XG4gIGNyZWRlbnRpYWxzOiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcjtcbiAgcmVxdWVzdEhhbmRsZXI6IE5vZGVIdHRwSGFuZGxlck9wdGlvbnM7XG4gIHJldHJ5U3RyYXRlZ3k6IENvbmZpZ3VyZWRSZXRyeVN0cmF0ZWd5O1xuICBjdXN0b21Vc2VyQWdlbnQ6IHN0cmluZztcbiAgbG9nZ2VyPzogTG9nZ2VyO1xuICBzM0Rpc2FibGVCb2R5U2lnbmluZz86IGJvb2xlYW47XG4gIGNvbXB1dGVDaGVja3N1bXM/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElBcHBTeW5jQ2xpZW50IHtcbiAgZ2V0U2NoZW1hQ3JlYXRpb25TdGF0dXMoaW5wdXQ6IEdldFNjaGVtYUNyZWF0aW9uU3RhdHVzQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRTY2hlbWFDcmVhdGlvblN0YXR1c0NvbW1hbmRPdXRwdXQ+O1xuICBzdGFydFNjaGVtYUNyZWF0aW9uKGlucHV0OiBTdGFydFNjaGVtYUNyZWF0aW9uQ29tbWFuZElucHV0KTogUHJvbWlzZTxTdGFydFNjaGVtYUNyZWF0aW9uQ29tbWFuZE91dHB1dD47XG4gIHVwZGF0ZUFwaUtleShpbnB1dDogVXBkYXRlQXBpS2V5Q29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVBcGlLZXlDb21tYW5kT3V0cHV0PjtcbiAgdXBkYXRlRnVuY3Rpb24oaW5wdXQ6IFVwZGF0ZUZ1bmN0aW9uQ29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVGdW5jdGlvbkNvbW1hbmRPdXRwdXQ+O1xuICB1cGRhdGVSZXNvbHZlcihpbnB1dDogVXBkYXRlUmVzb2x2ZXJDb21tYW5kSW5wdXQpOiBQcm9taXNlPFVwZGF0ZVJlc29sdmVyQ29tbWFuZE91dHB1dD47XG4gIC8vIFBhZ2luYXRpb24gZnVuY3Rpb25zXG4gIGxpc3RGdW5jdGlvbnMoaW5wdXQ6IExpc3RGdW5jdGlvbnNDb21tYW5kSW5wdXQpOiBQcm9taXNlPEZ1bmN0aW9uQ29uZmlndXJhdGlvbltdPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJQ2xvdWRDb250cm9sQ2xpZW50e1xuICBsaXN0UmVzb3VyY2VzKGlucHV0OiBMaXN0UmVzb3VyY2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMaXN0UmVzb3VyY2VzQ29tbWFuZE91dHB1dD47XG4gIGdldFJlc291cmNlKGlucHV0OiBHZXRSZXNvdXJjZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8R2V0UmVzb3VyY2VDb21tYW5kT3V0cHV0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJQ2xvdWRGb3JtYXRpb25DbGllbnQge1xuICBjb250aW51ZVVwZGF0ZVJvbGxiYWNrKGlucHV0OiBDb250aW51ZVVwZGF0ZVJvbGxiYWNrQ29tbWFuZElucHV0KTogUHJvbWlzZTxDb250aW51ZVVwZGF0ZVJvbGxiYWNrQ29tbWFuZE91dHB1dD47XG4gIGNyZWF0ZUNoYW5nZVNldChpbnB1dDogQ3JlYXRlQ2hhbmdlU2V0Q29tbWFuZElucHV0KTogUHJvbWlzZTxDcmVhdGVDaGFuZ2VTZXRDb21tYW5kT3V0cHV0PjtcbiAgY3JlYXRlR2VuZXJhdGVkVGVtcGxhdGUoaW5wdXQ6IENyZWF0ZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZElucHV0KTogUHJvbWlzZTxDcmVhdGVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRPdXRwdXQ+O1xuICBjcmVhdGVTdGFjayhpbnB1dDogQ3JlYXRlU3RhY2tDb21tYW5kSW5wdXQpOiBQcm9taXNlPENyZWF0ZVN0YWNrQ29tbWFuZE91dHB1dD47XG4gIGRlbGV0ZUNoYW5nZVNldChpbnB1dDogRGVsZXRlQ2hhbmdlU2V0Q29tbWFuZElucHV0KTogUHJvbWlzZTxEZWxldGVDaGFuZ2VTZXRDb21tYW5kT3V0cHV0PjtcbiAgZGVsZXRlR2VuZXJhdGVkVGVtcGxhdGUoaW5wdXQ6IERlbGV0ZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZWxldGVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRPdXRwdXQ+O1xuICBkZWxldGVTdGFjayhpbnB1dDogRGVsZXRlU3RhY2tDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlbGV0ZVN0YWNrQ29tbWFuZE91dHB1dD47XG4gIGRlc2NyaWJlQ2hhbmdlU2V0KGlucHV0OiBEZXNjcmliZUNoYW5nZVNldENvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVDaGFuZ2VTZXRDb21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZShcbiAgICBpbnB1dDogRGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRJbnB1dCxcbiAgKTogUHJvbWlzZTxEZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dD47XG4gIGRlc2NyaWJlUmVzb3VyY2VTY2FuKGlucHV0OiBEZXNjcmliZVJlc291cmNlU2NhbkNvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVSZXNvdXJjZVNjYW5Db21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVTdGFja0RyaWZ0RGV0ZWN0aW9uU3RhdHVzKGlucHV0OiBEZXNjcmliZVN0YWNrRHJpZnREZXRlY3Rpb25TdGF0dXNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlU3RhY2tEcmlmdERldGVjdGlvblN0YXR1c0NvbW1hbmRPdXRwdXQ+O1xuICBkZXNjcmliZVN0YWNrcyhpbnB1dDogRGVzY3JpYmVTdGFja3NDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlU3RhY2tzQ29tbWFuZE91dHB1dD47XG4gIGRlc2NyaWJlU3RhY2tSZXNvdXJjZURyaWZ0cyhpbnB1dDogRGVzY3JpYmVTdGFja1Jlc291cmNlRHJpZnRzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZXNjcmliZVN0YWNrUmVzb3VyY2VEcmlmdHNDb21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVTdGFja1Jlc291cmNlcyhpbnB1dDogRGVzY3JpYmVTdGFja1Jlc291cmNlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVTdGFja1Jlc291cmNlc0NvbW1hbmRPdXRwdXQ+O1xuICBkZXRlY3RTdGFja0RyaWZ0KGlucHV0OiBEZXRlY3RTdGFja0RyaWZ0Q29tbWFuZElucHV0KTogUHJvbWlzZTxEZXRlY3RTdGFja0RyaWZ0Q29tbWFuZE91dHB1dD47XG4gIGRldGVjdFN0YWNrUmVzb3VyY2VEcmlmdChpbnB1dDogRGV0ZWN0U3RhY2tSZXNvdXJjZURyaWZ0Q29tbWFuZElucHV0KTogUHJvbWlzZTxEZXRlY3RTdGFja1Jlc291cmNlRHJpZnRDb21tYW5kT3V0cHV0PjtcbiAgZXhlY3V0ZUNoYW5nZVNldChpbnB1dDogRXhlY3V0ZUNoYW5nZVNldENvbW1hbmRJbnB1dCk6IFByb21pc2U8RXhlY3V0ZUNoYW5nZVNldENvbW1hbmRPdXRwdXQ+O1xuICBnZXRHZW5lcmF0ZWRUZW1wbGF0ZShpbnB1dDogR2V0R2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldEdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dD47XG4gIGdldFRlbXBsYXRlKGlucHV0OiBHZXRUZW1wbGF0ZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8R2V0VGVtcGxhdGVDb21tYW5kT3V0cHV0PjtcbiAgZ2V0VGVtcGxhdGVTdW1tYXJ5KGlucHV0OiBHZXRUZW1wbGF0ZVN1bW1hcnlDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFRlbXBsYXRlU3VtbWFyeUNvbW1hbmRPdXRwdXQ+O1xuICBsaXN0RXhwb3J0cyhpbnB1dDogTGlzdEV4cG9ydHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RFeHBvcnRzQ29tbWFuZE91dHB1dD47XG4gIGxpc3RSZXNvdXJjZVNjYW5SZWxhdGVkUmVzb3VyY2VzKFxuICAgIGlucHV0OiBMaXN0UmVzb3VyY2VTY2FuUmVsYXRlZFJlc291cmNlc0NvbW1hbmRJbnB1dCxcbiAgKTogUHJvbWlzZTxMaXN0UmVzb3VyY2VTY2FuUmVsYXRlZFJlc291cmNlc0NvbW1hbmRPdXRwdXQ+O1xuICBsaXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzKFxuICAgIGlucHV0OiBMaXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzQ29tbWFuZElucHV0LFxuICApOiBQcm9taXNlPExpc3RSZXNvdXJjZVNjYW5SZXNvdXJjZXNDb21tYW5kT3V0cHV0PjtcbiAgbGlzdFJlc291cmNlU2NhbnMoaW5wdXQ/OiBMaXN0UmVzb3VyY2VTY2Fuc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8TGlzdFJlc291cmNlU2NhbnNDb21tYW5kT3V0cHV0PjtcbiAgbGlzdFN0YWNrcyhpbnB1dDogTGlzdFN0YWNrc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8TGlzdFN0YWNrc0NvbW1hbmRPdXRwdXQ+O1xuICByb2xsYmFja1N0YWNrKGlucHV0OiBSb2xsYmFja1N0YWNrQ29tbWFuZElucHV0KTogUHJvbWlzZTxSb2xsYmFja1N0YWNrQ29tbWFuZE91dHB1dD47XG4gIHN0YXJ0UmVzb3VyY2VTY2FuKGlucHV0OiBTdGFydFJlc291cmNlU2NhbkNvbW1hbmRJbnB1dCk6IFByb21pc2U8U3RhcnRSZXNvdXJjZVNjYW5Db21tYW5kT3V0cHV0PjtcbiAgdXBkYXRlU3RhY2soaW5wdXQ6IFVwZGF0ZVN0YWNrQ29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVTdGFja0NvbW1hbmRPdXRwdXQ+O1xuICB1cGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb24oXG4gICAgaW5wdXQ6IFVwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbkNvbW1hbmRJbnB1dCxcbiAgKTogUHJvbWlzZTxVcGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb25Db21tYW5kT3V0cHV0PjtcbiAgLy8gUGFnaW5hdGlvbiBmdW5jdGlvbnNcbiAgZGVzY3JpYmVTdGFja0V2ZW50cyhpbnB1dDogRGVzY3JpYmVTdGFja0V2ZW50c0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVTdGFja0V2ZW50c0NvbW1hbmRPdXRwdXQ+O1xuICBsaXN0U3RhY2tSZXNvdXJjZXMoaW5wdXQ6IExpc3RTdGFja1Jlc291cmNlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8U3RhY2tSZXNvdXJjZVN1bW1hcnlbXT47XG4gIHBhZ2luYXRlZExpc3RTdGFja3MoaW5wdXQ6IExpc3RTdGFja3NDb21tYW5kSW5wdXQpOiBQcm9taXNlPFN0YWNrU3VtbWFyeVtdPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJQ2xvdWRXYXRjaExvZ3NDbGllbnQge1xuICBkZXNjcmliZUxvZ0dyb3VwcyhpbnB1dDogRGVzY3JpYmVMb2dHcm91cHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlTG9nR3JvdXBzQ29tbWFuZE91dHB1dD47XG4gIGZpbHRlckxvZ0V2ZW50cyhpbnB1dDogRmlsdGVyTG9nRXZlbnRzQ29tbWFuZElucHV0KTogUHJvbWlzZTxGaWx0ZXJMb2dFdmVudHNDb21tYW5kT3V0cHV0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJQ29kZUJ1aWxkQ2xpZW50IHtcbiAgdXBkYXRlUHJvamVjdChpbnB1dDogVXBkYXRlUHJvamVjdENvbW1hbmRJbnB1dCk6IFByb21pc2U8VXBkYXRlUHJvamVjdENvbW1hbmRPdXRwdXQ+O1xufVxuZXhwb3J0IGludGVyZmFjZSBJRUMyQ2xpZW50IHtcbiAgZGVzY3JpYmVBdmFpbGFiaWxpdHlab25lcyhcbiAgICBpbnB1dDogRGVzY3JpYmVBdmFpbGFiaWxpdHlab25lc0NvbW1hbmRJbnB1dCxcbiAgKTogUHJvbWlzZTxEZXNjcmliZUF2YWlsYWJpbGl0eVpvbmVzQ29tbWFuZE91dHB1dD47XG4gIGRlc2NyaWJlSW1hZ2VzKGlucHV0OiBEZXNjcmliZUltYWdlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVJbWFnZXNDb21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVJbnN0YW5jZXMoaW5wdXQ6IERlc2NyaWJlSW5zdGFuY2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZXNjcmliZUluc3RhbmNlc0NvbW1hbmRPdXRwdXQ+O1xuICBkZXNjcmliZVJvdXRlVGFibGVzKGlucHV0OiBEZXNjcmliZVJvdXRlVGFibGVzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZXNjcmliZVJvdXRlVGFibGVzQ29tbWFuZE91dHB1dD47XG4gIGRlc2NyaWJlU2VjdXJpdHlHcm91cHMoaW5wdXQ6IERlc2NyaWJlU2VjdXJpdHlHcm91cHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlU2VjdXJpdHlHcm91cHNDb21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVTdWJuZXRzKGlucHV0OiBEZXNjcmliZVN1Ym5ldHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlU3VibmV0c0NvbW1hbmRPdXRwdXQ+O1xuICBkZXNjcmliZVZwY0VuZHBvaW50U2VydmljZXMoXG4gICAgaW5wdXQ6IERlc2NyaWJlVnBjRW5kcG9pbnRTZXJ2aWNlc0NvbW1hbmRJbnB1dCxcbiAgKTogUHJvbWlzZTxEZXNjcmliZVZwY0VuZHBvaW50U2VydmljZXNDb21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVWcGNzKGlucHV0OiBEZXNjcmliZVZwY3NDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlVnBjc0NvbW1hbmRPdXRwdXQ+O1xuICBkZXNjcmliZVZwbkdhdGV3YXlzKGlucHV0OiBEZXNjcmliZVZwbkdhdGV3YXlzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZXNjcmliZVZwbkdhdGV3YXlzQ29tbWFuZE91dHB1dD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUVDUkNsaWVudCB7XG4gIGJhdGNoRGVsZXRlSW1hZ2UoaW5wdXQ6IEJhdGNoRGVsZXRlSW1hZ2VDb21tYW5kSW5wdXQpOiBQcm9taXNlPEJhdGNoRGVsZXRlSW1hZ2VDb21tYW5kT3V0cHV0PjtcbiAgYmF0Y2hHZXRJbWFnZShpbnB1dDogQmF0Y2hHZXRJbWFnZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8QmF0Y2hHZXRJbWFnZUNvbW1hbmRPdXRwdXQ+O1xuICBjcmVhdGVSZXBvc2l0b3J5KGlucHV0OiBDcmVhdGVSZXBvc2l0b3J5Q29tbWFuZElucHV0KTogUHJvbWlzZTxDcmVhdGVSZXBvc2l0b3J5Q29tbWFuZE91dHB1dD47XG4gIGRlc2NyaWJlSW1hZ2VzKGlucHV0OiBFQ1JEZXNjcmliZUltYWdlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RUNSRGVzY3JpYmVJbWFnZXNDb21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVSZXBvc2l0b3JpZXMoaW5wdXQ6IERlc2NyaWJlUmVwb3NpdG9yaWVzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZXNjcmliZVJlcG9zaXRvcmllc0NvbW1hbmRPdXRwdXQ+O1xuICBnZXRBdXRob3JpemF0aW9uVG9rZW4oaW5wdXQ6IEdldEF1dGhvcml6YXRpb25Ub2tlbkNvbW1hbmRJbnB1dCk6IFByb21pc2U8R2V0QXV0aG9yaXphdGlvblRva2VuQ29tbWFuZE91dHB1dD47XG4gIGxpc3RJbWFnZXMoaW5wdXQ6IExpc3RJbWFnZXNDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RJbWFnZXNDb21tYW5kT3V0cHV0PjtcbiAgcHV0SW1hZ2UoaW5wdXQ6IFB1dEltYWdlQ29tbWFuZElucHV0KTogUHJvbWlzZTxQdXRJbWFnZUNvbW1hbmRPdXRwdXQ+O1xuICBwdXRJbWFnZVNjYW5uaW5nQ29uZmlndXJhdGlvbihcbiAgICBpbnB1dDogUHV0SW1hZ2VTY2FubmluZ0NvbmZpZ3VyYXRpb25Db21tYW5kSW5wdXQsXG4gICk6IFByb21pc2U8UHV0SW1hZ2VTY2FubmluZ0NvbmZpZ3VyYXRpb25Db21tYW5kT3V0cHV0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRUNTQ2xpZW50IHtcbiAgbGlzdENsdXN0ZXJzKGlucHV0OiBMaXN0Q2x1c3RlcnNDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RDbHVzdGVyc0NvbW1hbmRPdXRwdXQ+O1xuICByZWdpc3RlclRhc2tEZWZpbml0aW9uKGlucHV0OiBSZWdpc3RlclRhc2tEZWZpbml0aW9uQ29tbWFuZElucHV0KTogUHJvbWlzZTxSZWdpc3RlclRhc2tEZWZpbml0aW9uQ29tbWFuZE91dHB1dD47XG4gIHVwZGF0ZVNlcnZpY2UoaW5wdXQ6IFVwZGF0ZVNlcnZpY2VDb21tYW5kSW5wdXQpOiBQcm9taXNlPFVwZGF0ZVNlcnZpY2VDb21tYW5kT3V0cHV0PjtcbiAgLy8gV2FpdGVyc1xuICB3YWl0VW50aWxTZXJ2aWNlc1N0YWJsZShpbnB1dDogRGVzY3JpYmVTZXJ2aWNlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8V2FpdGVyUmVzdWx0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRWxhc3RpY0xvYWRCYWxhbmNpbmdWMkNsaWVudCB7XG4gIGRlc2NyaWJlTGlzdGVuZXJzKGlucHV0OiBEZXNjcmliZUxpc3RlbmVyc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVMaXN0ZW5lcnNDb21tYW5kT3V0cHV0PjtcbiAgZGVzY3JpYmVMb2FkQmFsYW5jZXJzKGlucHV0OiBEZXNjcmliZUxvYWRCYWxhbmNlcnNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlTG9hZEJhbGFuY2Vyc0NvbW1hbmRPdXRwdXQ+O1xuICBkZXNjcmliZVRhZ3MoaW5wdXQ6IERlc2NyaWJlVGFnc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVUYWdzQ29tbWFuZE91dHB1dD47XG4gIC8vIFBhZ2luYXRpb25cbiAgcGFnaW5hdGVEZXNjcmliZUxpc3RlbmVycyhpbnB1dDogRGVzY3JpYmVMaXN0ZW5lcnNDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RlbmVyW10+O1xuICBwYWdpbmF0ZURlc2NyaWJlTG9hZEJhbGFuY2VycyhpbnB1dDogRGVzY3JpYmVMb2FkQmFsYW5jZXJzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMb2FkQmFsYW5jZXJbXT47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUlBTUNsaWVudCB7XG4gIGNyZWF0ZVBvbGljeShpbnB1dDogQ3JlYXRlUG9saWN5Q29tbWFuZElucHV0KTogUHJvbWlzZTxDcmVhdGVQb2xpY3lDb21tYW5kT3V0cHV0PjtcbiAgZ2V0UG9saWN5KGlucHV0OiBHZXRQb2xpY3lDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFBvbGljeUNvbW1hbmRPdXRwdXQ+O1xuICBnZXRSb2xlKGlucHV0OiBHZXRSb2xlQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRSb2xlQ29tbWFuZE91dHB1dD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUtNU0NsaWVudCB7XG4gIGRlc2NyaWJlS2V5KGlucHV0OiBEZXNjcmliZUtleUNvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVLZXlDb21tYW5kT3V0cHV0PjtcbiAgbGlzdEFsaWFzZXMoaW5wdXQ6IExpc3RBbGlhc2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMaXN0QWxpYXNlc0NvbW1hbmRPdXRwdXQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElMYW1iZGFDbGllbnQge1xuICBpbnZva2VDb21tYW5kKGlucHV0OiBJbnZva2VDb21tYW5kSW5wdXQpOiBQcm9taXNlPEludm9rZUNvbW1hbmRPdXRwdXQ+O1xuICBwdWJsaXNoVmVyc2lvbihpbnB1dDogUHVibGlzaFZlcnNpb25Db21tYW5kSW5wdXQpOiBQcm9taXNlPFB1Ymxpc2hWZXJzaW9uQ29tbWFuZE91dHB1dD47XG4gIHVwZGF0ZUFsaWFzKGlucHV0OiBVcGRhdGVBbGlhc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8VXBkYXRlQWxpYXNDb21tYW5kT3V0cHV0PjtcbiAgdXBkYXRlRnVuY3Rpb25Db2RlKGlucHV0OiBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kSW5wdXQpOiBQcm9taXNlPFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmRPdXRwdXQ+O1xuICB1cGRhdGVGdW5jdGlvbkNvbmZpZ3VyYXRpb24oXG4gICAgaW5wdXQ6IFVwZGF0ZUZ1bmN0aW9uQ29uZmlndXJhdGlvbkNvbW1hbmRJbnB1dCxcbiAgKTogUHJvbWlzZTxVcGRhdGVGdW5jdGlvbkNvbmZpZ3VyYXRpb25Db21tYW5kT3V0cHV0PjtcbiAgLy8gV2FpdGVyc1xuICB3YWl0VW50aWxGdW5jdGlvblVwZGF0ZWQoZGVsYXlTZWNvbmRzOiBudW1iZXIsIGlucHV0OiBVcGRhdGVGdW5jdGlvbkNvbmZpZ3VyYXRpb25Db21tYW5kSW5wdXQpOiBQcm9taXNlPFdhaXRlclJlc3VsdD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVJvdXRlNTNDbGllbnQge1xuICBnZXRIb3N0ZWRab25lKGlucHV0OiBHZXRIb3N0ZWRab25lQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRIb3N0ZWRab25lQ29tbWFuZE91dHB1dD47XG4gIGxpc3RIb3N0ZWRab25lcyhpbnB1dDogTGlzdEhvc3RlZFpvbmVzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMaXN0SG9zdGVkWm9uZXNDb21tYW5kT3V0cHV0PjtcbiAgbGlzdEhvc3RlZFpvbmVzQnlOYW1lKGlucHV0OiBMaXN0SG9zdGVkWm9uZXNCeU5hbWVDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RIb3N0ZWRab25lc0J5TmFtZUNvbW1hbmRPdXRwdXQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElTM0NsaWVudCB7XG4gIGRlbGV0ZU9iamVjdHMoaW5wdXQ6IERlbGV0ZU9iamVjdHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlbGV0ZU9iamVjdHNDb21tYW5kT3V0cHV0PjtcbiAgZGVsZXRlT2JqZWN0VGFnZ2luZyhpbnB1dDogRGVsZXRlT2JqZWN0VGFnZ2luZ0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVsZXRlT2JqZWN0VGFnZ2luZ0NvbW1hbmRPdXRwdXQ+O1xuICBnZXRCdWNrZXRFbmNyeXB0aW9uKGlucHV0OiBHZXRCdWNrZXRFbmNyeXB0aW9uQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRCdWNrZXRFbmNyeXB0aW9uQ29tbWFuZE91dHB1dD47XG4gIGdldEJ1Y2tldExvY2F0aW9uKGlucHV0OiBHZXRCdWNrZXRMb2NhdGlvbkNvbW1hbmRJbnB1dCk6IFByb21pc2U8R2V0QnVja2V0TG9jYXRpb25Db21tYW5kT3V0cHV0PjtcbiAgZ2V0T2JqZWN0KGlucHV0OiBHZXRPYmplY3RDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldE9iamVjdENvbW1hbmRPdXRwdXQ+O1xuICBnZXRPYmplY3RUYWdnaW5nKGlucHV0OiBHZXRPYmplY3RUYWdnaW5nQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRPYmplY3RUYWdnaW5nQ29tbWFuZE91dHB1dD47XG4gIGxpc3RPYmplY3RzVjIoaW5wdXQ6IExpc3RPYmplY3RzVjJDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RPYmplY3RzVjJDb21tYW5kT3V0cHV0PjtcbiAgcHV0T2JqZWN0VGFnZ2luZyhpbnB1dDogUHV0T2JqZWN0VGFnZ2luZ0NvbW1hbmRJbnB1dCk6IFByb21pc2U8UHV0T2JqZWN0VGFnZ2luZ0NvbW1hbmRPdXRwdXQ+O1xuICB1cGxvYWQoaW5wdXQ6IFB1dE9iamVjdENvbW1hbmRJbnB1dCk6IFByb21pc2U8Q29tcGxldGVNdWx0aXBhcnRVcGxvYWRDb21tYW5kT3V0cHV0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJU2VjcmV0c01hbmFnZXJDbGllbnQge1xuICBnZXRTZWNyZXRWYWx1ZShpbnB1dDogR2V0U2VjcmV0VmFsdWVDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFNlY3JldFZhbHVlQ29tbWFuZE91dHB1dD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVNTTUNsaWVudCB7XG4gIGdldFBhcmFtZXRlcihpbnB1dDogR2V0UGFyYW1ldGVyQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRQYXJhbWV0ZXJDb21tYW5kT3V0cHV0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJU3RlcEZ1bmN0aW9uc0NsaWVudCB7XG4gIHVwZGF0ZVN0YXRlTWFjaGluZShpbnB1dDogVXBkYXRlU3RhdGVNYWNoaW5lQ29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVTdGF0ZU1hY2hpbmVDb21tYW5kT3V0cHV0Pjtcbn1cblxuLyoqXG4gKiBCYXNlIGZ1bmN0aW9uYWxpdHkgb2YgU0RLIHdpdGhvdXQgY3JlZGVudGlhbCBmZXRjaGluZ1xuICovXG5AdHJhY2VNZW1iZXJNZXRob2RzXG5leHBvcnQgY2xhc3MgU0RLIHtcbiAgcHVibGljIHJlYWRvbmx5IGN1cnJlbnRSZWdpb246IHN0cmluZztcblxuICBwdWJsaWMgcmVhZG9ubHkgY29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucztcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgbG9nZ2VyPzogTG9nZ2VyO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgYWNjb3VudENhY2hlO1xuXG4gIC8qKlxuICAgKiBTVFMgaXMgdXNlZCB0byBjaGVjayBjcmVkZW50aWFsIHZhbGlkaXR5LCBkb24ndCBkbyB0b28gbWFueSByZXRyaWVzLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBzdHNSZXRyeVN0cmF0ZWd5ID0gbmV3IENvbmZpZ3VyZWRSZXRyeVN0cmF0ZWd5KDMsIChhdHRlbXB0KSA9PiAxMDAgKiAoMiAqKiBhdHRlbXB0KSk7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgd2UgaGF2ZSBwcm9vZiB0aGF0IHRoZSBjcmVkZW50aWFscyBoYXZlIG5vdCBleHBpcmVkXG4gICAqXG4gICAqIFdlIG5lZWQgdG8gZG8gc29tZSBtYW51YWwgcGx1bWJpbmcgYXJvdW5kIHRoaXMgYmVjYXVzZSB0aGUgSlMgU0RLdjIgdHJlYXRzIGBFeHBpcmVkVG9rZW5gXG4gICAqIGFzIHJldHJpYWJsZSBhbmQgd2UgaGF2ZSBoZWZ0eSByZXRyaWVzIG9uIENGTiBjYWxscyBtYWtpbmcgdGhlIENMSSBoYW5nIGZvciBhIGdvb2QgMTUgbWludXRlc1xuICAgKiBpZiB0aGUgY3JlZGVudGlhbHMgaGF2ZSBleHBpcmVkLlxuICAgKi9cbiAgcHJpdmF0ZSBfY3JlZGVudGlhbHNWYWxpZGF0ZWQgPSBmYWxzZTtcblxuICAvKipcbiAgICogQSBmdW5jdGlvbiB0byBjcmVhdGUgZGVidWcgbWVzc2FnZXNcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNyZWRQcm92aWRlcjogQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXIsXG4gICAgcmVnaW9uOiBzdHJpbmcsXG4gICAgcmVxdWVzdEhhbmRsZXI6IE5vZGVIdHRwSGFuZGxlck9wdGlvbnMsXG4gICAgaW9IZWxwZXI6IElvSGVscGVyLFxuICAgIGxvZ2dlcj86IExvZ2dlcixcbiAgKSB7XG4gICAgY29uc3QgZGVidWdGbiA9IGFzeW5jIChtc2c6IHN0cmluZykgPT4gaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfU0RLX0RFQlVHLm1zZyhtc2cpKTtcbiAgICB0aGlzLmFjY291bnRDYWNoZSA9IG5ldyBBY2NvdW50QWNjZXNzS2V5Q2FjaGUoQWNjb3VudEFjY2Vzc0tleUNhY2hlLkRFRkFVTFRfUEFUSCwgZGVidWdGbik7XG4gICAgdGhpcy5kZWJ1ZyA9IGRlYnVnRm47XG4gICAgdGhpcy5jb25maWcgPSB7XG4gICAgICByZWdpb24sXG4gICAgICBjcmVkZW50aWFsczogY3JlZFByb3ZpZGVyLFxuICAgICAgcmVxdWVzdEhhbmRsZXIsXG4gICAgICByZXRyeVN0cmF0ZWd5OiBuZXcgQ29uZmlndXJlZFJldHJ5U3RyYXRlZ3koNywgKGF0dGVtcHQpID0+IDMwMCAqICgyICoqIGF0dGVtcHQpKSxcbiAgICAgIGN1c3RvbVVzZXJBZ2VudDogZGVmYXVsdENsaVVzZXJBZ2VudCgpLFxuICAgICAgbG9nZ2VyLFxuICAgIH07XG4gICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG4gICAgdGhpcy5jdXJyZW50UmVnaW9uID0gcmVnaW9uO1xuICB9XG5cbiAgcHVibGljIGFwcGVuZEN1c3RvbVVzZXJBZ2VudCh1c2VyQWdlbnREYXRhPzogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF1c2VyQWdlbnREYXRhKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudEN1c3RvbVVzZXJBZ2VudCA9IHRoaXMuY29uZmlnLmN1c3RvbVVzZXJBZ2VudDtcbiAgICB0aGlzLmNvbmZpZy5jdXN0b21Vc2VyQWdlbnQgPSBjdXJyZW50Q3VzdG9tVXNlckFnZW50ID8gYCR7Y3VycmVudEN1c3RvbVVzZXJBZ2VudH0gJHt1c2VyQWdlbnREYXRhfWAgOiB1c2VyQWdlbnREYXRhO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUN1c3RvbVVzZXJBZ2VudCh1c2VyQWdlbnREYXRhOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmNvbmZpZy5jdXN0b21Vc2VyQWdlbnQgPSB0aGlzLmNvbmZpZy5jdXN0b21Vc2VyQWdlbnQ/LnJlcGxhY2UodXNlckFnZW50RGF0YSwgJycpO1xuICB9XG5cbiAgcHVibGljIGFwcHN5bmMoKTogSUFwcFN5bmNDbGllbnQge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBBcHBTeW5jQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgZ2V0U2NoZW1hQ3JlYXRpb25TdGF0dXM6IChcbiAgICAgICAgaW5wdXQ6IEdldFNjaGVtYUNyZWF0aW9uU3RhdHVzQ29tbWFuZElucHV0LFxuICAgICAgKTogUHJvbWlzZTxHZXRTY2hlbWFDcmVhdGlvblN0YXR1c0NvbW1hbmRPdXRwdXQ+ID0+IGNsaWVudC5zZW5kKG5ldyBHZXRTY2hlbWFDcmVhdGlvblN0YXR1c0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHN0YXJ0U2NoZW1hQ3JlYXRpb246IChpbnB1dDogU3RhcnRTY2hlbWFDcmVhdGlvbkNvbW1hbmRJbnB1dCk6IFByb21pc2U8U3RhcnRTY2hlbWFDcmVhdGlvbkNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBTdGFydFNjaGVtYUNyZWF0aW9uQ29tbWFuZChpbnB1dCkpLFxuICAgICAgdXBkYXRlQXBpS2V5OiAoaW5wdXQ6IFVwZGF0ZUFwaUtleUNvbW1hbmRJbnB1dCk6IFByb21pc2U8VXBkYXRlQXBpS2V5Q29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFVwZGF0ZUFwaUtleUNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHVwZGF0ZUZ1bmN0aW9uOiAoaW5wdXQ6IFVwZGF0ZUZ1bmN0aW9uQ29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVGdW5jdGlvbkNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBVcGRhdGVGdW5jdGlvbkNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHVwZGF0ZVJlc29sdmVyOiAoaW5wdXQ6IFVwZGF0ZVJlc29sdmVyQ29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVSZXNvbHZlckNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBVcGRhdGVSZXNvbHZlckNvbW1hbmQoaW5wdXQpKSxcblxuICAgICAgLy8gUGFnaW5hdGlvbiBGdW5jdGlvbnNcbiAgICAgIGxpc3RGdW5jdGlvbnM6IGFzeW5jIChpbnB1dDogTGlzdEZ1bmN0aW9uc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RnVuY3Rpb25Db25maWd1cmF0aW9uW10+ID0+IHtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25zID0gQXJyYXk8RnVuY3Rpb25Db25maWd1cmF0aW9uPigpO1xuICAgICAgICBjb25zdCBwYWdpbmF0b3IgPSBwYWdpbmF0ZUxpc3RGdW5jdGlvbnMoeyBjbGllbnQgfSwgaW5wdXQpO1xuICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IHBhZ2Ugb2YgcGFnaW5hdG9yKSB7XG4gICAgICAgICAgZnVuY3Rpb25zLnB1c2goLi4uKHBhZ2UuZnVuY3Rpb25zIHx8IFtdKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9ucztcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBjbG91ZENvbnRyb2woKTogSUNsb3VkQ29udHJvbENsaWVudCB7XG4gICAgY29uc3QgY2xpZW50ID0gbmV3IENsb3VkQ29udHJvbENsaWVudCh0aGlzLmNvbmZpZyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxpc3RSZXNvdXJjZXM6IChpbnB1dDogTGlzdFJlc291cmNlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8TGlzdFJlc291cmNlc0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBMaXN0UmVzb3VyY2VzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZ2V0UmVzb3VyY2U6IChpbnB1dDogR2V0UmVzb3VyY2VDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFJlc291cmNlQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEdldFJlc291cmNlQ29tbWFuZChpbnB1dCkpLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgY2xvdWRGb3JtYXRpb24oKTogSUNsb3VkRm9ybWF0aW9uQ2xpZW50IHtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgQ2xvdWRGb3JtYXRpb25DbGllbnQoe1xuICAgICAgLi4udGhpcy5jb25maWcsXG4gICAgICByZXRyeVN0cmF0ZWd5OiBuZXcgQ29uZmlndXJlZFJldHJ5U3RyYXRlZ3koMTEsIChhdHRlbXB0OiBudW1iZXIpID0+IDEwMDAgKiAoMiAqKiBhdHRlbXB0KSksXG4gICAgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRpbnVlVXBkYXRlUm9sbGJhY2s6IGFzeW5jIChcbiAgICAgICAgaW5wdXQ6IENvbnRpbnVlVXBkYXRlUm9sbGJhY2tDb21tYW5kSW5wdXQsXG4gICAgICApOiBQcm9taXNlPENvbnRpbnVlVXBkYXRlUm9sbGJhY2tDb21tYW5kT3V0cHV0PiA9PiBjbGllbnQuc2VuZChuZXcgQ29udGludWVVcGRhdGVSb2xsYmFja0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGNyZWF0ZUNoYW5nZVNldDogKGlucHV0OiBDcmVhdGVDaGFuZ2VTZXRDb21tYW5kSW5wdXQpOiBQcm9taXNlPENyZWF0ZUNoYW5nZVNldENvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBDcmVhdGVDaGFuZ2VTZXRDb21tYW5kKGlucHV0KSksXG4gICAgICBjcmVhdGVHZW5lcmF0ZWRUZW1wbGF0ZTogKFxuICAgICAgICBpbnB1dDogQ3JlYXRlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kSW5wdXQsXG4gICAgICApOiBQcm9taXNlPENyZWF0ZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dD4gPT4gY2xpZW50LnNlbmQobmV3IENyZWF0ZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZChpbnB1dCkpLFxuICAgICAgY3JlYXRlU3RhY2s6IChpbnB1dDogQ3JlYXRlU3RhY2tDb21tYW5kSW5wdXQpOiBQcm9taXNlPENyZWF0ZVN0YWNrQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IENyZWF0ZVN0YWNrQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZGVsZXRlQ2hhbmdlU2V0OiAoaW5wdXQ6IERlbGV0ZUNoYW5nZVNldENvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVsZXRlQ2hhbmdlU2V0Q29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlbGV0ZUNoYW5nZVNldENvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlbGV0ZUdlbmVyYXRlZFRlbXBsYXRlOiAoXG4gICAgICAgIGlucHV0OiBEZWxldGVHZW5lcmF0ZWRUZW1wbGF0ZUNvbW1hbmRJbnB1dCxcbiAgICAgICk6IFByb21pc2U8RGVsZXRlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kT3V0cHV0PiA9PiBjbGllbnQuc2VuZChuZXcgRGVsZXRlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kKGlucHV0KSksXG4gICAgICBkZWxldGVTdGFjazogKGlucHV0OiBEZWxldGVTdGFja0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVsZXRlU3RhY2tDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGVsZXRlU3RhY2tDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXRlY3RTdGFja0RyaWZ0OiAoaW5wdXQ6IERldGVjdFN0YWNrRHJpZnRDb21tYW5kSW5wdXQpOiBQcm9taXNlPERldGVjdFN0YWNrRHJpZnRDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGV0ZWN0U3RhY2tEcmlmdENvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRldGVjdFN0YWNrUmVzb3VyY2VEcmlmdDogKGlucHV0OiBEZXRlY3RTdGFja1Jlc291cmNlRHJpZnRDb21tYW5kSW5wdXQpOiBQcm9taXNlPERldGVjdFN0YWNrUmVzb3VyY2VEcmlmdENvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZXRlY3RTdGFja1Jlc291cmNlRHJpZnRDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZUNoYW5nZVNldDogKGlucHV0OiBEZXNjcmliZUNoYW5nZVNldENvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVDaGFuZ2VTZXRDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVDaGFuZ2VTZXRDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlOiAoXG4gICAgICAgIGlucHV0OiBEZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZElucHV0LFxuICAgICAgKTogUHJvbWlzZTxEZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dD4gPT4gY2xpZW50LnNlbmQobmV3IERlc2NyaWJlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZVJlc291cmNlU2NhbjogKGlucHV0OiBEZXNjcmliZVJlc291cmNlU2NhbkNvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVSZXNvdXJjZVNjYW5Db21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVSZXNvdXJjZVNjYW5Db21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZVN0YWNrRHJpZnREZXRlY3Rpb25TdGF0dXM6IChpbnB1dDogRGVzY3JpYmVTdGFja0RyaWZ0RGV0ZWN0aW9uU3RhdHVzQ29tbWFuZElucHV0KTpcbiAgICAgIFByb21pc2U8RGVzY3JpYmVTdGFja0RyaWZ0RGV0ZWN0aW9uU3RhdHVzQ29tbWFuZE91dHB1dD4gPT4gY2xpZW50LnNlbmQobmV3IERlc2NyaWJlU3RhY2tEcmlmdERldGVjdGlvblN0YXR1c0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlc2NyaWJlU3RhY2tSZXNvdXJjZURyaWZ0czogKGlucHV0OiBEZXNjcmliZVN0YWNrUmVzb3VyY2VEcmlmdHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlU3RhY2tSZXNvdXJjZURyaWZ0c0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZXNjcmliZVN0YWNrUmVzb3VyY2VEcmlmdHNDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZVN0YWNrczogKGlucHV0OiBEZXNjcmliZVN0YWNrc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVTdGFja3NDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVTdGFja3NDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZVN0YWNrUmVzb3VyY2VzOiAoaW5wdXQ6IERlc2NyaWJlU3RhY2tSZXNvdXJjZXNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlU3RhY2tSZXNvdXJjZXNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVTdGFja1Jlc291cmNlc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGV4ZWN1dGVDaGFuZ2VTZXQ6IChpbnB1dDogRXhlY3V0ZUNoYW5nZVNldENvbW1hbmRJbnB1dCk6IFByb21pc2U8RXhlY3V0ZUNoYW5nZVNldENvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBFeGVjdXRlQ2hhbmdlU2V0Q29tbWFuZChpbnB1dCkpLFxuICAgICAgZ2V0R2VuZXJhdGVkVGVtcGxhdGU6IChpbnB1dDogR2V0R2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldEdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEdldEdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZ2V0VGVtcGxhdGU6IChpbnB1dDogR2V0VGVtcGxhdGVDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFRlbXBsYXRlQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEdldFRlbXBsYXRlQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZ2V0VGVtcGxhdGVTdW1tYXJ5OiAoaW5wdXQ6IEdldFRlbXBsYXRlU3VtbWFyeUNvbW1hbmRJbnB1dCk6IFByb21pc2U8R2V0VGVtcGxhdGVTdW1tYXJ5Q29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEdldFRlbXBsYXRlU3VtbWFyeUNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGxpc3RFeHBvcnRzOiAoaW5wdXQ6IExpc3RFeHBvcnRzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMaXN0RXhwb3J0c0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBMaXN0RXhwb3J0c0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGxpc3RSZXNvdXJjZVNjYW5SZWxhdGVkUmVzb3VyY2VzOiAoXG4gICAgICAgIGlucHV0OiBMaXN0UmVzb3VyY2VTY2FuUmVsYXRlZFJlc291cmNlc0NvbW1hbmRJbnB1dCxcbiAgICAgICk6IFByb21pc2U8TGlzdFJlc291cmNlU2NhblJlbGF0ZWRSZXNvdXJjZXNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgTGlzdFJlc291cmNlU2NhblJlbGF0ZWRSZXNvdXJjZXNDb21tYW5kKGlucHV0KSksXG4gICAgICBsaXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzOiAoXG4gICAgICAgIGlucHV0OiBMaXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzQ29tbWFuZElucHV0LFxuICAgICAgKTogUHJvbWlzZTxMaXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzQ29tbWFuZE91dHB1dD4gPT4gY2xpZW50LnNlbmQobmV3IExpc3RSZXNvdXJjZVNjYW5SZXNvdXJjZXNDb21tYW5kKGlucHV0KSksXG4gICAgICBsaXN0UmVzb3VyY2VTY2FuczogKGlucHV0OiBMaXN0UmVzb3VyY2VTY2Fuc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8TGlzdFJlc291cmNlU2NhbnNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgTGlzdFJlc291cmNlU2NhbnNDb21tYW5kKGlucHV0KSksXG4gICAgICBsaXN0U3RhY2tzOiAoaW5wdXQ6IExpc3RTdGFja3NDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RTdGFja3NDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgTGlzdFN0YWNrc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHJvbGxiYWNrU3RhY2s6IChpbnB1dDogUm9sbGJhY2tTdGFja0NvbW1hbmRJbnB1dCk6IFByb21pc2U8Um9sbGJhY2tTdGFja0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBSb2xsYmFja1N0YWNrQ29tbWFuZChpbnB1dCkpLFxuICAgICAgc3RhcnRSZXNvdXJjZVNjYW46IChpbnB1dDogU3RhcnRSZXNvdXJjZVNjYW5Db21tYW5kSW5wdXQpOiBQcm9taXNlPFN0YXJ0UmVzb3VyY2VTY2FuQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFN0YXJ0UmVzb3VyY2VTY2FuQ29tbWFuZChpbnB1dCkpLFxuICAgICAgdXBkYXRlU3RhY2s6IChpbnB1dDogVXBkYXRlU3RhY2tDb21tYW5kSW5wdXQpOiBQcm9taXNlPFVwZGF0ZVN0YWNrQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFVwZGF0ZVN0YWNrQ29tbWFuZChpbnB1dCkpLFxuICAgICAgdXBkYXRlVGVybWluYXRpb25Qcm90ZWN0aW9uOiAoXG4gICAgICAgIGlucHV0OiBVcGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb25Db21tYW5kSW5wdXQsXG4gICAgICApOiBQcm9taXNlPFVwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbkNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBVcGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb25Db21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZVN0YWNrRXZlbnRzOiAoaW5wdXQ6IERlc2NyaWJlU3RhY2tFdmVudHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlU3RhY2tFdmVudHNDb21tYW5kT3V0cHV0PiA9PiB7XG4gICAgICAgIHJldHVybiBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVTdGFja0V2ZW50c0NvbW1hbmQoaW5wdXQpKTtcbiAgICAgIH0sXG4gICAgICBsaXN0U3RhY2tSZXNvdXJjZXM6IGFzeW5jIChpbnB1dDogTGlzdFN0YWNrUmVzb3VyY2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxTdGFja1Jlc291cmNlU3VtbWFyeVtdPiA9PiB7XG4gICAgICAgIGNvbnN0IHN0YWNrUmVzb3VyY2VzID0gQXJyYXk8U3RhY2tSZXNvdXJjZVN1bW1hcnk+KCk7XG4gICAgICAgIGNvbnN0IHBhZ2luYXRvciA9IHBhZ2luYXRlTGlzdFN0YWNrUmVzb3VyY2VzKHsgY2xpZW50IH0sIGlucHV0KTtcbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBwYWdlIG9mIHBhZ2luYXRvcikge1xuICAgICAgICAgIHN0YWNrUmVzb3VyY2VzLnB1c2goLi4uKHBhZ2U/LlN0YWNrUmVzb3VyY2VTdW1tYXJpZXMgfHwgW10pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RhY2tSZXNvdXJjZXM7XG4gICAgICB9LFxuICAgICAgcGFnaW5hdGVkTGlzdFN0YWNrczogYXN5bmMgKGlucHV0OiBMaXN0U3RhY2tzQ29tbWFuZElucHV0KTogUHJvbWlzZTxTdGFja1N1bW1hcnlbXT4gPT4ge1xuICAgICAgICBjb25zdCBzdGFja1Jlc291cmNlcyA9IEFycmF5PFN0YWNrU3VtbWFyeT4oKTtcbiAgICAgICAgY29uc3QgcGFnaW5hdG9yID0gcGFnaW5hdGVMaXN0U3RhY2tzKHsgY2xpZW50IH0sIGlucHV0KTtcbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBwYWdlIG9mIHBhZ2luYXRvcikge1xuICAgICAgICAgIHN0YWNrUmVzb3VyY2VzLnB1c2goLi4uKHBhZ2U/LlN0YWNrU3VtbWFyaWVzIHx8IFtdKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0YWNrUmVzb3VyY2VzO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGNsb3VkV2F0Y2hMb2dzKCk6IElDbG91ZFdhdGNoTG9nc0NsaWVudCB7XG4gICAgY29uc3QgY2xpZW50ID0gbmV3IENsb3VkV2F0Y2hMb2dzQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGVzY3JpYmVMb2dHcm91cHM6IChpbnB1dDogRGVzY3JpYmVMb2dHcm91cHNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlTG9nR3JvdXBzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlc2NyaWJlTG9nR3JvdXBzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZmlsdGVyTG9nRXZlbnRzOiAoaW5wdXQ6IEZpbHRlckxvZ0V2ZW50c0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RmlsdGVyTG9nRXZlbnRzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEZpbHRlckxvZ0V2ZW50c0NvbW1hbmQoaW5wdXQpKSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGNvZGVCdWlsZCgpOiBJQ29kZUJ1aWxkQ2xpZW50IHtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgQ29kZUJ1aWxkQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgdXBkYXRlUHJvamVjdDogKGlucHV0OiBVcGRhdGVQcm9qZWN0Q29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVQcm9qZWN0Q29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFVwZGF0ZVByb2plY3RDb21tYW5kKGlucHV0KSksXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBlYzIoKTogSUVDMkNsaWVudCB7XG4gICAgY29uc3QgY2xpZW50ID0gbmV3IEVDMkNsaWVudCh0aGlzLmNvbmZpZyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlc2NyaWJlQXZhaWxhYmlsaXR5Wm9uZXM6IChcbiAgICAgICAgaW5wdXQ6IERlc2NyaWJlQXZhaWxhYmlsaXR5Wm9uZXNDb21tYW5kSW5wdXQsXG4gICAgICApOiBQcm9taXNlPERlc2NyaWJlQXZhaWxhYmlsaXR5Wm9uZXNDb21tYW5kT3V0cHV0PiA9PiBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVBdmFpbGFiaWxpdHlab25lc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlc2NyaWJlSW1hZ2VzOiAoaW5wdXQ6IERlc2NyaWJlSW1hZ2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZXNjcmliZUltYWdlc0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZXNjcmliZUltYWdlc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlc2NyaWJlSW5zdGFuY2VzOiAoaW5wdXQ6IERlc2NyaWJlSW5zdGFuY2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZXNjcmliZUluc3RhbmNlc0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlc2NyaWJlUm91dGVUYWJsZXM6IChpbnB1dDogRGVzY3JpYmVSb3V0ZVRhYmxlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVSb3V0ZVRhYmxlc0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZXNjcmliZVJvdXRlVGFibGVzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZGVzY3JpYmVTZWN1cml0eUdyb3VwczogKFxuICAgICAgICBpbnB1dDogRGVzY3JpYmVTZWN1cml0eUdyb3Vwc0NvbW1hbmRJbnB1dCxcbiAgICAgICk6IFByb21pc2U8RGVzY3JpYmVTZWN1cml0eUdyb3Vwc0NvbW1hbmRPdXRwdXQ+ID0+IGNsaWVudC5zZW5kKG5ldyBEZXNjcmliZVNlY3VyaXR5R3JvdXBzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZGVzY3JpYmVTdWJuZXRzOiAoaW5wdXQ6IERlc2NyaWJlU3VibmV0c0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVTdWJuZXRzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlc2NyaWJlU3VibmV0c0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlc2NyaWJlVnBjRW5kcG9pbnRTZXJ2aWNlczogKFxuICAgICAgICBpbnB1dDogRGVzY3JpYmVWcGNFbmRwb2ludFNlcnZpY2VzQ29tbWFuZElucHV0LFxuICAgICAgKTogUHJvbWlzZTxEZXNjcmliZVZwY0VuZHBvaW50U2VydmljZXNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVWcGNFbmRwb2ludFNlcnZpY2VzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZGVzY3JpYmVWcGNzOiAoaW5wdXQ6IERlc2NyaWJlVnBjc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVWcGNzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlc2NyaWJlVnBjc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlc2NyaWJlVnBuR2F0ZXdheXM6IChpbnB1dDogRGVzY3JpYmVWcG5HYXRld2F5c0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVWcG5HYXRld2F5c0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZXNjcmliZVZwbkdhdGV3YXlzQ29tbWFuZChpbnB1dCkpLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZWNyKCk6IElFQ1JDbGllbnQge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBFQ1JDbGllbnQodGhpcy5jb25maWcpO1xuICAgIHJldHVybiB7XG4gICAgICBiYXRjaERlbGV0ZUltYWdlOiAoaW5wdXQ6IEJhdGNoRGVsZXRlSW1hZ2VDb21tYW5kSW5wdXQpOiBQcm9taXNlPEJhdGNoRGVsZXRlSW1hZ2VDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgQmF0Y2hEZWxldGVJbWFnZUNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGJhdGNoR2V0SW1hZ2U6IChpbnB1dDogQmF0Y2hHZXRJbWFnZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8QmF0Y2hHZXRJbWFnZUNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBCYXRjaEdldEltYWdlQ29tbWFuZChpbnB1dCkpLFxuICAgICAgY3JlYXRlUmVwb3NpdG9yeTogKGlucHV0OiBDcmVhdGVSZXBvc2l0b3J5Q29tbWFuZElucHV0KTogUHJvbWlzZTxDcmVhdGVSZXBvc2l0b3J5Q29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZUltYWdlczogKGlucHV0OiBFQ1JEZXNjcmliZUltYWdlc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RUNSRGVzY3JpYmVJbWFnZXNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRUNSRGVzY3JpYmVJbWFnZXNDb21tYW5kKGlucHV0KSksXG4gICAgICBkZXNjcmliZVJlcG9zaXRvcmllczogKGlucHV0OiBEZXNjcmliZVJlcG9zaXRvcmllc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVSZXBvc2l0b3JpZXNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgRGVzY3JpYmVSZXBvc2l0b3JpZXNDb21tYW5kKGlucHV0KSksXG4gICAgICBnZXRBdXRob3JpemF0aW9uVG9rZW46IChpbnB1dDogR2V0QXV0aG9yaXphdGlvblRva2VuQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRBdXRob3JpemF0aW9uVG9rZW5Db21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgR2V0QXV0aG9yaXphdGlvblRva2VuQ29tbWFuZChpbnB1dCkpLFxuICAgICAgbGlzdEltYWdlczogKGlucHV0OiBMaXN0SW1hZ2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMaXN0SW1hZ2VzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IExpc3RJbWFnZXNDb21tYW5kKGlucHV0KSksXG4gICAgICBwdXRJbWFnZTogKGlucHV0OiBQdXRJbWFnZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8UHV0SW1hZ2VDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgUHV0SW1hZ2VDb21tYW5kKGlucHV0KSksXG4gICAgICBwdXRJbWFnZVNjYW5uaW5nQ29uZmlndXJhdGlvbjogKFxuICAgICAgICBpbnB1dDogUHV0SW1hZ2VTY2FubmluZ0NvbmZpZ3VyYXRpb25Db21tYW5kSW5wdXQsXG4gICAgICApOiBQcm9taXNlPFB1dEltYWdlU2Nhbm5pbmdDb25maWd1cmF0aW9uQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFB1dEltYWdlU2Nhbm5pbmdDb25maWd1cmF0aW9uQ29tbWFuZChpbnB1dCkpLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZWNzKCk6IElFQ1NDbGllbnQge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBFQ1NDbGllbnQodGhpcy5jb25maWcpO1xuICAgIHJldHVybiB7XG4gICAgICBsaXN0Q2x1c3RlcnM6IChpbnB1dDogTGlzdENsdXN0ZXJzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMaXN0Q2x1c3RlcnNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgTGlzdENsdXN0ZXJzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgcmVnaXN0ZXJUYXNrRGVmaW5pdGlvbjogKFxuICAgICAgICBpbnB1dDogUmVnaXN0ZXJUYXNrRGVmaW5pdGlvbkNvbW1hbmRJbnB1dCxcbiAgICAgICk6IFByb21pc2U8UmVnaXN0ZXJUYXNrRGVmaW5pdGlvbkNvbW1hbmRPdXRwdXQ+ID0+IGNsaWVudC5zZW5kKG5ldyBSZWdpc3RlclRhc2tEZWZpbml0aW9uQ29tbWFuZChpbnB1dCkpLFxuICAgICAgdXBkYXRlU2VydmljZTogKGlucHV0OiBVcGRhdGVTZXJ2aWNlQ29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVTZXJ2aWNlQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFVwZGF0ZVNlcnZpY2VDb21tYW5kKGlucHV0KSksXG4gICAgICAvLyBXYWl0ZXJzXG4gICAgICB3YWl0VW50aWxTZXJ2aWNlc1N0YWJsZTogKGlucHV0OiBEZXNjcmliZVNlcnZpY2VzQ29tbWFuZElucHV0KTogUHJvbWlzZTxXYWl0ZXJSZXN1bHQ+ID0+IHtcbiAgICAgICAgcmV0dXJuIHdhaXRVbnRpbFNlcnZpY2VzU3RhYmxlKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNsaWVudCxcbiAgICAgICAgICAgIG1heFdhaXRUaW1lOiA2MDAsXG4gICAgICAgICAgICBtaW5EZWxheTogNixcbiAgICAgICAgICAgIG1heERlbGF5OiA2LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW5wdXQsXG4gICAgICAgICk7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZWxidjIoKTogSUVsYXN0aWNMb2FkQmFsYW5jaW5nVjJDbGllbnQge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBFbGFzdGljTG9hZEJhbGFuY2luZ1YyQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGVzY3JpYmVMaXN0ZW5lcnM6IChpbnB1dDogRGVzY3JpYmVMaXN0ZW5lcnNDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlTGlzdGVuZXJzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlc2NyaWJlTGlzdGVuZXJzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZGVzY3JpYmVMb2FkQmFsYW5jZXJzOiAoaW5wdXQ6IERlc2NyaWJlTG9hZEJhbGFuY2Vyc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVzY3JpYmVMb2FkQmFsYW5jZXJzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlc2NyaWJlTG9hZEJhbGFuY2Vyc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGRlc2NyaWJlVGFnczogKGlucHV0OiBEZXNjcmliZVRhZ3NDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlVGFnc0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZXNjcmliZVRhZ3NDb21tYW5kKGlucHV0KSksXG4gICAgICAvLyBQYWdpbmF0aW9uIEZ1bmN0aW9uc1xuICAgICAgcGFnaW5hdGVEZXNjcmliZUxpc3RlbmVyczogYXN5bmMgKGlucHV0OiBEZXNjcmliZUxpc3RlbmVyc0NvbW1hbmRJbnB1dCk6IFByb21pc2U8TGlzdGVuZXJbXT4gPT4ge1xuICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSBBcnJheTxMaXN0ZW5lcj4oKTtcbiAgICAgICAgY29uc3QgcGFnaW5hdG9yID0gcGFnaW5hdGVEZXNjcmliZUxpc3RlbmVycyh7IGNsaWVudCB9LCBpbnB1dCk7XG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgcGFnZSBvZiBwYWdpbmF0b3IpIHtcbiAgICAgICAgICBsaXN0ZW5lcnMucHVzaCguLi4ocGFnZT8uTGlzdGVuZXJzIHx8IFtdKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxpc3RlbmVycztcbiAgICAgIH0sXG4gICAgICBwYWdpbmF0ZURlc2NyaWJlTG9hZEJhbGFuY2VyczogYXN5bmMgKGlucHV0OiBEZXNjcmliZUxvYWRCYWxhbmNlcnNDb21tYW5kSW5wdXQpOiBQcm9taXNlPExvYWRCYWxhbmNlcltdPiA9PiB7XG4gICAgICAgIGNvbnN0IGxvYWRCYWxhbmNlcnMgPSBBcnJheTxMb2FkQmFsYW5jZXI+KCk7XG4gICAgICAgIGNvbnN0IHBhZ2luYXRvciA9IHBhZ2luYXRlRGVzY3JpYmVMb2FkQmFsYW5jZXJzKHsgY2xpZW50IH0sIGlucHV0KTtcbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBwYWdlIG9mIHBhZ2luYXRvcikge1xuICAgICAgICAgIGxvYWRCYWxhbmNlcnMucHVzaCguLi4ocGFnZT8uTG9hZEJhbGFuY2VycyB8fCBbXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2FkQmFsYW5jZXJzO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGlhbSgpOiBJSUFNQ2xpZW50IHtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgSUFNQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgY3JlYXRlUG9saWN5OiAoaW5wdXQ6IENyZWF0ZVBvbGljeUNvbW1hbmRJbnB1dCk6IFByb21pc2U8Q3JlYXRlUG9saWN5Q29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IENyZWF0ZVBvbGljeUNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIGdldFBvbGljeTogKGlucHV0OiBHZXRQb2xpY3lDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFBvbGljeUNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBHZXRQb2xpY3lDb21tYW5kKGlucHV0KSksXG4gICAgICBnZXRSb2xlOiAoaW5wdXQ6IEdldFJvbGVDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFJvbGVDb21tYW5kT3V0cHV0PiA9PiBjbGllbnQuc2VuZChuZXcgR2V0Um9sZUNvbW1hbmQoaW5wdXQpKSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGttcygpOiBJS01TQ2xpZW50IHtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgS01TQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGVzY3JpYmVLZXk6IChpbnB1dDogRGVzY3JpYmVLZXlDb21tYW5kSW5wdXQpOiBQcm9taXNlPERlc2NyaWJlS2V5Q29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlc2NyaWJlS2V5Q29tbWFuZChpbnB1dCkpLFxuICAgICAgbGlzdEFsaWFzZXM6IChpbnB1dDogTGlzdEFsaWFzZXNDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RBbGlhc2VzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IExpc3RBbGlhc2VzQ29tbWFuZChpbnB1dCkpLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgbGFtYmRhKCk6IElMYW1iZGFDbGllbnQge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBMYW1iZGFDbGllbnQodGhpcy5jb25maWcpO1xuICAgIHJldHVybiB7XG4gICAgICBpbnZva2VDb21tYW5kOiAoaW5wdXQ6IEludm9rZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8SW52b2tlQ29tbWFuZE91dHB1dD4gPT4gY2xpZW50LnNlbmQobmV3IEludm9rZUNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHB1Ymxpc2hWZXJzaW9uOiAoaW5wdXQ6IFB1Ymxpc2hWZXJzaW9uQ29tbWFuZElucHV0KTogUHJvbWlzZTxQdWJsaXNoVmVyc2lvbkNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBQdWJsaXNoVmVyc2lvbkNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHVwZGF0ZUFsaWFzOiAoaW5wdXQ6IFVwZGF0ZUFsaWFzQ29tbWFuZElucHV0KTogUHJvbWlzZTxVcGRhdGVBbGlhc0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBVcGRhdGVBbGlhc0NvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHVwZGF0ZUZ1bmN0aW9uQ29kZTogKGlucHV0OiBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kSW5wdXQpOiBQcm9taXNlPFVwZGF0ZUZ1bmN0aW9uQ29kZUNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBVcGRhdGVGdW5jdGlvbkNvZGVDb21tYW5kKGlucHV0KSksXG4gICAgICB1cGRhdGVGdW5jdGlvbkNvbmZpZ3VyYXRpb246IChcbiAgICAgICAgaW5wdXQ6IFVwZGF0ZUZ1bmN0aW9uQ29uZmlndXJhdGlvbkNvbW1hbmRJbnB1dCxcbiAgICAgICk6IFByb21pc2U8VXBkYXRlRnVuY3Rpb25Db25maWd1cmF0aW9uQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFVwZGF0ZUZ1bmN0aW9uQ29uZmlndXJhdGlvbkNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIC8vIFdhaXRlcnNcbiAgICAgIHdhaXRVbnRpbEZ1bmN0aW9uVXBkYXRlZDogKFxuICAgICAgICBkZWxheVNlY29uZHM6IG51bWJlcixcbiAgICAgICAgaW5wdXQ6IFVwZGF0ZUZ1bmN0aW9uQ29uZmlndXJhdGlvbkNvbW1hbmRJbnB1dCxcbiAgICAgICk6IFByb21pc2U8V2FpdGVyUmVzdWx0PiA9PiB7XG4gICAgICAgIHJldHVybiB3YWl0VW50aWxGdW5jdGlvblVwZGF0ZWRWMihcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjbGllbnQsXG4gICAgICAgICAgICBtYXhEZWxheTogZGVsYXlTZWNvbmRzLFxuICAgICAgICAgICAgbWluRGVsYXk6IGRlbGF5U2Vjb25kcyxcbiAgICAgICAgICAgIG1heFdhaXRUaW1lOiBkZWxheVNlY29uZHMgKiA2MCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGlucHV0LFxuICAgICAgICApO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHJvdXRlNTMoKTogSVJvdXRlNTNDbGllbnQge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBSb3V0ZTUzQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgZ2V0SG9zdGVkWm9uZTogKGlucHV0OiBHZXRIb3N0ZWRab25lQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRIb3N0ZWRab25lQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEdldEhvc3RlZFpvbmVDb21tYW5kKGlucHV0KSksXG4gICAgICBsaXN0SG9zdGVkWm9uZXM6IChpbnB1dDogTGlzdEhvc3RlZFpvbmVzQ29tbWFuZElucHV0KTogUHJvbWlzZTxMaXN0SG9zdGVkWm9uZXNDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgTGlzdEhvc3RlZFpvbmVzQ29tbWFuZChpbnB1dCkpLFxuICAgICAgbGlzdEhvc3RlZFpvbmVzQnlOYW1lOiAoaW5wdXQ6IExpc3RIb3N0ZWRab25lc0J5TmFtZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8TGlzdEhvc3RlZFpvbmVzQnlOYW1lQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IExpc3RIb3N0ZWRab25lc0J5TmFtZUNvbW1hbmQoaW5wdXQpKSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHMzKCk6IElTM0NsaWVudCB7XG4gICAgY29uc3QgY2xpZW50ID0gbmV3IFMzQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGVsZXRlT2JqZWN0czogKGlucHV0OiBEZWxldGVPYmplY3RzQ29tbWFuZElucHV0KTogUHJvbWlzZTxEZWxldGVPYmplY3RzQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IERlbGV0ZU9iamVjdHNDb21tYW5kKHtcbiAgICAgICAgICAuLi5pbnB1dCxcbiAgICAgICAgICBDaGVja3N1bUFsZ29yaXRobTogJ1NIQTI1NicsXG4gICAgICAgIH0pKSxcbiAgICAgIGRlbGV0ZU9iamVjdFRhZ2dpbmc6IChpbnB1dDogRGVsZXRlT2JqZWN0VGFnZ2luZ0NvbW1hbmRJbnB1dCk6IFByb21pc2U8RGVsZXRlT2JqZWN0VGFnZ2luZ0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBEZWxldGVPYmplY3RUYWdnaW5nQ29tbWFuZChpbnB1dCkpLFxuICAgICAgZ2V0QnVja2V0RW5jcnlwdGlvbjogKGlucHV0OiBHZXRCdWNrZXRFbmNyeXB0aW9uQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRCdWNrZXRFbmNyeXB0aW9uQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEdldEJ1Y2tldEVuY3J5cHRpb25Db21tYW5kKGlucHV0KSksXG4gICAgICBnZXRCdWNrZXRMb2NhdGlvbjogKGlucHV0OiBHZXRCdWNrZXRMb2NhdGlvbkNvbW1hbmRJbnB1dCk6IFByb21pc2U8R2V0QnVja2V0TG9jYXRpb25Db21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgR2V0QnVja2V0TG9jYXRpb25Db21tYW5kKGlucHV0KSksXG4gICAgICBnZXRPYmplY3Q6IChpbnB1dDogR2V0T2JqZWN0Q29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRPYmplY3RDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgR2V0T2JqZWN0Q29tbWFuZChpbnB1dCkpLFxuICAgICAgZ2V0T2JqZWN0VGFnZ2luZzogKGlucHV0OiBHZXRPYmplY3RUYWdnaW5nQ29tbWFuZElucHV0KTogUHJvbWlzZTxHZXRPYmplY3RUYWdnaW5nQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IEdldE9iamVjdFRhZ2dpbmdDb21tYW5kKGlucHV0KSksXG4gICAgICBsaXN0T2JqZWN0c1YyOiAoaW5wdXQ6IExpc3RPYmplY3RzVjJDb21tYW5kSW5wdXQpOiBQcm9taXNlPExpc3RPYmplY3RzVjJDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgTGlzdE9iamVjdHNWMkNvbW1hbmQoaW5wdXQpKSxcbiAgICAgIHB1dE9iamVjdFRhZ2dpbmc6IChpbnB1dDogUHV0T2JqZWN0VGFnZ2luZ0NvbW1hbmRJbnB1dCk6IFByb21pc2U8UHV0T2JqZWN0VGFnZ2luZ0NvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBQdXRPYmplY3RUYWdnaW5nQ29tbWFuZCh7XG4gICAgICAgICAgLi4uaW5wdXQsXG4gICAgICAgICAgQ2hlY2tzdW1BbGdvcml0aG06ICdTSEEyNTYnLFxuICAgICAgICB9KSksXG4gICAgICB1cGxvYWQ6IChpbnB1dDogUHV0T2JqZWN0Q29tbWFuZElucHV0KTogUHJvbWlzZTxDb21wbGV0ZU11bHRpcGFydFVwbG9hZENvbW1hbmRPdXRwdXQ+ID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB1cGxvYWQgPSBuZXcgVXBsb2FkKHtcbiAgICAgICAgICAgIGNsaWVudCxcbiAgICAgICAgICAgIHBhcmFtczogeyAuLi5pbnB1dCwgQ2hlY2tzdW1BbGdvcml0aG06ICdTSEEyNTYnIH0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4gdXBsb2FkLmRvbmUoKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEF1dGhlbnRpY2F0aW9uRXJyb3IoYFVwbG9hZCBmYWlsZWQ6ICR7Zm9ybWF0RXJyb3JNZXNzYWdlKGUpfWApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgc2VjcmV0c01hbmFnZXIoKTogSVNlY3JldHNNYW5hZ2VyQ2xpZW50IHtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgU2VjcmV0c01hbmFnZXJDbGllbnQodGhpcy5jb25maWcpO1xuICAgIHJldHVybiB7XG4gICAgICBnZXRTZWNyZXRWYWx1ZTogKGlucHV0OiBHZXRTZWNyZXRWYWx1ZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8R2V0U2VjcmV0VmFsdWVDb21tYW5kT3V0cHV0PiA9PlxuICAgICAgICBjbGllbnQuc2VuZChuZXcgR2V0U2VjcmV0VmFsdWVDb21tYW5kKGlucHV0KSksXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBzc20oKTogSVNTTUNsaWVudCB7XG4gICAgY29uc3QgY2xpZW50ID0gbmV3IFNTTUNsaWVudCh0aGlzLmNvbmZpZyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGdldFBhcmFtZXRlcjogKGlucHV0OiBHZXRQYXJhbWV0ZXJDb21tYW5kSW5wdXQpOiBQcm9taXNlPEdldFBhcmFtZXRlckNvbW1hbmRPdXRwdXQ+ID0+XG4gICAgICAgIGNsaWVudC5zZW5kKG5ldyBHZXRQYXJhbWV0ZXJDb21tYW5kKGlucHV0KSksXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBzdGVwRnVuY3Rpb25zKCk6IElTdGVwRnVuY3Rpb25zQ2xpZW50IHtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgU0ZOQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICByZXR1cm4ge1xuICAgICAgdXBkYXRlU3RhdGVNYWNoaW5lOiAoaW5wdXQ6IFVwZGF0ZVN0YXRlTWFjaGluZUNvbW1hbmRJbnB1dCk6IFByb21pc2U8VXBkYXRlU3RhdGVNYWNoaW5lQ29tbWFuZE91dHB1dD4gPT5cbiAgICAgICAgY2xpZW50LnNlbmQobmV3IFVwZGF0ZVN0YXRlTWFjaGluZUNvbW1hbmQoaW5wdXQpKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgU0RLIHYzIHJlcXVpcmVzIGEgY2xpZW50IGNvbmZpZyBhbmQgYSBjb21tYW5kIGluIG9yZGVyIHRvIGdldCBhbiBlbmRwb2ludCBmb3JcbiAgICogYW55IGdpdmVuIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0VXJsU3VmZml4KHJlZ2lvbjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBjZm4gPSBuZXcgQ2xvdWRGb3JtYXRpb25DbGllbnQoeyByZWdpb24gfSk7XG4gICAgY29uc3QgZW5kcG9pbnQgPSBhd2FpdCBnZXRFbmRwb2ludEZyb21JbnN0cnVjdGlvbnMoe30sIERlc2NyaWJlU3RhY2tSZXNvdXJjZXNDb21tYW5kLCB7IC4uLmNmbi5jb25maWcgfSk7XG4gICAgcmV0dXJuIGVuZHBvaW50LnVybC5ob3N0bmFtZS5zcGxpdChgJHtyZWdpb259LmApLnBvcCgpITtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjdXJyZW50QWNjb3VudCgpOiBQcm9taXNlPEFjY291bnQ+IHtcbiAgICByZXR1cm4gY2FjaGVkQXN5bmModGhpcywgQ1VSUkVOVF9BQ0NPVU5UX0tFWSwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY3JlZHMgPSBhd2FpdCB0aGlzLmNyZWRQcm92aWRlcigpO1xuICAgICAgcmV0dXJuIHRoaXMuYWNjb3VudENhY2hlLmZldGNoKGNyZWRzLmFjY2Vzc0tleUlkLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIGlmIHdlIGRvbid0IGhhdmUgb25lLCByZXNvbHZlIGZyb20gU1RTIGFuZCBzdG9yZSBpbiBjYWNoZS5cbiAgICAgICAgYXdhaXQgdGhpcy5kZWJ1ZygnTG9va2luZyB1cCBkZWZhdWx0IGFjY291bnQgSUQgZnJvbSBTVFMnKTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gbmV3IFNUU0NsaWVudCh7XG4gICAgICAgICAgLi4udGhpcy5jb25maWcsXG4gICAgICAgICAgcmV0cnlTdHJhdGVneTogdGhpcy5zdHNSZXRyeVN0cmF0ZWd5LFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY29tbWFuZCA9IG5ldyBHZXRDYWxsZXJJZGVudGl0eUNvbW1hbmQoe30pO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjbGllbnQuc2VuZChjb21tYW5kKTtcbiAgICAgICAgY29uc3QgYWNjb3VudElkID0gcmVzdWx0LkFjY291bnQ7XG4gICAgICAgIGNvbnN0IHBhcnRpdGlvbiA9IHJlc3VsdC5Bcm4hLnNwbGl0KCc6JylbMV07XG4gICAgICAgIGlmICghYWNjb3VudElkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEF1dGhlbnRpY2F0aW9uRXJyb3IoXCJTVFMgZGlkbid0IHJldHVybiBhbiBhY2NvdW50IElEXCIpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuZGVidWcoYERlZmF1bHQgYWNjb3VudCBJRDogJHthY2NvdW50SWR9YCk7XG5cbiAgICAgICAgLy8gU2F2ZSBhbm90aGVyIFNUUyBjYWxsIGxhdGVyIGlmIHRoaXMgb25lIGFscmVhZHkgc3VjY2VlZGVkXG4gICAgICAgIHRoaXMuX2NyZWRlbnRpYWxzVmFsaWRhdGVkID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHsgYWNjb3VudElkLCBwYXJ0aXRpb24gfTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2Ugc3VyZSB0aGUgdGhlIGN1cnJlbnQgY3JlZGVudGlhbHMgYXJlIG5vdCBleHBpcmVkXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGVDcmVkZW50aWFscygpIHtcbiAgICBpZiAodGhpcy5fY3JlZGVudGlhbHNWYWxpZGF0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjbGllbnQgPSBuZXcgU1RTQ2xpZW50KHsgLi4udGhpcy5jb25maWcsIHJldHJ5U3RyYXRlZ3k6IHRoaXMuc3RzUmV0cnlTdHJhdGVneSB9KTtcbiAgICBhd2FpdCBjbGllbnQuc2VuZChuZXcgR2V0Q2FsbGVySWRlbnRpdHlDb21tYW5kKHt9KSk7XG4gICAgdGhpcy5fY3JlZGVudGlhbHNWYWxpZGF0ZWQgPSB0cnVlO1xuICB9XG59XG5cbmNvbnN0IENVUlJFTlRfQUNDT1VOVF9LRVkgPSBTeW1ib2woJ2N1cnJlbnRfYWNjb3VudF9rZXknKTtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.d.ts new file mode 100644 index 000000000..aa8a19170 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.d.ts @@ -0,0 +1,11 @@ +import type { Logger } from '@smithy/types'; +export declare function setSdkTracing(enabled: boolean): void; +/** + * Method decorator to trace a single static or member method, any time it's called + */ +export declare function callTrace(fn: string, className?: string, logger?: Logger): void; +/** + * Class decorator, enable tracing for all member methods on this class + * @deprecated this doesn't work well with localized logging instances, don't use + */ +export declare function traceMemberMethods(constructor: Function): void; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.js new file mode 100644 index 000000000..7b7cd36ca --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/tracing.js @@ -0,0 +1,60 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.setSdkTracing = setSdkTracing; +exports.callTrace = callTrace; +exports.traceMemberMethods = traceMemberMethods; +let ENABLED = false; +let INDENT = 0; +function setSdkTracing(enabled) { + ENABLED = enabled; +} +/** + * Method decorator to trace a single static or member method, any time it's called + */ +function callTrace(fn, className, logger) { + if (!ENABLED || !logger) { + return; + } + logger.info(`[trace] ${' '.repeat(INDENT)}${className || '(anonymous)'}#${fn}()`); +} +/** + * Method decorator to trace a single member method any time it's called + */ +function traceCall(receiver, _propertyKey, descriptor, parentClassName) { + const fn = descriptor.value; + const className = typeof receiver === 'function' ? receiver.name : parentClassName; + descriptor.value = function (...args) { + const logger = this.logger; + if (!ENABLED || typeof logger?.info !== 'function') { + return fn.apply(this, args); + } + logger.info.apply(logger, [`[trace] ${' '.repeat(INDENT)}${className || this.constructor.name || '(anonymous)'}#${fn.name}()`]); + INDENT += 2; + const ret = fn.apply(this, args); + if (ret instanceof Promise) { + return ret.finally(() => { + INDENT -= 2; + }); + } + else { + INDENT -= 2; + return ret; + } + }; + return descriptor; +} +/** + * Class decorator, enable tracing for all member methods on this class + * @deprecated this doesn't work well with localized logging instances, don't use + */ +function traceMemberMethods(constructor) { + // Instance members + for (const [name, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(constructor.prototype))) { + if (typeof descriptor.value !== 'function') { + continue; + } + const newDescriptor = traceCall(constructor.prototype, name, descriptor, constructor.name) ?? descriptor; + Object.defineProperty(constructor.prototype, name, newDescriptor); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvYXdzLWF1dGgvdHJhY2luZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUtBLHNDQUVDO0FBS0QsOEJBTUM7QUFtQ0QsZ0RBU0M7QUE1REQsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDO0FBQ3BCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztBQUVmLFNBQWdCLGFBQWEsQ0FBQyxPQUFnQjtJQUM1QyxPQUFPLEdBQUcsT0FBTyxDQUFDO0FBQ3BCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFNBQVMsQ0FBQyxFQUFVLEVBQUUsU0FBa0IsRUFBRSxNQUFlO0lBQ3ZFLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN4QixPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLFNBQVMsSUFBSSxhQUFhLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUNwRixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLFNBQVMsQ0FBQyxRQUFnQixFQUFFLFlBQW9CLEVBQUUsVUFBOEIsRUFBRSxlQUF3QjtJQUNqSCxNQUFNLEVBQUUsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO0lBQzVCLE1BQU0sU0FBUyxHQUFHLE9BQU8sUUFBUSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDO0lBRW5GLFVBQVUsQ0FBQyxLQUFLLEdBQUcsVUFBVSxHQUFHLElBQVc7UUFDekMsTUFBTSxNQUFNLEdBQUksSUFBWSxDQUFDLE1BQU0sQ0FBQztRQUNwQyxJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sTUFBTSxFQUFFLElBQUksS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUNuRCxPQUFPLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzlCLENBQUM7UUFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsU0FBUyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxJQUFJLGFBQWEsSUFBSSxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2hJLE1BQU0sSUFBSSxDQUFDLENBQUM7UUFFWixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNqQyxJQUFJLEdBQUcsWUFBWSxPQUFPLEVBQUUsQ0FBQztZQUMzQixPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFO2dCQUN0QixNQUFNLElBQUksQ0FBQyxDQUFDO1lBQ2QsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSSxDQUFDLENBQUM7WUFDWixPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUM7SUFDSCxDQUFDLENBQUM7SUFDRixPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBZ0Isa0JBQWtCLENBQUMsV0FBcUI7SUFDdEQsbUJBQW1CO0lBQ25CLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3pHLElBQUksT0FBTyxVQUFVLENBQUMsS0FBSyxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQzNDLFNBQVM7UUFDWCxDQUFDO1FBQ0QsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDO1FBQ3pHLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDcEUsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IExvZ2dlciB9IGZyb20gJ0BzbWl0aHkvdHlwZXMnO1xuXG5sZXQgRU5BQkxFRCA9IGZhbHNlO1xubGV0IElOREVOVCA9IDA7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRTZGtUcmFjaW5nKGVuYWJsZWQ6IGJvb2xlYW4pIHtcbiAgRU5BQkxFRCA9IGVuYWJsZWQ7XG59XG5cbi8qKlxuICogTWV0aG9kIGRlY29yYXRvciB0byB0cmFjZSBhIHNpbmdsZSBzdGF0aWMgb3IgbWVtYmVyIG1ldGhvZCwgYW55IHRpbWUgaXQncyBjYWxsZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGxUcmFjZShmbjogc3RyaW5nLCBjbGFzc05hbWU/OiBzdHJpbmcsIGxvZ2dlcj86IExvZ2dlcikge1xuICBpZiAoIUVOQUJMRUQgfHwgIWxvZ2dlcikge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxvZ2dlci5pbmZvKGBbdHJhY2VdICR7JyAnLnJlcGVhdChJTkRFTlQpfSR7Y2xhc3NOYW1lIHx8ICcoYW5vbnltb3VzKSd9IyR7Zm59KClgKTtcbn1cblxuLyoqXG4gKiBNZXRob2QgZGVjb3JhdG9yIHRvIHRyYWNlIGEgc2luZ2xlIG1lbWJlciBtZXRob2QgYW55IHRpbWUgaXQncyBjYWxsZWRcbiAqL1xuZnVuY3Rpb24gdHJhY2VDYWxsKHJlY2VpdmVyOiBvYmplY3QsIF9wcm9wZXJ0eUtleTogc3RyaW5nLCBkZXNjcmlwdG9yOiBQcm9wZXJ0eURlc2NyaXB0b3IsIHBhcmVudENsYXNzTmFtZT86IHN0cmluZykge1xuICBjb25zdCBmbiA9IGRlc2NyaXB0b3IudmFsdWU7XG4gIGNvbnN0IGNsYXNzTmFtZSA9IHR5cGVvZiByZWNlaXZlciA9PT0gJ2Z1bmN0aW9uJyA/IHJlY2VpdmVyLm5hbWUgOiBwYXJlbnRDbGFzc05hbWU7XG5cbiAgZGVzY3JpcHRvci52YWx1ZSA9IGZ1bmN0aW9uICguLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGxvZ2dlciA9ICh0aGlzIGFzIGFueSkubG9nZ2VyO1xuICAgIGlmICghRU5BQkxFRCB8fCB0eXBlb2YgbG9nZ2VyPy5pbmZvICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgfVxuXG4gICAgbG9nZ2VyLmluZm8uYXBwbHkobG9nZ2VyLCBbYFt0cmFjZV0gJHsnICcucmVwZWF0KElOREVOVCl9JHtjbGFzc05hbWUgfHwgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lIHx8ICcoYW5vbnltb3VzKSd9IyR7Zm4ubmFtZX0oKWBdKTtcbiAgICBJTkRFTlQgKz0gMjtcblxuICAgIGNvbnN0IHJldCA9IGZuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIGlmIChyZXQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICByZXR1cm4gcmV0LmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICBJTkRFTlQgLT0gMjtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBJTkRFTlQgLT0gMjtcbiAgICAgIHJldHVybiByZXQ7XG4gICAgfVxuICB9O1xuICByZXR1cm4gZGVzY3JpcHRvcjtcbn1cblxuLyoqXG4gKiBDbGFzcyBkZWNvcmF0b3IsIGVuYWJsZSB0cmFjaW5nIGZvciBhbGwgbWVtYmVyIG1ldGhvZHMgb24gdGhpcyBjbGFzc1xuICogQGRlcHJlY2F0ZWQgdGhpcyBkb2Vzbid0IHdvcmsgd2VsbCB3aXRoIGxvY2FsaXplZCBsb2dnaW5nIGluc3RhbmNlcywgZG9uJ3QgdXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFjZU1lbWJlck1ldGhvZHMoY29uc3RydWN0b3I6IEZ1bmN0aW9uKSB7XG4gIC8vIEluc3RhbmNlIG1lbWJlcnNcbiAgZm9yIChjb25zdCBbbmFtZSwgZGVzY3JpcHRvcl0gb2YgT2JqZWN0LmVudHJpZXMoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoY29uc3RydWN0b3IucHJvdG90eXBlKSkpIHtcbiAgICBpZiAodHlwZW9mIGRlc2NyaXB0b3IudmFsdWUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBuZXdEZXNjcmlwdG9yID0gdHJhY2VDYWxsKGNvbnN0cnVjdG9yLnByb3RvdHlwZSwgbmFtZSwgZGVzY3JpcHRvciwgY29uc3RydWN0b3IubmFtZSkgPz8gZGVzY3JpcHRvcjtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29uc3RydWN0b3IucHJvdG90eXBlLCBuYW1lLCBuZXdEZXNjcmlwdG9yKTtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.d.ts new file mode 100644 index 000000000..01ca9e12b --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.d.ts @@ -0,0 +1,7 @@ +/** + * Find the package.json from the main toolkit. + * + * If we can't read it for some reason, try to do something reasonable anyway. + * Fall back to argv[1], or a standard string if that is undefined for some reason. + */ +export declare function defaultCliUserAgent(): string; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.js new file mode 100644 index 000000000..2d83b73f5 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/user-agent.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.defaultCliUserAgent = defaultCliUserAgent; +const path = require("path"); +const util_1 = require("./util"); +const util_2 = require("../../util"); +/** + * Find the package.json from the main toolkit. + * + * If we can't read it for some reason, try to do something reasonable anyway. + * Fall back to argv[1], or a standard string if that is undefined for some reason. + */ +function defaultCliUserAgent() { + const root = (0, util_2.bundledPackageRootDir)(__dirname, false); + const pkg = JSON.parse((root ? (0, util_1.readIfPossible)(path.join(root, 'package.json')) : undefined) ?? '{}'); + const name = pkg.name ?? path.basename(process.argv[1] ?? 'cdk-cli'); + const version = pkg.version ?? ''; + return `${name}/${version}`; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci1hZ2VudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvYXdzLWF1dGgvdXNlci1hZ2VudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVNBLGtEQU1DO0FBZkQsNkJBQTZCO0FBQzdCLGlDQUF3QztBQUN4QyxxQ0FBbUQ7QUFDbkQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixtQkFBbUI7SUFDakMsTUFBTSxJQUFJLEdBQUcsSUFBQSw0QkFBcUIsRUFBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDckQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBQSxxQkFBYyxFQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDO0lBQ3JHLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxDQUFDO0lBQ3JFLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxPQUFPLElBQUksV0FBVyxDQUFDO0lBQzNDLE9BQU8sR0FBRyxJQUFJLElBQUksT0FBTyxFQUFFLENBQUM7QUFDOUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyByZWFkSWZQb3NzaWJsZSB9IGZyb20gJy4vdXRpbCc7XG5pbXBvcnQgeyBidW5kbGVkUGFja2FnZVJvb3REaXIgfSBmcm9tICcuLi8uLi91dGlsJztcbi8qKlxuICogRmluZCB0aGUgcGFja2FnZS5qc29uIGZyb20gdGhlIG1haW4gdG9vbGtpdC5cbiAqXG4gKiBJZiB3ZSBjYW4ndCByZWFkIGl0IGZvciBzb21lIHJlYXNvbiwgdHJ5IHRvIGRvIHNvbWV0aGluZyByZWFzb25hYmxlIGFueXdheS5cbiAqIEZhbGwgYmFjayB0byBhcmd2WzFdLCBvciBhIHN0YW5kYXJkIHN0cmluZyBpZiB0aGF0IGlzIHVuZGVmaW5lZCBmb3Igc29tZSByZWFzb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0Q2xpVXNlckFnZW50KCkge1xuICBjb25zdCByb290ID0gYnVuZGxlZFBhY2thZ2VSb290RGlyKF9fZGlybmFtZSwgZmFsc2UpO1xuICBjb25zdCBwa2cgPSBKU09OLnBhcnNlKChyb290ID8gcmVhZElmUG9zc2libGUocGF0aC5qb2luKHJvb3QsICdwYWNrYWdlLmpzb24nKSkgOiB1bmRlZmluZWQpID8/ICd7fScpO1xuICBjb25zdCBuYW1lID0gcGtnLm5hbWUgPz8gcGF0aC5iYXNlbmFtZShwcm9jZXNzLmFyZ3ZbMV0gPz8gJ2Nkay1jbGknKTtcbiAgY29uc3QgdmVyc2lvbiA9IHBrZy52ZXJzaW9uID8/ICc8dW5rbm93bj4nO1xuICByZXR1cm4gYCR7bmFtZX0vJHt2ZXJzaW9ufWA7XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.d.ts new file mode 100644 index 000000000..b84f5ca30 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.d.ts @@ -0,0 +1,6 @@ +/** + * Read a file if it exists, or return undefined + * + * Not async because it is used in the constructor + */ +export declare function readIfPossible(filename: string): string | undefined; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.js new file mode 100644 index 000000000..5fe1d4305 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/aws-auth/util.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.readIfPossible = readIfPossible; +const fs = require("fs-extra"); +/** + * Read a file if it exists, or return undefined + * + * Not async because it is used in the constructor + */ +function readIfPossible(filename) { + try { + if (!fs.pathExistsSync(filename)) { + return undefined; + } + return fs.readFileSync(filename, { encoding: 'utf-8' }); + } + catch (e) { + return undefined; + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvYXdzLWF1dGgvdXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU9BLHdDQVNDO0FBaEJELCtCQUErQjtBQUUvQjs7OztHQUlHO0FBQ0gsU0FBZ0IsY0FBYyxDQUFDLFFBQWdCO0lBQzdDLElBQUksQ0FBQztRQUNILElBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDakMsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztRQUNELE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztRQUNoQixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcblxuLyoqXG4gKiBSZWFkIGEgZmlsZSBpZiBpdCBleGlzdHMsIG9yIHJldHVybiB1bmRlZmluZWRcbiAqXG4gKiBOb3QgYXN5bmMgYmVjYXVzZSBpdCBpcyB1c2VkIGluIHRoZSBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZElmUG9zc2libGUoZmlsZW5hbWU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHRyeSB7XG4gICAgaWYgKCFmcy5wYXRoRXhpc3RzU3luYyhmaWxlbmFtZSkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiBmcy5yZWFkRmlsZVN5bmMoZmlsZW5hbWUsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSk7XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.d.ts new file mode 100644 index 000000000..6f74fc1f8 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.d.ts @@ -0,0 +1,35 @@ +import type * as cxapi from '@aws-cdk/cx-api'; +import type { BootstrapEnvironmentOptions } from './bootstrap-props'; +import type { SdkProvider } from '../aws-auth'; +import type { SuccessfulDeployStackResult } from '../deployments'; +import { type IoHelper } from '../io/private'; +export type BootstrapSource = { + source: 'legacy'; +} | { + source: 'default'; +} | { + source: 'custom'; + templateFile: string; +}; +export declare class Bootstrapper { + private readonly source; + private readonly ioHelper; + constructor(source: BootstrapSource | undefined, ioHelper: IoHelper); + bootstrapEnvironment(environment: cxapi.Environment, sdkProvider: SdkProvider, options?: BootstrapEnvironmentOptions): Promise; + showTemplate(json: boolean): Promise; + /** + * Deploy legacy bootstrap stack + * + */ + private legacyBootstrap; + /** + * Deploy CI/CD-ready bootstrap stack from template + * + */ + private modernBootstrap; + private getPolicyName; + private getExamplePermissionsBoundary; + private validatePolicyName; + private customBootstrap; + private loadTemplate; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.js new file mode 100644 index 000000000..7adb664b8 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-environment.js @@ -0,0 +1,323 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Bootstrapper = void 0; +const path = require("path"); +const deploy_bootstrap_1 = require("./deploy-bootstrap"); +const legacy_template_1 = require("./legacy-template"); +const util_1 = require("../../util"); +const private_1 = require("../io/private"); +const plugin_1 = require("../plugin"); +const toolkit_error_1 = require("../toolkit-error"); +const toolkit_info_1 = require("../toolkit-info"); +class Bootstrapper { + source; + ioHelper; + constructor(source = { source: 'default' }, ioHelper) { + this.source = source; + this.ioHelper = ioHelper; + } + bootstrapEnvironment(environment, sdkProvider, options = {}) { + switch (this.source.source) { + case 'legacy': + return this.legacyBootstrap(environment, sdkProvider, options); + case 'default': + return this.modernBootstrap(environment, sdkProvider, options); + case 'custom': + return this.customBootstrap(environment, sdkProvider, options); + } + } + async showTemplate(json) { + const template = await this.loadTemplate(); + process.stdout.write(`${(0, util_1.serializeStructure)(template, json)}\n`); + } + /** + * Deploy legacy bootstrap stack + * + */ + async legacyBootstrap(environment, sdkProvider, options = {}) { + const params = options.parameters ?? {}; + if (params.trustedAccounts?.length) { + throw new toolkit_error_1.ToolkitError('--trust can only be passed for the modern bootstrap experience.'); + } + if (params.cloudFormationExecutionPolicies?.length) { + throw new toolkit_error_1.ToolkitError('--cloudformation-execution-policies can only be passed for the modern bootstrap experience.'); + } + if (params.createCustomerMasterKey !== undefined) { + throw new toolkit_error_1.ToolkitError('--bootstrap-customer-key can only be passed for the modern bootstrap experience.'); + } + if (params.qualifier) { + throw new toolkit_error_1.ToolkitError('--qualifier can only be passed for the modern bootstrap experience.'); + } + const toolkitStackName = options.toolkitStackName ?? toolkit_info_1.DEFAULT_TOOLKIT_STACK_NAME; + const current = await deploy_bootstrap_1.BootstrapStack.lookup(sdkProvider, environment, toolkitStackName, this.ioHelper); + return current.update(await this.loadTemplate(params), {}, { + ...options, + terminationProtection: options.terminationProtection ?? current.terminationProtection, + }); + } + /** + * Deploy CI/CD-ready bootstrap stack from template + * + */ + async modernBootstrap(environment, sdkProvider, options = {}) { + const params = options.parameters ?? {}; + const bootstrapTemplate = await this.loadTemplate(); + const toolkitStackName = options.toolkitStackName ?? toolkit_info_1.DEFAULT_TOOLKIT_STACK_NAME; + const current = await deploy_bootstrap_1.BootstrapStack.lookup(sdkProvider, environment, toolkitStackName, this.ioHelper); + const partition = await current.partition(); + if (params.createCustomerMasterKey !== undefined && params.kmsKeyId) { + throw new toolkit_error_1.ToolkitError("You cannot pass '--bootstrap-kms-key-id' and '--bootstrap-customer-key' together. Specify one or the other"); + } + // If people re-bootstrap, existing parameter values are reused so that people don't accidentally change the configuration + // on their bootstrap stack (this happens automatically in deployStack). However, to do proper validation on the + // combined arguments (such that if --trust has been given, --cloudformation-execution-policies is necessary as well) + // we need to take this parameter reuse into account. + // + // Ideally we'd do this inside the template, but the `Rules` section of CFN + // templates doesn't seem to be able to express the conditions that we need + // (can't use Fn::Join or reference Conditions) so we do it here instead. + const allTrusted = new Set([ + ...params.trustedAccounts ?? [], + ...params.trustedAccountsForLookup ?? [], + ]); + const invalid = intersection(allTrusted, new Set(params.untrustedAccounts)); + if (invalid.size > 0) { + throw new toolkit_error_1.ToolkitError(`Accounts cannot be both trusted and untrusted. Found: ${[...invalid].join(',')}`); + } + const removeUntrusted = (accounts) => accounts.filter(acc => !params.untrustedAccounts?.map(String).includes(String(acc))); + const trustedAccounts = removeUntrusted(params.trustedAccounts ?? splitCfnArray(current.parameters.TrustedAccounts)); + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_INFO.msg(`Trusted accounts for deployment: ${trustedAccounts.length > 0 ? trustedAccounts.join(', ') : '(none)'}`)); + const trustedAccountsForLookup = removeUntrusted(params.trustedAccountsForLookup ?? splitCfnArray(current.parameters.TrustedAccountsForLookup)); + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_INFO.msg(`Trusted accounts for lookup: ${trustedAccountsForLookup.length > 0 ? trustedAccountsForLookup.join(', ') : '(none)'}`)); + const cloudFormationExecutionPolicies = params.cloudFormationExecutionPolicies ?? splitCfnArray(current.parameters.CloudFormationExecutionPolicies); + if (trustedAccounts.length === 0 && cloudFormationExecutionPolicies.length === 0) { + // For self-trust it's okay to default to AdministratorAccess, and it improves the usability of bootstrapping a lot. + // + // We don't actually make the implicitly policy a physical parameter. The template will infer it instead, + // we simply do the UI advertising that behavior here. + // + // If we DID make it an explicit parameter, we wouldn't be able to tell the difference between whether + // we inferred it or whether the user told us, and the sequence: + // + // $ cdk bootstrap + // $ cdk bootstrap --trust 1234 + // + // Would leave AdministratorAccess policies with a trust relationship, without the user explicitly + // approving the trust policy. + const implicitPolicy = `arn:${partition}:iam::aws:policy/AdministratorAccess`; + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_WARN.msg(`Using default execution policy of '${implicitPolicy}'. Pass '--cloudformation-execution-policies' to customize.`)); + } + else if (cloudFormationExecutionPolicies.length === 0) { + throw new toolkit_error_1.ToolkitError(`Please pass \'--cloudformation-execution-policies\' when using \'--trust\' to specify deployment permissions. Try a managed policy of the form \'arn:${partition}:iam::aws:policy/\'.`); + } + else { + // Remind people what the current settings are + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_INFO.msg(`Execution policies: ${cloudFormationExecutionPolicies.join(', ')}`)); + } + // * If an ARN is given, that ARN. Otherwise: + // * '-' if customerKey = false + // * '' if customerKey = true + // * if customerKey is also not given + // * undefined if we already had a value in place (reusing what we had) + // * '-' if this is the first time we're deploying this stack (or upgrading from old to new bootstrap) + const currentKmsKeyId = current.parameters.FileAssetsBucketKmsKeyId; + const kmsKeyId = params.kmsKeyId ?? + (params.createCustomerMasterKey === true + ? CREATE_NEW_KEY + : params.createCustomerMasterKey === false || currentKmsKeyId === undefined + ? USE_AWS_MANAGED_KEY + : undefined); + /* A permissions boundary can be provided via: + * - the flag indicating the example one should be used + * - the name indicating the custom permissions boundary to be used + * Re-bootstrapping will NOT be blocked by either tightening or relaxing the permissions' boundary. + */ + // InputPermissionsBoundary is an `any` type and if it is not defined it + // appears as an empty string ''. We need to force it to evaluate an empty string + // as undefined + const currentPermissionsBoundary = current.parameters.InputPermissionsBoundary || undefined; + const inputPolicyName = params.examplePermissionsBoundary + ? CDK_BOOTSTRAP_PERMISSIONS_BOUNDARY + : params.customPermissionsBoundary; + let policyName; + if (inputPolicyName) { + // If the example policy is not already in place, it must be created. + const sdk = (await sdkProvider.forEnvironment(environment, plugin_1.Mode.ForWriting)).sdk; + policyName = await this.getPolicyName(environment, sdk, inputPolicyName, partition, params); + } + if (currentPermissionsBoundary !== policyName) { + if (!currentPermissionsBoundary) { + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_WARN.msg(`Adding new permissions boundary ${policyName}`)); + } + else if (!policyName) { + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_WARN.msg(`Removing existing permissions boundary ${currentPermissionsBoundary}`)); + } + else { + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_WARN.msg(`Changing permissions boundary from ${currentPermissionsBoundary} to ${policyName}`)); + } + } + return current.update(bootstrapTemplate, { + FileAssetsBucketName: params.bucketName, + FileAssetsBucketKmsKeyId: kmsKeyId, + // Empty array becomes empty string + TrustedAccounts: trustedAccounts.join(','), + TrustedAccountsForLookup: trustedAccountsForLookup.join(','), + CloudFormationExecutionPolicies: cloudFormationExecutionPolicies.join(','), + Qualifier: params.qualifier, + PublicAccessBlockConfiguration: params.publicAccessBlockConfiguration || params.publicAccessBlockConfiguration === undefined + ? 'true' + : 'false', + InputPermissionsBoundary: policyName, + }, { + ...options, + terminationProtection: options.terminationProtection ?? current.terminationProtection, + }); + } + async getPolicyName(environment, sdk, permissionsBoundary, partition, params) { + if (permissionsBoundary !== CDK_BOOTSTRAP_PERMISSIONS_BOUNDARY) { + this.validatePolicyName(permissionsBoundary); + return Promise.resolve(permissionsBoundary); + } + // if no Qualifier is supplied, resort to the default one + const arn = await this.getExamplePermissionsBoundary(params.qualifier ?? 'hnb659fds', partition, environment.account, sdk); + const policyName = arn.split('/').pop(); + if (!policyName) { + throw new toolkit_error_1.ToolkitError('Could not retrieve the example permission boundary!'); + } + return Promise.resolve(policyName); + } + async getExamplePermissionsBoundary(qualifier, partition, account, sdk) { + const iam = sdk.iam(); + let policyName = `cdk-${qualifier}-permissions-boundary`; + const arn = `arn:${partition}:iam::${account}:policy/${policyName}`; + try { + let getPolicyResp = await iam.getPolicy({ PolicyArn: arn }); + if (getPolicyResp.Policy) { + return arn; + } + } + catch (e) { + // https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html#API_GetPolicy_Errors + if (e.name === 'NoSuchEntity') { + // noop, proceed with creating the policy + } + else { + throw e; + } + } + const policyDoc = { + Version: '2012-10-17', + Statement: [ + { + Action: ['*'], + Resource: '*', + Effect: 'Allow', + Sid: 'ExplicitAllowAll', + }, + { + Condition: { + StringEquals: { + 'iam:PermissionsBoundary': `arn:${partition}:iam::${account}:policy/cdk-${qualifier}-permissions-boundary`, + }, + }, + Action: [ + 'iam:CreateUser', + 'iam:CreateRole', + 'iam:PutRolePermissionsBoundary', + 'iam:PutUserPermissionsBoundary', + ], + Resource: '*', + Effect: 'Allow', + Sid: 'DenyAccessIfRequiredPermBoundaryIsNotBeingApplied', + }, + { + Action: [ + 'iam:CreatePolicyVersion', + 'iam:DeletePolicy', + 'iam:DeletePolicyVersion', + 'iam:SetDefaultPolicyVersion', + ], + Resource: `arn:${partition}:iam::${account}:policy/cdk-${qualifier}-permissions-boundary`, + Effect: 'Deny', + Sid: 'DenyPermBoundaryIAMPolicyAlteration', + }, + { + Action: ['iam:DeleteUserPermissionsBoundary', 'iam:DeleteRolePermissionsBoundary'], + Resource: '*', + Effect: 'Deny', + Sid: 'DenyRemovalOfPermBoundaryFromAnyUserOrRole', + }, + ], + }; + const request = { + PolicyName: policyName, + PolicyDocument: JSON.stringify(policyDoc), + }; + const createPolicyResponse = await iam.createPolicy(request); + if (createPolicyResponse.Policy?.Arn) { + return createPolicyResponse.Policy.Arn; + } + else { + throw new toolkit_error_1.ToolkitError(`Could not retrieve the example permission boundary ${arn}!`); + } + } + validatePolicyName(permissionsBoundary) { + // https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html + // Added support for policy names with a path + // See https://github.com/aws/aws-cdk/issues/26320 + const regexp = /[\w+\/=,.@-]+/; + const matches = regexp.exec(permissionsBoundary); + if (!(matches && matches.length === 1 && matches[0] === permissionsBoundary)) { + throw new toolkit_error_1.ToolkitError(`The permissions boundary name ${permissionsBoundary} does not match the IAM conventions.`); + } + } + async customBootstrap(environment, sdkProvider, options = {}) { + // Look at the template, decide whether it's most likely a legacy or modern bootstrap + // template, and use the right bootstrapper for that. + const version = (0, deploy_bootstrap_1.bootstrapVersionFromTemplate)(await this.loadTemplate()); + if (version === 0) { + return this.legacyBootstrap(environment, sdkProvider, options); + } + else { + return this.modernBootstrap(environment, sdkProvider, options); + } + } + async loadTemplate(params = {}) { + switch (this.source.source) { + case 'custom': + return (0, util_1.loadStructuredFile)(this.source.templateFile); + case 'default': + return (0, util_1.loadStructuredFile)(path.join((0, util_1.bundledPackageRootDir)(__dirname), 'lib', 'api', 'bootstrap', 'bootstrap-template.yaml')); + case 'legacy': + return (0, legacy_template_1.legacyBootstrapTemplate)(params); + } + } +} +exports.Bootstrapper = Bootstrapper; +/** + * Magic parameter value that will cause the bootstrap-template.yml to NOT create a CMK but use the default key + */ +const USE_AWS_MANAGED_KEY = 'AWS_MANAGED_KEY'; +/** + * Magic parameter value that will cause the bootstrap-template.yml to create a CMK + */ +const CREATE_NEW_KEY = ''; +/** + * Parameter value indicating the use of the default, CDK provided permissions boundary for bootstrap-template.yml + */ +const CDK_BOOTSTRAP_PERMISSIONS_BOUNDARY = 'CDK_BOOTSTRAP_PERMISSIONS_BOUNDARY'; +/** + * Split an array-like CloudFormation parameter on , + * + * An empty string is the empty array (instead of `['']`). + */ +function splitCfnArray(xs) { + if (xs === '' || xs === undefined) { + return []; + } + return xs.split(','); +} +function intersection(xs, ys) { + return new Set(Array.from(xs).filter(x => ys.has(x))); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLWVudmlyb25tZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9ib290c3RyYXAvYm9vdHN0cmFwLWVudmlyb25tZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE2QjtBQUc3Qix5REFBa0Y7QUFDbEYsdURBQTREO0FBQzVELHFDQUEyRjtBQUczRiwyQ0FBa0Q7QUFDbEQsc0NBQWlDO0FBQ2pDLG9EQUFnRDtBQUNoRCxrREFBNkQ7QUFJN0QsTUFBYSxZQUFZO0lBSUo7SUFIRixRQUFRLENBQVc7SUFFcEMsWUFDbUIsU0FBMEIsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEVBQ2hFLFFBQWtCO1FBREQsV0FBTSxHQUFOLE1BQU0sQ0FBeUM7UUFHaEUsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDM0IsQ0FBQztJQUVNLG9CQUFvQixDQUN6QixXQUE4QixFQUM5QixXQUF3QixFQUN4QixVQUF1QyxFQUFFO1FBRXpDLFFBQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMzQixLQUFLLFFBQVE7Z0JBQ1gsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDakUsS0FBSyxTQUFTO2dCQUNaLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2pFLEtBQUssUUFBUTtnQkFDWCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxFQUFFLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNuRSxDQUFDO0lBQ0gsQ0FBQztJQUVNLEtBQUssQ0FBQyxZQUFZLENBQUMsSUFBYTtRQUNyQyxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUMzQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUEseUJBQWtCLEVBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssS0FBSyxDQUFDLGVBQWUsQ0FDM0IsV0FBOEIsRUFDOUIsV0FBd0IsRUFDeEIsVUFBdUMsRUFBRTtRQUV6QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQztRQUV4QyxJQUFJLE1BQU0sQ0FBQyxlQUFlLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDbkMsTUFBTSxJQUFJLDRCQUFZLENBQUMsaUVBQWlFLENBQUMsQ0FBQztRQUM1RixDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsK0JBQStCLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDbkQsTUFBTSxJQUFJLDRCQUFZLENBQUMsNkZBQTZGLENBQUMsQ0FBQztRQUN4SCxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsdUJBQXVCLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDakQsTUFBTSxJQUFJLDRCQUFZLENBQUMsa0ZBQWtGLENBQUMsQ0FBQztRQUM3RyxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLDRCQUFZLENBQUMscUVBQXFFLENBQUMsQ0FBQztRQUNoRyxDQUFDO1FBRUQsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLElBQUkseUNBQTBCLENBQUM7UUFDaEYsTUFBTSxPQUFPLEdBQUcsTUFBTSxpQ0FBYyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2RyxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQ25CLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFDL0IsRUFBRSxFQUNGO1lBQ0UsR0FBRyxPQUFPO1lBQ1YscUJBQXFCLEVBQUUsT0FBTyxDQUFDLHFCQUFxQixJQUFJLE9BQU8sQ0FBQyxxQkFBcUI7U0FDdEYsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNLLEtBQUssQ0FBQyxlQUFlLENBQzNCLFdBQThCLEVBQzlCLFdBQXdCLEVBQ3hCLFVBQXVDLEVBQUU7UUFFekMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUM7UUFFeEMsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUVwRCxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSx5Q0FBMEIsQ0FBQztRQUNoRixNQUFNLE9BQU8sR0FBRyxNQUFNLGlDQUFjLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZHLE1BQU0sU0FBUyxHQUFHLE1BQU0sT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBRTVDLElBQUksTUFBTSxDQUFDLHVCQUF1QixLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEUsTUFBTSxJQUFJLDRCQUFZLENBQ3BCLDRHQUE0RyxDQUM3RyxDQUFDO1FBQ0osQ0FBQztRQUVELDBIQUEwSDtRQUMxSCxnSEFBZ0g7UUFDaEgscUhBQXFIO1FBQ3JILHFEQUFxRDtRQUNyRCxFQUFFO1FBQ0YsMkVBQTJFO1FBQzNFLDJFQUEyRTtRQUMzRSx5RUFBeUU7UUFDekUsTUFBTSxVQUFVLEdBQUcsSUFBSSxHQUFHLENBQUM7WUFDekIsR0FBRyxNQUFNLENBQUMsZUFBZSxJQUFJLEVBQUU7WUFDL0IsR0FBRyxNQUFNLENBQUMsd0JBQXdCLElBQUksRUFBRTtTQUN6QyxDQUFDLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBRyxZQUFZLENBQUMsVUFBVSxFQUFFLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFDNUUsSUFBSSxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3JCLE1BQU0sSUFBSSw0QkFBWSxDQUFDLHlEQUF5RCxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM1RyxDQUFDO1FBRUQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxRQUFrQixFQUFFLEVBQUUsQ0FDN0MsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV2RixNQUFNLGVBQWUsR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDLGVBQWUsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO1FBQ3JILE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsWUFBRSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FDcEQsb0NBQW9DLGVBQWUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FDekcsQ0FBQyxDQUFDO1FBRUgsTUFBTSx3QkFBd0IsR0FBRyxlQUFlLENBQzlDLE1BQU0sQ0FBQyx3QkFBd0IsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyx3QkFBd0IsQ0FBQyxDQUM5RixDQUFDO1FBQ0YsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxZQUFFLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUNwRCxnQ0FBZ0Msd0JBQXdCLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FDdkgsQ0FBQyxDQUFDO1FBRUgsTUFBTSwrQkFBK0IsR0FDbkMsTUFBTSxDQUFDLCtCQUErQixJQUFJLGFBQWEsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLCtCQUErQixDQUFDLENBQUM7UUFDOUcsSUFBSSxlQUFlLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSwrQkFBK0IsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDakYsb0hBQW9IO1lBQ3BILEVBQUU7WUFDRix5R0FBeUc7WUFDekcsc0RBQXNEO1lBQ3RELEVBQUU7WUFDRixzR0FBc0c7WUFDdEcsZ0VBQWdFO1lBQ2hFLEVBQUU7WUFDRixrQkFBa0I7WUFDbEIsK0JBQStCO1lBQy9CLEVBQUU7WUFDRixrR0FBa0c7WUFDbEcsOEJBQThCO1lBQzlCLE1BQU0sY0FBYyxHQUFHLE9BQU8sU0FBUyxzQ0FBc0MsQ0FBQztZQUM5RSxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFlBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQ3BELHNDQUFzQyxjQUFjLDZEQUE2RCxDQUNsSCxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sSUFBSSwrQkFBK0IsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEQsTUFBTSxJQUFJLDRCQUFZLENBQ3BCLHdKQUF3SixTQUFTLGtDQUFrQyxDQUNwTSxDQUFDO1FBQ0osQ0FBQzthQUFNLENBQUM7WUFDTiw4Q0FBOEM7WUFDOUMsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxZQUFFLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLHVCQUF1QiwrQkFBK0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0gsQ0FBQztRQUVELDZDQUE2QztRQUM3QyxpQ0FBaUM7UUFDakMsK0JBQStCO1FBQy9CLHVDQUF1QztRQUN2QywyRUFBMkU7UUFDM0UsMEdBQTBHO1FBQzFHLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsd0JBQXdCLENBQUM7UUFDcEUsTUFBTSxRQUFRLEdBQ1osTUFBTSxDQUFDLFFBQVE7WUFDZixDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsS0FBSyxJQUFJO2dCQUN0QyxDQUFDLENBQUMsY0FBYztnQkFDaEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsS0FBSyxLQUFLLElBQUksZUFBZSxLQUFLLFNBQVM7b0JBQ3pFLENBQUMsQ0FBQyxtQkFBbUI7b0JBQ3JCLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVuQjs7OztXQUlHO1FBRUgsd0VBQXdFO1FBQ3hFLGlGQUFpRjtRQUNqRixlQUFlO1FBQ2YsTUFBTSwwQkFBMEIsR0FBdUIsT0FBTyxDQUFDLFVBQVUsQ0FBQyx3QkFBd0IsSUFBSSxTQUFTLENBQUM7UUFDaEgsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDLDBCQUEwQjtZQUN2RCxDQUFDLENBQUMsa0NBQWtDO1lBQ3BDLENBQUMsQ0FBQyxNQUFNLENBQUMseUJBQXlCLENBQUM7UUFDckMsSUFBSSxVQUE4QixDQUFDO1FBQ25DLElBQUksZUFBZSxFQUFFLENBQUM7WUFDcEIscUVBQXFFO1lBQ3JFLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxXQUFXLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxhQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7WUFDakYsVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDOUYsQ0FBQztRQUNELElBQUksMEJBQTBCLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDOUMsSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7Z0JBQ2hDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsWUFBRSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FDcEQsbUNBQW1DLFVBQVUsRUFBRSxDQUNoRCxDQUFDLENBQUM7WUFDTCxDQUFDO2lCQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDdkIsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxZQUFFLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUNwRCwwQ0FBMEMsMEJBQTBCLEVBQUUsQ0FDdkUsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsWUFBRSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FDcEQsc0NBQXNDLDBCQUEwQixPQUFPLFVBQVUsRUFBRSxDQUNwRixDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FDbkIsaUJBQWlCLEVBQ2pCO1lBQ0Usb0JBQW9CLEVBQUUsTUFBTSxDQUFDLFVBQVU7WUFDdkMsd0JBQXdCLEVBQUUsUUFBUTtZQUNsQyxtQ0FBbUM7WUFDbkMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQzFDLHdCQUF3QixFQUFFLHdCQUF3QixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7WUFDNUQsK0JBQStCLEVBQUUsK0JBQStCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUMxRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7WUFDM0IsOEJBQThCLEVBQzVCLE1BQU0sQ0FBQyw4QkFBOEIsSUFBSSxNQUFNLENBQUMsOEJBQThCLEtBQUssU0FBUztnQkFDMUYsQ0FBQyxDQUFDLE1BQU07Z0JBQ1IsQ0FBQyxDQUFDLE9BQU87WUFDYix3QkFBd0IsRUFBRSxVQUFVO1NBQ3JDLEVBQ0Q7WUFDRSxHQUFHLE9BQU87WUFDVixxQkFBcUIsRUFBRSxPQUFPLENBQUMscUJBQXFCLElBQUksT0FBTyxDQUFDLHFCQUFxQjtTQUN0RixDQUNGLENBQUM7SUFDSixDQUFDO0lBRU8sS0FBSyxDQUFDLGFBQWEsQ0FDekIsV0FBOEIsRUFDOUIsR0FBUSxFQUNSLG1CQUEyQixFQUMzQixTQUFpQixFQUNqQixNQUErQjtRQUUvQixJQUFJLG1CQUFtQixLQUFLLGtDQUFrQyxFQUFFLENBQUM7WUFDL0QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDN0MsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUNELHlEQUF5RDtRQUN6RCxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyw2QkFBNkIsQ0FDbEQsTUFBTSxDQUFDLFNBQVMsSUFBSSxXQUFXLEVBQy9CLFNBQVMsRUFDVCxXQUFXLENBQUMsT0FBTyxFQUNuQixHQUFHLENBQ0osQ0FBQztRQUNGLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSw0QkFBWSxDQUFDLHFEQUFxRCxDQUFDLENBQUM7UUFDaEYsQ0FBQztRQUNELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRU8sS0FBSyxDQUFDLDZCQUE2QixDQUN6QyxTQUFpQixFQUNqQixTQUFpQixFQUNqQixPQUFlLEVBQ2YsR0FBUTtRQUVSLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUV0QixJQUFJLFVBQVUsR0FBRyxPQUFPLFNBQVMsdUJBQXVCLENBQUM7UUFDekQsTUFBTSxHQUFHLEdBQUcsT0FBTyxTQUFTLFNBQVMsT0FBTyxXQUFXLFVBQVUsRUFBRSxDQUFDO1FBRXBFLElBQUksQ0FBQztZQUNILElBQUksYUFBYSxHQUFHLE1BQU0sR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQzVELElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN6QixPQUFPLEdBQUcsQ0FBQztZQUNiLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztZQUNoQiw4RkFBOEY7WUFDOUYsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRSxDQUFDO2dCQUM5Qix5Q0FBeUM7WUFDM0MsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sQ0FBQyxDQUFDO1lBQ1YsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLFNBQVMsR0FBRztZQUNoQixPQUFPLEVBQUUsWUFBWTtZQUNyQixTQUFTLEVBQUU7Z0JBQ1Q7b0JBQ0UsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDO29CQUNiLFFBQVEsRUFBRSxHQUFHO29CQUNiLE1BQU0sRUFBRSxPQUFPO29CQUNmLEdBQUcsRUFBRSxrQkFBa0I7aUJBQ3hCO2dCQUNEO29CQUNFLFNBQVMsRUFBRTt3QkFDVCxZQUFZLEVBQUU7NEJBQ1oseUJBQXlCLEVBQUUsT0FBTyxTQUFTLFNBQVMsT0FBTyxlQUFlLFNBQVMsdUJBQXVCO3lCQUMzRztxQkFDRjtvQkFDRCxNQUFNLEVBQUU7d0JBQ04sZ0JBQWdCO3dCQUNoQixnQkFBZ0I7d0JBQ2hCLGdDQUFnQzt3QkFDaEMsZ0NBQWdDO3FCQUNqQztvQkFDRCxRQUFRLEVBQUUsR0FBRztvQkFDYixNQUFNLEVBQUUsT0FBTztvQkFDZixHQUFHLEVBQUUsbURBQW1EO2lCQUN6RDtnQkFDRDtvQkFDRSxNQUFNLEVBQUU7d0JBQ04seUJBQXlCO3dCQUN6QixrQkFBa0I7d0JBQ2xCLHlCQUF5Qjt3QkFDekIsNkJBQTZCO3FCQUM5QjtvQkFDRCxRQUFRLEVBQUUsT0FBTyxTQUFTLFNBQVMsT0FBTyxlQUFlLFNBQVMsdUJBQXVCO29CQUN6RixNQUFNLEVBQUUsTUFBTTtvQkFDZCxHQUFHLEVBQUUscUNBQXFDO2lCQUMzQztnQkFDRDtvQkFDRSxNQUFNLEVBQUUsQ0FBQyxtQ0FBbUMsRUFBRSxtQ0FBbUMsQ0FBQztvQkFDbEYsUUFBUSxFQUFFLEdBQUc7b0JBQ2IsTUFBTSxFQUFFLE1BQU07b0JBQ2QsR0FBRyxFQUFFLDRDQUE0QztpQkFDbEQ7YUFDRjtTQUNGLENBQUM7UUFDRixNQUFNLE9BQU8sR0FBRztZQUNkLFVBQVUsRUFBRSxVQUFVO1lBQ3RCLGNBQWMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQztTQUMxQyxDQUFDO1FBQ0YsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLEdBQUcsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDN0QsSUFBSSxvQkFBb0IsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFDckMsT0FBTyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO1FBQ3pDLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLDRCQUFZLENBQUMsc0RBQXNELEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDdkYsQ0FBQztJQUNILENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxtQkFBMkI7UUFDcEQsNEVBQTRFO1FBQzVFLDZDQUE2QztRQUM3QyxrREFBa0Q7UUFDbEQsTUFBTSxNQUFNLEdBQVcsZUFBZSxDQUFDO1FBQ3ZDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLG1CQUFtQixDQUFDLEVBQUUsQ0FBQztZQUM3RSxNQUFNLElBQUksNEJBQVksQ0FBQyxpQ0FBaUMsbUJBQW1CLHNDQUFzQyxDQUFDLENBQUM7UUFDckgsQ0FBQztJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsZUFBZSxDQUMzQixXQUE4QixFQUM5QixXQUF3QixFQUN4QixVQUF1QyxFQUFFO1FBRXpDLHFGQUFxRjtRQUNyRixxREFBcUQ7UUFDckQsTUFBTSxPQUFPLEdBQUcsSUFBQSwrQ0FBNEIsRUFBQyxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLElBQUksT0FBTyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2xCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2pFLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDakUsQ0FBQztJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsWUFBWSxDQUFDLFNBQWtDLEVBQUU7UUFDN0QsUUFBUSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzNCLEtBQUssUUFBUTtnQkFDWCxPQUFPLElBQUEseUJBQWtCLEVBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN0RCxLQUFLLFNBQVM7Z0JBQ1osT0FBTyxJQUFBLHlCQUFrQixFQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBQSw0QkFBcUIsRUFBQyxTQUFTLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSx5QkFBeUIsQ0FBQyxDQUFDLENBQUM7WUFDL0gsS0FBSyxRQUFRO2dCQUNYLE9BQU8sSUFBQSx5Q0FBdUIsRUFBQyxNQUFNLENBQUMsQ0FBQztRQUMzQyxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBN1dELG9DQTZXQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxpQkFBaUIsQ0FBQztBQUU5Qzs7R0FFRztBQUNILE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQztBQUMxQjs7R0FFRztBQUNILE1BQU0sa0NBQWtDLEdBQUcsb0NBQW9DLENBQUM7QUFFaEY7Ozs7R0FJRztBQUNILFNBQVMsYUFBYSxDQUFDLEVBQXNCO0lBQzNDLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDbEMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBQ0QsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLENBQUM7QUFFRCxTQUFTLFlBQVksQ0FBSSxFQUFVLEVBQUUsRUFBVTtJQUM3QyxPQUFPLElBQUksR0FBRyxDQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDM0QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgdHlwZSAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgdHlwZSB7IEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucywgQm9vdHN0cmFwcGluZ1BhcmFtZXRlcnMgfSBmcm9tICcuL2Jvb3RzdHJhcC1wcm9wcyc7XG5pbXBvcnQgeyBCb290c3RyYXBTdGFjaywgYm9vdHN0cmFwVmVyc2lvbkZyb21UZW1wbGF0ZSB9IGZyb20gJy4vZGVwbG95LWJvb3RzdHJhcCc7XG5pbXBvcnQgeyBsZWdhY3lCb290c3RyYXBUZW1wbGF0ZSB9IGZyb20gJy4vbGVnYWN5LXRlbXBsYXRlJztcbmltcG9ydCB7IGJ1bmRsZWRQYWNrYWdlUm9vdERpciwgbG9hZFN0cnVjdHVyZWRGaWxlLCBzZXJpYWxpemVTdHJ1Y3R1cmUgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB0eXBlIHsgU0RLLCBTZGtQcm92aWRlciB9IGZyb20gJy4uL2F3cy1hdXRoJztcbmltcG9ydCB0eXBlIHsgU3VjY2Vzc2Z1bERlcGxveVN0YWNrUmVzdWx0IH0gZnJvbSAnLi4vZGVwbG95bWVudHMnO1xuaW1wb3J0IHsgSU8sIHR5cGUgSW9IZWxwZXIgfSBmcm9tICcuLi9pby9wcml2YXRlJztcbmltcG9ydCB7IE1vZGUgfSBmcm9tICcuLi9wbHVnaW4nO1xuaW1wb3J0IHsgVG9vbGtpdEVycm9yIH0gZnJvbSAnLi4vdG9vbGtpdC1lcnJvcic7XG5pbXBvcnQgeyBERUZBVUxUX1RPT0xLSVRfU1RBQ0tfTkFNRSB9IGZyb20gJy4uL3Rvb2xraXQtaW5mbyc7XG5cbmV4cG9ydCB0eXBlIEJvb3RzdHJhcFNvdXJjZSA9IHsgc291cmNlOiAnbGVnYWN5JyB9IHwgeyBzb3VyY2U6ICdkZWZhdWx0JyB9IHwgeyBzb3VyY2U6ICdjdXN0b20nOyB0ZW1wbGF0ZUZpbGU6IHN0cmluZyB9O1xuXG5leHBvcnQgY2xhc3MgQm9vdHN0cmFwcGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBpb0hlbHBlcjogSW9IZWxwZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzb3VyY2U6IEJvb3RzdHJhcFNvdXJjZSA9IHsgc291cmNlOiAnZGVmYXVsdCcgfSxcbiAgICBpb0hlbHBlcjogSW9IZWxwZXIsXG4gICkge1xuICAgIHRoaXMuaW9IZWxwZXIgPSBpb0hlbHBlcjtcbiAgfVxuXG4gIHB1YmxpYyBib290c3RyYXBFbnZpcm9ubWVudChcbiAgICBlbnZpcm9ubWVudDogY3hhcGkuRW52aXJvbm1lbnQsXG4gICAgc2RrUHJvdmlkZXI6IFNka1Byb3ZpZGVyLFxuICAgIG9wdGlvbnM6IEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPFN1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdD4ge1xuICAgIHN3aXRjaCAodGhpcy5zb3VyY2Uuc291cmNlKSB7XG4gICAgICBjYXNlICdsZWdhY3knOlxuICAgICAgICByZXR1cm4gdGhpcy5sZWdhY3lCb290c3RyYXAoZW52aXJvbm1lbnQsIHNka1Byb3ZpZGVyLCBvcHRpb25zKTtcbiAgICAgIGNhc2UgJ2RlZmF1bHQnOlxuICAgICAgICByZXR1cm4gdGhpcy5tb2Rlcm5Cb290c3RyYXAoZW52aXJvbm1lbnQsIHNka1Byb3ZpZGVyLCBvcHRpb25zKTtcbiAgICAgIGNhc2UgJ2N1c3RvbSc6XG4gICAgICAgIHJldHVybiB0aGlzLmN1c3RvbUJvb3RzdHJhcChlbnZpcm9ubWVudCwgc2RrUHJvdmlkZXIsIG9wdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzaG93VGVtcGxhdGUoanNvbjogYm9vbGVhbikge1xuICAgIGNvbnN0IHRlbXBsYXRlID0gYXdhaXQgdGhpcy5sb2FkVGVtcGxhdGUoKTtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgJHtzZXJpYWxpemVTdHJ1Y3R1cmUodGVtcGxhdGUsIGpzb24pfVxcbmApO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcGxveSBsZWdhY3kgYm9vdHN0cmFwIHN0YWNrXG4gICAqXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGxlZ2FjeUJvb3RzdHJhcChcbiAgICBlbnZpcm9ubWVudDogY3hhcGkuRW52aXJvbm1lbnQsXG4gICAgc2RrUHJvdmlkZXI6IFNka1Byb3ZpZGVyLFxuICAgIG9wdGlvbnM6IEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPFN1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdD4ge1xuICAgIGNvbnN0IHBhcmFtcyA9IG9wdGlvbnMucGFyYW1ldGVycyA/PyB7fTtcblxuICAgIGlmIChwYXJhbXMudHJ1c3RlZEFjY291bnRzPy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJy0tdHJ1c3QgY2FuIG9ubHkgYmUgcGFzc2VkIGZvciB0aGUgbW9kZXJuIGJvb3RzdHJhcCBleHBlcmllbmNlLicpO1xuICAgIH1cbiAgICBpZiAocGFyYW1zLmNsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUG9saWNpZXM/Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignLS1jbG91ZGZvcm1hdGlvbi1leGVjdXRpb24tcG9saWNpZXMgY2FuIG9ubHkgYmUgcGFzc2VkIGZvciB0aGUgbW9kZXJuIGJvb3RzdHJhcCBleHBlcmllbmNlLicpO1xuICAgIH1cbiAgICBpZiAocGFyYW1zLmNyZWF0ZUN1c3RvbWVyTWFzdGVyS2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJy0tYm9vdHN0cmFwLWN1c3RvbWVyLWtleSBjYW4gb25seSBiZSBwYXNzZWQgZm9yIHRoZSBtb2Rlcm4gYm9vdHN0cmFwIGV4cGVyaWVuY2UuJyk7XG4gICAgfVxuICAgIGlmIChwYXJhbXMucXVhbGlmaWVyKSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCctLXF1YWxpZmllciBjYW4gb25seSBiZSBwYXNzZWQgZm9yIHRoZSBtb2Rlcm4gYm9vdHN0cmFwIGV4cGVyaWVuY2UuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgdG9vbGtpdFN0YWNrTmFtZSA9IG9wdGlvbnMudG9vbGtpdFN0YWNrTmFtZSA/PyBERUZBVUxUX1RPT0xLSVRfU1RBQ0tfTkFNRTtcbiAgICBjb25zdCBjdXJyZW50ID0gYXdhaXQgQm9vdHN0cmFwU3RhY2subG9va3VwKHNka1Byb3ZpZGVyLCBlbnZpcm9ubWVudCwgdG9vbGtpdFN0YWNrTmFtZSwgdGhpcy5pb0hlbHBlcik7XG4gICAgcmV0dXJuIGN1cnJlbnQudXBkYXRlKFxuICAgICAgYXdhaXQgdGhpcy5sb2FkVGVtcGxhdGUocGFyYW1zKSxcbiAgICAgIHt9LFxuICAgICAge1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICB0ZXJtaW5hdGlvblByb3RlY3Rpb246IG9wdGlvbnMudGVybWluYXRpb25Qcm90ZWN0aW9uID8/IGN1cnJlbnQudGVybWluYXRpb25Qcm90ZWN0aW9uLFxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcGxveSBDSS9DRC1yZWFkeSBib290c3RyYXAgc3RhY2sgZnJvbSB0ZW1wbGF0ZVxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBtb2Rlcm5Cb290c3RyYXAoXG4gICAgZW52aXJvbm1lbnQ6IGN4YXBpLkVudmlyb25tZW50LFxuICAgIHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlcixcbiAgICBvcHRpb25zOiBCb290c3RyYXBFbnZpcm9ubWVudE9wdGlvbnMgPSB7fSxcbiAgKTogUHJvbWlzZTxTdWNjZXNzZnVsRGVwbG95U3RhY2tSZXN1bHQ+IHtcbiAgICBjb25zdCBwYXJhbXMgPSBvcHRpb25zLnBhcmFtZXRlcnMgPz8ge307XG5cbiAgICBjb25zdCBib290c3RyYXBUZW1wbGF0ZSA9IGF3YWl0IHRoaXMubG9hZFRlbXBsYXRlKCk7XG5cbiAgICBjb25zdCB0b29sa2l0U3RhY2tOYW1lID0gb3B0aW9ucy50b29sa2l0U3RhY2tOYW1lID8/IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FO1xuICAgIGNvbnN0IGN1cnJlbnQgPSBhd2FpdCBCb290c3RyYXBTdGFjay5sb29rdXAoc2RrUHJvdmlkZXIsIGVudmlyb25tZW50LCB0b29sa2l0U3RhY2tOYW1lLCB0aGlzLmlvSGVscGVyKTtcbiAgICBjb25zdCBwYXJ0aXRpb24gPSBhd2FpdCBjdXJyZW50LnBhcnRpdGlvbigpO1xuXG4gICAgaWYgKHBhcmFtcy5jcmVhdGVDdXN0b21lck1hc3RlcktleSAhPT0gdW5kZWZpbmVkICYmIHBhcmFtcy5rbXNLZXlJZCkge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihcbiAgICAgICAgXCJZb3UgY2Fubm90IHBhc3MgJy0tYm9vdHN0cmFwLWttcy1rZXktaWQnIGFuZCAnLS1ib290c3RyYXAtY3VzdG9tZXIta2V5JyB0b2dldGhlci4gU3BlY2lmeSBvbmUgb3IgdGhlIG90aGVyXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIElmIHBlb3BsZSByZS1ib290c3RyYXAsIGV4aXN0aW5nIHBhcmFtZXRlciB2YWx1ZXMgYXJlIHJldXNlZCBzbyB0aGF0IHBlb3BsZSBkb24ndCBhY2NpZGVudGFsbHkgY2hhbmdlIHRoZSBjb25maWd1cmF0aW9uXG4gICAgLy8gb24gdGhlaXIgYm9vdHN0cmFwIHN0YWNrICh0aGlzIGhhcHBlbnMgYXV0b21hdGljYWxseSBpbiBkZXBsb3lTdGFjaykuIEhvd2V2ZXIsIHRvIGRvIHByb3BlciB2YWxpZGF0aW9uIG9uIHRoZVxuICAgIC8vIGNvbWJpbmVkIGFyZ3VtZW50cyAoc3VjaCB0aGF0IGlmIC0tdHJ1c3QgaGFzIGJlZW4gZ2l2ZW4sIC0tY2xvdWRmb3JtYXRpb24tZXhlY3V0aW9uLXBvbGljaWVzIGlzIG5lY2Vzc2FyeSBhcyB3ZWxsKVxuICAgIC8vIHdlIG5lZWQgdG8gdGFrZSB0aGlzIHBhcmFtZXRlciByZXVzZSBpbnRvIGFjY291bnQuXG4gICAgLy9cbiAgICAvLyBJZGVhbGx5IHdlJ2QgZG8gdGhpcyBpbnNpZGUgdGhlIHRlbXBsYXRlLCBidXQgdGhlIGBSdWxlc2Agc2VjdGlvbiBvZiBDRk5cbiAgICAvLyB0ZW1wbGF0ZXMgZG9lc24ndCBzZWVtIHRvIGJlIGFibGUgdG8gZXhwcmVzcyB0aGUgY29uZGl0aW9ucyB0aGF0IHdlIG5lZWRcbiAgICAvLyAoY2FuJ3QgdXNlIEZuOjpKb2luIG9yIHJlZmVyZW5jZSBDb25kaXRpb25zKSBzbyB3ZSBkbyBpdCBoZXJlIGluc3RlYWQuXG4gICAgY29uc3QgYWxsVHJ1c3RlZCA9IG5ldyBTZXQoW1xuICAgICAgLi4ucGFyYW1zLnRydXN0ZWRBY2NvdW50cyA/PyBbXSxcbiAgICAgIC4uLnBhcmFtcy50cnVzdGVkQWNjb3VudHNGb3JMb29rdXAgPz8gW10sXG4gICAgXSk7XG4gICAgY29uc3QgaW52YWxpZCA9IGludGVyc2VjdGlvbihhbGxUcnVzdGVkLCBuZXcgU2V0KHBhcmFtcy51bnRydXN0ZWRBY2NvdW50cykpO1xuICAgIGlmIChpbnZhbGlkLnNpemUgPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGBBY2NvdW50cyBjYW5ub3QgYmUgYm90aCB0cnVzdGVkIGFuZCB1bnRydXN0ZWQuIEZvdW5kOiAke1suLi5pbnZhbGlkXS5qb2luKCcsJyl9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVtb3ZlVW50cnVzdGVkID0gKGFjY291bnRzOiBzdHJpbmdbXSkgPT5cbiAgICAgIGFjY291bnRzLmZpbHRlcihhY2MgPT4gIXBhcmFtcy51bnRydXN0ZWRBY2NvdW50cz8ubWFwKFN0cmluZykuaW5jbHVkZXMoU3RyaW5nKGFjYykpKTtcblxuICAgIGNvbnN0IHRydXN0ZWRBY2NvdW50cyA9IHJlbW92ZVVudHJ1c3RlZChwYXJhbXMudHJ1c3RlZEFjY291bnRzID8/IHNwbGl0Q2ZuQXJyYXkoY3VycmVudC5wYXJhbWV0ZXJzLlRydXN0ZWRBY2NvdW50cykpO1xuICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9JTkZPLm1zZyhcbiAgICAgIGBUcnVzdGVkIGFjY291bnRzIGZvciBkZXBsb3ltZW50OiAke3RydXN0ZWRBY2NvdW50cy5sZW5ndGggPiAwID8gdHJ1c3RlZEFjY291bnRzLmpvaW4oJywgJykgOiAnKG5vbmUpJ31gLFxuICAgICkpO1xuXG4gICAgY29uc3QgdHJ1c3RlZEFjY291bnRzRm9yTG9va3VwID0gcmVtb3ZlVW50cnVzdGVkKFxuICAgICAgcGFyYW1zLnRydXN0ZWRBY2NvdW50c0Zvckxvb2t1cCA/PyBzcGxpdENmbkFycmF5KGN1cnJlbnQucGFyYW1ldGVycy5UcnVzdGVkQWNjb3VudHNGb3JMb29rdXApLFxuICAgICk7XG4gICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0lORk8ubXNnKFxuICAgICAgYFRydXN0ZWQgYWNjb3VudHMgZm9yIGxvb2t1cDogJHt0cnVzdGVkQWNjb3VudHNGb3JMb29rdXAubGVuZ3RoID4gMCA/IHRydXN0ZWRBY2NvdW50c0Zvckxvb2t1cC5qb2luKCcsICcpIDogJyhub25lKSd9YCxcbiAgICApKTtcblxuICAgIGNvbnN0IGNsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUG9saWNpZXMgPVxuICAgICAgcGFyYW1zLmNsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUG9saWNpZXMgPz8gc3BsaXRDZm5BcnJheShjdXJyZW50LnBhcmFtZXRlcnMuQ2xvdWRGb3JtYXRpb25FeGVjdXRpb25Qb2xpY2llcyk7XG4gICAgaWYgKHRydXN0ZWRBY2NvdW50cy5sZW5ndGggPT09IDAgJiYgY2xvdWRGb3JtYXRpb25FeGVjdXRpb25Qb2xpY2llcy5sZW5ndGggPT09IDApIHtcbiAgICAgIC8vIEZvciBzZWxmLXRydXN0IGl0J3Mgb2theSB0byBkZWZhdWx0IHRvIEFkbWluaXN0cmF0b3JBY2Nlc3MsIGFuZCBpdCBpbXByb3ZlcyB0aGUgdXNhYmlsaXR5IG9mIGJvb3RzdHJhcHBpbmcgYSBsb3QuXG4gICAgICAvL1xuICAgICAgLy8gV2UgZG9uJ3QgYWN0dWFsbHkgbWFrZSB0aGUgaW1wbGljaXRseSBwb2xpY3kgYSBwaHlzaWNhbCBwYXJhbWV0ZXIuIFRoZSB0ZW1wbGF0ZSB3aWxsIGluZmVyIGl0IGluc3RlYWQsXG4gICAgICAvLyB3ZSBzaW1wbHkgZG8gdGhlIFVJIGFkdmVydGlzaW5nIHRoYXQgYmVoYXZpb3IgaGVyZS5cbiAgICAgIC8vXG4gICAgICAvLyBJZiB3ZSBESUQgbWFrZSBpdCBhbiBleHBsaWNpdCBwYXJhbWV0ZXIsIHdlIHdvdWxkbid0IGJlIGFibGUgdG8gdGVsbCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHdoZXRoZXJcbiAgICAgIC8vIHdlIGluZmVycmVkIGl0IG9yIHdoZXRoZXIgdGhlIHVzZXIgdG9sZCB1cywgYW5kIHRoZSBzZXF1ZW5jZTpcbiAgICAgIC8vXG4gICAgICAvLyAkIGNkayBib290c3RyYXBcbiAgICAgIC8vICQgY2RrIGJvb3RzdHJhcCAtLXRydXN0IDEyMzRcbiAgICAgIC8vXG4gICAgICAvLyBXb3VsZCBsZWF2ZSBBZG1pbmlzdHJhdG9yQWNjZXNzIHBvbGljaWVzIHdpdGggYSB0cnVzdCByZWxhdGlvbnNoaXAsIHdpdGhvdXQgdGhlIHVzZXIgZXhwbGljaXRseVxuICAgICAgLy8gYXBwcm92aW5nIHRoZSB0cnVzdCBwb2xpY3kuXG4gICAgICBjb25zdCBpbXBsaWNpdFBvbGljeSA9IGBhcm46JHtwYXJ0aXRpb259OmlhbTo6YXdzOnBvbGljeS9BZG1pbmlzdHJhdG9yQWNjZXNzYDtcbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9XQVJOLm1zZyhcbiAgICAgICAgYFVzaW5nIGRlZmF1bHQgZXhlY3V0aW9uIHBvbGljeSBvZiAnJHtpbXBsaWNpdFBvbGljeX0nLiBQYXNzICctLWNsb3VkZm9ybWF0aW9uLWV4ZWN1dGlvbi1wb2xpY2llcycgdG8gY3VzdG9taXplLmAsXG4gICAgICApKTtcbiAgICB9IGVsc2UgaWYgKGNsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUG9saWNpZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKFxuICAgICAgICBgUGxlYXNlIHBhc3MgXFwnLS1jbG91ZGZvcm1hdGlvbi1leGVjdXRpb24tcG9saWNpZXNcXCcgd2hlbiB1c2luZyBcXCctLXRydXN0XFwnIHRvIHNwZWNpZnkgZGVwbG95bWVudCBwZXJtaXNzaW9ucy4gVHJ5IGEgbWFuYWdlZCBwb2xpY3kgb2YgdGhlIGZvcm0gXFwnYXJuOiR7cGFydGl0aW9ufTppYW06OmF3czpwb2xpY3kvPFBvbGljeU5hbWU+XFwnLmAsXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBSZW1pbmQgcGVvcGxlIHdoYXQgdGhlIGN1cnJlbnQgc2V0dGluZ3MgYXJlXG4gICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfSU5GTy5tc2coYEV4ZWN1dGlvbiBwb2xpY2llczogJHtjbG91ZEZvcm1hdGlvbkV4ZWN1dGlvblBvbGljaWVzLmpvaW4oJywgJyl9YCkpO1xuICAgIH1cblxuICAgIC8vICogSWYgYW4gQVJOIGlzIGdpdmVuLCB0aGF0IEFSTi4gT3RoZXJ3aXNlOlxuICAgIC8vICAgKiAnLScgaWYgY3VzdG9tZXJLZXkgPSBmYWxzZVxuICAgIC8vICAgKiAnJyBpZiBjdXN0b21lcktleSA9IHRydWVcbiAgICAvLyAgICogaWYgY3VzdG9tZXJLZXkgaXMgYWxzbyBub3QgZ2l2ZW5cbiAgICAvLyAgICAgKiB1bmRlZmluZWQgaWYgd2UgYWxyZWFkeSBoYWQgYSB2YWx1ZSBpbiBwbGFjZSAocmV1c2luZyB3aGF0IHdlIGhhZClcbiAgICAvLyAgICAgKiAnLScgaWYgdGhpcyBpcyB0aGUgZmlyc3QgdGltZSB3ZSdyZSBkZXBsb3lpbmcgdGhpcyBzdGFjayAob3IgdXBncmFkaW5nIGZyb20gb2xkIHRvIG5ldyBib290c3RyYXApXG4gICAgY29uc3QgY3VycmVudEttc0tleUlkID0gY3VycmVudC5wYXJhbWV0ZXJzLkZpbGVBc3NldHNCdWNrZXRLbXNLZXlJZDtcbiAgICBjb25zdCBrbXNLZXlJZCA9XG4gICAgICBwYXJhbXMua21zS2V5SWQgPz9cbiAgICAgIChwYXJhbXMuY3JlYXRlQ3VzdG9tZXJNYXN0ZXJLZXkgPT09IHRydWVcbiAgICAgICAgPyBDUkVBVEVfTkVXX0tFWVxuICAgICAgICA6IHBhcmFtcy5jcmVhdGVDdXN0b21lck1hc3RlcktleSA9PT0gZmFsc2UgfHwgY3VycmVudEttc0tleUlkID09PSB1bmRlZmluZWRcbiAgICAgICAgICA/IFVTRV9BV1NfTUFOQUdFRF9LRVlcbiAgICAgICAgICA6IHVuZGVmaW5lZCk7XG5cbiAgICAvKiBBIHBlcm1pc3Npb25zIGJvdW5kYXJ5IGNhbiBiZSBwcm92aWRlZCB2aWE6XG4gICAgICogICAgLSB0aGUgZmxhZyBpbmRpY2F0aW5nIHRoZSBleGFtcGxlIG9uZSBzaG91bGQgYmUgdXNlZFxuICAgICAqICAgIC0gdGhlIG5hbWUgaW5kaWNhdGluZyB0aGUgY3VzdG9tIHBlcm1pc3Npb25zIGJvdW5kYXJ5IHRvIGJlIHVzZWRcbiAgICAgKiBSZS1ib290c3RyYXBwaW5nIHdpbGwgTk9UIGJlIGJsb2NrZWQgYnkgZWl0aGVyIHRpZ2h0ZW5pbmcgb3IgcmVsYXhpbmcgdGhlIHBlcm1pc3Npb25zJyBib3VuZGFyeS5cbiAgICAgKi9cblxuICAgIC8vIElucHV0UGVybWlzc2lvbnNCb3VuZGFyeSBpcyBhbiBgYW55YCB0eXBlIGFuZCBpZiBpdCBpcyBub3QgZGVmaW5lZCBpdFxuICAgIC8vIGFwcGVhcnMgYXMgYW4gZW1wdHkgc3RyaW5nICcnLiBXZSBuZWVkIHRvIGZvcmNlIGl0IHRvIGV2YWx1YXRlIGFuIGVtcHR5IHN0cmluZ1xuICAgIC8vIGFzIHVuZGVmaW5lZFxuICAgIGNvbnN0IGN1cnJlbnRQZXJtaXNzaW9uc0JvdW5kYXJ5OiBzdHJpbmcgfCB1bmRlZmluZWQgPSBjdXJyZW50LnBhcmFtZXRlcnMuSW5wdXRQZXJtaXNzaW9uc0JvdW5kYXJ5IHx8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBpbnB1dFBvbGljeU5hbWUgPSBwYXJhbXMuZXhhbXBsZVBlcm1pc3Npb25zQm91bmRhcnlcbiAgICAgID8gQ0RLX0JPT1RTVFJBUF9QRVJNSVNTSU9OU19CT1VOREFSWVxuICAgICAgOiBwYXJhbXMuY3VzdG9tUGVybWlzc2lvbnNCb3VuZGFyeTtcbiAgICBsZXQgcG9saWN5TmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGlmIChpbnB1dFBvbGljeU5hbWUpIHtcbiAgICAgIC8vIElmIHRoZSBleGFtcGxlIHBvbGljeSBpcyBub3QgYWxyZWFkeSBpbiBwbGFjZSwgaXQgbXVzdCBiZSBjcmVhdGVkLlxuICAgICAgY29uc3Qgc2RrID0gKGF3YWl0IHNka1Byb3ZpZGVyLmZvckVudmlyb25tZW50KGVudmlyb25tZW50LCBNb2RlLkZvcldyaXRpbmcpKS5zZGs7XG4gICAgICBwb2xpY3lOYW1lID0gYXdhaXQgdGhpcy5nZXRQb2xpY3lOYW1lKGVudmlyb25tZW50LCBzZGssIGlucHV0UG9saWN5TmFtZSwgcGFydGl0aW9uLCBwYXJhbXMpO1xuICAgIH1cbiAgICBpZiAoY3VycmVudFBlcm1pc3Npb25zQm91bmRhcnkgIT09IHBvbGljeU5hbWUpIHtcbiAgICAgIGlmICghY3VycmVudFBlcm1pc3Npb25zQm91bmRhcnkpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX1dBUk4ubXNnKFxuICAgICAgICAgIGBBZGRpbmcgbmV3IHBlcm1pc3Npb25zIGJvdW5kYXJ5ICR7cG9saWN5TmFtZX1gLFxuICAgICAgICApKTtcbiAgICAgIH0gZWxzZSBpZiAoIXBvbGljeU5hbWUpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX1dBUk4ubXNnKFxuICAgICAgICAgIGBSZW1vdmluZyBleGlzdGluZyBwZXJtaXNzaW9ucyBib3VuZGFyeSAke2N1cnJlbnRQZXJtaXNzaW9uc0JvdW5kYXJ5fWAsXG4gICAgICAgICkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX1dBUk4ubXNnKFxuICAgICAgICAgIGBDaGFuZ2luZyBwZXJtaXNzaW9ucyBib3VuZGFyeSBmcm9tICR7Y3VycmVudFBlcm1pc3Npb25zQm91bmRhcnl9IHRvICR7cG9saWN5TmFtZX1gLFxuICAgICAgICApKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY3VycmVudC51cGRhdGUoXG4gICAgICBib290c3RyYXBUZW1wbGF0ZSxcbiAgICAgIHtcbiAgICAgICAgRmlsZUFzc2V0c0J1Y2tldE5hbWU6IHBhcmFtcy5idWNrZXROYW1lLFxuICAgICAgICBGaWxlQXNzZXRzQnVja2V0S21zS2V5SWQ6IGttc0tleUlkLFxuICAgICAgICAvLyBFbXB0eSBhcnJheSBiZWNvbWVzIGVtcHR5IHN0cmluZ1xuICAgICAgICBUcnVzdGVkQWNjb3VudHM6IHRydXN0ZWRBY2NvdW50cy5qb2luKCcsJyksXG4gICAgICAgIFRydXN0ZWRBY2NvdW50c0Zvckxvb2t1cDogdHJ1c3RlZEFjY291bnRzRm9yTG9va3VwLmpvaW4oJywnKSxcbiAgICAgICAgQ2xvdWRGb3JtYXRpb25FeGVjdXRpb25Qb2xpY2llczogY2xvdWRGb3JtYXRpb25FeGVjdXRpb25Qb2xpY2llcy5qb2luKCcsJyksXG4gICAgICAgIFF1YWxpZmllcjogcGFyYW1zLnF1YWxpZmllcixcbiAgICAgICAgUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uOlxuICAgICAgICAgIHBhcmFtcy5wdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb24gfHwgcGFyYW1zLnB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbiA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/ICd0cnVlJ1xuICAgICAgICAgICAgOiAnZmFsc2UnLFxuICAgICAgICBJbnB1dFBlcm1pc3Npb25zQm91bmRhcnk6IHBvbGljeU5hbWUsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICB0ZXJtaW5hdGlvblByb3RlY3Rpb246IG9wdGlvbnMudGVybWluYXRpb25Qcm90ZWN0aW9uID8/IGN1cnJlbnQudGVybWluYXRpb25Qcm90ZWN0aW9uLFxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRQb2xpY3lOYW1lKFxuICAgIGVudmlyb25tZW50OiBjeGFwaS5FbnZpcm9ubWVudCxcbiAgICBzZGs6IFNESyxcbiAgICBwZXJtaXNzaW9uc0JvdW5kYXJ5OiBzdHJpbmcsXG4gICAgcGFydGl0aW9uOiBzdHJpbmcsXG4gICAgcGFyYW1zOiBCb290c3RyYXBwaW5nUGFyYW1ldGVycyxcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAocGVybWlzc2lvbnNCb3VuZGFyeSAhPT0gQ0RLX0JPT1RTVFJBUF9QRVJNSVNTSU9OU19CT1VOREFSWSkge1xuICAgICAgdGhpcy52YWxpZGF0ZVBvbGljeU5hbWUocGVybWlzc2lvbnNCb3VuZGFyeSk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHBlcm1pc3Npb25zQm91bmRhcnkpO1xuICAgIH1cbiAgICAvLyBpZiBubyBRdWFsaWZpZXIgaXMgc3VwcGxpZWQsIHJlc29ydCB0byB0aGUgZGVmYXVsdCBvbmVcbiAgICBjb25zdCBhcm4gPSBhd2FpdCB0aGlzLmdldEV4YW1wbGVQZXJtaXNzaW9uc0JvdW5kYXJ5KFxuICAgICAgcGFyYW1zLnF1YWxpZmllciA/PyAnaG5iNjU5ZmRzJyxcbiAgICAgIHBhcnRpdGlvbixcbiAgICAgIGVudmlyb25tZW50LmFjY291bnQsXG4gICAgICBzZGssXG4gICAgKTtcbiAgICBjb25zdCBwb2xpY3lOYW1lID0gYXJuLnNwbGl0KCcvJykucG9wKCk7XG4gICAgaWYgKCFwb2xpY3lOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdDb3VsZCBub3QgcmV0cmlldmUgdGhlIGV4YW1wbGUgcGVybWlzc2lvbiBib3VuZGFyeSEnKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwb2xpY3lOYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0RXhhbXBsZVBlcm1pc3Npb25zQm91bmRhcnkoXG4gICAgcXVhbGlmaWVyOiBzdHJpbmcsXG4gICAgcGFydGl0aW9uOiBzdHJpbmcsXG4gICAgYWNjb3VudDogc3RyaW5nLFxuICAgIHNkazogU0RLLFxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGlhbSA9IHNkay5pYW0oKTtcblxuICAgIGxldCBwb2xpY3lOYW1lID0gYGNkay0ke3F1YWxpZmllcn0tcGVybWlzc2lvbnMtYm91bmRhcnlgO1xuICAgIGNvbnN0IGFybiA9IGBhcm46JHtwYXJ0aXRpb259OmlhbTo6JHthY2NvdW50fTpwb2xpY3kvJHtwb2xpY3lOYW1lfWA7XG5cbiAgICB0cnkge1xuICAgICAgbGV0IGdldFBvbGljeVJlc3AgPSBhd2FpdCBpYW0uZ2V0UG9saWN5KHsgUG9saWN5QXJuOiBhcm4gfSk7XG4gICAgICBpZiAoZ2V0UG9saWN5UmVzcC5Qb2xpY3kpIHtcbiAgICAgICAgcmV0dXJuIGFybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L0FQSVJlZmVyZW5jZS9BUElfR2V0UG9saWN5Lmh0bWwjQVBJX0dldFBvbGljeV9FcnJvcnNcbiAgICAgIGlmIChlLm5hbWUgPT09ICdOb1N1Y2hFbnRpdHknKSB7XG4gICAgICAgIC8vIG5vb3AsIHByb2NlZWQgd2l0aCBjcmVhdGluZyB0aGUgcG9saWN5XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHBvbGljeURvYyA9IHtcbiAgICAgIFZlcnNpb246ICcyMDEyLTEwLTE3JyxcbiAgICAgIFN0YXRlbWVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgQWN0aW9uOiBbJyonXSxcbiAgICAgICAgICBSZXNvdXJjZTogJyonLFxuICAgICAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgICAgICBTaWQ6ICdFeHBsaWNpdEFsbG93QWxsJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIENvbmRpdGlvbjoge1xuICAgICAgICAgICAgU3RyaW5nRXF1YWxzOiB7XG4gICAgICAgICAgICAgICdpYW06UGVybWlzc2lvbnNCb3VuZGFyeSc6IGBhcm46JHtwYXJ0aXRpb259OmlhbTo6JHthY2NvdW50fTpwb2xpY3kvY2RrLSR7cXVhbGlmaWVyfS1wZXJtaXNzaW9ucy1ib3VuZGFyeWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgQWN0aW9uOiBbXG4gICAgICAgICAgICAnaWFtOkNyZWF0ZVVzZXInLFxuICAgICAgICAgICAgJ2lhbTpDcmVhdGVSb2xlJyxcbiAgICAgICAgICAgICdpYW06UHV0Um9sZVBlcm1pc3Npb25zQm91bmRhcnknLFxuICAgICAgICAgICAgJ2lhbTpQdXRVc2VyUGVybWlzc2lvbnNCb3VuZGFyeScsXG4gICAgICAgICAgXSxcbiAgICAgICAgICBSZXNvdXJjZTogJyonLFxuICAgICAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgICAgICBTaWQ6ICdEZW55QWNjZXNzSWZSZXF1aXJlZFBlcm1Cb3VuZGFyeUlzTm90QmVpbmdBcHBsaWVkJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIEFjdGlvbjogW1xuICAgICAgICAgICAgJ2lhbTpDcmVhdGVQb2xpY3lWZXJzaW9uJyxcbiAgICAgICAgICAgICdpYW06RGVsZXRlUG9saWN5JyxcbiAgICAgICAgICAgICdpYW06RGVsZXRlUG9saWN5VmVyc2lvbicsXG4gICAgICAgICAgICAnaWFtOlNldERlZmF1bHRQb2xpY3lWZXJzaW9uJyxcbiAgICAgICAgICBdLFxuICAgICAgICAgIFJlc291cmNlOiBgYXJuOiR7cGFydGl0aW9ufTppYW06OiR7YWNjb3VudH06cG9saWN5L2Nkay0ke3F1YWxpZmllcn0tcGVybWlzc2lvbnMtYm91bmRhcnlgLFxuICAgICAgICAgIEVmZmVjdDogJ0RlbnknLFxuICAgICAgICAgIFNpZDogJ0RlbnlQZXJtQm91bmRhcnlJQU1Qb2xpY3lBbHRlcmF0aW9uJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIEFjdGlvbjogWydpYW06RGVsZXRlVXNlclBlcm1pc3Npb25zQm91bmRhcnknLCAnaWFtOkRlbGV0ZVJvbGVQZXJtaXNzaW9uc0JvdW5kYXJ5J10sXG4gICAgICAgICAgUmVzb3VyY2U6ICcqJyxcbiAgICAgICAgICBFZmZlY3Q6ICdEZW55JyxcbiAgICAgICAgICBTaWQ6ICdEZW55UmVtb3ZhbE9mUGVybUJvdW5kYXJ5RnJvbUFueVVzZXJPclJvbGUnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICBQb2xpY3lOYW1lOiBwb2xpY3lOYW1lLFxuICAgICAgUG9saWN5RG9jdW1lbnQ6IEpTT04uc3RyaW5naWZ5KHBvbGljeURvYyksXG4gICAgfTtcbiAgICBjb25zdCBjcmVhdGVQb2xpY3lSZXNwb25zZSA9IGF3YWl0IGlhbS5jcmVhdGVQb2xpY3kocmVxdWVzdCk7XG4gICAgaWYgKGNyZWF0ZVBvbGljeVJlc3BvbnNlLlBvbGljeT8uQXJuKSB7XG4gICAgICByZXR1cm4gY3JlYXRlUG9saWN5UmVzcG9uc2UuUG9saWN5LkFybjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgQ291bGQgbm90IHJldHJpZXZlIHRoZSBleGFtcGxlIHBlcm1pc3Npb24gYm91bmRhcnkgJHthcm59IWApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVQb2xpY3lOYW1lKHBlcm1pc3Npb25zQm91bmRhcnk6IHN0cmluZykge1xuICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L0FQSVJlZmVyZW5jZS9BUElfQ3JlYXRlUG9saWN5Lmh0bWxcbiAgICAvLyBBZGRlZCBzdXBwb3J0IGZvciBwb2xpY3kgbmFtZXMgd2l0aCBhIHBhdGhcbiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy8yNjMyMFxuICAgIGNvbnN0IHJlZ2V4cDogUmVnRXhwID0gL1tcXHcrXFwvPSwuQC1dKy87XG4gICAgY29uc3QgbWF0Y2hlcyA9IHJlZ2V4cC5leGVjKHBlcm1pc3Npb25zQm91bmRhcnkpO1xuICAgIGlmICghKG1hdGNoZXMgJiYgbWF0Y2hlcy5sZW5ndGggPT09IDEgJiYgbWF0Y2hlc1swXSA9PT0gcGVybWlzc2lvbnNCb3VuZGFyeSkpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoYFRoZSBwZXJtaXNzaW9ucyBib3VuZGFyeSBuYW1lICR7cGVybWlzc2lvbnNCb3VuZGFyeX0gZG9lcyBub3QgbWF0Y2ggdGhlIElBTSBjb252ZW50aW9ucy5gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGN1c3RvbUJvb3RzdHJhcChcbiAgICBlbnZpcm9ubWVudDogY3hhcGkuRW52aXJvbm1lbnQsXG4gICAgc2RrUHJvdmlkZXI6IFNka1Byb3ZpZGVyLFxuICAgIG9wdGlvbnM6IEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPFN1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdD4ge1xuICAgIC8vIExvb2sgYXQgdGhlIHRlbXBsYXRlLCBkZWNpZGUgd2hldGhlciBpdCdzIG1vc3QgbGlrZWx5IGEgbGVnYWN5IG9yIG1vZGVybiBib290c3RyYXBcbiAgICAvLyB0ZW1wbGF0ZSwgYW5kIHVzZSB0aGUgcmlnaHQgYm9vdHN0cmFwcGVyIGZvciB0aGF0LlxuICAgIGNvbnN0IHZlcnNpb24gPSBib290c3RyYXBWZXJzaW9uRnJvbVRlbXBsYXRlKGF3YWl0IHRoaXMubG9hZFRlbXBsYXRlKCkpO1xuICAgIGlmICh2ZXJzaW9uID09PSAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5sZWdhY3lCb290c3RyYXAoZW52aXJvbm1lbnQsIHNka1Byb3ZpZGVyLCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMubW9kZXJuQm9vdHN0cmFwKGVudmlyb25tZW50LCBzZGtQcm92aWRlciwgb3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2FkVGVtcGxhdGUocGFyYW1zOiBCb290c3RyYXBwaW5nUGFyYW1ldGVycyA9IHt9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBzd2l0Y2ggKHRoaXMuc291cmNlLnNvdXJjZSkge1xuICAgICAgY2FzZSAnY3VzdG9tJzpcbiAgICAgICAgcmV0dXJuIGxvYWRTdHJ1Y3R1cmVkRmlsZSh0aGlzLnNvdXJjZS50ZW1wbGF0ZUZpbGUpO1xuICAgICAgY2FzZSAnZGVmYXVsdCc6XG4gICAgICAgIHJldHVybiBsb2FkU3RydWN0dXJlZEZpbGUocGF0aC5qb2luKGJ1bmRsZWRQYWNrYWdlUm9vdERpcihfX2Rpcm5hbWUpLCAnbGliJywgJ2FwaScsICdib290c3RyYXAnLCAnYm9vdHN0cmFwLXRlbXBsYXRlLnlhbWwnKSk7XG4gICAgICBjYXNlICdsZWdhY3knOlxuICAgICAgICByZXR1cm4gbGVnYWN5Qm9vdHN0cmFwVGVtcGxhdGUocGFyYW1zKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBNYWdpYyBwYXJhbWV0ZXIgdmFsdWUgdGhhdCB3aWxsIGNhdXNlIHRoZSBib290c3RyYXAtdGVtcGxhdGUueW1sIHRvIE5PVCBjcmVhdGUgYSBDTUsgYnV0IHVzZSB0aGUgZGVmYXVsdCBrZXlcbiAqL1xuY29uc3QgVVNFX0FXU19NQU5BR0VEX0tFWSA9ICdBV1NfTUFOQUdFRF9LRVknO1xuXG4vKipcbiAqIE1hZ2ljIHBhcmFtZXRlciB2YWx1ZSB0aGF0IHdpbGwgY2F1c2UgdGhlIGJvb3RzdHJhcC10ZW1wbGF0ZS55bWwgdG8gY3JlYXRlIGEgQ01LXG4gKi9cbmNvbnN0IENSRUFURV9ORVdfS0VZID0gJyc7XG4vKipcbiAqIFBhcmFtZXRlciB2YWx1ZSBpbmRpY2F0aW5nIHRoZSB1c2Ugb2YgdGhlIGRlZmF1bHQsIENESyBwcm92aWRlZCBwZXJtaXNzaW9ucyBib3VuZGFyeSBmb3IgYm9vdHN0cmFwLXRlbXBsYXRlLnltbFxuICovXG5jb25zdCBDREtfQk9PVFNUUkFQX1BFUk1JU1NJT05TX0JPVU5EQVJZID0gJ0NES19CT09UU1RSQVBfUEVSTUlTU0lPTlNfQk9VTkRBUlknO1xuXG4vKipcbiAqIFNwbGl0IGFuIGFycmF5LWxpa2UgQ2xvdWRGb3JtYXRpb24gcGFyYW1ldGVyIG9uICxcbiAqXG4gKiBBbiBlbXB0eSBzdHJpbmcgaXMgdGhlIGVtcHR5IGFycmF5IChpbnN0ZWFkIG9mIGBbJyddYCkuXG4gKi9cbmZ1bmN0aW9uIHNwbGl0Q2ZuQXJyYXkoeHM6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZ1tdIHtcbiAgaWYgKHhzID09PSAnJyB8fCB4cyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiB4cy5zcGxpdCgnLCcpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb248QT4oeHM6IFNldDxBPiwgeXM6IFNldDxBPik6IFNldDxBPiB7XG4gIHJldHVybiBuZXcgU2V0PEE+KEFycmF5LmZyb20oeHMpLmZpbHRlcih4ID0+IHlzLmhhcyh4KSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.d.ts new file mode 100644 index 000000000..1240f55df --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.d.ts @@ -0,0 +1,130 @@ +import type { BootstrapSource } from './bootstrap-environment'; +import type { StringWithoutPlaceholders } from '../environment'; +import type { Tag } from '../tags'; +export declare const BUCKET_NAME_OUTPUT = "BucketName"; +export declare const REPOSITORY_NAME_OUTPUT = "ImageRepositoryName"; +export declare const BUCKET_DOMAIN_NAME_OUTPUT = "BucketDomainName"; +export declare const BOOTSTRAP_VERSION_OUTPUT = "BootstrapVersion"; +export declare const BOOTSTRAP_VERSION_RESOURCE = "CdkBootstrapVersion"; +export declare const BOOTSTRAP_VARIANT_PARAMETER = "BootstrapVariant"; +/** + * The assumed vendor of a template in case it is not set + */ +export declare const DEFAULT_BOOTSTRAP_VARIANT = "AWS CDK: Default Resources"; +/** + * Options for the bootstrapEnvironment operation(s) + */ +export interface BootstrapEnvironmentOptions { + readonly toolkitStackName?: string; + readonly roleArn?: StringWithoutPlaceholders; + readonly parameters?: BootstrappingParameters; + readonly forceDeployment?: boolean; + /** + * The source of the bootstrap stack + * + * @default - modern v2-style bootstrapping + */ + readonly source?: BootstrapSource; + /** + * Whether to execute the changeset or only create it and leave it in review. + * @default true + */ + readonly execute?: boolean; + /** + * Tags for cdktoolkit stack. + * + * @default - None. + */ + readonly tags?: Tag[]; + /** + * Whether the stacks created by the bootstrap process should be protected from termination. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-protect-stacks.html + * @default true + */ + readonly terminationProtection?: boolean; + /** + * Use previous values for unspecified parameters + * + * If not set, all parameters must be specified for every deployment. + * + * @default true + */ + usePreviousParameters?: boolean; +} +/** + * Parameters for the bootstrapping template + */ +export interface BootstrappingParameters { + /** + * The name to be given to the CDK Bootstrap bucket. + * + * @default - a name is generated by CloudFormation. + */ + readonly bucketName?: string; + /** + * The ID of an existing KMS key to be used for encrypting items in the bucket. + * + * @default - use the default KMS key or create a custom one + */ + readonly kmsKeyId?: string; + /** + * Whether or not to create a new customer master key (CMK) + * + * Only applies to modern bootstrapping. Legacy bootstrapping will never create + * a CMK, only use the default S3 key. + * + * @default false + */ + readonly createCustomerMasterKey?: boolean; + /** + * The list of AWS account IDs that are trusted to deploy into the environment being bootstrapped. + * + * @default - only the bootstrapped account can deploy into this environment + */ + readonly trustedAccounts?: string[]; + /** + * The list of AWS account IDs that are trusted to look up values in the environment being bootstrapped. + * + * @default - only the bootstrapped account can look up values in this environment + */ + readonly trustedAccountsForLookup?: string[]; + /** + * The list of AWS account IDs that should not be trusted by the bootstrapped environment. + * If these accounts are already trusted, they will be removed on bootstrapping. + * + * @default - no account will be untrusted. + */ + readonly untrustedAccounts?: string[]; + /** + * The ARNs of the IAM managed policies that should be attached to the role performing CloudFormation deployments. + * In most cases, this will be the AdministratorAccess policy. + * At least one policy is required if `trustedAccounts` were passed. + * + * @default - the role will have no policies attached + */ + readonly cloudFormationExecutionPolicies?: string[]; + /** + * Identifier to distinguish multiple bootstrapped environments + * + * @default - Default qualifier + */ + readonly qualifier?: string; + /** + * Whether or not to enable S3 Staging Bucket Public Access Block Configuration + * + * @default true + */ + readonly publicAccessBlockConfiguration?: boolean; + /** + * Flag for using the default permissions boundary for bootstrapping + * + * @default - No value, optional argument + */ + readonly examplePermissionsBoundary?: boolean; + /** + * Name for the customer's custom permissions boundary for bootstrapping + * + * @default - No value, optional argument + */ + readonly customPermissionsBoundary?: string; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.js new file mode 100644 index 000000000..6dbcce56e --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-props.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_BOOTSTRAP_VARIANT = exports.BOOTSTRAP_VARIANT_PARAMETER = exports.BOOTSTRAP_VERSION_RESOURCE = exports.BOOTSTRAP_VERSION_OUTPUT = exports.BUCKET_DOMAIN_NAME_OUTPUT = exports.REPOSITORY_NAME_OUTPUT = exports.BUCKET_NAME_OUTPUT = void 0; +exports.BUCKET_NAME_OUTPUT = 'BucketName'; +exports.REPOSITORY_NAME_OUTPUT = 'ImageRepositoryName'; +exports.BUCKET_DOMAIN_NAME_OUTPUT = 'BucketDomainName'; +exports.BOOTSTRAP_VERSION_OUTPUT = 'BootstrapVersion'; +exports.BOOTSTRAP_VERSION_RESOURCE = 'CdkBootstrapVersion'; +exports.BOOTSTRAP_VARIANT_PARAMETER = 'BootstrapVariant'; +/** + * The assumed vendor of a template in case it is not set + */ +exports.DEFAULT_BOOTSTRAP_VARIANT = 'AWS CDK: Default Resources'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLXByb3BzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9ib290c3RyYXAvYm9vdHN0cmFwLXByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUlhLFFBQUEsa0JBQWtCLEdBQUcsWUFBWSxDQUFDO0FBQ2xDLFFBQUEsc0JBQXNCLEdBQUcscUJBQXFCLENBQUM7QUFDL0MsUUFBQSx5QkFBeUIsR0FBRyxrQkFBa0IsQ0FBQztBQUMvQyxRQUFBLHdCQUF3QixHQUFHLGtCQUFrQixDQUFDO0FBQzlDLFFBQUEsMEJBQTBCLEdBQUcscUJBQXFCLENBQUM7QUFDbkQsUUFBQSwyQkFBMkIsR0FBRyxrQkFBa0IsQ0FBQztBQUU5RDs7R0FFRztBQUNVLFFBQUEseUJBQXlCLEdBQUcsNEJBQTRCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEJvb3RzdHJhcFNvdXJjZSB9IGZyb20gJy4vYm9vdHN0cmFwLWVudmlyb25tZW50JztcbmltcG9ydCB0eXBlIHsgU3RyaW5nV2l0aG91dFBsYWNlaG9sZGVycyB9IGZyb20gJy4uL2Vudmlyb25tZW50JztcbmltcG9ydCB0eXBlIHsgVGFnIH0gZnJvbSAnLi4vdGFncyc7XG5cbmV4cG9ydCBjb25zdCBCVUNLRVRfTkFNRV9PVVRQVVQgPSAnQnVja2V0TmFtZSc7XG5leHBvcnQgY29uc3QgUkVQT1NJVE9SWV9OQU1FX09VVFBVVCA9ICdJbWFnZVJlcG9zaXRvcnlOYW1lJztcbmV4cG9ydCBjb25zdCBCVUNLRVRfRE9NQUlOX05BTUVfT1VUUFVUID0gJ0J1Y2tldERvbWFpbk5hbWUnO1xuZXhwb3J0IGNvbnN0IEJPT1RTVFJBUF9WRVJTSU9OX09VVFBVVCA9ICdCb290c3RyYXBWZXJzaW9uJztcbmV4cG9ydCBjb25zdCBCT09UU1RSQVBfVkVSU0lPTl9SRVNPVVJDRSA9ICdDZGtCb290c3RyYXBWZXJzaW9uJztcbmV4cG9ydCBjb25zdCBCT09UU1RSQVBfVkFSSUFOVF9QQVJBTUVURVIgPSAnQm9vdHN0cmFwVmFyaWFudCc7XG5cbi8qKlxuICogVGhlIGFzc3VtZWQgdmVuZG9yIG9mIGEgdGVtcGxhdGUgaW4gY2FzZSBpdCBpcyBub3Qgc2V0XG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0JPT1RTVFJBUF9WQVJJQU5UID0gJ0FXUyBDREs6IERlZmF1bHQgUmVzb3VyY2VzJztcblxuLyoqXG4gKiBPcHRpb25zIGZvciB0aGUgYm9vdHN0cmFwRW52aXJvbm1lbnQgb3BlcmF0aW9uKHMpXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQm9vdHN0cmFwRW52aXJvbm1lbnRPcHRpb25zIHtcbiAgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgcm9sZUFybj86IFN0cmluZ1dpdGhvdXRQbGFjZWhvbGRlcnM7XG4gIHJlYWRvbmx5IHBhcmFtZXRlcnM/OiBCb290c3RyYXBwaW5nUGFyYW1ldGVycztcbiAgcmVhZG9ubHkgZm9yY2VEZXBsb3ltZW50PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIHNvdXJjZSBvZiB0aGUgYm9vdHN0cmFwIHN0YWNrXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbW9kZXJuIHYyLXN0eWxlIGJvb3RzdHJhcHBpbmdcbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZT86IEJvb3RzdHJhcFNvdXJjZTtcblxuICAvKipcbiAgICogV2hldGhlciB0byBleGVjdXRlIHRoZSBjaGFuZ2VzZXQgb3Igb25seSBjcmVhdGUgaXQgYW5kIGxlYXZlIGl0IGluIHJldmlldy5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY3V0ZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRhZ3MgZm9yIGNka3Rvb2xraXQgc3RhY2suXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZS5cbiAgICovXG4gIHJlYWRvbmx5IHRhZ3M/OiBUYWdbXTtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgc3RhY2tzIGNyZWF0ZWQgYnkgdGhlIGJvb3RzdHJhcCBwcm9jZXNzIHNob3VsZCBiZSBwcm90ZWN0ZWQgZnJvbSB0ZXJtaW5hdGlvbi5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS91c2luZy1jZm4tcHJvdGVjdC1zdGFja3MuaHRtbFxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSB0ZXJtaW5hdGlvblByb3RlY3Rpb24/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBVc2UgcHJldmlvdXMgdmFsdWVzIGZvciB1bnNwZWNpZmllZCBwYXJhbWV0ZXJzXG4gICAqXG4gICAqIElmIG5vdCBzZXQsIGFsbCBwYXJhbWV0ZXJzIG11c3QgYmUgc3BlY2lmaWVkIGZvciBldmVyeSBkZXBsb3ltZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICB1c2VQcmV2aW91c1BhcmFtZXRlcnM/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHRoZSBib290c3RyYXBwaW5nIHRlbXBsYXRlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQm9vdHN0cmFwcGluZ1BhcmFtZXRlcnMge1xuICAvKipcbiAgICogVGhlIG5hbWUgdG8gYmUgZ2l2ZW4gdG8gdGhlIENESyBCb290c3RyYXAgYnVja2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGEgbmFtZSBpcyBnZW5lcmF0ZWQgYnkgQ2xvdWRGb3JtYXRpb24uXG4gICAqL1xuICByZWFkb25seSBidWNrZXROYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgSUQgb2YgYW4gZXhpc3RpbmcgS01TIGtleSB0byBiZSB1c2VkIGZvciBlbmNyeXB0aW5nIGl0ZW1zIGluIHRoZSBidWNrZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBkZWZhdWx0IEtNUyBrZXkgb3IgY3JlYXRlIGEgY3VzdG9tIG9uZVxuICAgKi9cbiAgcmVhZG9ubHkga21zS2V5SWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRvIGNyZWF0ZSBhIG5ldyBjdXN0b21lciBtYXN0ZXIga2V5IChDTUspXG4gICAqXG4gICAqIE9ubHkgYXBwbGllcyB0byBtb2Rlcm4gYm9vdHN0cmFwcGluZy4gTGVnYWN5IGJvb3RzdHJhcHBpbmcgd2lsbCBuZXZlciBjcmVhdGVcbiAgICogYSBDTUssIG9ubHkgdXNlIHRoZSBkZWZhdWx0IFMzIGtleS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGNyZWF0ZUN1c3RvbWVyTWFzdGVyS2V5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgQVdTIGFjY291bnQgSURzIHRoYXQgYXJlIHRydXN0ZWQgdG8gZGVwbG95IGludG8gdGhlIGVudmlyb25tZW50IGJlaW5nIGJvb3RzdHJhcHBlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBvbmx5IHRoZSBib290c3RyYXBwZWQgYWNjb3VudCBjYW4gZGVwbG95IGludG8gdGhpcyBlbnZpcm9ubWVudFxuICAgKi9cbiAgcmVhZG9ubHkgdHJ1c3RlZEFjY291bnRzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBsaXN0IG9mIEFXUyBhY2NvdW50IElEcyB0aGF0IGFyZSB0cnVzdGVkIHRvIGxvb2sgdXAgdmFsdWVzIGluIHRoZSBlbnZpcm9ubWVudCBiZWluZyBib290c3RyYXBwZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gb25seSB0aGUgYm9vdHN0cmFwcGVkIGFjY291bnQgY2FuIGxvb2sgdXAgdmFsdWVzIGluIHRoaXMgZW52aXJvbm1lbnRcbiAgICovXG4gIHJlYWRvbmx5IHRydXN0ZWRBY2NvdW50c0Zvckxvb2t1cD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgbGlzdCBvZiBBV1MgYWNjb3VudCBJRHMgdGhhdCBzaG91bGQgbm90IGJlIHRydXN0ZWQgYnkgdGhlIGJvb3RzdHJhcHBlZCBlbnZpcm9ubWVudC5cbiAgICogSWYgdGhlc2UgYWNjb3VudHMgYXJlIGFscmVhZHkgdHJ1c3RlZCwgdGhleSB3aWxsIGJlIHJlbW92ZWQgb24gYm9vdHN0cmFwcGluZy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhY2NvdW50IHdpbGwgYmUgdW50cnVzdGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgdW50cnVzdGVkQWNjb3VudHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIEFSTnMgb2YgdGhlIElBTSBtYW5hZ2VkIHBvbGljaWVzIHRoYXQgc2hvdWxkIGJlIGF0dGFjaGVkIHRvIHRoZSByb2xlIHBlcmZvcm1pbmcgQ2xvdWRGb3JtYXRpb24gZGVwbG95bWVudHMuXG4gICAqIEluIG1vc3QgY2FzZXMsIHRoaXMgd2lsbCBiZSB0aGUgQWRtaW5pc3RyYXRvckFjY2VzcyBwb2xpY3kuXG4gICAqIEF0IGxlYXN0IG9uZSBwb2xpY3kgaXMgcmVxdWlyZWQgaWYgYHRydXN0ZWRBY2NvdW50c2Agd2VyZSBwYXNzZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIHJvbGUgd2lsbCBoYXZlIG5vIHBvbGljaWVzIGF0dGFjaGVkXG4gICAqL1xuICByZWFkb25seSBjbG91ZEZvcm1hdGlvbkV4ZWN1dGlvblBvbGljaWVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIElkZW50aWZpZXIgdG8gZGlzdGluZ3Vpc2ggbXVsdGlwbGUgYm9vdHN0cmFwcGVkIGVudmlyb25tZW50c1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIERlZmF1bHQgcXVhbGlmaWVyXG4gICAqL1xuICByZWFkb25seSBxdWFsaWZpZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRvIGVuYWJsZSBTMyBTdGFnaW5nIEJ1Y2tldCBQdWJsaWMgQWNjZXNzIEJsb2NrIENvbmZpZ3VyYXRpb25cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRmxhZyBmb3IgdXNpbmcgdGhlIGRlZmF1bHQgcGVybWlzc2lvbnMgYm91bmRhcnkgZm9yIGJvb3RzdHJhcHBpbmdcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyB2YWx1ZSwgb3B0aW9uYWwgYXJndW1lbnRcbiAgICovXG4gIHJlYWRvbmx5IGV4YW1wbGVQZXJtaXNzaW9uc0JvdW5kYXJ5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogTmFtZSBmb3IgdGhlIGN1c3RvbWVyJ3MgY3VzdG9tIHBlcm1pc3Npb25zIGJvdW5kYXJ5IGZvciBib290c3RyYXBwaW5nXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gdmFsdWUsIG9wdGlvbmFsIGFyZ3VtZW50XG4gICAqL1xuICByZWFkb25seSBjdXN0b21QZXJtaXNzaW9uc0JvdW5kYXJ5Pzogc3RyaW5nO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-template.yaml b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-template.yaml new file mode 100644 index 000000000..a1cf2b346 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/bootstrap-template.yaml @@ -0,0 +1,707 @@ +Description: This stack includes resources needed to deploy AWS CDK apps into this + environment +Parameters: + TrustedAccounts: + Description: List of AWS accounts that are trusted to publish assets and deploy + stacks to this environment + Default: '' + Type: CommaDelimitedList + TrustedAccountsForLookup: + Description: List of AWS accounts that are trusted to look up values in this + environment + Default: '' + Type: CommaDelimitedList + CloudFormationExecutionPolicies: + Description: List of the ManagedPolicy ARN(s) to attach to the CloudFormation + deployment role + Default: '' + Type: CommaDelimitedList + FileAssetsBucketName: + Description: The name of the S3 bucket used for file assets + Default: '' + Type: String + FileAssetsBucketKmsKeyId: + Description: Empty to create a new key (default), 'AWS_MANAGED_KEY' to use a managed + S3 key, or the ID/ARN of an existing key. + Default: '' + Type: String + ContainerAssetsRepositoryName: + Description: A user-provided custom name to use for the container assets ECR repository + Default: '' + Type: String + Qualifier: + Description: An identifier to distinguish multiple bootstrap stacks in the same environment + Default: hnb659fds + Type: String + # "cdk-(qualifier)-image-publishing-role-(account)-(region)" needs to be <= 64 chars + # account = 12, region <= 14, 10 chars for qualifier and 28 for rest of role name + AllowedPattern: "[A-Za-z0-9_-]{1,10}" + ConstraintDescription: Qualifier must be an alphanumeric identifier of at most 10 characters + PublicAccessBlockConfiguration: + Description: Whether or not to enable S3 Staging Bucket Public Access Block Configuration + Default: 'true' + Type: 'String' + AllowedValues: ['true', 'false'] + InputPermissionsBoundary: + Description: Whether or not to use either the CDK supplied or custom permissions boundary + Default: '' + Type: 'String' + UseExamplePermissionsBoundary: + Default: 'false' + AllowedValues: [ 'true', 'false' ] + Type: String + BootstrapVariant: + Type: String + Default: 'AWS CDK: Default Resources' + Description: Describe the provenance of the resources in this bootstrap + stack. Change this when you customize the template. To prevent accidents, + the CDK CLI will not overwrite bootstrap stacks with a different variant. +Conditions: + HasTrustedAccounts: + Fn::Not: + - Fn::Equals: + - '' + - Fn::Join: + - '' + - Ref: TrustedAccounts + HasTrustedAccountsForLookup: + Fn::Not: + - Fn::Equals: + - '' + - Fn::Join: + - '' + - Ref: TrustedAccountsForLookup + HasCloudFormationExecutionPolicies: + Fn::Not: + - Fn::Equals: + - '' + - Fn::Join: + - '' + - Ref: CloudFormationExecutionPolicies + HasCustomFileAssetsBucketName: + Fn::Not: + - Fn::Equals: + - '' + - Ref: FileAssetsBucketName + CreateNewKey: + Fn::Equals: + - '' + - Ref: FileAssetsBucketKmsKeyId + UseAwsManagedKey: + Fn::Equals: + - 'AWS_MANAGED_KEY' + - Ref: FileAssetsBucketKmsKeyId + ShouldCreatePermissionsBoundary: + Fn::Equals: + - 'true' + - Ref: UseExamplePermissionsBoundary + PermissionsBoundarySet: + Fn::Not: + - Fn::Equals: + - '' + - Ref: InputPermissionsBoundary + HasCustomContainerAssetsRepositoryName: + Fn::Not: + - Fn::Equals: + - '' + - Ref: ContainerAssetsRepositoryName + UsePublicAccessBlockConfiguration: + Fn::Equals: + - 'true' + - Ref: PublicAccessBlockConfiguration +Resources: + FileAssetsBucketEncryptionKey: + Type: AWS::KMS::Key + Properties: + KeyPolicy: + Statement: + - Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + - kms:GenerateDataKey + - kms:TagResource + - kms:UntagResource + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + # Not actually everyone -- see below for Conditions + AWS: "*" + Resource: "*" + Condition: + StringEquals: + # See https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-kms-caller-account + kms:CallerAccount: + Ref: AWS::AccountId + kms:ViaService: + - Fn::Sub: s3.${AWS::Region}.amazonaws.com + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::Sub: "${FilePublishingRole.Arn}" + Resource: "*" + Condition: CreateNewKey + UpdateReplacePolicy: Delete + DeletionPolicy: Delete + FileAssetsBucketEncryptionKeyAlias: + Condition: CreateNewKey + Type: AWS::KMS::Alias + Properties: + AliasName: + Fn::Sub: "alias/cdk-${Qualifier}-assets-key" + TargetKeyId: + Ref: FileAssetsBucketEncryptionKey + StagingBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: + Fn::If: + - HasCustomFileAssetsBucketName + - Fn::Sub: "${FileAssetsBucketName}" + - Fn::Sub: cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region} + AccessControl: Private + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: aws:kms + KMSMasterKeyID: + Fn::If: + - CreateNewKey + - Fn::Sub: "${FileAssetsBucketEncryptionKey.Arn}" + - Fn::If: + - UseAwsManagedKey + - Ref: AWS::NoValue + - Fn::Sub: "${FileAssetsBucketKmsKeyId}" + PublicAccessBlockConfiguration: + Fn::If: + - UsePublicAccessBlockConfiguration + - BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + - Ref: AWS::NoValue + VersioningConfiguration: + Status: Enabled + LifecycleConfiguration: + Rules: + # Objects will only be noncurrent if they are deleted via garbage collection. + - Id: CleanupOldVersions + Status: Enabled + NoncurrentVersionExpiration: + NoncurrentDays: 30 + - Id: AbortIncompleteMultipartUploads + Status: Enabled + AbortIncompleteMultipartUpload: + DaysAfterInitiation: 1 + UpdateReplacePolicy: Retain + DeletionPolicy: Retain + StagingBucketPolicy: + Type: 'AWS::S3::BucketPolicy' + Properties: + Bucket: { Ref: 'StagingBucket' } + PolicyDocument: + Id: 'AccessControl' + Version: '2012-10-17' + Statement: + - Sid: 'AllowSSLRequestsOnly' + Action: 's3:*' + Effect: 'Deny' + Resource: + - { 'Fn::Sub': '${StagingBucket.Arn}' } + - { 'Fn::Sub': '${StagingBucket.Arn}/*' } + Condition: + Bool: { 'aws:SecureTransport': 'false' } + Principal: '*' + ContainerAssetsRepository: + Type: AWS::ECR::Repository + Properties: + ImageTagMutability: IMMUTABLE + # Untagged images should never exist but Security Hub wants this rule to exist + LifecyclePolicy: + LifecyclePolicyText: | + { + "rules": [ + { + "rulePriority": 1, + "description": "Untagged images should not exist, but expire any older than one year", + "selection": { + "tagStatus": "untagged", + "countType": "sinceImagePushed", + "countUnit": "days", + "countNumber": 365 + }, + "action": { "type": "expire" } + } + ] + } + RepositoryName: + Fn::If: + - HasCustomContainerAssetsRepositoryName + - Fn::Sub: "${ContainerAssetsRepositoryName}" + - Fn::Sub: cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region} + RepositoryPolicyText: + Version: "2012-10-17" + Statement: + # Necessary for Lambda container images + # https://docs.aws.amazon.com/lambda/latest/dg/configuration-images.html#configuration-images-permissions + - Sid: LambdaECRImageRetrievalPolicy + Effect: Allow + Principal: { Service: "lambda.amazonaws.com" } + Action: + - ecr:BatchGetImage + - ecr:GetDownloadUrlForLayer + Condition: + StringLike: + "aws:sourceArn": { "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*" } + # Necessary for EMR Serverless container images + # https://docs.aws.amazon.com/emr/latest/EMR-Serverless-UserGuide/application-custom-image.html#access-repo + - Sid: EmrServerlessImageRetrievalPolicy + Effect: Allow + Principal: + Service: emr-serverless.amazonaws.com + Action: + - ecr:BatchGetImage + - ecr:GetDownloadUrlForLayer + - ecr:DescribeImages + Condition: + StringLike: + "aws:sourceArn": { "Fn::Sub": "arn:${AWS::Partition}:emr-serverless:${AWS::Region}:${AWS::AccountId}:/applications/*" } + FilePublishingRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + # allows this role to be assumed with session tags. + # see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_permissions-required + - Action: sts:TagSession + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Fn::If: + - HasTrustedAccounts + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: TrustedAccounts + - Ref: AWS::NoValue + RoleName: + Fn::Sub: cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region} + Tags: + - Key: aws-cdk:bootstrap-role + Value: file-publishing + ImagePublishingRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + # allows this role to be assumed with session tags. + # see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_permissions-required + - Action: sts:TagSession + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Fn::If: + - HasTrustedAccounts + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: TrustedAccounts + - Ref: AWS::NoValue + RoleName: + Fn::Sub: cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region} + Tags: + - Key: aws-cdk:bootstrap-role + Value: image-publishing + LookupRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + # allows this role to be assumed with session tags. + # see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_permissions-required + - Action: sts:TagSession + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Fn::If: + - HasTrustedAccountsForLookup + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: TrustedAccountsForLookup + - Ref: AWS::NoValue + - Fn::If: + - HasTrustedAccounts + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: TrustedAccounts + - Ref: AWS::NoValue + RoleName: + Fn::Sub: cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region} + ManagedPolicyArns: + - Fn::Sub: "arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess" + Policies: + - PolicyDocument: + Statement: + - Sid: DontReadSecrets + Effect: Deny + Action: + - kms:Decrypt + Resource: "*" + Version: '2012-10-17' + PolicyName: LookupRolePolicy + Tags: + - Key: aws-cdk:bootstrap-role + Value: lookup + FilePublishingRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:GetEncryptionConfiguration + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Resource: + - Fn::Sub: "${StagingBucket.Arn}" + - Fn::Sub: "${StagingBucket.Arn}/*" + Condition: + StringEquals: + aws:ResourceAccount: + - Fn::Sub: ${AWS::AccountId} + Effect: Allow + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Resource: + Fn::If: + - CreateNewKey + - Fn::Sub: "${FileAssetsBucketEncryptionKey.Arn}" + - Fn::Sub: arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/${FileAssetsBucketKmsKeyId} + Version: '2012-10-17' + Roles: + - Ref: FilePublishingRole + PolicyName: + Fn::Sub: cdk-${Qualifier}-file-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region} + ImagePublishingRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - ecr:PutImage + - ecr:InitiateLayerUpload + - ecr:UploadLayerPart + - ecr:CompleteLayerUpload + - ecr:BatchCheckLayerAvailability + - ecr:DescribeRepositories + - ecr:DescribeImages + - ecr:BatchGetImage + - ecr:GetDownloadUrlForLayer + Resource: + Fn::Sub: "${ContainerAssetsRepository.Arn}" + Effect: Allow + - Action: + - ecr:GetAuthorizationToken + Resource: "*" + Effect: Allow + Version: '2012-10-17' + Roles: + - Ref: ImagePublishingRole + PolicyName: + Fn::Sub: cdk-${Qualifier}-image-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region} + DeploymentActionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + # allows this role to be assumed with session tags. + # see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_permissions-required + - Action: sts:TagSession + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + - Fn::If: + - HasTrustedAccounts + - Action: sts:AssumeRole + Effect: Allow + Principal: + AWS: + Ref: TrustedAccounts + - Ref: AWS::NoValue + Policies: + - PolicyDocument: + Statement: + - Sid: CloudFormationPermissions + Effect: Allow + Action: + - cloudformation:CreateChangeSet + - cloudformation:DeleteChangeSet + - cloudformation:DescribeChangeSet + - cloudformation:DescribeStacks + - cloudformation:ExecuteChangeSet + - cloudformation:CreateStack + - cloudformation:UpdateStack + - cloudformation:RollbackStack + - cloudformation:ContinueUpdateRollback + Resource: "*" + - Sid: PipelineCrossAccountArtifactsBucket + # Read/write buckets in different accounts. Permissions to buckets in + # same account are granted by bucket policies. + # + # Write permissions necessary to write outputs to the cross-region artifact replication bucket + # https://aws.amazon.com/premiumsupport/knowledge-center/codepipeline-deploy-cloudformation/. + Effect: Allow + Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:Abort* + - s3:DeleteObject* + - s3:PutObject* + Resource: "*" + Condition: + StringNotEquals: + s3:ResourceAccount: + Ref: 'AWS::AccountId' + - Sid: PipelineCrossAccountArtifactsKey + # Use keys only for the purposes of reading encrypted files from S3. + Effect: Allow + Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Resource: "*" + Condition: + StringEquals: + kms:ViaService: + Fn::Sub: s3.${AWS::Region}.amazonaws.com + - Action: iam:PassRole + Resource: + Fn::Sub: "${CloudFormationExecutionRole.Arn}" + Effect: Allow + - Sid: CliPermissions + Action: + # Permissions needed by the CLI when doing `cdk deploy`. + # Our CI/CD does not need DeleteStack, + # but we also want to use this role from the CLI, + # and there you can call `cdk destroy` + - cloudformation:DescribeStackEvents + - cloudformation:GetTemplate + - cloudformation:DeleteStack + - cloudformation:UpdateTerminationProtection + - sts:GetCallerIdentity + # `cdk import` + - cloudformation:GetTemplateSummary + Resource: "*" + Effect: Allow + - Sid: CliStagingBucket + Effect: Allow + Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + Resource: + - Fn::Sub: ${StagingBucket.Arn} + - Fn::Sub: ${StagingBucket.Arn}/* + - Sid: ReadVersion + Effect: Allow + Action: + - ssm:GetParameter + - ssm:GetParameters # CreateChangeSet uses this to evaluate any SSM parameters (like `CdkBootstrapVersion`) + Resource: + - Fn::Sub: "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${CdkBootstrapVersion}" + Version: '2012-10-17' + PolicyName: default + RoleName: + Fn::Sub: cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region} + Tags: + - Key: aws-cdk:bootstrap-role + Value: deploy + CloudFormationExecutionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: cloudformation.amazonaws.com + Version: '2012-10-17' + ManagedPolicyArns: + Fn::If: + - HasCloudFormationExecutionPolicies + - Ref: CloudFormationExecutionPolicies + - Fn::If: + - HasTrustedAccounts + # The CLI will prevent this case from occurring + - Ref: AWS::NoValue + # The CLI will advertise that we picked this implicitly + - - Fn::Sub: "arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess" + RoleName: + Fn::Sub: cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region} + PermissionsBoundary: + Fn::If: + - PermissionsBoundarySet + - Fn::Sub: 'arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}' + - Ref: AWS::NoValue + CdkBoostrapPermissionsBoundaryPolicy: + # Edit the template prior to boostrap in order to have this example policy created + Condition: ShouldCreatePermissionsBoundary + Type: AWS::IAM::ManagedPolicy + Properties: + PolicyDocument: + Statement: + # If permission boundaries do not have an explicit `allow`, then the effect is `deny` + - Sid: ExplicitAllowAll + Action: + - "*" + Effect: Allow + Resource: "*" + # Default permissions to prevent privilege escalation + - Sid: DenyAccessIfRequiredPermBoundaryIsNotBeingApplied + Action: + - iam:CreateUser + - iam:CreateRole + - iam:PutRolePermissionsBoundary + - iam:PutUserPermissionsBoundary + Condition: + StringNotEquals: + iam:PermissionsBoundary: + Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region} + Effect: Deny + Resource: "*" + # Forbid the policy itself being edited + - Sid: DenyPermBoundaryIAMPolicyAlteration + Action: + - iam:CreatePolicyVersion + - iam:DeletePolicy + - iam:DeletePolicyVersion + - iam:SetDefaultPolicyVersion + Effect: Deny + Resource: + Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region} + # Forbid removing the permissions boundary from any user or role that has it associated + - Sid: DenyRemovalOfPermBoundaryFromAnyUserOrRole + Action: + - iam:DeleteUserPermissionsBoundary + - iam:DeleteRolePermissionsBoundary + Effect: Deny + Resource: "*" + # Add your specific organizational security policy here + # Uncomment the example to deny access to AWS Config + #- Sid: OrganizationalSecurityPolicy + # Action: + # - "config:*" + # Effect: Deny + # Resource: "*" + Version: "2012-10-17" + Description: "Bootstrap Permission Boundary" + ManagedPolicyName: + Fn::Sub: cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region} + Path: / + # The SSM parameter is used in pipeline-deployed templates to verify the version + # of the bootstrap resources. + CdkBootstrapVersion: + Type: AWS::SSM::Parameter + Properties: + Type: String + Name: + Fn::Sub: '/cdk-bootstrap/${Qualifier}/version' + Value: '27' +Outputs: + BucketName: + Description: The name of the S3 bucket owned by the CDK toolkit stack + Value: + Fn::Sub: "${StagingBucket}" + BucketDomainName: + Description: The domain name of the S3 bucket owned by the CDK toolkit stack + Value: + Fn::Sub: "${StagingBucket.RegionalDomainName}" + # @deprecated - This Export can be removed at some future point in time. + # We can't do it today because if there are stacks that use it, the bootstrap + # stack cannot be updated. Not used anymore by apps >= 1.60.0 + FileAssetKeyArn: + Description: The ARN of the KMS key used to encrypt the asset bucket (deprecated) + Value: + Fn::If: + - CreateNewKey + - Fn::Sub: "${FileAssetsBucketEncryptionKey.Arn}" + - Fn::Sub: "${FileAssetsBucketKmsKeyId}" + Export: + Name: + Fn::Sub: CdkBootstrap-${Qualifier}-FileAssetKeyArn + ImageRepositoryName: + Description: The name of the ECR repository which hosts docker image assets + Value: + Fn::Sub: "${ContainerAssetsRepository}" + # The Output is used by the CLI to verify the version of the bootstrap resources. + BootstrapVersion: + Description: The version of the bootstrap resources that are currently mastered + in this stack + Value: + Fn::GetAtt: [CdkBootstrapVersion, Value] diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.d.ts new file mode 100644 index 000000000..a7bfd1b4c --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.d.ts @@ -0,0 +1,39 @@ +import type { Environment } from '@aws-cdk/cx-api'; +import type { BootstrapEnvironmentOptions } from './bootstrap-props'; +import type { SDK, SdkProvider } from '../aws-auth'; +import type { SuccessfulDeployStackResult } from '../deployments'; +import { type IoHelper } from '../io/private'; +import { ToolkitInfo } from '../toolkit-info'; +/** + * A class to hold state around stack bootstrapping + * + * This class exists so we can break bootstrapping into 2 phases: + * + * ```ts + * const current = BootstrapStack.lookup(...); + * // ... + * current.update(newTemplate, ...); + * ``` + * + * And do something in between the two phases (such as look at the + * current bootstrap stack and doing something intelligent). + */ +export declare class BootstrapStack { + private readonly sdkProvider; + private readonly sdk; + private readonly resolvedEnvironment; + private readonly toolkitStackName; + private readonly currentToolkitInfo; + private readonly ioHelper; + static lookup(sdkProvider: SdkProvider, environment: Environment, toolkitStackName: string, ioHelper: IoHelper): Promise; + protected constructor(sdkProvider: SdkProvider, sdk: SDK, resolvedEnvironment: Environment, toolkitStackName: string, currentToolkitInfo: ToolkitInfo, ioHelper: IoHelper); + get parameters(): Record; + get terminationProtection(): boolean | undefined; + partition(): Promise; + /** + * Perform the actual deployment of a bootstrap stack, given a template and some parameters + */ + update(template: any, parameters: Record, options: Omit): Promise; +} +export declare function bootstrapVersionFromTemplate(template: any): number; +export declare function bootstrapVariantFromTemplate(template: any): string; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.js new file mode 100644 index 000000000..b0aa14c62 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/deploy-bootstrap.js @@ -0,0 +1,147 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BootstrapStack = void 0; +exports.bootstrapVersionFromTemplate = bootstrapVersionFromTemplate; +exports.bootstrapVariantFromTemplate = bootstrapVariantFromTemplate; +const os = require("os"); +const path = require("path"); +const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema"); +const cx_api_1 = require("@aws-cdk/cx-api"); +const fs = require("fs-extra"); +const bootstrap_props_1 = require("./bootstrap-props"); +const deployments_1 = require("../deployments"); +const deploy_stack_1 = require("../deployments/deploy-stack"); +const environment_1 = require("../environment"); +const private_1 = require("../io/private"); +const plugin_1 = require("../plugin"); +const toolkit_info_1 = require("../toolkit-info"); +/** + * A class to hold state around stack bootstrapping + * + * This class exists so we can break bootstrapping into 2 phases: + * + * ```ts + * const current = BootstrapStack.lookup(...); + * // ... + * current.update(newTemplate, ...); + * ``` + * + * And do something in between the two phases (such as look at the + * current bootstrap stack and doing something intelligent). + */ +class BootstrapStack { + sdkProvider; + sdk; + resolvedEnvironment; + toolkitStackName; + currentToolkitInfo; + ioHelper; + static async lookup(sdkProvider, environment, toolkitStackName, ioHelper) { + toolkitStackName = toolkitStackName ?? toolkit_info_1.DEFAULT_TOOLKIT_STACK_NAME; + const resolvedEnvironment = await sdkProvider.resolveEnvironment(environment); + const sdk = (await sdkProvider.forEnvironment(resolvedEnvironment, plugin_1.Mode.ForWriting)).sdk; + const currentToolkitInfo = await toolkit_info_1.ToolkitInfo.lookup(resolvedEnvironment, sdk, ioHelper, toolkitStackName); + return new BootstrapStack(sdkProvider, sdk, resolvedEnvironment, toolkitStackName, currentToolkitInfo, ioHelper); + } + constructor(sdkProvider, sdk, resolvedEnvironment, toolkitStackName, currentToolkitInfo, ioHelper) { + this.sdkProvider = sdkProvider; + this.sdk = sdk; + this.resolvedEnvironment = resolvedEnvironment; + this.toolkitStackName = toolkitStackName; + this.currentToolkitInfo = currentToolkitInfo; + this.ioHelper = ioHelper; + } + get parameters() { + return this.currentToolkitInfo.found ? this.currentToolkitInfo.bootstrapStack.parameters : {}; + } + get terminationProtection() { + return this.currentToolkitInfo.found ? this.currentToolkitInfo.bootstrapStack.terminationProtection : undefined; + } + async partition() { + return (await this.sdk.currentAccount()).partition; + } + /** + * Perform the actual deployment of a bootstrap stack, given a template and some parameters + */ + async update(template, parameters, options) { + if (this.currentToolkitInfo.found && !options.forceDeployment) { + // Safety checks + const abortResponse = { + type: 'did-deploy-stack', + noOp: true, + outputs: {}, + stackArn: this.currentToolkitInfo.bootstrapStack.stackId, + }; + // Validate that the bootstrap stack we're trying to replace is from the same variant as the one we're trying to deploy + const currentVariant = this.currentToolkitInfo.variant; + const newVariant = bootstrapVariantFromTemplate(template); + if (currentVariant !== newVariant) { + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_WARN.msg(`Bootstrap stack already exists, containing '${currentVariant}'. Not overwriting it with a template containing '${newVariant}' (use --force if you intend to overwrite)`)); + return abortResponse; + } + // Validate that we're not downgrading the bootstrap stack + const newVersion = bootstrapVersionFromTemplate(template); + const currentVersion = this.currentToolkitInfo.version; + if (newVersion < currentVersion) { + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_WARN.msg(`Bootstrap stack already at version ${currentVersion}. Not downgrading it to version ${newVersion} (use --force if you intend to downgrade)`)); + if (newVersion === 0) { + // A downgrade with 0 as target version means we probably have a new-style bootstrap in the account, + // and an old-style bootstrap as current target, which means the user probably forgot to put this flag in. + await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_WARN.msg("(Did you set the '@aws-cdk/core:newStyleStackSynthesis' feature flag in cdk.json?)")); + } + return abortResponse; + } + } + const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap')); + const builder = new cx_api_1.CloudAssemblyBuilder(outdir); + const templateFile = `${this.toolkitStackName}.template.json`; + await fs.writeJson(path.join(builder.outdir, templateFile), template, { + spaces: 2, + }); + builder.addArtifact(this.toolkitStackName, { + type: cloud_assembly_schema_1.ArtifactType.AWS_CLOUDFORMATION_STACK, + environment: cx_api_1.EnvironmentUtils.format(this.resolvedEnvironment.account, this.resolvedEnvironment.region), + properties: { + templateFile, + terminationProtection: options.terminationProtection ?? false, + }, + }); + const assembly = builder.buildAssembly(); + const ret = await (0, deploy_stack_1.deployStack)({ + stack: assembly.getStackByName(this.toolkitStackName), + resolvedEnvironment: this.resolvedEnvironment, + sdk: this.sdk, + sdkProvider: this.sdkProvider, + forceDeployment: options.forceDeployment, + roleArn: options.roleArn, + tags: options.tags, + deploymentMethod: { method: 'change-set', execute: options.execute }, + parameters, + usePreviousParameters: options.usePreviousParameters ?? true, + // Obviously we can't need a bootstrap stack to deploy a bootstrap stack + envResources: new environment_1.NoBootstrapStackEnvironmentResources(this.resolvedEnvironment, this.sdk, this.ioHelper), + }, this.ioHelper); + (0, deployments_1.assertIsSuccessfulDeployStackResult)(ret); + return ret; + } +} +exports.BootstrapStack = BootstrapStack; +function bootstrapVersionFromTemplate(template) { + const versionSources = [ + template.Outputs?.[bootstrap_props_1.BOOTSTRAP_VERSION_OUTPUT]?.Value, + template.Resources?.[bootstrap_props_1.BOOTSTRAP_VERSION_RESOURCE]?.Properties?.Value, + ]; + for (const vs of versionSources) { + if (typeof vs === 'number') { + return vs; + } + if (typeof vs === 'string' && !isNaN(parseInt(vs, 10))) { + return parseInt(vs, 10); + } + } + return 0; +} +function bootstrapVariantFromTemplate(template) { + return template.Parameters?.[bootstrap_props_1.BOOTSTRAP_VARIANT_PARAMETER]?.Default ?? bootstrap_props_1.DEFAULT_BOOTSTRAP_VARIANT; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95LWJvb3RzdHJhcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvYm9vdHN0cmFwL2RlcGxveS1ib290c3RyYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBMEpBLG9FQWVDO0FBRUQsb0VBRUM7QUE3S0QseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3QiwwRUFBOEQ7QUFFOUQsNENBQXlFO0FBQ3pFLCtCQUErQjtBQUUvQix1REFLMkI7QUFHM0IsZ0RBQXFFO0FBQ3JFLDhEQUEwRDtBQUMxRCxnREFBc0U7QUFDdEUsMkNBQWtEO0FBQ2xELHNDQUFpQztBQUNqQyxrREFBMEU7QUFFMUU7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQWEsY0FBYztJQWFOO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQWpCWixNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUF3QixFQUFFLFdBQXdCLEVBQUUsZ0JBQXdCLEVBQUUsUUFBa0I7UUFDekgsZ0JBQWdCLEdBQUcsZ0JBQWdCLElBQUkseUNBQTBCLENBQUM7UUFFbEUsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5RSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sV0FBVyxDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsRUFBRSxhQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFFekYsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLDBCQUFXLENBQUMsTUFBTSxDQUFDLG1CQUFtQixFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUUxRyxPQUFPLElBQUksY0FBYyxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUUsbUJBQW1CLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDbkgsQ0FBQztJQUVELFlBQ21CLFdBQXdC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RUFBRSxPQUFPLElBQUksMkNBQXlCLENBQUM7QUFDbEcsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBBcnRpZmFjdFR5cGUgfSBmcm9tICdAYXdzLWNkay9jbG91ZC1hc3NlbWJseS1zY2hlbWEnO1xuaW1wb3J0IHR5cGUgeyBFbnZpcm9ubWVudCB9IGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBDbG91ZEFzc2VtYmx5QnVpbGRlciwgRW52aXJvbm1lbnRVdGlscyB9IGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgdHlwZSB7IEJvb3RzdHJhcEVudmlyb25tZW50T3B0aW9ucyB9IGZyb20gJy4vYm9vdHN0cmFwLXByb3BzJztcbmltcG9ydCB7XG4gIEJPT1RTVFJBUF9WQVJJQU5UX1BBUkFNRVRFUixcbiAgQk9PVFNUUkFQX1ZFUlNJT05fT1VUUFVULFxuICBCT09UU1RSQVBfVkVSU0lPTl9SRVNPVVJDRSxcbiAgREVGQVVMVF9CT09UU1RSQVBfVkFSSUFOVCxcbn0gZnJvbSAnLi9ib290c3RyYXAtcHJvcHMnO1xuaW1wb3J0IHR5cGUgeyBTREssIFNka1Byb3ZpZGVyIH0gZnJvbSAnLi4vYXdzLWF1dGgnO1xuaW1wb3J0IHR5cGUgeyBTdWNjZXNzZnVsRGVwbG95U3RhY2tSZXN1bHQgfSBmcm9tICcuLi9kZXBsb3ltZW50cyc7XG5pbXBvcnQgeyBhc3NlcnRJc1N1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdCB9IGZyb20gJy4uL2RlcGxveW1lbnRzJztcbmltcG9ydCB7IGRlcGxveVN0YWNrIH0gZnJvbSAnLi4vZGVwbG95bWVudHMvZGVwbG95LXN0YWNrJztcbmltcG9ydCB7IE5vQm9vdHN0cmFwU3RhY2tFbnZpcm9ubWVudFJlc291cmNlcyB9IGZyb20gJy4uL2Vudmlyb25tZW50JztcbmltcG9ydCB7IElPLCB0eXBlIElvSGVscGVyIH0gZnJvbSAnLi4vaW8vcHJpdmF0ZSc7XG5pbXBvcnQgeyBNb2RlIH0gZnJvbSAnLi4vcGx1Z2luJztcbmltcG9ydCB7IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FLCBUb29sa2l0SW5mbyB9IGZyb20gJy4uL3Rvb2xraXQtaW5mbyc7XG5cbi8qKlxuICogQSBjbGFzcyB0byBob2xkIHN0YXRlIGFyb3VuZCBzdGFjayBib290c3RyYXBwaW5nXG4gKlxuICogVGhpcyBjbGFzcyBleGlzdHMgc28gd2UgY2FuIGJyZWFrIGJvb3RzdHJhcHBpbmcgaW50byAyIHBoYXNlczpcbiAqXG4gKiBgYGB0c1xuICogY29uc3QgY3VycmVudCA9IEJvb3RzdHJhcFN0YWNrLmxvb2t1cCguLi4pO1xuICogLy8gLi4uXG4gKiBjdXJyZW50LnVwZGF0ZShuZXdUZW1wbGF0ZSwgLi4uKTtcbiAqIGBgYFxuICpcbiAqIEFuZCBkbyBzb21ldGhpbmcgaW4gYmV0d2VlbiB0aGUgdHdvIHBoYXNlcyAoc3VjaCBhcyBsb29rIGF0IHRoZVxuICogY3VycmVudCBib290c3RyYXAgc3RhY2sgYW5kIGRvaW5nIHNvbWV0aGluZyBpbnRlbGxpZ2VudCkuXG4gKi9cbmV4cG9ydCBjbGFzcyBCb290c3RyYXBTdGFjayB7XG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgbG9va3VwKHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlciwgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LCB0b29sa2l0U3RhY2tOYW1lOiBzdHJpbmcsIGlvSGVscGVyOiBJb0hlbHBlcikge1xuICAgIHRvb2xraXRTdGFja05hbWUgPSB0b29sa2l0U3RhY2tOYW1lID8/IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FO1xuXG4gICAgY29uc3QgcmVzb2x2ZWRFbnZpcm9ubWVudCA9IGF3YWl0IHNka1Byb3ZpZGVyLnJlc29sdmVFbnZpcm9ubWVudChlbnZpcm9ubWVudCk7XG4gICAgY29uc3Qgc2RrID0gKGF3YWl0IHNka1Byb3ZpZGVyLmZvckVudmlyb25tZW50KHJlc29sdmVkRW52aXJvbm1lbnQsIE1vZGUuRm9yV3JpdGluZykpLnNkaztcblxuICAgIGNvbnN0IGN1cnJlbnRUb29sa2l0SW5mbyA9IGF3YWl0IFRvb2xraXRJbmZvLmxvb2t1cChyZXNvbHZlZEVudmlyb25tZW50LCBzZGssIGlvSGVscGVyLCB0b29sa2l0U3RhY2tOYW1lKTtcblxuICAgIHJldHVybiBuZXcgQm9vdHN0cmFwU3RhY2soc2RrUHJvdmlkZXIsIHNkaywgcmVzb2x2ZWRFbnZpcm9ubWVudCwgdG9vbGtpdFN0YWNrTmFtZSwgY3VycmVudFRvb2xraXRJbmZvLCBpb0hlbHBlcik7XG4gIH1cblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZGtQcm92aWRlcjogU2RrUHJvdmlkZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZGs6IFNESyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlc29sdmVkRW52aXJvbm1lbnQ6IEVudmlyb25tZW50LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY3VycmVudFRvb2xraXRJbmZvOiBUb29sa2l0SW5mbyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGlvSGVscGVyOiBJb0hlbHBlcixcbiAgKSB7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHBhcmFtZXRlcnMoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudFRvb2xraXRJbmZvLmZvdW5kID8gdGhpcy5jdXJyZW50VG9vbGtpdEluZm8uYm9vdHN0cmFwU3RhY2sucGFyYW1ldGVycyA6IHt9O1xuICB9XG5cbiAgcHVibGljIGdldCB0ZXJtaW5hdGlvblByb3RlY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudFRvb2xraXRJbmZvLmZvdW5kID8gdGhpcy5jdXJyZW50VG9vbGtpdEluZm8uYm9vdHN0cmFwU3RhY2sudGVybWluYXRpb25Qcm90ZWN0aW9uIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHBhcnRpdGlvbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5zZGsuY3VycmVudEFjY291bnQoKSkucGFydGl0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gdGhlIGFjdHVhbCBkZXBsb3ltZW50IG9mIGEgYm9vdHN0cmFwIHN0YWNrLCBnaXZlbiBhIHRlbXBsYXRlIGFuZCBzb21lIHBhcmFtZXRlcnNcbiAgICovXG4gIHB1YmxpYyBhc3luYyB1cGRhdGUoXG4gICAgdGVtcGxhdGU6IGFueSxcbiAgICBwYXJhbWV0ZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+LFxuICAgIG9wdGlvbnM6IE9taXQ8Qm9vdHN0cmFwRW52aXJvbm1lbnRPcHRpb25zLCAncGFyYW1ldGVycyc+LFxuICApOiBQcm9taXNlPFN1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdD4ge1xuICAgIGlmICh0aGlzLmN1cnJlbnRUb29sa2l0SW5mby5mb3VuZCAmJiAhb3B0aW9ucy5mb3JjZURlcGxveW1lbnQpIHtcbiAgICAgIC8vIFNhZmV0eSBjaGVja3NcbiAgICAgIGNvbnN0IGFib3J0UmVzcG9uc2UgPSB7XG4gICAgICAgIHR5cGU6ICdkaWQtZGVwbG95LXN0YWNrJyxcbiAgICAgICAgbm9PcDogdHJ1ZSxcbiAgICAgICAgb3V0cHV0czoge30sXG4gICAgICAgIHN0YWNrQXJuOiB0aGlzLmN1cnJlbnRUb29sa2l0SW5mby5ib290c3RyYXBTdGFjay5zdGFja0lkLFxuICAgICAgfSBzYXRpc2ZpZXMgU3VjY2Vzc2Z1bERlcGxveVN0YWNrUmVzdWx0O1xuXG4gICAgICAvLyBWYWxpZGF0ZSB0aGF0IHRoZSBib290c3RyYXAgc3RhY2sgd2UncmUgdHJ5aW5nIHRvIHJlcGxhY2UgaXMgZnJvbSB0aGUgc2FtZSB2YXJpYW50IGFzIHRoZSBvbmUgd2UncmUgdHJ5aW5nIHRvIGRlcGxveVxuICAgICAgY29uc3QgY3VycmVudFZhcmlhbnQgPSB0aGlzLmN1cnJlbnRUb29sa2l0SW5mby52YXJpYW50O1xuICAgICAgY29uc3QgbmV3VmFyaWFudCA9IGJvb3RzdHJhcFZhcmlhbnRGcm9tVGVtcGxhdGUodGVtcGxhdGUpO1xuICAgICAgaWYgKGN1cnJlbnRWYXJpYW50ICE9PSBuZXdWYXJpYW50KSB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9XQVJOLm1zZyhcbiAgICAgICAgICBgQm9vdHN0cmFwIHN0YWNrIGFscmVhZHkgZXhpc3RzLCBjb250YWluaW5nICcke2N1cnJlbnRWYXJpYW50fScuIE5vdCBvdmVyd3JpdGluZyBpdCB3aXRoIGEgdGVtcGxhdGUgY29udGFpbmluZyAnJHtuZXdWYXJpYW50fScgKHVzZSAtLWZvcmNlIGlmIHlvdSBpbnRlbmQgdG8gb3ZlcndyaXRlKWAsXG4gICAgICAgICkpO1xuICAgICAgICByZXR1cm4gYWJvcnRSZXNwb25zZTtcbiAgICAgIH1cblxuICAgICAgLy8gVmFsaWRhdGUgdGhhdCB3ZSdyZSBub3QgZG93bmdyYWRpbmcgdGhlIGJvb3RzdHJhcCBzdGFja1xuICAgICAgY29uc3QgbmV3VmVyc2lvbiA9IGJvb3RzdHJhcFZlcnNpb25Gcm9tVGVtcGxhdGUodGVtcGxhdGUpO1xuICAgICAgY29uc3QgY3VycmVudFZlcnNpb24gPSB0aGlzLmN1cnJlbnRUb29sa2l0SW5mby52ZXJzaW9uO1xuICAgICAgaWYgKG5ld1ZlcnNpb24gPCBjdXJyZW50VmVyc2lvbikge1xuICAgICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfV0FSTi5tc2coXG4gICAgICAgICAgYEJvb3RzdHJhcCBzdGFjayBhbHJlYWR5IGF0IHZlcnNpb24gJHtjdXJyZW50VmVyc2lvbn0uIE5vdCBkb3duZ3JhZGluZyBpdCB0byB2ZXJzaW9uICR7bmV3VmVyc2lvbn0gKHVzZSAtLWZvcmNlIGlmIHlvdSBpbnRlbmQgdG8gZG93bmdyYWRlKWAsXG4gICAgICAgICkpO1xuICAgICAgICBpZiAobmV3VmVyc2lvbiA9PT0gMCkge1xuICAgICAgICAgIC8vIEEgZG93bmdyYWRlIHdpdGggMCBhcyB0YXJnZXQgdmVyc2lvbiBtZWFucyB3ZSBwcm9iYWJseSBoYXZlIGEgbmV3LXN0eWxlIGJvb3RzdHJhcCBpbiB0aGUgYWNjb3VudCxcbiAgICAgICAgICAvLyBhbmQgYW4gb2xkLXN0eWxlIGJvb3RzdHJhcCBhcyBjdXJyZW50IHRhcmdldCwgd2hpY2ggbWVhbnMgdGhlIHVzZXIgcHJvYmFibHkgZm9yZ290IHRvIHB1dCB0aGlzIGZsYWcgaW4uXG4gICAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX1dBUk4ubXNnKFxuICAgICAgICAgICAgXCIoRGlkIHlvdSBzZXQgdGhlICdAYXdzLWNkay9jb3JlOm5ld1N0eWxlU3RhY2tTeW50aGVzaXMnIGZlYXR1cmUgZmxhZyBpbiBjZGsuanNvbj8pXCIsXG4gICAgICAgICAgKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFib3J0UmVzcG9uc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0ZGlyID0gYXdhaXQgZnMubWtkdGVtcChwYXRoLmpvaW4ob3MudG1wZGlyKCksICdjZGstYm9vdHN0cmFwJykpO1xuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgQ2xvdWRBc3NlbWJseUJ1aWxkZXIob3V0ZGlyKTtcbiAgICBjb25zdCB0ZW1wbGF0ZUZpbGUgPSBgJHt0aGlzLnRvb2xraXRTdGFja05hbWV9LnRlbXBsYXRlLmpzb25gO1xuICAgIGF3YWl0IGZzLndyaXRlSnNvbihwYXRoLmpvaW4oYnVpbGRlci5vdXRkaXIsIHRlbXBsYXRlRmlsZSksIHRlbXBsYXRlLCB7XG4gICAgICBzcGFjZXM6IDIsXG4gICAgfSk7XG5cbiAgICBidWlsZGVyLmFkZEFydGlmYWN0KHRoaXMudG9vbGtpdFN0YWNrTmFtZSwge1xuICAgICAgdHlwZTogQXJ0aWZhY3RUeXBlLkFXU19DTE9VREZPUk1BVElPTl9TVEFDSyxcbiAgICAgIGVudmlyb25tZW50OiBFbnZpcm9ubWVudFV0aWxzLmZvcm1hdCh0aGlzLnJlc29sdmVkRW52aXJvbm1lbnQuYWNjb3VudCwgdGhpcy5yZXNvbHZlZEVudmlyb25tZW50LnJlZ2lvbiksXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIHRlbXBsYXRlRmlsZSxcbiAgICAgICAgdGVybWluYXRpb25Qcm90ZWN0aW9uOiBvcHRpb25zLnRlcm1pbmF0aW9uUHJvdGVjdGlvbiA/PyBmYWxzZSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBhc3NlbWJseSA9IGJ1aWxkZXIuYnVpbGRBc3NlbWJseSgpO1xuXG4gICAgY29uc3QgcmV0ID0gYXdhaXQgZGVwbG95U3RhY2soe1xuICAgICAgc3RhY2s6IGFzc2VtYmx5LmdldFN0YWNrQnlOYW1lKHRoaXMudG9vbGtpdFN0YWNrTmFtZSksXG4gICAgICByZXNvbHZlZEVudmlyb25tZW50OiB0aGlzLnJlc29sdmVkRW52aXJvbm1lbnQsXG4gICAgICBzZGs6IHRoaXMuc2RrLFxuICAgICAgc2RrUHJvdmlkZXI6IHRoaXMuc2RrUHJvdmlkZXIsXG4gICAgICBmb3JjZURlcGxveW1lbnQ6IG9wdGlvbnMuZm9yY2VEZXBsb3ltZW50LFxuICAgICAgcm9sZUFybjogb3B0aW9ucy5yb2xlQXJuLFxuICAgICAgdGFnczogb3B0aW9ucy50YWdzLFxuICAgICAgZGVwbG95bWVudE1ldGhvZDogeyBtZXRob2Q6ICdjaGFuZ2Utc2V0JywgZXhlY3V0ZTogb3B0aW9ucy5leGVjdXRlIH0sXG4gICAgICBwYXJhbWV0ZXJzLFxuICAgICAgdXNlUHJldmlvdXNQYXJhbWV0ZXJzOiBvcHRpb25zLnVzZVByZXZpb3VzUGFyYW1ldGVycyA/PyB0cnVlLFxuICAgICAgLy8gT2J2aW91c2x5IHdlIGNhbid0IG5lZWQgYSBib290c3RyYXAgc3RhY2sgdG8gZGVwbG95IGEgYm9vdHN0cmFwIHN0YWNrXG4gICAgICBlbnZSZXNvdXJjZXM6IG5ldyBOb0Jvb3RzdHJhcFN0YWNrRW52aXJvbm1lbnRSZXNvdXJjZXModGhpcy5yZXNvbHZlZEVudmlyb25tZW50LCB0aGlzLnNkaywgdGhpcy5pb0hlbHBlciksXG4gICAgfSwgdGhpcy5pb0hlbHBlcik7XG5cbiAgICBhc3NlcnRJc1N1Y2Nlc3NmdWxEZXBsb3lTdGFja1Jlc3VsdChyZXQpO1xuXG4gICAgcmV0dXJuIHJldDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYm9vdHN0cmFwVmVyc2lvbkZyb21UZW1wbGF0ZSh0ZW1wbGF0ZTogYW55KTogbnVtYmVyIHtcbiAgY29uc3QgdmVyc2lvblNvdXJjZXMgPSBbXG4gICAgdGVtcGxhdGUuT3V0cHV0cz8uW0JPT1RTVFJBUF9WRVJTSU9OX09VVFBVVF0/LlZhbHVlLFxuICAgIHRlbXBsYXRlLlJlc291cmNlcz8uW0JPT1RTVFJBUF9WRVJTSU9OX1JFU09VUkNFXT8uUHJvcGVydGllcz8uVmFsdWUsXG4gIF07XG5cbiAgZm9yIChjb25zdCB2cyBvZiB2ZXJzaW9uU291cmNlcykge1xuICAgIGlmICh0eXBlb2YgdnMgPT09ICdudW1iZXInKSB7XG4gICAgICByZXR1cm4gdnM7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdnMgPT09ICdzdHJpbmcnICYmICFpc05hTihwYXJzZUludCh2cywgMTApKSkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KHZzLCAxMCk7XG4gICAgfVxuICB9XG4gIHJldHVybiAwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYm9vdHN0cmFwVmFyaWFudEZyb21UZW1wbGF0ZSh0ZW1wbGF0ZTogYW55KTogc3RyaW5nIHtcbiAgcmV0dXJuIHRlbXBsYXRlLlBhcmFtZXRlcnM/LltCT09UU1RSQVBfVkFSSUFOVF9QQVJBTUVURVJdPy5EZWZhdWx0ID8/IERFRkFVTFRfQk9PVFNUUkFQX1ZBUklBTlQ7XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.d.ts new file mode 100644 index 000000000..a4f40cbbb --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.d.ts @@ -0,0 +1,3 @@ +export * from './bootstrap-environment'; +export * from './bootstrap-props'; +export { legacyBootstrapTemplate } from './legacy-template'; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.js new file mode 100644 index 000000000..daab97189 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/index.js @@ -0,0 +1,23 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.legacyBootstrapTemplate = void 0; +__exportStar(require("./bootstrap-environment"), exports); +__exportStar(require("./bootstrap-props"), exports); +// testing exports +var legacy_template_1 = require("./legacy-template"); +Object.defineProperty(exports, "legacyBootstrapTemplate", { enumerable: true, get: function () { return legacy_template_1.legacyBootstrapTemplate; } }); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2Jvb3RzdHJhcC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDBEQUF3QztBQUN4QyxvREFBa0M7QUFFbEMsa0JBQWtCO0FBQ2xCLHFEQUE0RDtBQUFuRCwwSEFBQSx1QkFBdUIsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vYm9vdHN0cmFwLWVudmlyb25tZW50JztcbmV4cG9ydCAqIGZyb20gJy4vYm9vdHN0cmFwLXByb3BzJztcblxuLy8gdGVzdGluZyBleHBvcnRzXG5leHBvcnQgeyBsZWdhY3lCb290c3RyYXBUZW1wbGF0ZSB9IGZyb20gJy4vbGVnYWN5LXRlbXBsYXRlJztcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.d.ts new file mode 100644 index 000000000..2aeeb0038 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.d.ts @@ -0,0 +1,2 @@ +import type { BootstrappingParameters } from './bootstrap-props'; +export declare function legacyBootstrapTemplate(params: BootstrappingParameters): any; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.js new file mode 100644 index 000000000..239491537 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/bootstrap/legacy-template.js @@ -0,0 +1,82 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.legacyBootstrapTemplate = legacyBootstrapTemplate; +const bootstrap_props_1 = require("./bootstrap-props"); +function legacyBootstrapTemplate(params) { + return { + Description: 'The CDK Toolkit Stack. It was created by `cdk bootstrap` and manages resources necessary for managing your Cloud Applications with AWS CDK.', + Conditions: { + UsePublicAccessBlockConfiguration: { + 'Fn::Equals': [ + params.publicAccessBlockConfiguration || params.publicAccessBlockConfiguration === undefined ? 'true' : 'false', + 'true', + ], + }, + }, + Resources: { + StagingBucket: { + Type: 'AWS::S3::Bucket', + Properties: { + BucketName: params.bucketName, + AccessControl: 'Private', + BucketEncryption: { + ServerSideEncryptionConfiguration: [{ + ServerSideEncryptionByDefault: { + SSEAlgorithm: 'aws:kms', + KMSMasterKeyID: params.kmsKeyId, + }, + }], + }, + PublicAccessBlockConfiguration: { + 'Fn::If': [ + 'UsePublicAccessBlockConfiguration', + { + BlockPublicAcls: true, + BlockPublicPolicy: true, + IgnorePublicAcls: true, + RestrictPublicBuckets: true, + }, + { Ref: 'AWS::NoValue' }, + ], + }, + }, + }, + StagingBucketPolicy: { + Type: 'AWS::S3::BucketPolicy', + Properties: { + Bucket: { Ref: 'StagingBucket' }, + PolicyDocument: { + Id: 'AccessControl', + Version: '2012-10-17', + Statement: [ + { + Sid: 'AllowSSLRequestsOnly', + Action: 's3:*', + Effect: 'Deny', + Resource: [ + { 'Fn::Sub': '${StagingBucket.Arn}' }, + { 'Fn::Sub': '${StagingBucket.Arn}/*' }, + ], + Condition: { + Bool: { 'aws:SecureTransport': 'false' }, + }, + Principal: '*', + }, + ], + }, + }, + }, + }, + Outputs: { + [bootstrap_props_1.BUCKET_NAME_OUTPUT]: { + Description: 'The name of the S3 bucket owned by the CDK toolkit stack', + Value: { Ref: 'StagingBucket' }, + }, + [bootstrap_props_1.BUCKET_DOMAIN_NAME_OUTPUT]: { + Description: 'The domain name of the S3 bucket owned by the CDK toolkit stack', + Value: { 'Fn::GetAtt': ['StagingBucket', 'RegionalDomainName'] }, + }, + }, + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVnYWN5LXRlbXBsYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9ib290c3RyYXAvbGVnYWN5LXRlbXBsYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBR0EsMERBNEVDO0FBOUVELHVEQUFrRjtBQUVsRixTQUFnQix1QkFBdUIsQ0FBQyxNQUErQjtJQUNyRSxPQUFPO1FBQ0wsV0FBVyxFQUFFLDZJQUE2STtRQUMxSixVQUFVLEVBQUU7WUFDVixpQ0FBaUMsRUFBRTtnQkFDakMsWUFBWSxFQUFFO29CQUNaLE1BQU0sQ0FBQyw4QkFBOEIsSUFBSSxNQUFNLENBQUMsOEJBQThCLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU87b0JBQy9HLE1BQU07aUJBQ1A7YUFDRjtTQUNGO1FBQ0QsU0FBUyxFQUFFO1lBQ1QsYUFBYSxFQUFFO2dCQUNiLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLFVBQVUsRUFBRTtvQkFDVixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7b0JBQzdCLGFBQWEsRUFBRSxTQUFTO29CQUN4QixnQkFBZ0IsRUFBRTt3QkFDaEIsaUNBQWlDLEVBQUUsQ0FBQztnQ0FDbEMsNkJBQTZCLEVBQUU7b0NBQzdCLFlBQVksRUFBRSxTQUFTO29DQUN2QixjQUFjLEVBQUUsTUFBTSxDQUFDLFFBQVE7aUNBQ2hDOzZCQUNGLENBQUM7cUJBQ0g7b0JBQ0QsOEJBQThCLEVBQUU7d0JBQzlCLFFBQVEsRUFBRTs0QkFDUixtQ0FBbUM7NEJBQ25DO2dDQUNFLGVBQWUsRUFBRSxJQUFJO2dDQUNyQixpQkFBaUIsRUFBRSxJQUFJO2dDQUN2QixnQkFBZ0IsRUFBRSxJQUFJO2dDQUN0QixxQkFBcUIsRUFBRSxJQUFJOzZCQUM1Qjs0QkFDRCxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUU7eUJBQ3hCO3FCQUNGO2lCQUNGO2FBQ0Y7WUFDRCxtQkFBbUIsRUFBRTtnQkFDbkIsSUFBSSxFQUFFLHVCQUF1QjtnQkFDN0IsVUFBVSxFQUFFO29CQUNWLE1BQU0sRUFBRSxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUU7b0JBQ2hDLGNBQWMsRUFBRTt3QkFDZCxFQUFFLEVBQUUsZUFBZTt3QkFDbkIsT0FBTyxFQUFFLFlBQVk7d0JBQ3JCLFNBQVMsRUFBRTs0QkFDVDtnQ0FDRSxHQUFHLEVBQUUsc0JBQXNCO2dDQUMzQixNQUFNLEVBQUUsTUFBTTtnQ0FDZCxNQUFNLEVBQUUsTUFBTTtnQ0FDZCxRQUFRLEVBQUU7b0NBQ1IsRUFBRSxTQUFTLEVBQUUsc0JBQXNCLEVBQUU7b0NBQ3JDLEVBQUUsU0FBUyxFQUFFLHdCQUF3QixFQUFFO2lDQUN4QztnQ0FDRCxTQUFTLEVBQUU7b0NBQ1QsSUFBSSxFQUFFLEVBQUUscUJBQXFCLEVBQUUsT0FBTyxFQUFFO2lDQUN6QztnQ0FDRCxTQUFTLEVBQUUsR0FBRzs2QkFDZjt5QkFDRjtxQkFDRjtpQkFDRjthQUNGO1NBQ0Y7UUFDRCxPQUFPLEVBQUU7WUFDUCxDQUFDLG9DQUFrQixDQUFDLEVBQUU7Z0JBQ3BCLFdBQVcsRUFBRSwwREFBMEQ7Z0JBQ3ZFLEtBQUssRUFBRSxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUU7YUFDaEM7WUFDRCxDQUFDLDJDQUF5QixDQUFDLEVBQUU7Z0JBQzNCLFdBQVcsRUFBRSxpRUFBaUU7Z0JBQzlFLEtBQUssRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDLGVBQWUsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFO2FBQ2pFO1NBQ0Y7S0FDRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgQm9vdHN0cmFwcGluZ1BhcmFtZXRlcnMgfSBmcm9tICcuL2Jvb3RzdHJhcC1wcm9wcyc7XG5pbXBvcnQgeyBCVUNLRVRfRE9NQUlOX05BTUVfT1VUUFVULCBCVUNLRVRfTkFNRV9PVVRQVVQgfSBmcm9tICcuL2Jvb3RzdHJhcC1wcm9wcyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBsZWdhY3lCb290c3RyYXBUZW1wbGF0ZShwYXJhbXM6IEJvb3RzdHJhcHBpbmdQYXJhbWV0ZXJzKTogYW55IHtcbiAgcmV0dXJuIHtcbiAgICBEZXNjcmlwdGlvbjogJ1RoZSBDREsgVG9vbGtpdCBTdGFjay4gSXQgd2FzIGNyZWF0ZWQgYnkgYGNkayBib290c3RyYXBgIGFuZCBtYW5hZ2VzIHJlc291cmNlcyBuZWNlc3NhcnkgZm9yIG1hbmFnaW5nIHlvdXIgQ2xvdWQgQXBwbGljYXRpb25zIHdpdGggQVdTIENESy4nLFxuICAgIENvbmRpdGlvbnM6IHtcbiAgICAgIFVzZVB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbjoge1xuICAgICAgICAnRm46OkVxdWFscyc6IFtcbiAgICAgICAgICBwYXJhbXMucHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uIHx8IHBhcmFtcy5wdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb24gPT09IHVuZGVmaW5lZCA/ICd0cnVlJyA6ICdmYWxzZScsXG4gICAgICAgICAgJ3RydWUnLFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICB9LFxuICAgIFJlc291cmNlczoge1xuICAgICAgU3RhZ2luZ0J1Y2tldDoge1xuICAgICAgICBUeXBlOiAnQVdTOjpTMzo6QnVja2V0JyxcbiAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgIEJ1Y2tldE5hbWU6IHBhcmFtcy5idWNrZXROYW1lLFxuICAgICAgICAgIEFjY2Vzc0NvbnRyb2w6ICdQcml2YXRlJyxcbiAgICAgICAgICBCdWNrZXRFbmNyeXB0aW9uOiB7XG4gICAgICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb246IFt7XG4gICAgICAgICAgICAgIFNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0OiB7XG4gICAgICAgICAgICAgICAgU1NFQWxnb3JpdGhtOiAnYXdzOmttcycsXG4gICAgICAgICAgICAgICAgS01TTWFzdGVyS2V5SUQ6IHBhcmFtcy5rbXNLZXlJZCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH1dLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uOiB7XG4gICAgICAgICAgICAnRm46OklmJzogW1xuICAgICAgICAgICAgICAnVXNlUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIEJsb2NrUHVibGljQWNsczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBCbG9ja1B1YmxpY1BvbGljeTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBJZ25vcmVQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgICAgICAgICAgIFJlc3RyaWN0UHVibGljQnVja2V0czogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgeyBSZWY6ICdBV1M6Ok5vVmFsdWUnIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgU3RhZ2luZ0J1Y2tldFBvbGljeToge1xuICAgICAgICBUeXBlOiAnQVdTOjpTMzo6QnVja2V0UG9saWN5JyxcbiAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgIEJ1Y2tldDogeyBSZWY6ICdTdGFnaW5nQnVja2V0JyB9LFxuICAgICAgICAgIFBvbGljeURvY3VtZW50OiB7XG4gICAgICAgICAgICBJZDogJ0FjY2Vzc0NvbnRyb2wnLFxuICAgICAgICAgICAgVmVyc2lvbjogJzIwMTItMTAtMTcnLFxuICAgICAgICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBTaWQ6ICdBbGxvd1NTTFJlcXVlc3RzT25seScsXG4gICAgICAgICAgICAgICAgQWN0aW9uOiAnczM6KicsXG4gICAgICAgICAgICAgICAgRWZmZWN0OiAnRGVueScsXG4gICAgICAgICAgICAgICAgUmVzb3VyY2U6IFtcbiAgICAgICAgICAgICAgICAgIHsgJ0ZuOjpTdWInOiAnJHtTdGFnaW5nQnVja2V0LkFybn0nIH0sXG4gICAgICAgICAgICAgICAgICB7ICdGbjo6U3ViJzogJyR7U3RhZ2luZ0J1Y2tldC5Bcm59LyonIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICBDb25kaXRpb246IHtcbiAgICAgICAgICAgICAgICAgIEJvb2w6IHsgJ2F3czpTZWN1cmVUcmFuc3BvcnQnOiAnZmFsc2UnIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBQcmluY2lwYWw6ICcqJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBPdXRwdXRzOiB7XG4gICAgICBbQlVDS0VUX05BTUVfT1VUUFVUXToge1xuICAgICAgICBEZXNjcmlwdGlvbjogJ1RoZSBuYW1lIG9mIHRoZSBTMyBidWNrZXQgb3duZWQgYnkgdGhlIENESyB0b29sa2l0IHN0YWNrJyxcbiAgICAgICAgVmFsdWU6IHsgUmVmOiAnU3RhZ2luZ0J1Y2tldCcgfSxcbiAgICAgIH0sXG4gICAgICBbQlVDS0VUX0RPTUFJTl9OQU1FX09VVFBVVF06IHtcbiAgICAgICAgRGVzY3JpcHRpb246ICdUaGUgZG9tYWluIG5hbWUgb2YgdGhlIFMzIGJ1Y2tldCBvd25lZCBieSB0aGUgQ0RLIHRvb2xraXQgc3RhY2snLFxuICAgICAgICBWYWx1ZTogeyAnRm46OkdldEF0dCc6IFsnU3RhZ2luZ0J1Y2tldCcsICdSZWdpb25hbERvbWFpbk5hbWUnXSB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.d.ts new file mode 100644 index 000000000..f23e1ffb4 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.d.ts @@ -0,0 +1,43 @@ +import type { SdkProvider } from '../aws-auth'; +import type { Settings } from '../settings'; +/** + * If we don't have region/account defined in context, we fall back to the default SDK behavior + * where region is retrieved from ~/.aws/config and account is based on default credentials provider + * chain and then STS is queried. + * + * This is done opportunistically: for example, if we can't access STS for some reason or the region + * is not configured, the context value will be 'null' and there could failures down the line. In + * some cases, synthesis does not require region/account information at all, so that might be perfectly + * fine in certain scenarios. + * + * @param context The context key/value bash. + */ +export declare function prepareDefaultEnvironment(aws: SdkProvider, debugFn: (msg: string) => Promise): Promise<{ + [key: string]: string; +}>; +/** + * Settings related to synthesis are read from context. + * The merging of various configuration sources like cli args or cdk.json has already happened. + * We now need to set the final values to the context. + */ +export declare function prepareContext(settings: Settings, context: { + [key: string]: any; +}, env: { + [key: string]: string | undefined; +}, debugFn: (msg: string) => Promise): Promise<{ + [key: string]: any; +}>; +export declare function spaceAvailableForContext(env: { + [key: string]: string; +}, limit: number): number; +/** + * Guess the executable from the command-line argument + * + * Only do this if the file is NOT marked as executable. If it is, + * we'll defer to the shebang inside the file itself. + * + * If we're on Windows, we ALWAYS take the handler, since it's hard to + * verify if registry associations have or have not been set up for this + * file type, so we'll assume the worst and take control. + */ +export declare function guessExecutable(app: string, debugFn: (msg: string) => Promise): Promise; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.js new file mode 100644 index 000000000..cff245cff --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/environment.js @@ -0,0 +1,127 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.prepareDefaultEnvironment = prepareDefaultEnvironment; +exports.prepareContext = prepareContext; +exports.spaceAvailableForContext = spaceAvailableForContext; +exports.guessExecutable = guessExecutable; +const path = require("path"); +const util_1 = require("util"); +const cxapi = require("@aws-cdk/cx-api"); +const fs = require("fs-extra"); +/** + * If we don't have region/account defined in context, we fall back to the default SDK behavior + * where region is retrieved from ~/.aws/config and account is based on default credentials provider + * chain and then STS is queried. + * + * This is done opportunistically: for example, if we can't access STS for some reason or the region + * is not configured, the context value will be 'null' and there could failures down the line. In + * some cases, synthesis does not require region/account information at all, so that might be perfectly + * fine in certain scenarios. + * + * @param context The context key/value bash. + */ +async function prepareDefaultEnvironment(aws, debugFn) { + const env = {}; + env[cxapi.DEFAULT_REGION_ENV] = aws.defaultRegion; + await debugFn(`Setting "${cxapi.DEFAULT_REGION_ENV}" environment variable to ${env[cxapi.DEFAULT_REGION_ENV]}`); + const accountId = (await aws.defaultAccount())?.accountId; + if (accountId) { + env[cxapi.DEFAULT_ACCOUNT_ENV] = accountId; + await debugFn(`Setting "${cxapi.DEFAULT_ACCOUNT_ENV}" environment variable to ${env[cxapi.DEFAULT_ACCOUNT_ENV]}`); + } + return env; +} +/** + * Settings related to synthesis are read from context. + * The merging of various configuration sources like cli args or cdk.json has already happened. + * We now need to set the final values to the context. + */ +async function prepareContext(settings, context, env, debugFn) { + const debugMode = settings.get(['debug']) ?? true; + if (debugMode) { + env.CDK_DEBUG = 'true'; + } + const pathMetadata = settings.get(['pathMetadata']) ?? true; + if (pathMetadata) { + context[cxapi.PATH_METADATA_ENABLE_CONTEXT] = true; + } + const assetMetadata = settings.get(['assetMetadata']) ?? true; + if (assetMetadata) { + context[cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT] = true; + } + const versionReporting = settings.get(['versionReporting']) ?? true; + if (versionReporting) { + context[cxapi.ANALYTICS_REPORTING_ENABLED_CONTEXT] = true; + } + // We need to keep on doing this for framework version from before this flag was deprecated. + if (!versionReporting) { + context['aws:cdk:disable-version-reporting'] = true; + } + const stagingEnabled = settings.get(['staging']) ?? true; + if (!stagingEnabled) { + context[cxapi.DISABLE_ASSET_STAGING_CONTEXT] = true; + } + const bundlingStacks = settings.get(['bundlingStacks']) ?? ['**']; + context[cxapi.BUNDLING_STACKS] = bundlingStacks; + await debugFn((0, util_1.format)('context:', context)); + return context; +} +function spaceAvailableForContext(env, limit) { + const size = (value) => value != null ? Buffer.byteLength(value) : 0; + const usedSpace = Object.entries(env) + .map(([k, v]) => k === cxapi.CONTEXT_ENV ? size(k) : size(k) + size(v)) + .reduce((a, b) => a + b, 0); + return Math.max(0, limit - usedSpace); +} +/** + * Guess the executable from the command-line argument + * + * Only do this if the file is NOT marked as executable. If it is, + * we'll defer to the shebang inside the file itself. + * + * If we're on Windows, we ALWAYS take the handler, since it's hard to + * verify if registry associations have or have not been set up for this + * file type, so we'll assume the worst and take control. + */ +async function guessExecutable(app, debugFn) { + const commandLine = appToArray(app); + if (commandLine.length === 1) { + let fstat; + try { + fstat = await fs.stat(commandLine[0]); + } + catch { + await debugFn(`Not a file: '${commandLine[0]}'. Using '${commandLine}' as command-line`); + return commandLine; + } + // eslint-disable-next-line no-bitwise + const isExecutable = (fstat.mode & fs.constants.X_OK) !== 0; + const isWindows = process.platform === 'win32'; + const handler = EXTENSION_MAP.get(path.extname(commandLine[0])); + if (handler && (!isExecutable || isWindows)) { + return handler(commandLine[0]); + } + } + return commandLine; +} +/** + * Mapping of extensions to command-line generators + */ +const EXTENSION_MAP = new Map([ + ['.js', executeNode], +]); +/** + * Execute the given file with the same 'node' process as is running the current process + */ +function executeNode(scriptFile) { + return [process.execPath, scriptFile]; +} +/** + * Make sure the 'app' is an array + * + * If it's a string, split on spaces as a trivial way of tokenizing the command line. + */ +function appToArray(app) { + return typeof app === 'string' ? app.split(' ') : app; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52aXJvbm1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2Nsb3VkLWFzc2VtYmx5L2Vudmlyb25tZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBbUJBLDhEQWdCQztBQU9ELHdDQXlDQztBQUVELDREQVFDO0FBWUQsMENBc0JDO0FBL0hELDZCQUE2QjtBQUM3QiwrQkFBOEI7QUFDOUIseUNBQXlDO0FBQ3pDLCtCQUErQjtBQUkvQjs7Ozs7Ozs7Ozs7R0FXRztBQUNJLEtBQUssVUFBVSx5QkFBeUIsQ0FDN0MsR0FBZ0IsRUFDaEIsT0FBdUM7SUFFdkMsTUFBTSxHQUFHLEdBQThCLEVBQUcsQ0FBQztJQUUzQyxHQUFHLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQztJQUNsRCxNQUFNLE9BQU8sQ0FBQyxZQUFZLEtBQUssQ0FBQyxrQkFBa0IsNkJBQTZCLEdBQUcsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFaEgsTUFBTSxTQUFTLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxFQUFFLFNBQVMsQ0FBQztJQUMxRCxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQ2QsR0FBRyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLFNBQVMsQ0FBQztRQUMzQyxNQUFNLE9BQU8sQ0FBQyxZQUFZLEtBQUssQ0FBQyxtQkFBbUIsNkJBQTZCLEdBQUcsQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDcEgsQ0FBQztJQUVELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUsY0FBYyxDQUNsQyxRQUFrQixFQUNsQixPQUE2QixFQUM3QixHQUF5QyxFQUN6QyxPQUF1QztJQUV2QyxNQUFNLFNBQVMsR0FBWSxRQUFRLENBQUMsR0FB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QUNILFNBQVMsVUFBVSxDQUFDLEdBQVE7SUFDMUIsT0FBTyxPQUFPLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztBQUN4RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGZvcm1hdCB9IGZyb20gJ3V0aWwnO1xuaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB0eXBlIHsgU2RrUHJvdmlkZXIgfSBmcm9tICcuLi9hd3MtYXV0aCc7XG5pbXBvcnQgdHlwZSB7IFNldHRpbmdzIH0gZnJvbSAnLi4vc2V0dGluZ3MnO1xuXG4vKipcbiAqIElmIHdlIGRvbid0IGhhdmUgcmVnaW9uL2FjY291bnQgZGVmaW5lZCBpbiBjb250ZXh0LCB3ZSBmYWxsIGJhY2sgdG8gdGhlIGRlZmF1bHQgU0RLIGJlaGF2aW9yXG4gKiB3aGVyZSByZWdpb24gaXMgcmV0cmlldmVkIGZyb20gfi8uYXdzL2NvbmZpZyBhbmQgYWNjb3VudCBpcyBiYXNlZCBvbiBkZWZhdWx0IGNyZWRlbnRpYWxzIHByb3ZpZGVyXG4gKiBjaGFpbiBhbmQgdGhlbiBTVFMgaXMgcXVlcmllZC5cbiAqXG4gKiBUaGlzIGlzIGRvbmUgb3Bwb3J0dW5pc3RpY2FsbHk6IGZvciBleGFtcGxlLCBpZiB3ZSBjYW4ndCBhY2Nlc3MgU1RTIGZvciBzb21lIHJlYXNvbiBvciB0aGUgcmVnaW9uXG4gKiBpcyBub3QgY29uZmlndXJlZCwgdGhlIGNvbnRleHQgdmFsdWUgd2lsbCBiZSAnbnVsbCcgYW5kIHRoZXJlIGNvdWxkIGZhaWx1cmVzIGRvd24gdGhlIGxpbmUuIEluXG4gKiBzb21lIGNhc2VzLCBzeW50aGVzaXMgZG9lcyBub3QgcmVxdWlyZSByZWdpb24vYWNjb3VudCBpbmZvcm1hdGlvbiBhdCBhbGwsIHNvIHRoYXQgbWlnaHQgYmUgcGVyZmVjdGx5XG4gKiBmaW5lIGluIGNlcnRhaW4gc2NlbmFyaW9zLlxuICpcbiAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IGtleS92YWx1ZSBiYXNoLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJlcGFyZURlZmF1bHRFbnZpcm9ubWVudChcbiAgYXdzOiBTZGtQcm92aWRlcixcbiAgZGVidWdGbjogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTx7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9PiB7XG4gIGNvbnN0IGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHsgfTtcblxuICBlbnZbY3hhcGkuREVGQVVMVF9SRUdJT05fRU5WXSA9IGF3cy5kZWZhdWx0UmVnaW9uO1xuICBhd2FpdCBkZWJ1Z0ZuKGBTZXR0aW5nIFwiJHtjeGFwaS5ERUZBVUxUX1JFR0lPTl9FTlZ9XCIgZW52aXJvbm1lbnQgdmFyaWFibGUgdG8gJHtlbnZbY3hhcGkuREVGQVVMVF9SRUdJT05fRU5WXX1gKTtcblxuICBjb25zdCBhY2NvdW50SWQgPSAoYXdhaXQgYXdzLmRlZmF1bHRBY2NvdW50KCkpPy5hY2NvdW50SWQ7XG4gIGlmIChhY2NvdW50SWQpIHtcbiAgICBlbnZbY3hhcGkuREVGQVVMVF9BQ0NPVU5UX0VOVl0gPSBhY2NvdW50SWQ7XG4gICAgYXdhaXQgZGVidWdGbihgU2V0dGluZyBcIiR7Y3hhcGkuREVGQVVMVF9BQ0NPVU5UX0VOVn1cIiBlbnZpcm9ubWVudCB2YXJpYWJsZSB0byAke2VudltjeGFwaS5ERUZBVUxUX0FDQ09VTlRfRU5WXX1gKTtcbiAgfVxuXG4gIHJldHVybiBlbnY7XG59XG5cbi8qKlxuICogU2V0dGluZ3MgcmVsYXRlZCB0byBzeW50aGVzaXMgYXJlIHJlYWQgZnJvbSBjb250ZXh0LlxuICogVGhlIG1lcmdpbmcgb2YgdmFyaW91cyBjb25maWd1cmF0aW9uIHNvdXJjZXMgbGlrZSBjbGkgYXJncyBvciBjZGsuanNvbiBoYXMgYWxyZWFkeSBoYXBwZW5lZC5cbiAqIFdlIG5vdyBuZWVkIHRvIHNldCB0aGUgZmluYWwgdmFsdWVzIHRvIHRoZSBjb250ZXh0LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJlcGFyZUNvbnRleHQoXG4gIHNldHRpbmdzOiBTZXR0aW5ncyxcbiAgY29udGV4dDoge1trZXk6IHN0cmluZ106IGFueX0sXG4gIGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCB1bmRlZmluZWR9LFxuICBkZWJ1Z0ZuOiAobXNnOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4sXG4pIHtcbiAgY29uc3QgZGVidWdNb2RlOiBib29sZWFuID0gc2V0dGluZ3MuZ2V0KFsnZGVidWcnXSkgPz8gdHJ1ZTtcbiAgaWYgKGRlYnVnTW9kZSkge1xuICAgIGVudi5DREtfREVCVUcgPSAndHJ1ZSc7XG4gIH1cblxuICBjb25zdCBwYXRoTWV0YWRhdGE6IGJvb2xlYW4gPSBzZXR0aW5ncy5nZXQoWydwYXRoTWV0YWRhdGEnXSkgPz8gdHJ1ZTtcbiAgaWYgKHBhdGhNZXRhZGF0YSkge1xuICAgIGNvbnRleHRbY3hhcGkuUEFUSF9NRVRBREFUQV9FTkFCTEVfQ09OVEVYVF0gPSB0cnVlO1xuICB9XG5cbiAgY29uc3QgYXNzZXRNZXRhZGF0YTogYm9vbGVhbiA9IHNldHRpbmdzLmdldChbJ2Fzc2V0TWV0YWRhdGEnXSkgPz8gdHJ1ZTtcbiAgaWYgKGFzc2V0TWV0YWRhdGEpIHtcbiAgICBjb250ZXh0W2N4YXBpLkFTU0VUX1JFU09VUkNFX01FVEFEQVRBX0VOQUJMRURfQ09OVEVYVF0gPSB0cnVlO1xuICB9XG5cbiAgY29uc3QgdmVyc2lvblJlcG9ydGluZzogYm9vbGVhbiA9IHNldHRpbmdzLmdldChbJ3ZlcnNpb25SZXBvcnRpbmcnXSkgPz8gdHJ1ZTtcbiAgaWYgKHZlcnNpb25SZXBvcnRpbmcpIHtcbiAgICBjb250ZXh0W2N4YXBpLkFOQUxZVElDU19SRVBPUlRJTkdfRU5BQkxFRF9DT05URVhUXSA9IHRydWU7XG4gIH1cbiAgLy8gV2UgbmVlZCB0byBrZWVwIG9uIGRvaW5nIHRoaXMgZm9yIGZyYW1ld29yayB2ZXJzaW9uIGZyb20gYmVmb3JlIHRoaXMgZmxhZyB3YXMgZGVwcmVjYXRlZC5cbiAgaWYgKCF2ZXJzaW9uUmVwb3J0aW5nKSB7XG4gICAgY29udGV4dFsnYXdzOmNkazpkaXNhYmxlLXZlcnNpb24tcmVwb3J0aW5nJ10gPSB0cnVlO1xuICB9XG5cbiAgY29uc3Qgc3RhZ2luZ0VuYWJsZWQgPSBzZXR0aW5ncy5nZXQoWydzdGFnaW5nJ10pID8/IHRydWU7XG4gIGlmICghc3RhZ2luZ0VuYWJsZWQpIHtcbiAgICBjb250ZXh0W2N4YXBpLkRJU0FCTEVfQVNTRVRfU1RBR0lOR19DT05URVhUXSA9IHRydWU7XG4gIH1cblxuICBjb25zdCBidW5kbGluZ1N0YWNrcyA9IHNldHRpbmdzLmdldChbJ2J1bmRsaW5nU3RhY2tzJ10pID8/IFsnKionXTtcbiAgY29udGV4dFtjeGFwaS5CVU5ETElOR19TVEFDS1NdID0gYnVuZGxpbmdTdGFja3M7XG5cbiAgYXdhaXQgZGVidWdGbihmb3JtYXQoJ2NvbnRleHQ6JywgY29udGV4dCkpO1xuXG4gIHJldHVybiBjb250ZXh0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3BhY2VBdmFpbGFibGVGb3JDb250ZXh0KGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSwgbGltaXQ6IG51bWJlcikge1xuICBjb25zdCBzaXplID0gKHZhbHVlOiBzdHJpbmcpID0+IHZhbHVlICE9IG51bGwgPyBCdWZmZXIuYnl0ZUxlbmd0aCh2YWx1ZSkgOiAwO1xuXG4gIGNvbnN0IHVzZWRTcGFjZSA9IE9iamVjdC5lbnRyaWVzKGVudilcbiAgICAubWFwKChbaywgdl0pID0+IGsgPT09IGN4YXBpLkNPTlRFWFRfRU5WID8gc2l6ZShrKSA6IHNpemUoaykgKyBzaXplKHYpKVxuICAgIC5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcblxuICByZXR1cm4gTWF0aC5tYXgoMCwgbGltaXQgLSB1c2VkU3BhY2UpO1xufVxuXG4vKipcbiAqIEd1ZXNzIHRoZSBleGVjdXRhYmxlIGZyb20gdGhlIGNvbW1hbmQtbGluZSBhcmd1bWVudFxuICpcbiAqIE9ubHkgZG8gdGhpcyBpZiB0aGUgZmlsZSBpcyBOT1QgbWFya2VkIGFzIGV4ZWN1dGFibGUuIElmIGl0IGlzLFxuICogd2UnbGwgZGVmZXIgdG8gdGhlIHNoZWJhbmcgaW5zaWRlIHRoZSBmaWxlIGl0c2VsZi5cbiAqXG4gKiBJZiB3ZSdyZSBvbiBXaW5kb3dzLCB3ZSBBTFdBWVMgdGFrZSB0aGUgaGFuZGxlciwgc2luY2UgaXQncyBoYXJkIHRvXG4gKiB2ZXJpZnkgaWYgcmVnaXN0cnkgYXNzb2NpYXRpb25zIGhhdmUgb3IgaGF2ZSBub3QgYmVlbiBzZXQgdXAgZm9yIHRoaXNcbiAqIGZpbGUgdHlwZSwgc28gd2UnbGwgYXNzdW1lIHRoZSB3b3JzdCBhbmQgdGFrZSBjb250cm9sLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ3Vlc3NFeGVjdXRhYmxlKGFwcDogc3RyaW5nLCBkZWJ1Z0ZuOiAobXNnOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgY29uc3QgY29tbWFuZExpbmUgPSBhcHBUb0FycmF5KGFwcCk7XG4gIGlmIChjb21tYW5kTGluZS5sZW5ndGggPT09IDEpIHtcbiAgICBsZXQgZnN0YXQ7XG5cbiAgICB0cnkge1xuICAgICAgZnN0YXQgPSBhd2FpdCBmcy5zdGF0KGNvbW1hbmRMaW5lWzBdKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGF3YWl0IGRlYnVnRm4oYE5vdCBhIGZpbGU6ICcke2NvbW1hbmRMaW5lWzBdfScuIFVzaW5nICcke2NvbW1hbmRMaW5lfScgYXMgY29tbWFuZC1saW5lYCk7XG4gICAgICByZXR1cm4gY29tbWFuZExpbmU7XG4gICAgfVxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICBjb25zdCBpc0V4ZWN1dGFibGUgPSAoZnN0YXQubW9kZSAmIGZzLmNvbnN0YW50cy5YX09LKSAhPT0gMDtcbiAgICBjb25zdCBpc1dpbmRvd3MgPSBwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInO1xuXG4gICAgY29uc3QgaGFuZGxlciA9IEVYVEVOU0lPTl9NQVAuZ2V0KHBhdGguZXh0bmFtZShjb21tYW5kTGluZVswXSkpO1xuICAgIGlmIChoYW5kbGVyICYmICghaXNFeGVjdXRhYmxlIHx8IGlzV2luZG93cykpIHtcbiAgICAgIHJldHVybiBoYW5kbGVyKGNvbW1hbmRMaW5lWzBdKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNvbW1hbmRMaW5lO1xufVxuXG4vKipcbiAqIE1hcHBpbmcgb2YgZXh0ZW5zaW9ucyB0byBjb21tYW5kLWxpbmUgZ2VuZXJhdG9yc1xuICovXG5jb25zdCBFWFRFTlNJT05fTUFQID0gbmV3IE1hcDxzdHJpbmcsIENvbW1hbmRHZW5lcmF0b3I+KFtcbiAgWycuanMnLCBleGVjdXRlTm9kZV0sXG5dKTtcblxudHlwZSBDb21tYW5kR2VuZXJhdG9yID0gKGZpbGU6IHN0cmluZykgPT4gc3RyaW5nW107XG5cbi8qKlxuICogRXhlY3V0ZSB0aGUgZ2l2ZW4gZmlsZSB3aXRoIHRoZSBzYW1lICdub2RlJyBwcm9jZXNzIGFzIGlzIHJ1bm5pbmcgdGhlIGN1cnJlbnQgcHJvY2Vzc1xuICovXG5mdW5jdGlvbiBleGVjdXRlTm9kZShzY3JpcHRGaWxlOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbcHJvY2Vzcy5leGVjUGF0aCwgc2NyaXB0RmlsZV07XG59XG5cbi8qKlxuICogTWFrZSBzdXJlIHRoZSAnYXBwJyBpcyBhbiBhcnJheVxuICpcbiAqIElmIGl0J3MgYSBzdHJpbmcsIHNwbGl0IG9uIHNwYWNlcyBhcyBhIHRyaXZpYWwgd2F5IG9mIHRva2VuaXppbmcgdGhlIGNvbW1hbmQgbGluZS5cbiAqL1xuZnVuY3Rpb24gYXBwVG9BcnJheShhcHA6IGFueSkge1xuICByZXR1cm4gdHlwZW9mIGFwcCA9PT0gJ3N0cmluZycgPyBhcHAuc3BsaXQoJyAnKSA6IGFwcDtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.d.ts new file mode 100644 index 000000000..7ed5f6288 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.d.ts @@ -0,0 +1,4 @@ +export * from './environment'; +export * from './stack-assembly'; +export * from './stack-collection'; +export * from './stack-selector'; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.js new file mode 100644 index 000000000..f002d6fc7 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/index.js @@ -0,0 +1,21 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./environment"), exports); +__exportStar(require("./stack-assembly"), exports); +__exportStar(require("./stack-collection"), exports); +__exportStar(require("./stack-selector"), exports); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2Nsb3VkLWFzc2VtYmx5L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxnREFBOEI7QUFDOUIsbURBQWlDO0FBQ2pDLHFEQUFtQztBQUNuQyxtREFBaUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2Vudmlyb25tZW50JztcbmV4cG9ydCAqIGZyb20gJy4vc3RhY2stYXNzZW1ibHknO1xuZXhwb3J0ICogZnJvbSAnLi9zdGFjay1jb2xsZWN0aW9uJztcbmV4cG9ydCAqIGZyb20gJy4vc3RhY2stc2VsZWN0b3InO1xuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.d.ts new file mode 100644 index 000000000..8ac4814de --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.d.ts @@ -0,0 +1,55 @@ +import type * as cxapi from '@aws-cdk/cx-api'; +import { StackCollection } from './stack-collection'; +import type { IoHelper } from '../io/private/io-helper'; +export interface IStackAssembly { + /** + * The directory this CloudAssembly was read from + */ + directory: string; + /** + * Select a single stack by its ID + */ + stackById(stackId: string): StackCollection; +} +/** + * When selecting stacks, what other stacks to include because of dependencies + */ +export declare enum ExtendedStackSelection { + /** + * Don't select any extra stacks + */ + None = 0, + /** + * Include stacks that this stack depends on + */ + Upstream = 1, + /** + * Include stacks that depend on this stack + */ + Downstream = 2 +} +/** + * A single Cloud Assembly and the operations we do on it to deploy the artifacts inside + */ +export declare abstract class BaseStackAssembly implements IStackAssembly { + readonly assembly: cxapi.CloudAssembly; + /** + * Sanitize a list of stack match patterns + */ + protected static sanitizePatterns(patterns: string[]): string[]; + /** + * The directory this CloudAssembly was read from + */ + readonly directory: string; + /** + * The IoHelper used for messaging + */ + protected readonly ioHelper: IoHelper; + constructor(assembly: cxapi.CloudAssembly, ioHelper: IoHelper); + /** + * Select a single stack by its ID + */ + stackById(stackId: string): StackCollection; + protected selectMatchingStacks(stacks: cxapi.CloudFormationStackArtifact[], patterns: string[], extend?: ExtendedStackSelection): Promise; + protected extendStacks(matched: cxapi.CloudFormationStackArtifact[], all: cxapi.CloudFormationStackArtifact[], extend?: ExtendedStackSelection): Promise; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.js new file mode 100644 index 000000000..12c74c393 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-assembly.js @@ -0,0 +1,139 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseStackAssembly = exports.ExtendedStackSelection = void 0; +const chalk = require("chalk"); +const minimatch_1 = require("minimatch"); +const stack_collection_1 = require("./stack-collection"); +const util_1 = require("../../util"); +const private_1 = require("../io/private"); +/** + * When selecting stacks, what other stacks to include because of dependencies + */ +var ExtendedStackSelection; +(function (ExtendedStackSelection) { + /** + * Don't select any extra stacks + */ + ExtendedStackSelection[ExtendedStackSelection["None"] = 0] = "None"; + /** + * Include stacks that this stack depends on + */ + ExtendedStackSelection[ExtendedStackSelection["Upstream"] = 1] = "Upstream"; + /** + * Include stacks that depend on this stack + */ + ExtendedStackSelection[ExtendedStackSelection["Downstream"] = 2] = "Downstream"; +})(ExtendedStackSelection || (exports.ExtendedStackSelection = ExtendedStackSelection = {})); +/** + * A single Cloud Assembly and the operations we do on it to deploy the artifacts inside + */ +class BaseStackAssembly { + assembly; + /** + * Sanitize a list of stack match patterns + */ + static sanitizePatterns(patterns) { + let sanitized = patterns.filter(s => s != null); // filter null/undefined + sanitized = [...new Set(sanitized)]; // make them unique + return sanitized; + } + /** + * The directory this CloudAssembly was read from + */ + directory; + /** + * The IoHelper used for messaging + */ + ioHelper; + constructor(assembly, ioHelper) { + this.assembly = assembly; + this.directory = assembly.directory; + this.ioHelper = ioHelper; + } + /** + * Select a single stack by its ID + */ + stackById(stackId) { + return new stack_collection_1.StackCollection(this, [this.assembly.getStackArtifact(stackId)]); + } + async selectMatchingStacks(stacks, patterns, extend = ExtendedStackSelection.None) { + const matchingPattern = (pattern) => (stack) => (0, minimatch_1.minimatch)(stack.hierarchicalId, pattern); + const matchedStacks = (0, util_1.flatten)(patterns.map(pattern => stacks.filter(matchingPattern(pattern)))); + return this.extendStacks(matchedStacks, stacks, extend); + } + async extendStacks(matched, all, extend = ExtendedStackSelection.None) { + const allStacks = new Map(); + for (const stack of all) { + allStacks.set(stack.hierarchicalId, stack); + } + const index = indexByHierarchicalId(matched); + switch (extend) { + case ExtendedStackSelection.Downstream: + await includeDownstreamStacks(this.ioHelper, index, allStacks); + break; + case ExtendedStackSelection.Upstream: + await includeUpstreamStacks(this.ioHelper, index, allStacks); + break; + } + // Filter original array because it is in the right order + const selectedList = all.filter(s => index.has(s.hierarchicalId)); + return new stack_collection_1.StackCollection(this, selectedList); + } +} +exports.BaseStackAssembly = BaseStackAssembly; +function indexByHierarchicalId(stacks) { + const result = new Map(); + for (const stack of stacks) { + result.set(stack.hierarchicalId, stack); + } + return result; +} +/** + * Calculate the transitive closure of stack dependents. + * + * Modifies `selectedStacks` in-place. + */ +async function includeDownstreamStacks(ioHelper, selectedStacks, allStacks) { + const added = new Array(); + let madeProgress; + do { + madeProgress = false; + for (const [id, stack] of allStacks) { + // Select this stack if it's not selected yet AND it depends on a stack that's in the selected set + if (!selectedStacks.has(id) && (stack.dependencies || []).some(dep => selectedStacks.has(dep.id))) { + selectedStacks.set(id, stack); + added.push(id); + madeProgress = true; + } + } + } while (madeProgress); + if (added.length > 0) { + await ioHelper.notify(private_1.IO.DEFAULT_ASSEMBLY_INFO.msg(`Including depending stacks: ${chalk.bold(added.join(', '))}`)); + } +} +/** + * Calculate the transitive closure of stack dependencies. + * + * Modifies `selectedStacks` in-place. + */ +async function includeUpstreamStacks(ioHelper, selectedStacks, allStacks) { + const added = new Array(); + let madeProgress = true; + while (madeProgress) { + madeProgress = false; + for (const stack of selectedStacks.values()) { + // Select an additional stack if it's not selected yet and a dependency of a selected stack (and exists, obviously) + for (const dependencyId of stack.dependencies.map(x => x.manifest.displayName ?? x.id)) { + if (!selectedStacks.has(dependencyId) && allStacks.has(dependencyId)) { + added.push(dependencyId); + selectedStacks.set(dependencyId, allStacks.get(dependencyId)); + madeProgress = true; + } + } + } + } + if (added.length > 0) { + await ioHelper.notify(private_1.IO.DEFAULT_ASSEMBLY_INFO.msg(`Including dependency stacks: ${chalk.bold(added.join(', '))}`)); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stYXNzZW1ibHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2Nsb3VkLWFzc2VtYmx5L3N0YWNrLWFzc2VtYmx5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLCtCQUErQjtBQUMvQix5Q0FBc0M7QUFDdEMseURBQXFEO0FBQ3JELHFDQUFxQztBQUNyQywyQ0FBbUM7QUFlbkM7O0dBRUc7QUFDSCxJQUFZLHNCQWVYO0FBZkQsV0FBWSxzQkFBc0I7SUFDaEM7O09BRUc7SUFDSCxtRUFBSSxDQUFBO0lBRUo7O09BRUc7SUFDSCwyRUFBUSxDQUFBO0lBRVI7O09BRUc7SUFDSCwrRUFBVSxDQUFBO0FBQ1osQ0FBQyxFQWZXLHNCQUFzQixzQ0FBdEIsc0JBQXNCLFFBZWpDO0FBRUQ7O0dBRUc7QUFDSCxNQUFzQixpQkFBaUI7SUFvQlQ7SUFuQjVCOztPQUVHO0lBQ08sTUFBTSxDQUFDLGdCQUFnQixDQUFDLFFBQWtCO1FBQ2xELElBQUksU0FBUyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7UUFDekUsU0FBUyxHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CO1FBQ3hELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7T0FFRztJQUNhLFNBQVMsQ0FBUztJQUVsQzs7T0FFRztJQUNnQixRQUFRLENBQVc7SUFFdEMsWUFBNEIsUUFBNkIsRUFBRSxRQUFrQjtRQUFqRCxhQUFRLEdBQVIsUUFBUSxDQUFxQjtRQUN2RCxJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDcEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDM0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ksU0FBUyxDQUFDLE9BQWU7UUFD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QyxZQUFZLENBQUMsSUFBSSxTQUFTLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7b0JBQ3JFLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQ3pCLGNBQWMsQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFFLENBQUMsQ0FBQztvQkFDL0QsWUFBWSxHQUFHLElBQUksQ0FBQztnQkFDdEIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNyQixNQUFNLFFBQVEsQ0FBQyxNQUFNLENBQUMsWUFBRSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxnQ0FBZ0MsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEgsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgKiBhcyBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQgeyBtaW5pbWF0Y2ggfSBmcm9tICdtaW5pbWF0Y2gnO1xuaW1wb3J0IHsgU3RhY2tDb2xsZWN0aW9uIH0gZnJvbSAnLi9zdGFjay1jb2xsZWN0aW9uJztcbmltcG9ydCB7IGZsYXR0ZW4gfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IElPIH0gZnJvbSAnLi4vaW8vcHJpdmF0ZSc7XG5pbXBvcnQgdHlwZSB7IElvSGVscGVyIH0gZnJvbSAnLi4vaW8vcHJpdmF0ZS9pby1oZWxwZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIElTdGFja0Fzc2VtYmx5IHtcbiAgLyoqXG4gICAqIFRoZSBkaXJlY3RvcnkgdGhpcyBDbG91ZEFzc2VtYmx5IHdhcyByZWFkIGZyb21cbiAgICovXG4gIGRpcmVjdG9yeTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTZWxlY3QgYSBzaW5nbGUgc3RhY2sgYnkgaXRzIElEXG4gICAqL1xuICBzdGFja0J5SWQoc3RhY2tJZDogc3RyaW5nKTogU3RhY2tDb2xsZWN0aW9uO1xufVxuXG4vKipcbiAqIFdoZW4gc2VsZWN0aW5nIHN0YWNrcywgd2hhdCBvdGhlciBzdGFja3MgdG8gaW5jbHVkZSBiZWNhdXNlIG9mIGRlcGVuZGVuY2llc1xuICovXG5leHBvcnQgZW51bSBFeHRlbmRlZFN0YWNrU2VsZWN0aW9uIHtcbiAgLyoqXG4gICAqIERvbid0IHNlbGVjdCBhbnkgZXh0cmEgc3RhY2tzXG4gICAqL1xuICBOb25lLFxuXG4gIC8qKlxuICAgKiBJbmNsdWRlIHN0YWNrcyB0aGF0IHRoaXMgc3RhY2sgZGVwZW5kcyBvblxuICAgKi9cbiAgVXBzdHJlYW0sXG5cbiAgLyoqXG4gICAqIEluY2x1ZGUgc3RhY2tzIHRoYXQgZGVwZW5kIG9uIHRoaXMgc3RhY2tcbiAgICovXG4gIERvd25zdHJlYW0sXG59XG5cbi8qKlxuICogQSBzaW5nbGUgQ2xvdWQgQXNzZW1ibHkgYW5kIHRoZSBvcGVyYXRpb25zIHdlIGRvIG9uIGl0IHRvIGRlcGxveSB0aGUgYXJ0aWZhY3RzIGluc2lkZVxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZVN0YWNrQXNzZW1ibHkgaW1wbGVtZW50cyBJU3RhY2tBc3NlbWJseSB7XG4gIC8qKlxuICAgKiBTYW5pdGl6ZSBhIGxpc3Qgb2Ygc3RhY2sgbWF0Y2ggcGF0dGVybnNcbiAgICovXG4gIHByb3RlY3RlZCBzdGF0aWMgc2FuaXRpemVQYXR0ZXJucyhwYXR0ZXJuczogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gICAgbGV0IHNhbml0aXplZCA9IHBhdHRlcm5zLmZpbHRlcihzID0+IHMgIT0gbnVsbCk7IC8vIGZpbHRlciBudWxsL3VuZGVmaW5lZFxuICAgIHNhbml0aXplZCA9IFsuLi5uZXcgU2V0KHNhbml0aXplZCldOyAvLyBtYWtlIHRoZW0gdW5pcXVlXG4gICAgcmV0dXJuIHNhbml0aXplZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgZGlyZWN0b3J5IHRoaXMgQ2xvdWRBc3NlbWJseSB3YXMgcmVhZCBmcm9tXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZGlyZWN0b3J5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBJb0hlbHBlciB1c2VkIGZvciBtZXNzYWdpbmdcbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSBpb0hlbHBlcjogSW9IZWxwZXI7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IGFzc2VtYmx5OiBjeGFwaS5DbG91ZEFzc2VtYmx5LCBpb0hlbHBlcjogSW9IZWxwZXIpIHtcbiAgICB0aGlzLmRpcmVjdG9yeSA9IGFzc2VtYmx5LmRpcmVjdG9yeTtcbiAgICB0aGlzLmlvSGVscGVyID0gaW9IZWxwZXI7XG4gIH1cblxuICAvKipcbiAgICogU2VsZWN0IGEgc2luZ2xlIHN0YWNrIGJ5IGl0cyBJRFxuICAgKi9cbiAgcHVibGljIHN0YWNrQnlJZChzdGFja0lkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IFN0YWNrQ29sbGVjdGlvbih0aGlzLCBbdGhpcy5hc3NlbWJseS5nZXRTdGFja0FydGlmYWN0KHN0YWNrSWQpXSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgc2VsZWN0TWF0Y2hpbmdTdGFja3MoXG4gICAgc3RhY2tzOiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RbXSxcbiAgICBwYXR0ZXJuczogc3RyaW5nW10sXG4gICAgZXh0ZW5kOiBFeHRlbmRlZFN0YWNrU2VsZWN0aW9uID0gRXh0ZW5kZWRTdGFja1NlbGVjdGlvbi5Ob25lLFxuICApOiBQcm9taXNlPFN0YWNrQ29sbGVjdGlvbj4ge1xuICAgIGNvbnN0IG1hdGNoaW5nUGF0dGVybiA9IChwYXR0ZXJuOiBzdHJpbmcpID0+IChzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0KSA9PiBtaW5pbWF0Y2goc3RhY2suaGllcmFyY2hpY2FsSWQsIHBhdHRlcm4pO1xuICAgIGNvbnN0IG1hdGNoZWRTdGFja3MgPSBmbGF0dGVuKHBhdHRlcm5zLm1hcChwYXR0ZXJuID0+IHN0YWNrcy5maWx0ZXIobWF0Y2hpbmdQYXR0ZXJuKHBhdHRlcm4pKSkpO1xuXG4gICAgcmV0dXJuIHRoaXMuZXh0ZW5kU3RhY2tzKG1hdGNoZWRTdGFja3MsIHN0YWNrcywgZXh0ZW5kKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBleHRlbmRTdGFja3MoXG4gICAgbWF0Y2hlZDogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0W10sXG4gICAgYWxsOiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RbXSxcbiAgICBleHRlbmQ6IEV4dGVuZGVkU3RhY2tTZWxlY3Rpb24gPSBFeHRlbmRlZFN0YWNrU2VsZWN0aW9uLk5vbmUsXG4gICkge1xuICAgIGNvbnN0IGFsbFN0YWNrcyA9IG5ldyBNYXA8c3RyaW5nLCBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3Q+KCk7XG4gICAgZm9yIChjb25zdCBzdGFjayBvZiBhbGwpIHtcbiAgICAgIGFsbFN0YWNrcy5zZXQoc3RhY2suaGllcmFyY2hpY2FsSWQsIHN0YWNrKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbmRleCA9IGluZGV4QnlIaWVyYXJjaGljYWxJZChtYXRjaGVkKTtcblxuICAgIHN3aXRjaCAoZXh0ZW5kKSB7XG4gICAgICBjYXNlIEV4dGVuZGVkU3RhY2tTZWxlY3Rpb24uRG93bnN0cmVhbTpcbiAgICAgICAgYXdhaXQgaW5jbHVkZURvd25zdHJlYW1TdGFja3ModGhpcy5pb0hlbHBlciwgaW5kZXgsIGFsbFN0YWNrcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBFeHRlbmRlZFN0YWNrU2VsZWN0aW9uLlVwc3RyZWFtOlxuICAgICAgICBhd2FpdCBpbmNsdWRlVXBzdHJlYW1TdGFja3ModGhpcy5pb0hlbHBlciwgaW5kZXgsIGFsbFN0YWNrcyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8vIEZpbHRlciBvcmlnaW5hbCBhcnJheSBiZWNhdXNlIGl0IGlzIGluIHRoZSByaWdodCBvcmRlclxuICAgIGNvbnN0IHNlbGVjdGVkTGlzdCA9IGFsbC5maWx0ZXIocyA9PiBpbmRleC5oYXMocy5oaWVyYXJjaGljYWxJZCkpO1xuXG4gICAgcmV0dXJuIG5ldyBTdGFja0NvbGxlY3Rpb24odGhpcywgc2VsZWN0ZWRMaXN0KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbmRleEJ5SGllcmFyY2hpY2FsSWQoc3RhY2tzOiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RbXSk6IE1hcDxzdHJpbmcsIGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdD4ge1xuICBjb25zdCByZXN1bHQgPSBuZXcgTWFwPHN0cmluZywgY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0PigpO1xuXG4gIGZvciAoY29uc3Qgc3RhY2sgb2Ygc3RhY2tzKSB7XG4gICAgcmVzdWx0LnNldChzdGFjay5oaWVyYXJjaGljYWxJZCwgc3RhY2spO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIHRyYW5zaXRpdmUgY2xvc3VyZSBvZiBzdGFjayBkZXBlbmRlbnRzLlxuICpcbiAqIE1vZGlmaWVzIGBzZWxlY3RlZFN0YWNrc2AgaW4tcGxhY2UuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluY2x1ZGVEb3duc3RyZWFtU3RhY2tzKFxuICBpb0hlbHBlcjogSW9IZWxwZXIsXG4gIHNlbGVjdGVkU3RhY2tzOiBNYXA8c3RyaW5nLCBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3Q+LFxuICBhbGxTdGFja3M6IE1hcDxzdHJpbmcsIGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdD4sXG4pIHtcbiAgY29uc3QgYWRkZWQgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuXG4gIGxldCBtYWRlUHJvZ3Jlc3M7XG4gIGRvIHtcbiAgICBtYWRlUHJvZ3Jlc3MgPSBmYWxzZTtcblxuICAgIGZvciAoY29uc3QgW2lkLCBzdGFja10gb2YgYWxsU3RhY2tzKSB7XG4gICAgICAvLyBTZWxlY3QgdGhpcyBzdGFjayBpZiBpdCdzIG5vdCBzZWxlY3RlZCB5ZXQgQU5EIGl0IGRlcGVuZHMgb24gYSBzdGFjayB0aGF0J3MgaW4gdGhlIHNlbGVjdGVkIHNldFxuICAgICAgaWYgKCFzZWxlY3RlZFN0YWNrcy5oYXMoaWQpICYmIChzdGFjay5kZXBlbmRlbmNpZXMgfHwgW10pLnNvbWUoZGVwID0+IHNlbGVjdGVkU3RhY2tzLmhhcyhkZXAuaWQpKSkge1xuICAgICAgICBzZWxlY3RlZFN0YWNrcy5zZXQoaWQsIHN0YWNrKTtcbiAgICAgICAgYWRkZWQucHVzaChpZCk7XG4gICAgICAgIG1hZGVQcm9ncmVzcyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9IHdoaWxlIChtYWRlUHJvZ3Jlc3MpO1xuXG4gIGlmIChhZGRlZC5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfQVNTRU1CTFlfSU5GTy5tc2coYEluY2x1ZGluZyBkZXBlbmRpbmcgc3RhY2tzOiAke2NoYWxrLmJvbGQoYWRkZWQuam9pbignLCAnKSl9YCkpO1xuICB9XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSB0cmFuc2l0aXZlIGNsb3N1cmUgb2Ygc3RhY2sgZGVwZW5kZW5jaWVzLlxuICpcbiAqIE1vZGlmaWVzIGBzZWxlY3RlZFN0YWNrc2AgaW4tcGxhY2UuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluY2x1ZGVVcHN0cmVhbVN0YWNrcyhcbiAgaW9IZWxwZXI6IElvSGVscGVyLFxuICBzZWxlY3RlZFN0YWNrczogTWFwPHN0cmluZywgY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0PixcbiAgYWxsU3RhY2tzOiBNYXA8c3RyaW5nLCBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3Q+LFxuKSB7XG4gIGNvbnN0IGFkZGVkID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgbGV0IG1hZGVQcm9ncmVzcyA9IHRydWU7XG4gIHdoaWxlIChtYWRlUHJvZ3Jlc3MpIHtcbiAgICBtYWRlUHJvZ3Jlc3MgPSBmYWxzZTtcblxuICAgIGZvciAoY29uc3Qgc3RhY2sgb2Ygc2VsZWN0ZWRTdGFja3MudmFsdWVzKCkpIHtcbiAgICAgIC8vIFNlbGVjdCBhbiBhZGRpdGlvbmFsIHN0YWNrIGlmIGl0J3Mgbm90IHNlbGVjdGVkIHlldCBhbmQgYSBkZXBlbmRlbmN5IG9mIGEgc2VsZWN0ZWQgc3RhY2sgKGFuZCBleGlzdHMsIG9idmlvdXNseSlcbiAgICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeUlkIG9mIHN0YWNrLmRlcGVuZGVuY2llcy5tYXAoeCA9PiB4Lm1hbmlmZXN0LmRpc3BsYXlOYW1lID8/IHguaWQpKSB7XG4gICAgICAgIGlmICghc2VsZWN0ZWRTdGFja3MuaGFzKGRlcGVuZGVuY3lJZCkgJiYgYWxsU3RhY2tzLmhhcyhkZXBlbmRlbmN5SWQpKSB7XG4gICAgICAgICAgYWRkZWQucHVzaChkZXBlbmRlbmN5SWQpO1xuICAgICAgICAgIHNlbGVjdGVkU3RhY2tzLnNldChkZXBlbmRlbmN5SWQsIGFsbFN0YWNrcy5nZXQoZGVwZW5kZW5jeUlkKSEpO1xuICAgICAgICAgIG1hZGVQcm9ncmVzcyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAoYWRkZWQubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IGlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX0FTU0VNQkxZX0lORk8ubXNnKGBJbmNsdWRpbmcgZGVwZW5kZW5jeSBzdGFja3M6ICR7Y2hhbGsuYm9sZChhZGRlZC5qb2luKCcsICcpKX1gKSk7XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.d.ts new file mode 100644 index 000000000..fd65fff87 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.d.ts @@ -0,0 +1,27 @@ +import type * as cxapi from '@aws-cdk/cx-api'; +import type { IStackAssembly } from './stack-assembly'; +import { type StackDetails } from '../../payloads/stack-details'; +/** + * A collection of stacks and related artifacts + * + * In practice, not all artifacts in the CloudAssembly are created equal; + * stacks can be selected independently, but other artifacts such as asset + * bundles cannot. + */ +export declare class StackCollection { + readonly assembly: IStackAssembly; + readonly stackArtifacts: cxapi.CloudFormationStackArtifact[]; + constructor(assembly: IStackAssembly, stackArtifacts: cxapi.CloudFormationStackArtifact[]); + get stackCount(): number; + get firstStack(): cxapi.CloudFormationStackArtifact; + get stackIds(): string[]; + get hierarchicalIds(): string[]; + withDependencies(): StackDetails[]; + reversed(): StackCollection; + filter(predicate: (art: cxapi.CloudFormationStackArtifact) => boolean): StackCollection; + concat(...others: StackCollection[]): StackCollection; + /** + * Extracts 'aws:cdk:warning|info|error' metadata entries from the stack synthesis + */ + validateMetadata(failAt?: 'warn' | 'error' | 'none', logger?: (level: 'info' | 'error' | 'warn', msg: cxapi.SynthesisMessage) => Promise): Promise; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.js new file mode 100644 index 000000000..915dfeecd --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-collection.js @@ -0,0 +1,112 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StackCollection = void 0; +const cx_api_1 = require("@aws-cdk/cx-api"); +const toolkit_error_1 = require("../toolkit-error"); +/** + * A collection of stacks and related artifacts + * + * In practice, not all artifacts in the CloudAssembly are created equal; + * stacks can be selected independently, but other artifacts such as asset + * bundles cannot. + */ +class StackCollection { + assembly; + stackArtifacts; + constructor(assembly, stackArtifacts) { + this.assembly = assembly; + this.stackArtifacts = stackArtifacts; + } + get stackCount() { + return this.stackArtifacts.length; + } + get firstStack() { + if (this.stackCount < 1) { + throw new toolkit_error_1.ToolkitError('StackCollection contains no stack artifacts (trying to access the first one)'); + } + return this.stackArtifacts[0]; + } + get stackIds() { + return this.stackArtifacts.map(s => s.id); + } + get hierarchicalIds() { + return this.stackArtifacts.map(s => s.hierarchicalId); + } + withDependencies() { + const allData = []; + for (const stack of this.stackArtifacts) { + const data = { + id: stack.displayName ?? stack.id, + name: stack.stackName, + environment: stack.environment, + dependencies: [], + }; + for (const dependencyId of stack.dependencies.map(x => x.id)) { + if (dependencyId.includes('.assets')) { + continue; + } + const depStack = this.assembly.stackById(dependencyId); + if (depStack.firstStack.dependencies.filter((dep) => !(dep.id).includes('.assets')).length > 0) { + for (const stackDetail of depStack.withDependencies()) { + data.dependencies.push({ + id: stackDetail.id, + dependencies: stackDetail.dependencies, + }); + } + } + else { + data.dependencies.push({ + id: depStack.firstStack.displayName ?? depStack.firstStack.id, + dependencies: [], + }); + } + } + allData.push(data); + } + return allData; + } + reversed() { + const arts = [...this.stackArtifacts]; + arts.reverse(); + return new StackCollection(this.assembly, arts); + } + filter(predicate) { + return new StackCollection(this.assembly, this.stackArtifacts.filter(predicate)); + } + concat(...others) { + return new StackCollection(this.assembly, this.stackArtifacts.concat(...others.map(o => o.stackArtifacts))); + } + /** + * Extracts 'aws:cdk:warning|info|error' metadata entries from the stack synthesis + */ + async validateMetadata(failAt = 'error', logger = async () => { + }) { + let warnings = false; + let errors = false; + for (const stack of this.stackArtifacts) { + for (const message of stack.messages) { + switch (message.level) { + case cx_api_1.SynthesisMessageLevel.WARNING: + warnings = true; + await logger('warn', message); + break; + case cx_api_1.SynthesisMessageLevel.ERROR: + errors = true; + await logger('error', message); + break; + case cx_api_1.SynthesisMessageLevel.INFO: + await logger('info', message); + break; + } + } + } + if (errors && failAt != 'none') { + throw toolkit_error_1.AssemblyError.withStacks('Found errors', this.stackArtifacts); + } + if (warnings && failAt === 'warn') { + throw toolkit_error_1.AssemblyError.withStacks('Found warnings (--strict mode)', this.stackArtifacts); + } + } +} +exports.StackCollection = StackCollection; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvY2xvdWQtYXNzZW1ibHkvc3RhY2stY29sbGVjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSw0Q0FBd0Q7QUFDeEQsb0RBQStEO0FBSS9EOzs7Ozs7R0FNRztBQUNILE1BQWEsZUFBZTtJQUNFO0lBQTBDO0lBQXRFLFlBQTRCLFFBQXdCLEVBQWtCLGNBQW1EO1FBQTdGLGFBQVEsR0FBUixRQUFRLENBQWdCO1FBQWtCLG1CQUFjLEdBQWQsY0FBYyxDQUFxQztJQUN6SCxDQUFDO0lBRUQsSUFBVyxVQUFVO1FBQ25CLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUM7SUFDcEMsQ0FBQztJQUVELElBQVcsVUFBVTtRQUNuQixJQUFJLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDeEIsTUFBTSxJQUFJLDRCQUFZLENBQUMsOEVBQThFLENBQUMsQ0FBQztRQUN6RyxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRCxJQUFXLFFBQVE7UUFDakIsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsSUFBVyxlQUFlO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVNLGdCQUFnQjtRQUNyQixNQUFNLE9BQU8sR0FBbUIsRUFBRSxDQUFDO1FBRW5DLEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxHQUFpQjtnQkFDekIs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QUssOEJBQXFCLENBQUMsT0FBTzt3QkFDaEMsUUFBUSxHQUFHLElBQUksQ0FBQzt3QkFDaEIsTUFBTSxNQUFNLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO3dCQUM5QixNQUFNO29CQUNSLEtBQUssOEJBQXFCLENBQUMsS0FBSzt3QkFDOUIsTUFBTSxHQUFHLElBQUksQ0FBQzt3QkFDZCxNQUFNLE1BQU0sQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7d0JBQy9CLE1BQU07b0JBQ1IsS0FBSyw4QkFBcUIsQ0FBQyxJQUFJO3dCQUM3QixNQUFNLE1BQU0sQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7d0JBQzlCLE1BQU07Z0JBQ1YsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxNQUFNLElBQUksTUFBTSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQy9CLE1BQU0sNkJBQWEsQ0FBQyxVQUFVLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN0RSxDQUFDO1FBRUQsSUFBSSxRQUFRLElBQUksTUFBTSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ2xDLE1BQU0sNkJBQWEsQ0FBQyxVQUFVLENBQUMsZ0NBQWdDLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3hGLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFqSEQsMENBaUhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgU3ludGhlc2lzTWVzc2FnZUxldmVsIH0gZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCB7IEFzc2VtYmx5RXJyb3IsIFRvb2xraXRFcnJvciB9IGZyb20gJy4uL3Rvb2xraXQtZXJyb3InO1xuaW1wb3J0IHR5cGUgeyBJU3RhY2tBc3NlbWJseSB9IGZyb20gJy4vc3RhY2stYXNzZW1ibHknO1xuaW1wb3J0IHsgdHlwZSBTdGFja0RldGFpbHMgfSBmcm9tICcuLi8uLi9wYXlsb2Fkcy9zdGFjay1kZXRhaWxzJztcblxuLyoqXG4gKiBBIGNvbGxlY3Rpb24gb2Ygc3RhY2tzIGFuZCByZWxhdGVkIGFydGlmYWN0c1xuICpcbiAqIEluIHByYWN0aWNlLCBub3QgYWxsIGFydGlmYWN0cyBpbiB0aGUgQ2xvdWRBc3NlbWJseSBhcmUgY3JlYXRlZCBlcXVhbDtcbiAqIHN0YWNrcyBjYW4gYmUgc2VsZWN0ZWQgaW5kZXBlbmRlbnRseSwgYnV0IG90aGVyIGFydGlmYWN0cyBzdWNoIGFzIGFzc2V0XG4gKiBidW5kbGVzIGNhbm5vdC5cbiAqL1xuZXhwb3J0IGNsYXNzIFN0YWNrQ29sbGVjdGlvbiB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBhc3NlbWJseTogSVN0YWNrQXNzZW1ibHksIHB1YmxpYyByZWFkb25seSBzdGFja0FydGlmYWN0czogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0W10pIHtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc3RhY2tDb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja0FydGlmYWN0cy5sZW5ndGg7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGZpcnN0U3RhY2soKSB7XG4gICAgaWYgKHRoaXMuc3RhY2tDb3VudCA8IDEpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ1N0YWNrQ29sbGVjdGlvbiBjb250YWlucyBubyBzdGFjayBhcnRpZmFjdHMgKHRyeWluZyB0byBhY2Nlc3MgdGhlIGZpcnN0IG9uZSknKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3RhY2tBcnRpZmFjdHNbMF07XG4gIH1cblxuICBwdWJsaWMgZ2V0IHN0YWNrSWRzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja0FydGlmYWN0cy5tYXAocyA9PiBzLmlkKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaGllcmFyY2hpY2FsSWRzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5zdGFja0FydGlmYWN0cy5tYXAocyA9PiBzLmhpZXJhcmNoaWNhbElkKTtcbiAgfVxuXG4gIHB1YmxpYyB3aXRoRGVwZW5kZW5jaWVzKCk6IFN0YWNrRGV0YWlsc1tdIHtcbiAgICBjb25zdCBhbGxEYXRhOiBTdGFja0RldGFpbHNbXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBzdGFjayBvZiB0aGlzLnN0YWNrQXJ0aWZhY3RzKSB7XG4gICAgICBjb25zdCBkYXRhOiBTdGFja0RldGFpbHMgPSB7XG4gICAgICAgIGlkOiBzdGFjay5kaXNwbGF5TmFtZSA/PyBzdGFjay5pZCxcbiAgICAgICAgbmFtZTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgICBlbnZpcm9ubWVudDogc3RhY2suZW52aXJvbm1lbnQsXG4gICAgICAgIGRlcGVuZGVuY2llczogW10sXG4gICAgICB9O1xuXG4gICAgICBmb3IgKGNvbnN0IGRlcGVuZGVuY3lJZCBvZiBzdGFjay5kZXBlbmRlbmNpZXMubWFwKHggPT4geC5pZCkpIHtcbiAgICAgICAgaWYgKGRlcGVuZGVuY3lJZC5pbmNsdWRlcygnLmFzc2V0cycpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkZXBTdGFjayA9IHRoaXMuYXNzZW1ibHkuc3RhY2tCeUlkKGRlcGVuZGVuY3lJZCk7XG5cbiAgICAgICAgaWYgKGRlcFN0YWNrLmZpcnN0U3RhY2suZGVwZW5kZW5jaWVzLmZpbHRlcigoZGVwKSA9PiAhKGRlcC5pZCkuaW5jbHVkZXMoJy5hc3NldHMnKSkubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGZvciAoY29uc3Qgc3RhY2tEZXRhaWwgb2YgZGVwU3RhY2sud2l0aERlcGVuZGVuY2llcygpKSB7XG4gICAgICAgICAgICBkYXRhLmRlcGVuZGVuY2llcy5wdXNoKHtcbiAgICAgICAgICAgICAgaWQ6IHN0YWNrRGV0YWlsLmlkLFxuICAgICAgICAgICAgICBkZXBlbmRlbmNpZXM6IHN0YWNrRGV0YWlsLmRlcGVuZGVuY2llcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkYXRhLmRlcGVuZGVuY2llcy5wdXNoKHtcbiAgICAgICAgICAgIGlkOiBkZXBTdGFjay5maXJzdFN0YWNrLmRpc3BsYXlOYW1lID8/IGRlcFN0YWNrLmZpcnN0U3RhY2suaWQsXG4gICAgICAgICAgICBkZXBlbmRlbmNpZXM6IFtdLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGFsbERhdGEucHVzaChkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYWxsRGF0YTtcbiAgfVxuXG4gIHB1YmxpYyByZXZlcnNlZCgpIHtcbiAgICBjb25zdCBhcnRzID0gWy4uLnRoaXMuc3RhY2tBcnRpZmFjdHNdO1xuICAgIGFydHMucmV2ZXJzZSgpO1xuICAgIHJldHVybiBuZXcgU3RhY2tDb2xsZWN0aW9uKHRoaXMuYXNzZW1ibHksIGFydHMpO1xuICB9XG5cbiAgcHVibGljIGZpbHRlcihwcmVkaWNhdGU6IChhcnQ6IGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCkgPT4gYm9vbGVhbik6IFN0YWNrQ29sbGVjdGlvbiB7XG4gICAgcmV0dXJuIG5ldyBTdGFja0NvbGxlY3Rpb24odGhpcy5hc3NlbWJseSwgdGhpcy5zdGFja0FydGlmYWN0cy5maWx0ZXIocHJlZGljYXRlKSk7XG4gIH1cblxuICBwdWJsaWMgY29uY2F0KC4uLm90aGVyczogU3RhY2tDb2xsZWN0aW9uW10pOiBTdGFja0NvbGxlY3Rpb24ge1xuICAgIHJldHVybiBuZXcgU3RhY2tDb2xsZWN0aW9uKHRoaXMuYXNzZW1ibHksIHRoaXMuc3RhY2tBcnRpZmFjdHMuY29uY2F0KC4uLm90aGVycy5tYXAobyA9PiBvLnN0YWNrQXJ0aWZhY3RzKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhY3RzICdhd3M6Y2RrOndhcm5pbmd8aW5mb3xlcnJvcicgbWV0YWRhdGEgZW50cmllcyBmcm9tIHRoZSBzdGFjayBzeW50aGVzaXNcbiAgICovXG4gIHB1YmxpYyBhc3luYyB2YWxpZGF0ZU1ldGFkYXRhKFxuICAgIGZhaWxBdDogJ3dhcm4nIHwgJ2Vycm9yJyB8ICdub25lJyA9ICdlcnJvcicsXG4gICAgbG9nZ2VyOiAobGV2ZWw6ICdpbmZvJyB8ICdlcnJvcicgfCAnd2FybicsIG1zZzogY3hhcGkuU3ludGhlc2lzTWVzc2FnZSkgPT4gUHJvbWlzZTx2b2lkPiA9IGFzeW5jICgpID0+IHtcbiAgICB9LFxuICApIHtcbiAgICBsZXQgd2FybmluZ3MgPSBmYWxzZTtcbiAgICBsZXQgZXJyb3JzID0gZmFsc2U7XG5cbiAgICBmb3IgKGNvbnN0IHN0YWNrIG9mIHRoaXMuc3RhY2tBcnRpZmFjdHMpIHtcbiAgICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiBzdGFjay5tZXNzYWdlcykge1xuICAgICAgICBzd2l0Y2ggKG1lc3NhZ2UubGV2ZWwpIHtcbiAgICAgICAgICBjYXNlIFN5bnRoZXNpc01lc3NhZ2VMZXZlbC5XQVJOSU5HOlxuICAgICAgICAgICAgd2FybmluZ3MgPSB0cnVlO1xuICAgICAgICAgICAgYXdhaXQgbG9nZ2VyKCd3YXJuJywgbWVzc2FnZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIFN5bnRoZXNpc01lc3NhZ2VMZXZlbC5FUlJPUjpcbiAgICAgICAgICAgIGVycm9ycyA9IHRydWU7XG4gICAgICAgICAgICBhd2FpdCBsb2dnZXIoJ2Vycm9yJywgbWVzc2FnZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIFN5bnRoZXNpc01lc3NhZ2VMZXZlbC5JTkZPOlxuICAgICAgICAgICAgYXdhaXQgbG9nZ2VyKCdpbmZvJywgbWVzc2FnZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlcnJvcnMgJiYgZmFpbEF0ICE9ICdub25lJykge1xuICAgICAgdGhyb3cgQXNzZW1ibHlFcnJvci53aXRoU3RhY2tzKCdGb3VuZCBlcnJvcnMnLCB0aGlzLnN0YWNrQXJ0aWZhY3RzKTtcbiAgICB9XG5cbiAgICBpZiAod2FybmluZ3MgJiYgZmFpbEF0ID09PSAnd2FybicpIHtcbiAgICAgIHRocm93IEFzc2VtYmx5RXJyb3Iud2l0aFN0YWNrcygnRm91bmQgd2FybmluZ3MgKC0tc3RyaWN0IG1vZGUpJywgdGhpcy5zdGFja0FydGlmYWN0cyk7XG4gICAgfVxuICB9XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.d.ts new file mode 100644 index 000000000..d6be0fad6 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.d.ts @@ -0,0 +1,81 @@ +/** + * Which stacks should be selected from a cloud assembly + */ +export declare enum StackSelectionStrategy { + /** + * Returns all stacks in the app regardless of patterns, + * including stacks inside nested assemblies. + */ + ALL_STACKS = "all-stacks", + /** + * Returns all stacks in the main (top level) assembly only. + */ + MAIN_ASSEMBLY = "main-assembly", + /** + * If the assembly includes a single stack, returns it. + * Otherwise throws an exception. + */ + ONLY_SINGLE = "only-single", + /** + * Return stacks matched by patterns. + * If no stacks are found, execution is halted successfully. + * Most likely you don't want to use this but `StackSelectionStrategy.MUST_MATCH_PATTERN` + */ + PATTERN_MATCH = "pattern-match", + /** + * Return stacks matched by patterns. + * Throws an exception if the patterns don't match at least one stack in the assembly. + */ + PATTERN_MUST_MATCH = "pattern-must-match", + /** + * Returns if exactly one stack is matched by the pattern(s). + * Throws an exception if no stack, or more than exactly one stack are matched. + */ + PATTERN_MUST_MATCH_SINGLE = "pattern-must-match-single" +} +/** + * When selecting stacks, what other stacks to include because of dependencies + */ +export declare enum ExpandStackSelection { + /** + * Don't select any extra stacks + */ + NONE = "none", + /** + * Include stacks that this stack depends on + */ + UPSTREAM = "upstream", + /** + * Include stacks that depend on this stack + */ + DOWNSTREAM = "downstream" +} +/** + * A specification of which stacks should be selected + */ +export interface StackSelector { + /** + * The behavior if if no selectors are provided. + */ + strategy: StackSelectionStrategy; + /** + * A list of patterns to match the stack hierarchical ids + * Only used with `PATTERN_*` selection strategies. + */ + patterns?: string[]; + /** + * Expand the selection to upstream/downstream stacks. + * @default ExpandStackSelection.None only select the specified/matched stacks + */ + expand?: ExpandStackSelection; + /** + * By default, we throw an exception if the assembly contains no stacks. + * Set to `false`, to halt execution for empty assemblies without error. + * + * Note that actions can still throw if a stack selection result is empty, + * but the assembly contains stacks in principle. + * + * @default true + */ + failOnEmpty?: boolean; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.js new file mode 100644 index 000000000..b3083e976 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloud-assembly/stack-selector.js @@ -0,0 +1,64 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ExpandStackSelection = exports.StackSelectionStrategy = void 0; +/** + * Which stacks should be selected from a cloud assembly + */ +var StackSelectionStrategy; +(function (StackSelectionStrategy) { + /** + * Returns all stacks in the app regardless of patterns, + * including stacks inside nested assemblies. + */ + StackSelectionStrategy["ALL_STACKS"] = "all-stacks"; + /** + * Returns all stacks in the main (top level) assembly only. + */ + StackSelectionStrategy["MAIN_ASSEMBLY"] = "main-assembly"; + /** + * If the assembly includes a single stack, returns it. + * Otherwise throws an exception. + */ + StackSelectionStrategy["ONLY_SINGLE"] = "only-single"; + /** + * Return stacks matched by patterns. + * If no stacks are found, execution is halted successfully. + * Most likely you don't want to use this but `StackSelectionStrategy.MUST_MATCH_PATTERN` + */ + StackSelectionStrategy["PATTERN_MATCH"] = "pattern-match"; + /** + * Return stacks matched by patterns. + * Throws an exception if the patterns don't match at least one stack in the assembly. + */ + StackSelectionStrategy["PATTERN_MUST_MATCH"] = "pattern-must-match"; + /** + * Returns if exactly one stack is matched by the pattern(s). + * Throws an exception if no stack, or more than exactly one stack are matched. + */ + StackSelectionStrategy["PATTERN_MUST_MATCH_SINGLE"] = "pattern-must-match-single"; +})(StackSelectionStrategy || (exports.StackSelectionStrategy = StackSelectionStrategy = {})); +/** + * When selecting stacks, what other stacks to include because of dependencies + */ +var ExpandStackSelection; +(function (ExpandStackSelection) { + /** + * Don't select any extra stacks + */ + ExpandStackSelection["NONE"] = "none"; + /** + * Include stacks that this stack depends on + */ + ExpandStackSelection["UPSTREAM"] = "upstream"; + /** + * Include stacks that depend on this stack + */ + ExpandStackSelection["DOWNSTREAM"] = "downstream"; + /** + * @TODO + * Include both directions. + * I.e. stacks that this stack depends on, and stacks that depend on this stack. + */ + // FULL = 'full', +})(ExpandStackSelection || (exports.ExpandStackSelection = ExpandStackSelection = {})); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stc2VsZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2Nsb3VkLWFzc2VtYmx5L3N0YWNrLXNlbGVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOztHQUVHO0FBQ0gsSUFBWSxzQkFvQ1g7QUFwQ0QsV0FBWSxzQkFBc0I7SUFDaEM7OztPQUdHO0lBQ0gsbURBQXlCLENBQUE7SUFFekI7O09BRUc7SUFDSCx5REFBK0IsQ0FBQTtJQUUvQjs7O09BR0c7SUFDSCxxREFBMkIsQ0FBQTtJQUUzQjs7OztPQUlHO0lBQ0gseURBQStCLENBQUE7SUFFL0I7OztPQUdHO0lBQ0gsbUVBQXlDLENBQUE7SUFFekM7OztPQUdHO0lBQ0gsaUZBQXVELENBQUE7QUFDekQsQ0FBQyxFQXBDVyxzQkFBc0Isc0NBQXRCLHNCQUFzQixRQW9DakM7QUFFRDs7R0FFRztBQUNILElBQVksb0JBc0JYO0FBdEJELFdBQVksb0JBQW9CO0lBQzlCOztPQUVHO0lBQ0gscUNBQWEsQ0FBQTtJQUViOztPQUVHO0lBQ0gsNkNBQXFCLENBQUE7SUFFckI7O09BRUc7SUFDSCxpREFBeUIsQ0FBQTtJQUV6Qjs7OztPQUlHO0lBQ0gsaUJBQWlCO0FBQ25CLENBQUMsRUF0Qlcsb0JBQW9CLG9DQUFwQixvQkFBb0IsUUFzQi9CIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXaGljaCBzdGFja3Mgc2hvdWxkIGJlIHNlbGVjdGVkIGZyb20gYSBjbG91ZCBhc3NlbWJseVxuICovXG5leHBvcnQgZW51bSBTdGFja1NlbGVjdGlvblN0cmF0ZWd5IHtcbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIHN0YWNrcyBpbiB0aGUgYXBwIHJlZ2FyZGxlc3Mgb2YgcGF0dGVybnMsXG4gICAqIGluY2x1ZGluZyBzdGFja3MgaW5zaWRlIG5lc3RlZCBhc3NlbWJsaWVzLlxuICAgKi9cbiAgQUxMX1NUQUNLUyA9ICdhbGwtc3RhY2tzJyxcblxuICAvKipcbiAgICogUmV0dXJucyBhbGwgc3RhY2tzIGluIHRoZSBtYWluICh0b3AgbGV2ZWwpIGFzc2VtYmx5IG9ubHkuXG4gICAqL1xuICBNQUlOX0FTU0VNQkxZID0gJ21haW4tYXNzZW1ibHknLFxuXG4gIC8qKlxuICAgKiBJZiB0aGUgYXNzZW1ibHkgaW5jbHVkZXMgYSBzaW5nbGUgc3RhY2ssIHJldHVybnMgaXQuXG4gICAqIE90aGVyd2lzZSB0aHJvd3MgYW4gZXhjZXB0aW9uLlxuICAgKi9cbiAgT05MWV9TSU5HTEUgPSAnb25seS1zaW5nbGUnLFxuXG4gIC8qKlxuICAgKiBSZXR1cm4gc3RhY2tzIG1hdGNoZWQgYnkgcGF0dGVybnMuXG4gICAqIElmIG5vIHN0YWNrcyBhcmUgZm91bmQsIGV4ZWN1dGlvbiBpcyBoYWx0ZWQgc3VjY2Vzc2Z1bGx5LlxuICAgKiBNb3N0IGxpa2VseSB5b3UgZG9uJ3Qgd2FudCB0byB1c2UgdGhpcyBidXQgYFN0YWNrU2VsZWN0aW9uU3RyYXRlZ3kuTVVTVF9NQVRDSF9QQVRURVJOYFxuICAgKi9cbiAgUEFUVEVSTl9NQVRDSCA9ICdwYXR0ZXJuLW1hdGNoJyxcblxuICAvKipcbiAgICogUmV0dXJuIHN0YWNrcyBtYXRjaGVkIGJ5IHBhdHRlcm5zLlxuICAgKiBUaHJvd3MgYW4gZXhjZXB0aW9uIGlmIHRoZSBwYXR0ZXJucyBkb24ndCBtYXRjaCBhdCBsZWFzdCBvbmUgc3RhY2sgaW4gdGhlIGFzc2VtYmx5LlxuICAgKi9cbiAgUEFUVEVSTl9NVVNUX01BVENIID0gJ3BhdHRlcm4tbXVzdC1tYXRjaCcsXG5cbiAgLyoqXG4gICAqIFJldHVybnMgaWYgZXhhY3RseSBvbmUgc3RhY2sgaXMgbWF0Y2hlZCBieSB0aGUgcGF0dGVybihzKS5cbiAgICogVGhyb3dzIGFuIGV4Y2VwdGlvbiBpZiBubyBzdGFjaywgb3IgbW9yZSB0aGFuIGV4YWN0bHkgb25lIHN0YWNrIGFyZSBtYXRjaGVkLlxuICAgKi9cbiAgUEFUVEVSTl9NVVNUX01BVENIX1NJTkdMRSA9ICdwYXR0ZXJuLW11c3QtbWF0Y2gtc2luZ2xlJyxcbn1cblxuLyoqXG4gKiBXaGVuIHNlbGVjdGluZyBzdGFja3MsIHdoYXQgb3RoZXIgc3RhY2tzIHRvIGluY2x1ZGUgYmVjYXVzZSBvZiBkZXBlbmRlbmNpZXNcbiAqL1xuZXhwb3J0IGVudW0gRXhwYW5kU3RhY2tTZWxlY3Rpb24ge1xuICAvKipcbiAgICogRG9uJ3Qgc2VsZWN0IGFueSBleHRyYSBzdGFja3NcbiAgICovXG4gIE5PTkUgPSAnbm9uZScsXG5cbiAgLyoqXG4gICAqIEluY2x1ZGUgc3RhY2tzIHRoYXQgdGhpcyBzdGFjayBkZXBlbmRzIG9uXG4gICAqL1xuICBVUFNUUkVBTSA9ICd1cHN0cmVhbScsXG5cbiAgLyoqXG4gICAqIEluY2x1ZGUgc3RhY2tzIHRoYXQgZGVwZW5kIG9uIHRoaXMgc3RhY2tcbiAgICovXG4gIERPV05TVFJFQU0gPSAnZG93bnN0cmVhbScsXG5cbiAgLyoqXG4gICAqIEBUT0RPXG4gICAqIEluY2x1ZGUgYm90aCBkaXJlY3Rpb25zLlxuICAgKiBJLmUuIHN0YWNrcyB0aGF0IHRoaXMgc3RhY2sgZGVwZW5kcyBvbiwgYW5kIHN0YWNrcyB0aGF0IGRlcGVuZCBvbiB0aGlzIHN0YWNrLlxuICAgKi9cbiAgLy8gRlVMTCA9ICdmdWxsJyxcbn1cblxuLyoqXG4gKiBBIHNwZWNpZmljYXRpb24gb2Ygd2hpY2ggc3RhY2tzIHNob3VsZCBiZSBzZWxlY3RlZFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YWNrU2VsZWN0b3Ige1xuICAvKipcbiAgICogVGhlIGJlaGF2aW9yIGlmIGlmIG5vIHNlbGVjdG9ycyBhcmUgcHJvdmlkZWQuXG4gICAqL1xuICBzdHJhdGVneTogU3RhY2tTZWxlY3Rpb25TdHJhdGVneTtcblxuICAvKipcbiAgICogQSBsaXN0IG9mIHBhdHRlcm5zIHRvIG1hdGNoIHRoZSBzdGFjayBoaWVyYXJjaGljYWwgaWRzXG4gICAqIE9ubHkgdXNlZCB3aXRoIGBQQVRURVJOXypgIHNlbGVjdGlvbiBzdHJhdGVnaWVzLlxuICAgKi9cbiAgcGF0dGVybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogRXhwYW5kIHRoZSBzZWxlY3Rpb24gdG8gdXBzdHJlYW0vZG93bnN0cmVhbSBzdGFja3MuXG4gICAqIEBkZWZhdWx0IEV4cGFuZFN0YWNrU2VsZWN0aW9uLk5vbmUgb25seSBzZWxlY3QgdGhlIHNwZWNpZmllZC9tYXRjaGVkIHN0YWNrc1xuICAgKi9cbiAgZXhwYW5kPzogRXhwYW5kU3RhY2tTZWxlY3Rpb247XG5cbiAgLyoqXG4gICAqIEJ5IGRlZmF1bHQsIHdlIHRocm93IGFuIGV4Y2VwdGlvbiBpZiB0aGUgYXNzZW1ibHkgY29udGFpbnMgbm8gc3RhY2tzLlxuICAgKiBTZXQgdG8gYGZhbHNlYCwgdG8gaGFsdCBleGVjdXRpb24gZm9yIGVtcHR5IGFzc2VtYmxpZXMgd2l0aG91dCBlcnJvci5cbiAgICpcbiAgICogTm90ZSB0aGF0IGFjdGlvbnMgY2FuIHN0aWxsIHRocm93IGlmIGEgc3RhY2sgc2VsZWN0aW9uIHJlc3VsdCBpcyBlbXB0eSxcbiAgICogYnV0IHRoZSBhc3NlbWJseSBjb250YWlucyBzdGFja3MgaW4gcHJpbmNpcGxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICBmYWlsT25FbXB0eT86IGJvb2xlYW47XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.d.ts new file mode 100644 index 000000000..461c34402 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.d.ts @@ -0,0 +1,85 @@ +import type { CloudFormationStackArtifact } from '@aws-cdk/cx-api'; +import type { Export, StackResourceSummary } from '@aws-sdk/client-cloudformation'; +import type { SDK } from '../aws-auth'; +import type { NestedStackTemplates } from './nested-stack-helpers'; +import type { Template } from './stack-helpers'; +import type { ResourceMetadata } from '../resource-metadata'; +export interface ListStackResources { + listStackResources(): Promise; +} +export declare class LazyListStackResources implements ListStackResources { + private readonly sdk; + private readonly stackName; + private stackResources; + constructor(sdk: SDK, stackName: string); + listStackResources(): Promise; +} +export interface LookupExport { + lookupExport(name: string): Promise; +} +export declare class LookupExportError extends Error { +} +export declare class LazyLookupExport implements LookupExport { + private readonly sdk; + private cachedExports; + constructor(sdk: SDK); + lookupExport(name: string): Promise; + private listExports; +} +export declare class CfnEvaluationException extends Error { +} +export interface ResourceDefinition { + readonly LogicalId: string; + readonly Type: string; + readonly Properties: { + [p: string]: any; + }; +} +export interface EvaluateCloudFormationTemplateProps { + readonly stackArtifact: CloudFormationStackArtifact; + readonly stackName?: string; + readonly template?: Template; + readonly parameters: { + [parameterName: string]: string; + }; + readonly account: string; + readonly region: string; + readonly partition: string; + readonly sdk: SDK; + readonly nestedStacks?: { + [nestedStackLogicalId: string]: NestedStackTemplates; + }; +} +export declare class EvaluateCloudFormationTemplate { + readonly stackArtifact: CloudFormationStackArtifact; + private readonly stackName; + private readonly template; + private readonly context; + private readonly account; + private readonly region; + private readonly partition; + private readonly sdk; + private readonly nestedStacks; + private readonly stackResources; + private readonly lookupExport; + private cachedUrlSuffix; + constructor(props: EvaluateCloudFormationTemplateProps); + createNestedEvaluateCloudFormationTemplate(stackName: string, nestedTemplate: Template, nestedStackParameters: { + [parameterName: string]: any; + }): Promise; + establishResourcePhysicalName(logicalId: string, physicalNameInCfnTemplate: any): Promise; + findPhysicalNameFor(logicalId: string): Promise; + findLogicalIdForPhysicalName(physicalName: string): Promise; + findReferencesTo(logicalId: string): Array; + evaluateCfnExpression(cfnExpression: any): Promise; + getResourceProperty(logicalId: string, propertyName: string): any; + metadataFor(logicalId: string): ResourceMetadata | undefined; + private references; + private parseIntrinsic; + private findRefTarget; + private findGetAttTarget; + private findNestedStack; + private formatResourceAttribute; + private getServiceOfResource; + private getResourceTypeArnPartOfResource; +} diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.js new file mode 100644 index 000000000..8c866cdb1 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/evaluate-cloudformation-template.js @@ -0,0 +1,456 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EvaluateCloudFormationTemplate = exports.CfnEvaluationException = exports.LazyLookupExport = exports.LookupExportError = exports.LazyListStackResources = void 0; +const toolkit_error_1 = require("../toolkit-error"); +const resource_metadata_1 = require("../resource-metadata"); +class LazyListStackResources { + sdk; + stackName; + stackResources; + constructor(sdk, stackName) { + this.sdk = sdk; + this.stackName = stackName; + } + async listStackResources() { + if (this.stackResources === undefined) { + this.stackResources = this.sdk.cloudFormation().listStackResources({ + StackName: this.stackName, + }); + } + return this.stackResources; + } +} +exports.LazyListStackResources = LazyListStackResources; +class LookupExportError extends Error { +} +exports.LookupExportError = LookupExportError; +class LazyLookupExport { + sdk; + cachedExports = {}; + constructor(sdk) { + this.sdk = sdk; + } + async lookupExport(name) { + if (this.cachedExports[name]) { + return this.cachedExports[name]; + } + for await (const cfnExport of this.listExports()) { + if (!cfnExport.Name) { + continue; // ignore any result that omits a name + } + this.cachedExports[cfnExport.Name] = cfnExport; + if (cfnExport.Name === name) { + return cfnExport; + } + } + return undefined; // export not found + } + // TODO: Paginate + async *listExports() { + let nextToken = undefined; + while (true) { + const response = await this.sdk.cloudFormation().listExports({ NextToken: nextToken }); + for (const cfnExport of response.Exports ?? []) { + yield cfnExport; + } + if (!response.NextToken) { + return; + } + nextToken = response.NextToken; + } + } +} +exports.LazyLookupExport = LazyLookupExport; +class CfnEvaluationException extends Error { +} +exports.CfnEvaluationException = CfnEvaluationException; +class EvaluateCloudFormationTemplate { + stackArtifact; + stackName; + template; + context; + account; + region; + partition; + sdk; + nestedStacks; + stackResources; + lookupExport; + cachedUrlSuffix; + constructor(props) { + this.stackArtifact = props.stackArtifact; + this.stackName = props.stackName ?? props.stackArtifact.stackName; + this.template = props.template ?? props.stackArtifact.template; + this.context = { + 'AWS::AccountId': props.account, + 'AWS::Region': props.region, + 'AWS::Partition': props.partition, + ...props.parameters, + }; + this.account = props.account; + this.region = props.region; + this.partition = props.partition; + this.sdk = props.sdk; + // We need names of nested stack so we can evaluate cross stack references + this.nestedStacks = props.nestedStacks ?? {}; + // The current resources of the Stack. + // We need them to figure out the physical name of a resource in case it wasn't specified by the user. + // We fetch it lazily, to save a service call, in case all hotswapped resources have their physical names set. + this.stackResources = new LazyListStackResources(this.sdk, this.stackName); + // CloudFormation Exports lookup to be able to resolve Fn::ImportValue intrinsics in template + this.lookupExport = new LazyLookupExport(this.sdk); + } + // clones current EvaluateCloudFormationTemplate object, but updates the stack name + async createNestedEvaluateCloudFormationTemplate(stackName, nestedTemplate, nestedStackParameters) { + const evaluatedParams = await this.evaluateCfnExpression(nestedStackParameters); + return new EvaluateCloudFormationTemplate({ + stackArtifact: this.stackArtifact, + stackName, + template: nestedTemplate, + parameters: evaluatedParams, + account: this.account, + region: this.region, + partition: this.partition, + sdk: this.sdk, + nestedStacks: this.nestedStacks, + }); + } + async establishResourcePhysicalName(logicalId, physicalNameInCfnTemplate) { + if (physicalNameInCfnTemplate != null) { + try { + return await this.evaluateCfnExpression(physicalNameInCfnTemplate); + } + catch (e) { + // If we can't evaluate the resource's name CloudFormation expression, + // just look it up in the currently deployed Stack + if (!(e instanceof CfnEvaluationException)) { + throw e; + } + } + } + return this.findPhysicalNameFor(logicalId); + } + async findPhysicalNameFor(logicalId) { + const stackResources = await this.stackResources.listStackResources(); + return stackResources.find((sr) => sr.LogicalResourceId === logicalId)?.PhysicalResourceId; + } + async findLogicalIdForPhysicalName(physicalName) { + const stackResources = await this.stackResources.listStackResources(); + return stackResources.find((sr) => sr.PhysicalResourceId === physicalName)?.LogicalResourceId; + } + findReferencesTo(logicalId) { + const ret = new Array(); + for (const [resourceLogicalId, resourceDef] of Object.entries(this.template?.Resources ?? {})) { + if (logicalId !== resourceLogicalId && this.references(logicalId, resourceDef)) { + ret.push({ + ...resourceDef, + LogicalId: resourceLogicalId, + }); + } + } + return ret; + } + async evaluateCfnExpression(cfnExpression) { + const self = this; + /** + * Evaluates CloudFormation intrinsic functions + * + * Note that supported intrinsic functions are documented in README.md -- please update + * list of supported functions when adding new evaluations + * + * See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html + */ + class CfnIntrinsics { + evaluateIntrinsic(intrinsic) { + const intrinsicFunc = this[intrinsic.name]; + if (!intrinsicFunc) { + throw new CfnEvaluationException(`CloudFormation function ${intrinsic.name} is not supported`); + } + const argsAsArray = Array.isArray(intrinsic.args) ? intrinsic.args : [intrinsic.args]; + return intrinsicFunc.apply(this, argsAsArray); + } + async 'Fn::Join'(separator, args) { + const evaluatedArgs = await self.evaluateCfnExpression(args); + return evaluatedArgs.join(separator); + } + async 'Fn::Split'(separator, args) { + const evaluatedArgs = await self.evaluateCfnExpression(args); + return evaluatedArgs.split(separator); + } + async 'Fn::Select'(index, args) { + const evaluatedArgs = await self.evaluateCfnExpression(args); + return evaluatedArgs[index]; + } + async Ref(logicalId) { + const refTarget = await self.findRefTarget(logicalId); + if (refTarget) { + return refTarget; + } + else { + throw new CfnEvaluationException(`Parameter or resource '${logicalId}' could not be found for evaluation`); + } + } + async 'Fn::GetAtt'(logicalId, attributeName) { + // ToDo handle the 'logicalId.attributeName' form of Fn::GetAtt + const attrValue = await self.findGetAttTarget(logicalId, attributeName); + if (attrValue) { + return attrValue; + } + else { + throw new CfnEvaluationException(`Attribute '${attributeName}' of resource '${logicalId}' could not be found for evaluation`); + } + } + async 'Fn::Sub'(template, explicitPlaceholders) { + const placeholders = explicitPlaceholders ? await self.evaluateCfnExpression(explicitPlaceholders) : {}; + return asyncGlobalReplace(template, /\${([^}]*)}/g, (key) => { + if (key in placeholders) { + return placeholders[key]; + } + else { + const splitKey = key.split('.'); + return splitKey.length === 1 ? this.Ref(key) : this['Fn::GetAtt'](splitKey[0], splitKey.slice(1).join('.')); + } + }); + } + async 'Fn::ImportValue'(name) { + const exported = await self.lookupExport.lookupExport(name); + if (!exported) { + throw new CfnEvaluationException(`Export '${name}' could not be found for evaluation`); + } + if (!exported.Value) { + throw new CfnEvaluationException(`Export '${name}' exists without a value`); + } + return exported.Value; + } + } + if (cfnExpression == null) { + return cfnExpression; + } + if (Array.isArray(cfnExpression)) { + // Small arrays in practice + // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism + return Promise.all(cfnExpression.map((expr) => this.evaluateCfnExpression(expr))); + } + if (typeof cfnExpression === 'object') { + const intrinsic = this.parseIntrinsic(cfnExpression); + if (intrinsic) { + return new CfnIntrinsics().evaluateIntrinsic(intrinsic); + } + else { + const ret = {}; + for (const [key, val] of Object.entries(cfnExpression)) { + ret[key] = await this.evaluateCfnExpression(val); + } + return ret; + } + } + return cfnExpression; + } + getResourceProperty(logicalId, propertyName) { + return this.template.Resources?.[logicalId]?.Properties?.[propertyName]; + } + metadataFor(logicalId) { + return (0, resource_metadata_1.resourceMetadata)(this.stackArtifact, logicalId); + } + references(logicalId, templateElement) { + if (typeof templateElement === 'string') { + return logicalId === templateElement; + } + if (templateElement == null) { + return false; + } + if (Array.isArray(templateElement)) { + return templateElement.some((el) => this.references(logicalId, el)); + } + if (typeof templateElement === 'object') { + return Object.values(templateElement).some((el) => this.references(logicalId, el)); + } + return false; + } + parseIntrinsic(x) { + const keys = Object.keys(x); + if (keys.length === 1 && (keys[0].startsWith('Fn::') || keys[0] === 'Ref')) { + return { + name: keys[0], + args: x[keys[0]], + }; + } + return undefined; + } + async findRefTarget(logicalId) { + // first, check to see if the Ref is a Parameter who's value we have + if (logicalId === 'AWS::URLSuffix') { + if (!this.cachedUrlSuffix) { + this.cachedUrlSuffix = await this.sdk.getUrlSuffix(this.region); + } + return this.cachedUrlSuffix; + } + // Try finding the ref in the passed in parameters + const parameterTarget = this.context[logicalId]; + if (parameterTarget) { + return parameterTarget; + } + // If not in the passed in parameters, see if there is a default value in the template parameter that was not passed in + const defaultParameterValue = this.template.Parameters?.[logicalId]?.Default; + if (defaultParameterValue) { + return defaultParameterValue; + } + // if it's not a Parameter, we need to search in the current Stack resources + return this.findGetAttTarget(logicalId); + } + async findGetAttTarget(logicalId, attribute) { + // Handle case where the attribute is referencing a stack output (used in nested stacks to share parameters) + // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-cloudformation.html#w2ab1c17c23c19b5 + if (logicalId === 'Outputs' && attribute) { + return this.evaluateCfnExpression(this.template.Outputs[attribute]?.Value); + } + const stackResources = await this.stackResources.listStackResources(); + const foundResource = stackResources.find((sr) => sr.LogicalResourceId === logicalId); + if (!foundResource) { + return undefined; + } + if (foundResource.ResourceType == 'AWS::CloudFormation::Stack' && attribute?.startsWith('Outputs.')) { + const dependantStack = this.findNestedStack(logicalId, this.nestedStacks); + if (!dependantStack || !dependantStack.physicalName) { + // this is a newly created nested stack and cannot be hotswapped + return undefined; + } + const evaluateCfnTemplate = await this.createNestedEvaluateCloudFormationTemplate(dependantStack.physicalName, dependantStack.generatedTemplate, dependantStack.generatedTemplate.Parameters); + // Split Outputs. into 'Outputs' and '' and recursively call evaluate + return evaluateCfnTemplate.evaluateCfnExpression({ + 'Fn::GetAtt': attribute.split(/\.(.*)/s), + }); + } + // now, we need to format the appropriate identifier depending on the resource type, + // and the requested attribute name + return this.formatResourceAttribute(foundResource, attribute); + } + findNestedStack(logicalId, nestedStacks) { + for (const nestedStackLogicalId of Object.keys(nestedStacks)) { + if (nestedStackLogicalId === logicalId) { + return nestedStacks[nestedStackLogicalId]; + } + const checkInNestedChildStacks = this.findNestedStack(logicalId, nestedStacks[nestedStackLogicalId].nestedStackTemplates); + if (checkInNestedChildStacks) + return checkInNestedChildStacks; + } + return undefined; + } + formatResourceAttribute(resource, attribute) { + const physicalId = resource.PhysicalResourceId; + // no attribute means Ref expression, for which we use the physical ID directly + if (!attribute) { + return physicalId; + } + const resourceTypeFormats = RESOURCE_TYPE_ATTRIBUTES_FORMATS[resource.ResourceType]; + if (!resourceTypeFormats) { + throw new CfnEvaluationException(`We don't support attributes of the '${resource.ResourceType}' resource. This is a CDK limitation. ` + + 'Please report it at https://github.com/aws/aws-cdk/issues/new/choose'); + } + const attributeFmtFunc = resourceTypeFormats[attribute]; + if (!attributeFmtFunc) { + throw new CfnEvaluationException(`We don't support the '${attribute}' attribute of the '${resource.ResourceType}' resource. This is a CDK limitation. ` + + 'Please report it at https://github.com/aws/aws-cdk/issues/new/choose'); + } + const service = this.getServiceOfResource(resource); + const resourceTypeArnPart = this.getResourceTypeArnPartOfResource(resource); + return attributeFmtFunc({ + partition: this.partition, + service, + region: this.region, + account: this.account, + resourceType: resourceTypeArnPart, + resourceName: physicalId, + }); + } + getServiceOfResource(resource) { + return resource.ResourceType.split('::')[1].toLowerCase(); + } + getResourceTypeArnPartOfResource(resource) { + const resourceType = resource.ResourceType; + const specialCaseResourceType = RESOURCE_TYPE_SPECIAL_NAMES[resourceType]?.resourceType; + return specialCaseResourceType + ? specialCaseResourceType + : // this is the default case + resourceType.split('::')[2].toLowerCase(); + } +} +exports.EvaluateCloudFormationTemplate = EvaluateCloudFormationTemplate; +/** + * Usually, we deduce the names of the service and the resource type used to format the ARN from the CloudFormation resource type. + * For a CFN type like AWS::Service::ResourceType, the second segment becomes the service name, and the third the resource type + * (after converting both of them to lowercase). + * However, some resource types break this simple convention, and we need to special-case them. + * This map is for storing those cases. + */ +const RESOURCE_TYPE_SPECIAL_NAMES = { + 'AWS::Events::EventBus': { + resourceType: 'event-bus', + }, +}; +const RESOURCE_TYPE_ATTRIBUTES_FORMATS = { + 'AWS::IAM::Role': { Arn: iamArnFmt }, + 'AWS::IAM::User': { Arn: iamArnFmt }, + 'AWS::IAM::Group': { Arn: iamArnFmt }, + 'AWS::S3::Bucket': { Arn: s3ArnFmt }, + 'AWS::Lambda::Function': { Arn: stdColonResourceArnFmt }, + 'AWS::Events::EventBus': { + Arn: stdSlashResourceArnFmt, + // the name attribute of the EventBus is the same as the Ref + Name: (parts) => parts.resourceName, + }, + 'AWS::DynamoDB::Table': { Arn: stdSlashResourceArnFmt }, + 'AWS::AppSync::GraphQLApi': { ApiId: appsyncGraphQlApiApiIdFmt }, + 'AWS::AppSync::FunctionConfiguration': { + FunctionId: appsyncGraphQlFunctionIDFmt, + }, + 'AWS::AppSync::DataSource': { Name: appsyncGraphQlDataSourceNameFmt }, + 'AWS::KMS::Key': { Arn: stdSlashResourceArnFmt }, +}; +function iamArnFmt(parts) { + // we skip region for IAM resources + return `arn:${parts.partition}:${parts.service}::${parts.account}:${parts.resourceType}/${parts.resourceName}`; +} +function s3ArnFmt(parts) { + // we skip account, region and resourceType for S3 resources + return `arn:${parts.partition}:${parts.service}:::${parts.resourceName}`; +} +function stdColonResourceArnFmt(parts) { + // this is a standard format for ARNs like: arn:aws:service:region:account:resourceType:resourceName + return `arn:${parts.partition}:${parts.service}:${parts.region}:${parts.account}:${parts.resourceType}:${parts.resourceName}`; +} +function stdSlashResourceArnFmt(parts) { + // this is a standard format for ARNs like: arn:aws:service:region:account:resourceType/resourceName + return `arn:${parts.partition}:${parts.service}:${parts.region}:${parts.account}:${parts.resourceType}/${parts.resourceName}`; +} +function appsyncGraphQlApiApiIdFmt(parts) { + // arn:aws:appsync:us-east-1:111111111111:apis/ + return parts.resourceName.split('/')[1]; +} +function appsyncGraphQlFunctionIDFmt(parts) { + // arn:aws:appsync:us-east-1:111111111111:apis//functions/ + return parts.resourceName.split('/')[3]; +} +function appsyncGraphQlDataSourceNameFmt(parts) { + // arn:aws:appsync:us-east-1:111111111111:apis//datasources/ + return parts.resourceName.split('/')[3]; +} +async function asyncGlobalReplace(str, regex, cb) { + if (!regex.global) { + throw new toolkit_error_1.ToolkitError('Regex must be created with /g flag'); + } + const ret = new Array(); + let start = 0; + while (true) { + const match = regex.exec(str); + if (!match) { + break; + } + ret.push(str.substring(start, match.index)); + ret.push(await cb(match[1])); + start = regex.lastIndex; + } + ret.push(str.slice(start)); + return ret.join(''); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZhbHVhdGUtY2xvdWRmb3JtYXRpb24tdGVtcGxhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2Nsb3VkZm9ybWF0aW9uL2V2YWx1YXRlLWNsb3VkZm9ybWF0aW9uLXRlbXBsYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUdBLG9EQUFnRDtBQUloRCw0REFBd0Q7QUFNeEQsTUFBYSxzQkFBc0I7SUFJZDtJQUNBO0lBSlgsY0FBYyxDQUE4QztJQUVwRSxZQUNtQixHQUFRLEVBQ1IsU0FBaUI7UUFEakIsUUFBRyxHQUFILEdBQUcsQ0FBSztRQUNSLGNBQVMsR0FBVCxTQUFTLENBQVE7SUFFcEMsQ0FBQztJQUVNLEtBQUssQ0FBQyxrQkFBa0I7UUFDN0IsSUFBSSxJQUFJLENBQUMsY0FBYyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQztnQkFDakUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO2FBQzFCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztDQUNGO0FBakJELHdEQWlCQztBQU1ELE1BQWEsaUJBQWtCLFNBQVEsS0FBSztDQUMzQztBQURELDhDQUNDO0FBRUQsTUFBYSxnQkFBZ0I7SUFHRTtJQUZyQixhQUFhLEdBQStCLEVBQUUsQ0FBQztJQUV2RCxZQUE2QixHQUFRO1FBQVIsUUFBRyxHQUFILEdBQUcsQ0FBSztJQUNyQyxDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFZO1FBQzdCLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzdCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsQyxDQUFDO1FBRUQsSUFBSSxLQUFLLEVBQUUsTUFBTSxTQUFTLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDakQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDcEIsU0FBUyxDQUFDLHNDQUFzQztZQUNsRCxDQUFDO1lBQ0QsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDO1lBRS9DLElBQUksU0FBUyxDQUFDLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDNUIsT0FBTyxTQUFTLENBQUM7WUFDbkIsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLFNBQVMsQ0FBQyxDQUFDLG1CQUFtQjtJQUN2QyxDQUFDO0lBRUQsaUJBQWlCO0lBQ1QsS0FBSyxDQUFDLENBQUMsV0FBVztRQUN4QixJQUFJLFNBQVMsR0FBdUIsU0FBUyxDQUFDO1FBQzlDLE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixNQUFNLFFBQVEsR0FBNkIsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDLFdBQVcsQ0FBQyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO1lBQ2pILEtBQUssTUFBTSxTQUFTLElBQUksUUFBUSxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUUsQ0FBQztnQkFDL0MsTUFBTSxTQUFTLENBQUM7WUFDbEIsQ0FBQztZQUVELElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3hCLE9BQU87WUFDVCxDQUFDO1lBQ0QsU0FBUyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDakMsQ0FBQztJQUNILENBQUM7Q0FDRjtBQXhDRCw0Q0F3Q0M7QUFFRCxNQUFhLHNCQUF1QixTQUFRLEtBQUs7Q0FDaEQ7QUFERCx3REFDQztBQXNCRCxNQUFhLDhCQUE4QjtJQUN6QixhQUFhLENBQThCO0lBQzFDLFNBQVMsQ0FBUztJQUNsQixRQUFRLENBQVc7SUFDbkIsT0FBTyxDQUF1QjtJQUM5QixPQUFPLENBQVM7SUFDaEIsTUFBTSxDQUFTO0lBQ2YsU0FBUyxDQUFTO0lBQ2xCLEdBQUcsQ0FBTTtJQUNULFlBQVksQ0FFM0I7SUFDZSxjQUFjLENBQXFCO0lBQ25DLFlBQVksQ0FBZTtJQUVwQyxlQUFlLENBQXFCO0lBRTVDLFlBQVksS0FBMEM7UUFDcEQsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsYUFBYSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQztRQUNsRSxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUM7UUFDL0QsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNiLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQy9CLGFBQWEsRUFBRSxLQUFLLENBQUMsTUFBTTtZQUMzQixnQkFBZ0IsRUFBRSxLQUFLLENBQUMsU0FBUztZQUNqQyxHQUFHLEtBQUssQ0FBQyxVQUFVO1NBQ3BCLENBQUM7UUFDRixJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDN0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQzNCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQztRQUNqQyxJQUFJLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUM7UUFFckIsMEVBQTBFO1FBQzFFLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksSUFBSSxFQUFFLENBQUM7UUFFN0Msc0NBQXNDO1FBQ3RDLHNHQUFzRztRQUN0Ryw4R0FBOEc7UUFDOUcsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLHNCQUFzQixDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRTNFLDZGQUE2RjtRQUM3RixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRCxtRkFBbUY7SUFDNUUsS0FBSyxDQUFDLDBDQUEwQyxDQUNyRCxTQUFpQixFQUNqQixjQUF3QixFQUN4QixxQkFBdUQ7UUFFdkQsTUFBTSxlQUFlLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUNoRixPQUFPLElBQUksOEJBQThCLENBQUM7WUFDeEMsYUFBYSxFQUFFLElBQUksQ0FBQyxhQUFhO1lBQ2pDLFNBQVM7WUFDVCxRQUFRLEVBQUUsY0FBYztZQUN4QixVQUFVLEVBQUUsZUFBZTtZQUMzQixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7WUFDYixZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7U0FDaEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQyw2QkFBNkIsQ0FDeEMsU0FBaUIsRUFDakIseUJBQThCO1FBRTlCLElBQUkseUJBQXlCLElBQUksSUFBSSxFQUFFLENBQUM7WUFDdEMsSUFBSSxDQUFDO2dCQUNILE9BQU8sTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMseUJBQXlCLENBQUMsQ0FBQztZQUNyRSxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDWCxzRUFBc0U7Z0JBQ3RFLGtEQUFrRDtnQkFDbEQsSUFBSSxDQUFDLENBQUMsQ0FBQyxZQUFZLHNCQUFzQixDQUFDLEVBQUUsQ0FBQztvQkFDM0MsTUFBTSxDQUFDLENBQUM7Z0JBQ1YsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVNLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxTQUFpQjtRQUNoRCxNQUFNLGNBQWMsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUN0RSxPQUFPLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsS0FBSyxTQUFTLENBQUMsRUFBRSxrQkFBa0IsQ0FBQztJQUM3RixDQUFDO0lBRU0sS0FBSyxDQUFDLDRCQUE0QixDQUFDLFlBQW9CO1FBQzVELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQ3RFLE9BQU8sY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLGtCQUFrQixLQUFLLFlBQVksQ0FBQyxFQUFFLGlCQUFpQixDQUFDO0lBQ2hHLENBQUM7SUFFTSxnQkFBZ0IsQ0FBQyxTQUFpQjtRQUN2QyxNQUFNLEdBQUcsR0FBRyxJQUFJLEtBQUssRUFBc0IsQ0FBQztRQUM1QyxLQUFLLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxXQUFXLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDOUYsSUFBSSxTQUFTLEtBQUssaUJBQWlCLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQztnQkFDL0UsR0FBRyxDQUFDLElBQUksQ0FBQztvQkFDUCxHQUFJLFdBQW1CO29CQUN2QixTQUFTLEVBQUUsaUJBQWlCO2lCQUM3QixDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVNLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxhQUFrQjtRQUNuRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7UUFDbEI7Ozs7Ozs7V0FPRztRQUNILE1BQU0sYUFBYTtZQUNWLGlCQUFpQixDQUFDLFNBQW9CO2dCQUMzQyxNQUFNLGFBQWEsR0FBSSxJQUFZLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNwRCxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7b0JBQ25CLE1BQU0sSUFBSSxzQkFBc0IsQ0FBQywyQkFBMkIsU0FBUyxDQUFDLElBQUksbUJBQW1CLENBQUMsQ0FBQztnQkFDakcsQ0FBQztnQkFFRCxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRXRGLE9BQU8sYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDaEQsQ0FBQztZQUVELEtBQUssQ0FBQyxVQUFVLENBQUMsU0FBaUIsRUFBRSxJQUFXO2dCQUM3QyxNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDN0QsT0FBTyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3ZDLENBQUM7WUFFRCxLQUFLLENBQUMsV0FBVyxDQUFDLFNBQWlCLEVBQUUsSUFBUztnQkFDNUMsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzdELE9BQU8sYUFBYSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN4QyxDQUFDO1lBRUQsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFhLEVBQUUsSUFBVztnQkFDM0MsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzdELE9BQU8sYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzlCLENBQUM7WUFFRCxLQUFLLENBQUMsR0FBRyxDQUFDLFNBQWlCO2dCQUN6QixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3RELElBQUksU0FBUyxFQUFFLENBQUM7b0JBQ2QsT0FBTyxTQUFTLENBQUM7Z0JBQ25CLENBQUM7cUJBQU0sQ0FBQztvQkFDTixNQUFNLElBQUksc0JBQXNCLENBQUMsMEJBQTBCLFNBQVMscUNBQXFDLENBQUMsQ0FBQztnQkFDN0csQ0FBQztZQUNILENBQUM7WUFFRCxLQUFLLENBQUMsWUFBWSxDQUFDLFNBQWlCLEVBQUUsYUFBcUI7Z0JBQ3pELCtEQUErRDtnQkFDL0QsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDO2dCQUN4RSxJQUFJLFNBQVMsRUFBRSxDQUFDO29CQUNkLE9BQU8sU0FBUyxDQUFDO2dCQUNuQixDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxJQUFJLHNCQUFzQixDQUM5QixjQUFjLGFBQWEsa0JBQWtCLFNBQVMscUNBQXFDLENBQzVGLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7WUFFRCxLQUFLLENBQUMsU0FBUyxDQUFDLFFBQWdCLEVBQUUsb0JBQXFEO2dCQUNyRixNQUFNLFlBQVksR0FBRyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUV4RyxPQUFPLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxjQUFjLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtvQkFDMUQsSUFBSSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7d0JBQ3hCLE9BQU8sWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUMzQixDQUFDO3lCQUFNLENBQUM7d0JBQ04sTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQzt3QkFDaEMsT0FBTyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUM5RyxDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFZO2dCQUNsQyxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUM1RCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQ2QsTUFBTSxJQUFJLHNCQUFzQixDQUFDLFdBQVcsSUFBSSxxQ0FBcUMsQ0FBQyxDQUFDO2dCQUN6RixDQUFDO2dCQUNELElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ3BCLE1BQU0sSUFBSSxzQkFBc0IsQ0FBQyxXQUFXLElBQUksMEJBQTBCLENBQUMsQ0FBQztnQkFDOUUsQ0FBQztnQkFDRCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUM7WUFDeEIsQ0FBQztTQUNGO1FBRUQsSUFBSSxhQUFhLElBQUksSUFBSSxFQUFFLENBQUM7WUFDMUIsT0FBTyxhQUFhLENBQUM7UUFDdkIsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ2pDLDJCQUEyQjtZQUMzQix3RUFBd0U7WUFDeEUsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEYsQ0FBQztRQUVELElBQUksT0FBTyxhQUFhLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDdEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUNyRCxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNkLE9BQU8sSUFBSSxhQUFhLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMxRCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxHQUFHLEdBQTJCLEVBQUUsQ0FBQztnQkFDdkMsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztvQkFDdkQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNuRCxDQUFDO2dCQUNELE9BQU8sR0FBRyxDQUFDO1lBQ2IsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLGFBQWEsQ0FBQztJQUN2QixDQUFDO0lBRU0sbUJBQW1CLENBQUMsU0FBaUIsRUFBRSxZQUFvQjtRQUNoRSxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsVUFBVSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUVNLFdBQVcsQ0FBQyxTQUFpQjtRQUNsQyxPQUFPLElBQUEsb0NBQWdCLEVBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRU8sVUFBVSxDQUFDLFNBQWlCLEVBQUUsZUFBb0I7UUFDeEQsSUFBSSxPQUFPLGVBQWUsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN4QyxPQUFPLFNBQVMsS0FBSyxlQUFlLENBQUM7UUFDdkMsQ0FBQztRQUVELElBQUksZUFBZSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQzVCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1lBQ25DLE9BQU8sZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN0RSxDQUFDO1FBRUQsSUFBSSxPQUFPLGVBQWUsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN4QyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JGLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFTyxjQUFjLENBQUMsQ0FBTTtRQUMzQixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzVCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzNFLE9BQU87Z0JBQ0wsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ2IsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDakIsQ0FBQztRQUNKLENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRU8sS0FBSyxDQUFDLGFBQWEsQ0FBQyxTQUFpQjtRQUMzQyxvRUFBb0U7UUFDcEUsSUFBSSxTQUFTLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUMxQixJQUFJLENBQUMsZUFBZSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2xFLENBQUM7WUFFRCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDOUIsQ0FBQztRQUVELGtEQUFrRDtRQUNsRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2hELElBQUksZUFBZSxFQUFFLENBQUM7WUFDcEIsT0FBTyxlQUFlLENBQUM7UUFDekIsQ0FBQztRQUVELHVIQUF1SDtRQUN2SCxNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxDQUFDO1FBQzdFLElBQUkscUJBQXFCLEVBQUUsQ0FBQztZQUMxQixPQUFPLHFCQUFxQixDQUFDO1FBQy9CLENBQUM7UUFFRCw0RUFBNEU7UUFDNUUsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVPLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFpQixFQUFFLFNBQWtCO1FBQ2xFLDRHQUE0RztRQUM1RyxtSEFBbUg7UUFDbkgsSUFBSSxTQUFTLEtBQUssU0FBUyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQ3pDLE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdFLENBQUM7UUFFRCxNQUFNLGNBQWMsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUN0RSxNQUFNLGFBQWEsR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsaUJBQWlCLEtBQUssU0FBUyxDQUFDLENBQUM7UUFDdEYsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ25CLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFFRCxJQUFJLGFBQWEsQ0FBQyxZQUFZLElBQUksNEJBQTRCLElBQUksU0FBUyxFQUFFLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ3BHLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUMxRSxJQUFJLENBQUMsY0FBYyxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNwRCxnRUFBZ0U7Z0JBQ2hFLE9BQU8sU0FBUyxDQUFDO1lBQ25CLENBQUM7WUFDRCxNQUFNLG1CQUFtQixHQUFHLE1BQU0sSUFBSSxDQUFDLDBDQUEwQyxDQUMvRSxjQUFjLENBQUMsWUFBWSxFQUMzQixjQUFjLENBQUMsaUJBQWlCLEVBQ2hDLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxVQUFXLENBQzdDLENBQUM7WUFFRix1RkFBdUY7WUFDdkYsT0FBTyxtQkFBbUIsQ0FBQyxxQkFBcUIsQ0FBQztnQkFDL0MsWUFBWSxFQUFFLFNBQVMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO2FBQ3pDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxvRkFBb0Y7UUFDcEYsbUNBQW1DO1FBQ25DLE9BQU8sSUFBSSxDQUFDLHVCQUF1QixDQUFDLGFBQWEsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRU8sZUFBZSxDQUNyQixTQUFpQixFQUNqQixZQUVDO1FBRUQsS0FBSyxNQUFNLG9CQUFvQixJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUM3RCxJQUFJLG9CQUFvQixLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUN2QyxPQUFPLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBQzVDLENBQUM7WUFDRCxNQUFNLHdCQUF3QixHQUFHLElBQUksQ0FBQyxlQUFlLENBQ25ELFNBQVMsRUFDVCxZQUFZLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxvQkFBb0IsQ0FDeEQsQ0FBQztZQUNGLElBQUksd0JBQXdCO2dCQUFFLE9BQU8sd0JBQXdCLENBQUM7UUFDaEUsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFTyx1QkFBdUIsQ0FBQyxRQUE4QixFQUFFLFNBQTZCO1FBQzNGLE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQztRQUUvQywrRUFBK0U7UUFDL0UsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2YsT0FBTyxVQUFVLENBQUM7UUFDcEIsQ0FBQztRQUVELE1BQU0sbUJBQW1CLEdBQUcsZ0NBQWdDLENBQUMsUUFBUSxDQUFDLFlBQWEsQ0FBQyxDQUFDO1FBQ3JGLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sSUFBSSxzQkFBc0IsQ0FDOUIsdUNBQXVDLFFBQVEsQ0FBQyxZQUFZLHdDQUF3QztnQkFDbEcsc0VBQXNFLENBQ3pFLENBQUM7UUFDSixDQUFDO1FBQ0QsTUFBTSxnQkFBZ0IsR0FBRyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksc0JBQXNCLENBQzlCLHlCQUF5QixTQUFTLHVCQUF1QixRQUFRLENBQUMsWUFBWSx3Q0FBd0M7Z0JBQ3BILHNFQUFzRSxDQUN6RSxDQUFDO1FBQ0osQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNwRCxNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RSxPQUFPLGdCQUFnQixDQUFDO1lBQ3RCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixPQUFPO1lBQ1AsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztZQUNyQixZQUFZLEVBQUUsbUJBQW1CO1lBQ2pDLFlBQVksRUFBRSxVQUFXO1NBQzFCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxvQkFBb0IsQ0FBQyxRQUE4QjtRQUN6RCxPQUFPLFFBQVEsQ0FBQyxZQUFhLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzdELENBQUM7SUFFTyxnQ0FBZ0MsQ0FBQyxRQUE4QjtRQUNyRSxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsWUFBYSxDQUFDO1FBQzVDLE1BQU0sdUJBQXVCLEdBQUcsMkJBQTJCLENBQUMsWUFBWSxDQUFDLEVBQUUsWUFBWSxDQUFDO1FBQ3hGLE9BQU8sdUJBQXVCO1lBQzVCLENBQUMsQ0FBQyx1QkFBdUI7WUFDekIsQ0FBQyxDQUFDLDJCQUEyQjtnQkFDN0IsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM5QyxDQUFDO0NBQ0Y7QUEzWEQsd0VBMlhDO0FBV0Q7Ozs7OztHQU1HO0FBQ0gsTUFBTSwyQkFBMkIsR0FFN0I7SUFDRix1QkFBdUIsRUFBRTtRQUN2QixZQUFZLEVBQUUsV0FBVztLQUMxQjtDQUNGLENBQUM7QUFFRixNQUFNLGdDQUFnQyxHQUVsQztJQUNGLGdCQUFnQixFQUFFLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRTtJQUNwQyxnQkFBZ0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUU7SUFDcEMsaUJBQWlCLEVBQUUsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFO0lBQ3JDLGlCQUFpQixFQUFFLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRTtJQUNwQyx1QkFBdUIsRUFBRSxFQUFFLEdBQUcsRUFBRSxzQkFBc0IsRUFBRTtJQUN4RCx1QkFBdUIsRUFBRTtRQUN2QixHQUFHLEVBQUUsc0JBQXNCO1FBQzNCLDREQUE0RDtRQUM1RCxJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxZQUFZO0tBQ3BDO0lBQ0Qsc0JBQXNCLEVBQUUsRUFBRSxHQUFHLEVBQUUsc0JBQXNCLEVBQUU7SUFDdkQsMEJBQTBCLEVBQUUsRUFBRSxLQUFLLEVBQUUseUJBQXlCLEVBQUU7SUFDaEUscUNBQXFDLEVBQUU7UUFDckMsVUFBVSxFQUFFLDJCQUEyQjtLQUN4QztJQUNELDBCQUEwQixFQUFFLEVBQUUsSUFBSSxFQUFFLCtCQUErQixFQUFFO0lBQ3JFLGVBQWUsRUFBRSxFQUFFLEdBQUcsRUFBRSxzQkFBc0IsRUFBRTtDQUNqRCxDQUFDO0FBRUYsU0FBUyxTQUFTLENBQUMsS0FBZTtJQUNoQyxtQ0FBbUM7SUFDbkMsT0FBTyxPQUFPLEtBQUssQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLE9BQU8sS0FBSyxLQUFLLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLElBQUksS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDO0FBQ2pILENBQUM7QUFFRCxTQUFTLFFBQVEsQ0FBQyxLQUFlO0lBQy9CLDREQUE0RDtJQUM1RCxPQUFPLE9BQU8sS0FBSyxDQUFDLFNBQVMsSUFBSSxLQUFLLENBQUMsT0FBTyxNQUFNLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztBQUMzRSxDQUFDO0FBRUQsU0FBUyxzQkFBc0IsQ0FBQyxLQUFlO0lBQzdDLG9HQUFvRztJQUNwRyxPQUFPLE9BQU8sS0FBSyxDQUFDLFNBQVMsSUFBSSxLQUFLLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sSUFBSSxLQUFLLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztBQUNoSSxDQUFDO0FBRUQsU0FBUyxzQkFBc0IsQ0FBQyxLQUFlO0lBQzdDLG9HQUFvRztJQUNwRyxPQUFPLE9BQU8sS0FBSyxDQUFDLFNBQVMsSUFBSSxLQUFLLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sSUFBSSxLQUFLLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztBQUNoSSxDQUFDO0FBRUQsU0FBUyx5QkFBeUIsQ0FBQyxLQUFlO0lBQ2hELHNEQUFzRDtJQUN0RCxPQUFPLEtBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzFDLENBQUM7QUFFRCxTQUFTLDJCQUEyQixDQUFDLEtBQWU7SUFDbEQsNkVBQTZFO0lBQzdFLE9BQU8sS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDMUMsQ0FBQztBQUVELFNBQVMsK0JBQStCLENBQUMsS0FBZTtJQUN0RCx5RUFBeUU7SUFDekUsT0FBTyxLQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxQyxDQUFDO0FBT0QsS0FBSyxVQUFVLGtCQUFrQixDQUFDLEdBQVcsRUFBRSxLQUFhLEVBQUUsRUFBa0M7SUFDOUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNsQixNQUFNLElBQUksNEJBQVksQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLEtBQUssRUFBVSxDQUFDO0lBQ2hDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNkLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDWixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU07UUFDUixDQUFDO1FBRUQsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUM1QyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFN0IsS0FBSyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7SUFDMUIsQ0FBQztJQUNELEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBRTNCLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QgfSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHR5cGUgeyBFeHBvcnQsIExpc3RFeHBvcnRzQ29tbWFuZE91dHB1dCwgU3RhY2tSZXNvdXJjZVN1bW1hcnkgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtY2xvdWRmb3JtYXRpb24nO1xuaW1wb3J0IHR5cGUgeyBTREsgfSBmcm9tICcuLi9hd3MtYXV0aCc7XG5pbXBvcnQgeyBUb29sa2l0RXJyb3IgfSBmcm9tICcuLi90b29sa2l0LWVycm9yJztcbmltcG9ydCB0eXBlIHsgTmVzdGVkU3RhY2tUZW1wbGF0ZXMgfSBmcm9tICcuL25lc3RlZC1zdGFjay1oZWxwZXJzJztcbmltcG9ydCB0eXBlIHsgVGVtcGxhdGUgfSBmcm9tICcuL3N0YWNrLWhlbHBlcnMnO1xuaW1wb3J0IHR5cGUgeyBSZXNvdXJjZU1ldGFkYXRhIH0gZnJvbSAnLi4vcmVzb3VyY2UtbWV0YWRhdGEnO1xuaW1wb3J0IHsgcmVzb3VyY2VNZXRhZGF0YSB9IGZyb20gJy4uL3Jlc291cmNlLW1ldGFkYXRhJztcblxuZXhwb3J0IGludGVyZmFjZSBMaXN0U3RhY2tSZXNvdXJjZXMge1xuICBsaXN0U3RhY2tSZXNvdXJjZXMoKTogUHJvbWlzZTxTdGFja1Jlc291cmNlU3VtbWFyeVtdPjtcbn1cblxuZXhwb3J0IGNsYXNzIExhenlMaXN0U3RhY2tSZXNvdXJjZXMgaW1wbGVtZW50cyBMaXN0U3RhY2tSZXNvdXJjZXMge1xuICBwcml2YXRlIHN0YWNrUmVzb3VyY2VzOiBQcm9taXNlPFN0YWNrUmVzb3VyY2VTdW1tYXJ5W10+IHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2RrOiBTREssXG4gICAgcHJpdmF0ZSByZWFkb25seSBzdGFja05hbWU6IHN0cmluZyxcbiAgKSB7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgbGlzdFN0YWNrUmVzb3VyY2VzKCk6IFByb21pc2U8U3RhY2tSZXNvdXJjZVN1bW1hcnlbXT4ge1xuICAgIGlmICh0aGlzLnN0YWNrUmVzb3VyY2VzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuc3RhY2tSZXNvdXJjZXMgPSB0aGlzLnNkay5jbG91ZEZvcm1hdGlvbigpLmxpc3RTdGFja1Jlc291cmNlcyh7XG4gICAgICAgIFN0YWNrTmFtZTogdGhpcy5zdGFja05hbWUsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3RhY2tSZXNvdXJjZXM7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBMb29rdXBFeHBvcnQge1xuICBsb29rdXBFeHBvcnQobmFtZTogc3RyaW5nKTogUHJvbWlzZTxFeHBvcnQgfCB1bmRlZmluZWQ+O1xufVxuXG5leHBvcnQgY2xhc3MgTG9va3VwRXhwb3J0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG59XG5cbmV4cG9ydCBjbGFzcyBMYXp5TG9va3VwRXhwb3J0IGltcGxlbWVudHMgTG9va3VwRXhwb3J0IHtcbiAgcHJpdmF0ZSBjYWNoZWRFeHBvcnRzOiB7IFtuYW1lOiBzdHJpbmddOiBFeHBvcnQgfSA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgc2RrOiBTREspIHtcbiAgfVxuXG4gIGFzeW5jIGxvb2t1cEV4cG9ydChuYW1lOiBzdHJpbmcpOiBQcm9taXNlPEV4cG9ydCB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICh0aGlzLmNhY2hlZEV4cG9ydHNbbmFtZV0pIHtcbiAgICAgIHJldHVybiB0aGlzLmNhY2hlZEV4cG9ydHNbbmFtZV07XG4gICAgfVxuXG4gICAgZm9yIGF3YWl0IChjb25zdCBjZm5FeHBvcnQgb2YgdGhpcy5saXN0RXhwb3J0cygpKSB7XG4gICAgICBpZiAoIWNmbkV4cG9ydC5OYW1lKSB7XG4gICAgICAgIGNvbnRpbnVlOyAvLyBpZ25vcmUgYW55IHJlc3VsdCB0aGF0IG9taXRzIGEgbmFtZVxuICAgICAgfVxuICAgICAgdGhpcy5jYWNoZWRFeHBvcnRzW2NmbkV4cG9ydC5OYW1lXSA9IGNmbkV4cG9ydDtcblxuICAgICAgaWYgKGNmbkV4cG9ydC5OYW1lID09PSBuYW1lKSB7XG4gICAgICAgIHJldHVybiBjZm5FeHBvcnQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDsgLy8gZXhwb3J0IG5vdCBmb3VuZFxuICB9XG5cbiAgLy8gVE9ETzogUGFnaW5hdGVcbiAgcHJpdmF0ZSBhc3luYyAqbGlzdEV4cG9ydHMoKSB7XG4gICAgbGV0IG5leHRUb2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCByZXNwb25zZTogTGlzdEV4cG9ydHNDb21tYW5kT3V0cHV0ID0gYXdhaXQgdGhpcy5zZGsuY2xvdWRGb3JtYXRpb24oKS5saXN0RXhwb3J0cyh7IE5leHRUb2tlbjogbmV4dFRva2VuIH0pO1xuICAgICAgZm9yIChjb25zdCBjZm5FeHBvcnQgb2YgcmVzcG9uc2UuRXhwb3J0cyA/PyBbXSkge1xuICAgICAgICB5aWVsZCBjZm5FeHBvcnQ7XG4gICAgICB9XG5cbiAgICAgIGlmICghcmVzcG9uc2UuTmV4dFRva2VuKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIG5leHRUb2tlbiA9IHJlc3BvbnNlLk5leHRUb2tlbjtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENmbkV2YWx1YXRpb25FeGNlcHRpb24gZXh0ZW5kcyBFcnJvciB7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VEZWZpbml0aW9uIHtcbiAgcmVhZG9ubHkgTG9naWNhbElkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IFR5cGU6IHN0cmluZztcbiAgcmVhZG9ubHkgUHJvcGVydGllczogeyBbcDogc3RyaW5nXTogYW55IH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXZhbHVhdGVDbG91ZEZvcm1hdGlvblRlbXBsYXRlUHJvcHMge1xuICByZWFkb25seSBzdGFja0FydGlmYWN0OiBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3Q7XG4gIHJlYWRvbmx5IHN0YWNrTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgdGVtcGxhdGU/OiBUZW1wbGF0ZTtcbiAgcmVhZG9ubHkgcGFyYW1ldGVyczogeyBbcGFyYW1ldGVyTmFtZTogc3RyaW5nXTogc3RyaW5nIH07XG4gIHJlYWRvbmx5IGFjY291bnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhcnRpdGlvbjogc3RyaW5nO1xuICByZWFkb25seSBzZGs6IFNESztcbiAgcmVhZG9ubHkgbmVzdGVkU3RhY2tzPzoge1xuICAgIFtuZXN0ZWRTdGFja0xvZ2ljYWxJZDogc3RyaW5nXTogTmVzdGVkU3RhY2tUZW1wbGF0ZXM7XG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBFdmFsdWF0ZUNsb3VkRm9ybWF0aW9uVGVtcGxhdGUge1xuICBwdWJsaWMgcmVhZG9ubHkgc3RhY2tBcnRpZmFjdDogQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0O1xuICBwcml2YXRlIHJlYWRvbmx5IHN0YWNrTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHRlbXBsYXRlOiBUZW1wbGF0ZTtcbiAgcHJpdmF0ZSByZWFkb25seSBjb250ZXh0OiB7IFtrOiBzdHJpbmddOiBhbnkgfTtcbiAgcHJpdmF0ZSByZWFkb25seSBhY2NvdW50OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGFydGl0aW9uOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2RrOiBTREs7XG4gIHByaXZhdGUgcmVhZG9ubHkgbmVzdGVkU3RhY2tzOiB7XG4gICAgW25lc3RlZFN0YWNrTG9naWNhbElkOiBzdHJpbmddOiBOZXN0ZWRTdGFja1RlbXBsYXRlcztcbiAgfTtcbiAgcHJpdmF0ZSByZWFkb25seSBzdGFja1Jlc291cmNlczogTGlzdFN0YWNrUmVzb3VyY2VzO1xuICBwcml2YXRlIHJlYWRvbmx5IGxvb2t1cEV4cG9ydDogTG9va3VwRXhwb3J0O1xuXG4gIHByaXZhdGUgY2FjaGVkVXJsU3VmZml4OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IocHJvcHM6IEV2YWx1YXRlQ2xvdWRGb3JtYXRpb25UZW1wbGF0ZVByb3BzKSB7XG4gICAgdGhpcy5zdGFja0FydGlmYWN0ID0gcHJvcHMuc3RhY2tBcnRpZmFjdDtcbiAgICB0aGlzLnN0YWNrTmFtZSA9IHByb3BzLnN0YWNrTmFtZSA/PyBwcm9wcy5zdGFja0FydGlmYWN0LnN0YWNrTmFtZTtcbiAgICB0aGlzLnRlbXBsYXRlID0gcHJvcHMudGVtcGxhdGUgPz8gcHJvcHMuc3RhY2tBcnRpZmFjdC50ZW1wbGF0ZTtcbiAgICB0aGlzLmNvbnRleHQgPSB7XG4gICAgICAnQVdTOjpBY2NvdW50SWQnOiBwcm9wcy5hY2NvdW50LFxuICAgICAgJ0FXUzo6UmVnaW9uJzogcHJvcHMucmVnaW9uLFxuICAgICAgJ0FXUzo6UGFydGl0aW9uJzogcHJvcHMucGFydGl0aW9uLFxuICAgICAgLi4ucHJvcHMucGFyYW1ldGVycyxcbiAgICB9O1xuICAgIHRoaXMuYWNjb3VudCA9IHByb3BzLmFjY291bnQ7XG4gICAgdGhpcy5yZWdpb24gPSBwcm9wcy5yZWdpb247XG4gICAgdGhpcy5wYXJ0aXRpb24gPSBwcm9wcy5wYXJ0aXRpb247XG4gICAgdGhpcy5zZGsgPSBwcm9wcy5zZGs7XG5cbiAgICAvLyBXZSBuZWVkIG5hbWVzIG9mIG5lc3RlZCBzdGFjayBzbyB3ZSBjYW4gZXZhbHVhdGUgY3Jvc3Mgc3RhY2sgcmVmZXJlbmNlc1xuICAgIHRoaXMubmVzdGVkU3RhY2tzID0gcHJvcHMubmVzdGVkU3RhY2tzID8/IHt9O1xuXG4gICAgLy8gVGhlIGN1cnJlbnQgcmVzb3VyY2VzIG9mIHRoZSBTdGFjay5cbiAgICAvLyBXZSBuZWVkIHRoZW0gdG8gZmlndXJlIG91dCB0aGUgcGh5c2ljYWwgbmFtZSBvZiBhIHJlc291cmNlIGluIGNhc2UgaXQgd2Fzbid0IHNwZWNpZmllZCBieSB0aGUgdXNlci5cbiAgICAvLyBXZSBmZXRjaCBpdCBsYXppbHksIHRvIHNhdmUgYSBzZXJ2aWNlIGNhbGwsIGluIGNhc2UgYWxsIGhvdHN3YXBwZWQgcmVzb3VyY2VzIGhhdmUgdGhlaXIgcGh5c2ljYWwgbmFtZXMgc2V0LlxuICAgIHRoaXMuc3RhY2tSZXNvdXJjZXMgPSBuZXcgTGF6eUxpc3RTdGFja1Jlc291cmNlcyh0aGlzLnNkaywgdGhpcy5zdGFja05hbWUpO1xuXG4gICAgLy8gQ2xvdWRGb3JtYXRpb24gRXhwb3J0cyBsb29rdXAgdG8gYmUgYWJsZSB0byByZXNvbHZlIEZuOjpJbXBvcnRWYWx1ZSBpbnRyaW5zaWNzIGluIHRlbXBsYXRlXG4gICAgdGhpcy5sb29rdXBFeHBvcnQgPSBuZXcgTGF6eUxvb2t1cEV4cG9ydCh0aGlzLnNkayk7XG4gIH1cblxuICAvLyBjbG9uZXMgY3VycmVudCBFdmFsdWF0ZUNsb3VkRm9ybWF0aW9uVGVtcGxhdGUgb2JqZWN0LCBidXQgdXBkYXRlcyB0aGUgc3RhY2sgbmFtZVxuICBwdWJsaWMgYXN5bmMgY3JlYXRlTmVzdGVkRXZhbHVhdGVDbG91ZEZvcm1hdGlvblRlbXBsYXRlKFxuICAgIHN0YWNrTmFtZTogc3RyaW5nLFxuICAgIG5lc3RlZFRlbXBsYXRlOiBUZW1wbGF0ZSxcbiAgICBuZXN0ZWRTdGFja1BhcmFtZXRlcnM6IHsgW3BhcmFtZXRlck5hbWU6IHN0cmluZ106IGFueSB9LFxuICApIHtcbiAgICBjb25zdCBldmFsdWF0ZWRQYXJhbXMgPSBhd2FpdCB0aGlzLmV2YWx1YXRlQ2ZuRXhwcmVzc2lvbihuZXN0ZWRTdGFja1BhcmFtZXRlcnMpO1xuICAgIHJldHVybiBuZXcgRXZhbHVhdGVDbG91ZEZvcm1hdGlvblRlbXBsYXRlKHtcbiAgICAgIHN0YWNrQXJ0aWZhY3Q6IHRoaXMuc3RhY2tBcnRpZmFjdCxcbiAgICAgIHN0YWNrTmFtZSxcbiAgICAgIHRlbXBsYXRlOiBuZXN0ZWRUZW1wbGF0ZSxcbiAgICAgIHBhcmFtZXRlcnM6IGV2YWx1YXRlZFBhcmFtcyxcbiAgICAgIGFjY291bnQ6IHRoaXMuYWNjb3VudCxcbiAgICAgIHJlZ2lvbjogdGhpcy5yZWdpb24sXG4gICAgICBwYXJ0aXRpb246IHRoaXMucGFydGl0aW9uLFxuICAgICAgc2RrOiB0aGlzLnNkayxcbiAgICAgIG5lc3RlZFN0YWNrczogdGhpcy5uZXN0ZWRTdGFja3MsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZXN0YWJsaXNoUmVzb3VyY2VQaHlzaWNhbE5hbWUoXG4gICAgbG9naWNhbElkOiBzdHJpbmcsXG4gICAgcGh5c2ljYWxOYW1lSW5DZm5UZW1wbGF0ZTogYW55LFxuICApOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGlmIChwaHlzaWNhbE5hbWVJbkNmblRlbXBsYXRlICE9IG51bGwpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmV2YWx1YXRlQ2ZuRXhwcmVzc2lvbihwaHlzaWNhbE5hbWVJbkNmblRlbXBsYXRlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gSWYgd2UgY2FuJ3QgZXZhbHVhdGUgdGhlIHJlc291cmNlJ3MgbmFtZSBDbG91ZEZvcm1hdGlvbiBleHByZXNzaW9uLFxuICAgICAgICAvLyBqdXN0IGxvb2sgaXQgdXAgaW4gdGhlIGN1cnJlbnRseSBkZXBsb3llZCBTdGFja1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgQ2ZuRXZhbHVhdGlvbkV4Y2VwdGlvbikpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmZpbmRQaHlzaWNhbE5hbWVGb3IobG9naWNhbElkKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBmaW5kUGh5c2ljYWxOYW1lRm9yKGxvZ2ljYWxJZDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBzdGFja1Jlc291cmNlcyA9IGF3YWl0IHRoaXMuc3RhY2tSZXNvdXJjZXMubGlzdFN0YWNrUmVzb3VyY2VzKCk7XG4gICAgcmV0dXJuIHN0YWNrUmVzb3VyY2VzLmZpbmQoKHNyKSA9PiBzci5Mb2dpY2FsUmVzb3VyY2VJZCA9PT0gbG9naWNhbElkKT8uUGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGZpbmRMb2dpY2FsSWRGb3JQaHlzaWNhbE5hbWUocGh5c2ljYWxOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHN0YWNrUmVzb3VyY2VzID0gYXdhaXQgdGhpcy5zdGFja1Jlc291cmNlcy5saXN0U3RhY2tSZXNvdXJjZXMoKTtcbiAgICByZXR1cm4gc3RhY2tSZXNvdXJjZXMuZmluZCgoc3IpID0+IHNyLlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gcGh5c2ljYWxOYW1lKT8uTG9naWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwdWJsaWMgZmluZFJlZmVyZW5jZXNUbyhsb2dpY2FsSWQ6IHN0cmluZyk6IEFycmF5PFJlc291cmNlRGVmaW5pdGlvbj4ge1xuICAgIGNvbnN0IHJldCA9IG5ldyBBcnJheTxSZXNvdXJjZURlZmluaXRpb24+KCk7XG4gICAgZm9yIChjb25zdCBbcmVzb3VyY2VMb2dpY2FsSWQsIHJlc291cmNlRGVmXSBvZiBPYmplY3QuZW50cmllcyh0aGlzLnRlbXBsYXRlPy5SZXNvdXJjZXMgPz8ge30pKSB7XG4gICAgICBpZiAobG9naWNhbElkICE9PSByZXNvdXJjZUxvZ2ljYWxJZCAmJiB0aGlzLnJlZmVyZW5jZXMobG9naWNhbElkLCByZXNvdXJjZURlZikpIHtcbiAgICAgICAgcmV0LnB1c2goe1xuICAgICAgICAgIC4uLihyZXNvdXJjZURlZiBhcyBhbnkpLFxuICAgICAgICAgIExvZ2ljYWxJZDogcmVzb3VyY2VMb2dpY2FsSWQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGV2YWx1YXRlQ2ZuRXhwcmVzc2lvbihjZm5FeHByZXNzaW9uOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIC8qKlxuICAgICAqIEV2YWx1YXRlcyBDbG91ZEZvcm1hdGlvbiBpbnRyaW5zaWMgZnVuY3Rpb25zXG4gICAgICpcbiAgICAgKiBOb3RlIHRoYXQgc3VwcG9ydGVkIGludHJpbnNpYyBmdW5jdGlvbnMgYXJlIGRvY3VtZW50ZWQgaW4gUkVBRE1FLm1kIC0tIHBsZWFzZSB1cGRhdGVcbiAgICAgKiBsaXN0IG9mIHN1cHBvcnRlZCBmdW5jdGlvbnMgd2hlbiBhZGRpbmcgbmV3IGV2YWx1YXRpb25zXG4gICAgICpcbiAgICAgKiBTZWU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2ludHJpbnNpYy1mdW5jdGlvbi1yZWZlcmVuY2UuaHRtbFxuICAgICAqL1xuICAgIGNsYXNzIENmbkludHJpbnNpY3Mge1xuICAgICAgcHVibGljIGV2YWx1YXRlSW50cmluc2ljKGludHJpbnNpYzogSW50cmluc2ljKTogYW55IHtcbiAgICAgICAgY29uc3QgaW50cmluc2ljRnVuYyA9ICh0aGlzIGFzIGFueSlbaW50cmluc2ljLm5hbWVdO1xuICAgICAgICBpZiAoIWludHJpbnNpY0Z1bmMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQ2ZuRXZhbHVhdGlvbkV4Y2VwdGlvbihgQ2xvdWRGb3JtYXRpb24gZnVuY3Rpb24gJHtpbnRyaW5zaWMubmFtZX0gaXMgbm90IHN1cHBvcnRlZGApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYXJnc0FzQXJyYXkgPSBBcnJheS5pc0FycmF5KGludHJpbnNpYy5hcmdzKSA/IGludHJpbnNpYy5hcmdzIDogW2ludHJpbnNpYy5hcmdzXTtcblxuICAgICAgICByZXR1cm4gaW50cmluc2ljRnVuYy5hcHBseSh0aGlzLCBhcmdzQXNBcnJheSk7XG4gICAgICB9XG5cbiAgICAgIGFzeW5jICdGbjo6Sm9pbicoc2VwYXJhdG9yOiBzdHJpbmcsIGFyZ3M6IGFueVtdKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgY29uc3QgZXZhbHVhdGVkQXJncyA9IGF3YWl0IHNlbGYuZXZhbHVhdGVDZm5FeHByZXNzaW9uKGFyZ3MpO1xuICAgICAgICByZXR1cm4gZXZhbHVhdGVkQXJncy5qb2luKHNlcGFyYXRvcik7XG4gICAgICB9XG5cbiAgICAgIGFzeW5jICdGbjo6U3BsaXQnKHNlcGFyYXRvcjogc3RyaW5nLCBhcmdzOiBhbnkpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICBjb25zdCBldmFsdWF0ZWRBcmdzID0gYXdhaXQgc2VsZi5ldmFsdWF0ZUNmbkV4cHJlc3Npb24oYXJncyk7XG4gICAgICAgIHJldHVybiBldmFsdWF0ZWRBcmdzLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICB9XG5cbiAgICAgIGFzeW5jICdGbjo6U2VsZWN0JyhpbmRleDogbnVtYmVyLCBhcmdzOiBhbnlbXSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIGNvbnN0IGV2YWx1YXRlZEFyZ3MgPSBhd2FpdCBzZWxmLmV2YWx1YXRlQ2ZuRXhwcmVzc2lvbihhcmdzKTtcbiAgICAgICAgcmV0dXJuIGV2YWx1YXRlZEFyZ3NbaW5kZXhdO1xuICAgICAgfVxuXG4gICAgICBhc3luYyBSZWYobG9naWNhbElkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICBjb25zdCByZWZUYXJnZXQgPSBhd2FpdCBzZWxmLmZpbmRSZWZUYXJnZXQobG9naWNhbElkKTtcbiAgICAgICAgaWYgKHJlZlRhcmdldCkge1xuICAgICAgICAgIHJldHVybiByZWZUYXJnZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IENmbkV2YWx1YXRpb25FeGNlcHRpb24oYFBhcmFtZXRlciBvciByZXNvdXJjZSAnJHtsb2dpY2FsSWR9JyBjb3VsZCBub3QgYmUgZm91bmQgZm9yIGV2YWx1YXRpb25gKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhc3luYyAnRm46OkdldEF0dCcobG9naWNhbElkOiBzdHJpbmcsIGF0dHJpYnV0ZU5hbWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIC8vIFRvRG8gaGFuZGxlIHRoZSAnbG9naWNhbElkLmF0dHJpYnV0ZU5hbWUnIGZvcm0gb2YgRm46OkdldEF0dFxuICAgICAgICBjb25zdCBhdHRyVmFsdWUgPSBhd2FpdCBzZWxmLmZpbmRHZXRBdHRUYXJnZXQobG9naWNhbElkLCBhdHRyaWJ1dGVOYW1lKTtcbiAgICAgICAgaWYgKGF0dHJWYWx1ZSkge1xuICAgICAgICAgIHJldHVybiBhdHRyVmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IENmbkV2YWx1YXRpb25FeGNlcHRpb24oXG4gICAgICAgICAgICBgQXR0cmlidXRlICcke2F0dHJpYnV0ZU5hbWV9JyBvZiByZXNvdXJjZSAnJHtsb2dpY2FsSWR9JyBjb3VsZCBub3QgYmUgZm91bmQgZm9yIGV2YWx1YXRpb25gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgYXN5bmMgJ0ZuOjpTdWInKHRlbXBsYXRlOiBzdHJpbmcsIGV4cGxpY2l0UGxhY2Vob2xkZXJzPzogeyBbdmFyaWFibGU6IHN0cmluZ106IHN0cmluZyB9KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgY29uc3QgcGxhY2Vob2xkZXJzID0gZXhwbGljaXRQbGFjZWhvbGRlcnMgPyBhd2FpdCBzZWxmLmV2YWx1YXRlQ2ZuRXhwcmVzc2lvbihleHBsaWNpdFBsYWNlaG9sZGVycykgOiB7fTtcblxuICAgICAgICByZXR1cm4gYXN5bmNHbG9iYWxSZXBsYWNlKHRlbXBsYXRlLCAvXFwkeyhbXn1dKil9L2csIChrZXkpID0+IHtcbiAgICAgICAgICBpZiAoa2V5IGluIHBsYWNlaG9sZGVycykge1xuICAgICAgICAgICAgcmV0dXJuIHBsYWNlaG9sZGVyc1trZXldO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBzcGxpdEtleSA9IGtleS5zcGxpdCgnLicpO1xuICAgICAgICAgICAgcmV0dXJuIHNwbGl0S2V5Lmxlbmd0aCA9PT0gMSA/IHRoaXMuUmVmKGtleSkgOiB0aGlzWydGbjo6R2V0QXR0J10oc3BsaXRLZXlbMF0sIHNwbGl0S2V5LnNsaWNlKDEpLmpvaW4oJy4nKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgYXN5bmMgJ0ZuOjpJbXBvcnRWYWx1ZScobmFtZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgY29uc3QgZXhwb3J0ZWQgPSBhd2FpdCBzZWxmLmxvb2t1cEV4cG9ydC5sb29rdXBFeHBvcnQobmFtZSk7XG4gICAgICAgIGlmICghZXhwb3J0ZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQ2ZuRXZhbHVhdGlvbkV4Y2VwdGlvbihgRXhwb3J0ICcke25hbWV9JyBjb3VsZCBub3QgYmUgZm91bmQgZm9yIGV2YWx1YXRpb25gKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWV4cG9ydGVkLlZhbHVlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IENmbkV2YWx1YXRpb25FeGNlcHRpb24oYEV4cG9ydCAnJHtuYW1lfScgZXhpc3RzIHdpdGhvdXQgYSB2YWx1ZWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBleHBvcnRlZC5WYWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2ZuRXhwcmVzc2lvbiA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY2ZuRXhwcmVzc2lvbjtcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShjZm5FeHByZXNzaW9uKSkge1xuICAgICAgLy8gU21hbGwgYXJyYXlzIGluIHByYWN0aWNlXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGNka2xhYnMvcHJvbWlzZWFsbC1uby11bmJvdW5kZWQtcGFyYWxsZWxpc21cbiAgICAgIHJldHVybiBQcm9taXNlLmFsbChjZm5FeHByZXNzaW9uLm1hcCgoZXhwcikgPT4gdGhpcy5ldmFsdWF0ZUNmbkV4cHJlc3Npb24oZXhwcikpKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGNmbkV4cHJlc3Npb24gPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCBpbnRyaW5zaWMgPSB0aGlzLnBhcnNlSW50cmluc2ljKGNmbkV4cHJlc3Npb24pO1xuICAgICAgaWYgKGludHJpbnNpYykge1xuICAgICAgICByZXR1cm4gbmV3IENmbkludHJpbnNpY3MoKS5ldmFsdWF0ZUludHJpbnNpYyhpbnRyaW5zaWMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcmV0OiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0ge307XG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBPYmplY3QuZW50cmllcyhjZm5FeHByZXNzaW9uKSkge1xuICAgICAgICAgIHJldFtrZXldID0gYXdhaXQgdGhpcy5ldmFsdWF0ZUNmbkV4cHJlc3Npb24odmFsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjZm5FeHByZXNzaW9uO1xuICB9XG5cbiAgcHVibGljIGdldFJlc291cmNlUHJvcGVydHkobG9naWNhbElkOiBzdHJpbmcsIHByb3BlcnR5TmFtZTogc3RyaW5nKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy50ZW1wbGF0ZS5SZXNvdXJjZXM/Lltsb2dpY2FsSWRdPy5Qcm9wZXJ0aWVzPy5bcHJvcGVydHlOYW1lXTtcbiAgfVxuXG4gIHB1YmxpYyBtZXRhZGF0YUZvcihsb2dpY2FsSWQ6IHN0cmluZyk6IFJlc291cmNlTWV0YWRhdGEgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiByZXNvdXJjZU1ldGFkYXRhKHRoaXMuc3RhY2tBcnRpZmFjdCwgbG9naWNhbElkKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVmZXJlbmNlcyhsb2dpY2FsSWQ6IHN0cmluZywgdGVtcGxhdGVFbGVtZW50OiBhbnkpOiBib29sZWFuIHtcbiAgICBpZiAodHlwZW9mIHRlbXBsYXRlRWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBsb2dpY2FsSWQgPT09IHRlbXBsYXRlRWxlbWVudDtcbiAgICB9XG5cbiAgICBpZiAodGVtcGxhdGVFbGVtZW50ID09IG51bGwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0ZW1wbGF0ZUVsZW1lbnQpKSB7XG4gICAgICByZXR1cm4gdGVtcGxhdGVFbGVtZW50LnNvbWUoKGVsKSA9PiB0aGlzLnJlZmVyZW5jZXMobG9naWNhbElkLCBlbCkpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdGVtcGxhdGVFbGVtZW50ID09PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGVtcGxhdGVFbGVtZW50KS5zb21lKChlbCkgPT4gdGhpcy5yZWZlcmVuY2VzKGxvZ2ljYWxJZCwgZWwpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIHBhcnNlSW50cmluc2ljKHg6IGFueSk6IEludHJpbnNpYyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHgpO1xuICAgIGlmIChrZXlzLmxlbmd0aCA9PT0gMSAmJiAoa2V5c1swXS5zdGFydHNXaXRoKCdGbjo6JykgfHwga2V5c1swXSA9PT0gJ1JlZicpKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBrZXlzWzBdLFxuICAgICAgICBhcmdzOiB4W2tleXNbMF1dLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmluZFJlZlRhcmdldChsb2dpY2FsSWQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgLy8gZmlyc3QsIGNoZWNrIHRvIHNlZSBpZiB0aGUgUmVmIGlzIGEgUGFyYW1ldGVyIHdobydzIHZhbHVlIHdlIGhhdmVcbiAgICBpZiAobG9naWNhbElkID09PSAnQVdTOjpVUkxTdWZmaXgnKSB7XG4gICAgICBpZiAoIXRoaXMuY2FjaGVkVXJsU3VmZml4KSB7XG4gICAgICAgIHRoaXMuY2FjaGVkVXJsU3VmZml4ID0gYXdhaXQgdGhpcy5zZGsuZ2V0VXJsU3VmZml4KHRoaXMucmVnaW9uKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuY2FjaGVkVXJsU3VmZml4O1xuICAgIH1cblxuICAgIC8vIFRyeSBmaW5kaW5nIHRoZSByZWYgaW4gdGhlIHBhc3NlZCBpbiBwYXJhbWV0ZXJzXG4gICAgY29uc3QgcGFyYW1ldGVyVGFyZ2V0ID0gdGhpcy5jb250ZXh0W2xvZ2ljYWxJZF07XG4gICAgaWYgKHBhcmFtZXRlclRhcmdldCkge1xuICAgICAgcmV0dXJuIHBhcmFtZXRlclRhcmdldDtcbiAgICB9XG5cbiAgICAvLyBJZiBub3QgaW4gdGhlIHBhc3NlZCBpbiBwYXJhbWV0ZXJzLCBzZWUgaWYgdGhlcmUgaXMgYSBkZWZhdWx0IHZhbHVlIGluIHRoZSB0ZW1wbGF0ZSBwYXJhbWV0ZXIgdGhhdCB3YXMgbm90IHBhc3NlZCBpblxuICAgIGNvbnN0IGRlZmF1bHRQYXJhbWV0ZXJWYWx1ZSA9IHRoaXMudGVtcGxhdGUuUGFyYW1ldGVycz8uW2xvZ2ljYWxJZF0/LkRlZmF1bHQ7XG4gICAgaWYgKGRlZmF1bHRQYXJhbWV0ZXJWYWx1ZSkge1xuICAgICAgcmV0dXJuIGRlZmF1bHRQYXJhbWV0ZXJWYWx1ZTtcbiAgICB9XG5cbiAgICAvLyBpZiBpdCdzIG5vdCBhIFBhcmFtZXRlciwgd2UgbmVlZCB0byBzZWFyY2ggaW4gdGhlIGN1cnJlbnQgU3RhY2sgcmVzb3VyY2VzXG4gICAgcmV0dXJuIHRoaXMuZmluZEdldEF0dFRhcmdldChsb2dpY2FsSWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5kR2V0QXR0VGFyZ2V0KGxvZ2ljYWxJZDogc3RyaW5nLCBhdHRyaWJ1dGU/OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIC8vIEhhbmRsZSBjYXNlIHdoZXJlIHRoZSBhdHRyaWJ1dGUgaXMgcmVmZXJlbmNpbmcgYSBzdGFjayBvdXRwdXQgKHVzZWQgaW4gbmVzdGVkIHN0YWNrcyB0byBzaGFyZSBwYXJhbWV0ZXJzKVxuICAgIC8vIFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9xdWlja3JlZi1jbG91ZGZvcm1hdGlvbi5odG1sI3cyYWIxYzE3YzIzYzE5YjVcbiAgICBpZiAobG9naWNhbElkID09PSAnT3V0cHV0cycgJiYgYXR0cmlidXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5ldmFsdWF0ZUNmbkV4cHJlc3Npb24odGhpcy50ZW1wbGF0ZS5PdXRwdXRzW2F0dHJpYnV0ZV0/LlZhbHVlKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFja1Jlc291cmNlcyA9IGF3YWl0IHRoaXMuc3RhY2tSZXNvdXJjZXMubGlzdFN0YWNrUmVzb3VyY2VzKCk7XG4gICAgY29uc3QgZm91bmRSZXNvdXJjZSA9IHN0YWNrUmVzb3VyY2VzLmZpbmQoKHNyKSA9PiBzci5Mb2dpY2FsUmVzb3VyY2VJZCA9PT0gbG9naWNhbElkKTtcbiAgICBpZiAoIWZvdW5kUmVzb3VyY2UpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKGZvdW5kUmVzb3VyY2UuUmVzb3VyY2VUeXBlID09ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycgJiYgYXR0cmlidXRlPy5zdGFydHNXaXRoKCdPdXRwdXRzLicpKSB7XG4gICAgICBjb25zdCBkZXBlbmRhbnRTdGFjayA9IHRoaXMuZmluZE5lc3RlZFN0YWNrKGxvZ2ljYWxJZCwgdGhpcy5uZXN0ZWRTdGFja3MpO1xuICAgICAgaWYgKCFkZXBlbmRhbnRTdGFjayB8fCAhZGVwZW5kYW50U3RhY2sucGh5c2ljYWxOYW1lKSB7XG4gICAgICAgIC8vIHRoaXMgaXMgYSBuZXdseSBjcmVhdGVkIG5lc3RlZCBzdGFjayBhbmQgY2Fubm90IGJlIGhvdHN3YXBwZWRcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV2YWx1YXRlQ2ZuVGVtcGxhdGUgPSBhd2FpdCB0aGlzLmNyZWF0ZU5lc3RlZEV2YWx1YXRlQ2xvdWRGb3JtYXRpb25UZW1wbGF0ZShcbiAgICAgICAgZGVwZW5kYW50U3RhY2sucGh5c2ljYWxOYW1lLFxuICAgICAgICBkZXBlbmRhbnRTdGFjay5nZW5lcmF0ZWRUZW1wbGF0ZSxcbiAgICAgICAgZGVwZW5kYW50U3RhY2suZ2VuZXJhdGVkVGVtcGxhdGUuUGFyYW1ldGVycyEsXG4gICAgICApO1xuXG4gICAgICAvLyBTcGxpdCBPdXRwdXRzLjxyZWZOYW1lPiBpbnRvICdPdXRwdXRzJyBhbmQgJzxyZWZOYW1lPicgYW5kIHJlY3Vyc2l2ZWx5IGNhbGwgZXZhbHVhdGVcbiAgICAgIHJldHVybiBldmFsdWF0ZUNmblRlbXBsYXRlLmV2YWx1YXRlQ2ZuRXhwcmVzc2lvbih7XG4gICAgICAgICdGbjo6R2V0QXR0JzogYXR0cmlidXRlLnNwbGl0KC9cXC4oLiopL3MpLFxuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIG5vdywgd2UgbmVlZCB0byBmb3JtYXQgdGhlIGFwcHJvcHJpYXRlIGlkZW50aWZpZXIgZGVwZW5kaW5nIG9uIHRoZSByZXNvdXJjZSB0eXBlLFxuICAgIC8vIGFuZCB0aGUgcmVxdWVzdGVkIGF0dHJpYnV0ZSBuYW1lXG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0UmVzb3VyY2VBdHRyaWJ1dGUoZm91bmRSZXNvdXJjZSwgYXR0cmlidXRlKTtcbiAgfVxuXG4gIHByaXZhdGUgZmluZE5lc3RlZFN0YWNrKFxuICAgIGxvZ2ljYWxJZDogc3RyaW5nLFxuICAgIG5lc3RlZFN0YWNrczoge1xuICAgICAgW25lc3RlZFN0YWNrTG9naWNhbElkOiBzdHJpbmddOiBOZXN0ZWRTdGFja1RlbXBsYXRlcztcbiAgICB9LFxuICApOiBOZXN0ZWRTdGFja1RlbXBsYXRlcyB8IHVuZGVmaW5lZCB7XG4gICAgZm9yIChjb25zdCBuZXN0ZWRTdGFja0xvZ2ljYWxJZCBvZiBPYmplY3Qua2V5cyhuZXN0ZWRTdGFja3MpKSB7XG4gICAgICBpZiAobmVzdGVkU3RhY2tMb2dpY2FsSWQgPT09IGxvZ2ljYWxJZCkge1xuICAgICAgICByZXR1cm4gbmVzdGVkU3RhY2tzW25lc3RlZFN0YWNrTG9naWNhbElkXTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNoZWNrSW5OZXN0ZWRDaGlsZFN0YWNrcyA9IHRoaXMuZmluZE5lc3RlZFN0YWNrKFxuICAgICAgICBsb2dpY2FsSWQsXG4gICAgICAgIG5lc3RlZFN0YWNrc1tuZXN0ZWRTdGFja0xvZ2ljYWxJZF0ubmVzdGVkU3RhY2tUZW1wbGF0ZXMsXG4gICAgICApO1xuICAgICAgaWYgKGNoZWNrSW5OZXN0ZWRDaGlsZFN0YWNrcykgcmV0dXJuIGNoZWNrSW5OZXN0ZWRDaGlsZFN0YWNrcztcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgZm9ybWF0UmVzb3VyY2VBdHRyaWJ1dGUocmVzb3VyY2U6IFN0YWNrUmVzb3VyY2VTdW1tYXJ5LCBhdHRyaWJ1dGU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgcGh5c2ljYWxJZCA9IHJlc291cmNlLlBoeXNpY2FsUmVzb3VyY2VJZDtcblxuICAgIC8vIG5vIGF0dHJpYnV0ZSBtZWFucyBSZWYgZXhwcmVzc2lvbiwgZm9yIHdoaWNoIHdlIHVzZSB0aGUgcGh5c2ljYWwgSUQgZGlyZWN0bHlcbiAgICBpZiAoIWF0dHJpYnV0ZSkge1xuICAgICAgcmV0dXJuIHBoeXNpY2FsSWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzb3VyY2VUeXBlRm9ybWF0cyA9IFJFU09VUkNFX1RZUEVfQVRUUklCVVRFU19GT1JNQVRTW3Jlc291cmNlLlJlc291cmNlVHlwZSFdO1xuICAgIGlmICghcmVzb3VyY2VUeXBlRm9ybWF0cykge1xuICAgICAgdGhyb3cgbmV3IENmbkV2YWx1YXRpb25FeGNlcHRpb24oXG4gICAgICAgIGBXZSBkb24ndCBzdXBwb3J0IGF0dHJpYnV0ZXMgb2YgdGhlICcke3Jlc291cmNlLlJlc291cmNlVHlwZX0nIHJlc291cmNlLiBUaGlzIGlzIGEgQ0RLIGxpbWl0YXRpb24uIGAgK1xuICAgICAgICAgICdQbGVhc2UgcmVwb3J0IGl0IGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvbmV3L2Nob29zZScsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBhdHRyaWJ1dGVGbXRGdW5jID0gcmVzb3VyY2VUeXBlRm9ybWF0c1thdHRyaWJ1dGVdO1xuICAgIGlmICghYXR0cmlidXRlRm10RnVuYykge1xuICAgICAgdGhyb3cgbmV3IENmbkV2YWx1YXRpb25FeGNlcHRpb24oXG4gICAgICAgIGBXZSBkb24ndCBzdXBwb3J0IHRoZSAnJHthdHRyaWJ1dGV9JyBhdHRyaWJ1dGUgb2YgdGhlICcke3Jlc291cmNlLlJlc291cmNlVHlwZX0nIHJlc291cmNlLiBUaGlzIGlzIGEgQ0RLIGxpbWl0YXRpb24uIGAgK1xuICAgICAgICAgICdQbGVhc2UgcmVwb3J0IGl0IGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvbmV3L2Nob29zZScsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBzZXJ2aWNlID0gdGhpcy5nZXRTZXJ2aWNlT2ZSZXNvdXJjZShyZXNvdXJjZSk7XG4gICAgY29uc3QgcmVzb3VyY2VUeXBlQXJuUGFydCA9IHRoaXMuZ2V0UmVzb3VyY2VUeXBlQXJuUGFydE9mUmVzb3VyY2UocmVzb3VyY2UpO1xuICAgIHJldHVybiBhdHRyaWJ1dGVGbXRGdW5jKHtcbiAgICAgIHBhcnRpdGlvbjogdGhpcy5wYXJ0aXRpb24sXG4gICAgICBzZXJ2aWNlLFxuICAgICAgcmVnaW9uOiB0aGlzLnJlZ2lvbixcbiAgICAgIGFjY291bnQ6IHRoaXMuYWNjb3VudCxcbiAgICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2VUeXBlQXJuUGFydCxcbiAgICAgIHJlc291cmNlTmFtZTogcGh5c2ljYWxJZCEsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldFNlcnZpY2VPZlJlc291cmNlKHJlc291cmNlOiBTdGFja1Jlc291cmNlU3VtbWFyeSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHJlc291cmNlLlJlc291cmNlVHlwZSEuc3BsaXQoJzo6JylbMV0udG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UmVzb3VyY2VUeXBlQXJuUGFydE9mUmVzb3VyY2UocmVzb3VyY2U6IFN0YWNrUmVzb3VyY2VTdW1tYXJ5KTogc3RyaW5nIHtcbiAgICBjb25zdCByZXNvdXJjZVR5cGUgPSByZXNvdXJjZS5SZXNvdXJjZVR5cGUhO1xuICAgIGNvbnN0IHNwZWNpYWxDYXNlUmVzb3VyY2VUeXBlID0gUkVTT1VSQ0VfVFlQRV9TUEVDSUFMX05BTUVTW3Jlc291cmNlVHlwZV0/LnJlc291cmNlVHlwZTtcbiAgICByZXR1cm4gc3BlY2lhbENhc2VSZXNvdXJjZVR5cGVcbiAgICAgID8gc3BlY2lhbENhc2VSZXNvdXJjZVR5cGVcbiAgICAgIDogLy8gdGhpcyBpcyB0aGUgZGVmYXVsdCBjYXNlXG4gICAgICByZXNvdXJjZVR5cGUuc3BsaXQoJzo6JylbMl0udG9Mb3dlckNhc2UoKTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgQXJuUGFydHMge1xuICByZWFkb25seSBwYXJ0aXRpb246IHN0cmluZztcbiAgcmVhZG9ubHkgc2VydmljZTogc3RyaW5nO1xuICByZWFkb25seSByZWdpb246IHN0cmluZztcbiAgcmVhZG9ubHkgYWNjb3VudDogc3RyaW5nO1xuICByZWFkb25seSByZXNvdXJjZVR5cGU6IHN0cmluZztcbiAgcmVhZG9ubHkgcmVzb3VyY2VOYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVXN1YWxseSwgd2UgZGVkdWNlIHRoZSBuYW1lcyBvZiB0aGUgc2VydmljZSBhbmQgdGhlIHJlc291cmNlIHR5cGUgdXNlZCB0byBmb3JtYXQgdGhlIEFSTiBmcm9tIHRoZSBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSB0eXBlLlxuICogRm9yIGEgQ0ZOIHR5cGUgbGlrZSBBV1M6OlNlcnZpY2U6OlJlc291cmNlVHlwZSwgdGhlIHNlY29uZCBzZWdtZW50IGJlY29tZXMgdGhlIHNlcnZpY2UgbmFtZSwgYW5kIHRoZSB0aGlyZCB0aGUgcmVzb3VyY2UgdHlwZVxuICogKGFmdGVyIGNvbnZlcnRpbmcgYm90aCBvZiB0aGVtIHRvIGxvd2VyY2FzZSkuXG4gKiBIb3dldmVyLCBzb21lIHJlc291cmNlIHR5cGVzIGJyZWFrIHRoaXMgc2ltcGxlIGNvbnZlbnRpb24sIGFuZCB3ZSBuZWVkIHRvIHNwZWNpYWwtY2FzZSB0aGVtLlxuICogVGhpcyBtYXAgaXMgZm9yIHN0b3JpbmcgdGhvc2UgY2FzZXMuXG4gKi9cbmNvbnN0IFJFU09VUkNFX1RZUEVfU1BFQ0lBTF9OQU1FUzoge1xuICBbdHlwZTogc3RyaW5nXTogeyByZXNvdXJjZVR5cGU6IHN0cmluZyB9O1xufSA9IHtcbiAgJ0FXUzo6RXZlbnRzOjpFdmVudEJ1cyc6IHtcbiAgICByZXNvdXJjZVR5cGU6ICdldmVudC1idXMnLFxuICB9LFxufTtcblxuY29uc3QgUkVTT1VSQ0VfVFlQRV9BVFRSSUJVVEVTX0ZPUk1BVFM6IHtcbiAgW3R5cGU6IHN0cmluZ106IHsgW2F0dHJpYnV0ZTogc3RyaW5nXTogKHBhcnRzOiBBcm5QYXJ0cykgPT4gc3RyaW5nIH07XG59ID0ge1xuICAnQVdTOjpJQU06OlJvbGUnOiB7IEFybjogaWFtQXJuRm10IH0sXG4gICdBV1M6OklBTTo6VXNlcic6IHsgQXJuOiBpYW1Bcm5GbXQgfSxcbiAgJ0FXUzo6SUFNOjpHcm91cCc6IHsgQXJuOiBpYW1Bcm5GbXQgfSxcbiAgJ0FXUzo6UzM6OkJ1Y2tldCc6IHsgQXJuOiBzM0FybkZtdCB9LFxuICAnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJzogeyBBcm46IHN0ZENvbG9uUmVzb3VyY2VBcm5GbXQgfSxcbiAgJ0FXUzo6RXZlbnRzOjpFdmVudEJ1cyc6IHtcbiAgICBBcm46IHN0ZFNsYXNoUmVzb3VyY2VBcm5GbXQsXG4gICAgLy8gdGhlIG5hbWUgYXR0cmlidXRlIG9mIHRoZSBFdmVudEJ1cyBpcyB0aGUgc2FtZSBhcyB0aGUgUmVmXG4gICAgTmFtZTogKHBhcnRzKSA9PiBwYXJ0cy5yZXNvdXJjZU5hbWUsXG4gIH0sXG4gICdBV1M6OkR5bmFtb0RCOjpUYWJsZSc6IHsgQXJuOiBzdGRTbGFzaFJlc291cmNlQXJuRm10IH0sXG4gICdBV1M6OkFwcFN5bmM6OkdyYXBoUUxBcGknOiB7IEFwaUlkOiBhcHBzeW5jR3JhcGhRbEFwaUFwaUlkRm10IH0sXG4gICdBV1M6OkFwcFN5bmM6OkZ1bmN0aW9uQ29uZmlndXJhdGlvbic6IHtcbiAgICBGdW5jdGlvbklkOiBhcHBzeW5jR3JhcGhRbEZ1bmN0aW9uSURGbXQsXG4gIH0sXG4gICdBV1M6OkFwcFN5bmM6OkRhdGFTb3VyY2UnOiB7IE5hbWU6IGFwcHN5bmNHcmFwaFFsRGF0YVNvdXJjZU5hbWVGbXQgfSxcbiAgJ0FXUzo6S01TOjpLZXknOiB7IEFybjogc3RkU2xhc2hSZXNvdXJjZUFybkZtdCB9LFxufTtcblxuZnVuY3Rpb24gaWFtQXJuRm10KHBhcnRzOiBBcm5QYXJ0cyk6IHN0cmluZyB7XG4gIC8vIHdlIHNraXAgcmVnaW9uIGZvciBJQU0gcmVzb3VyY2VzXG4gIHJldHVybiBgYXJuOiR7cGFydHMucGFydGl0aW9ufToke3BhcnRzLnNlcnZpY2V9Ojoke3BhcnRzLmFjY291bnR9OiR7cGFydHMucmVzb3VyY2VUeXBlfS8ke3BhcnRzLnJlc291cmNlTmFtZX1gO1xufVxuXG5mdW5jdGlvbiBzM0FybkZtdChwYXJ0czogQXJuUGFydHMpOiBzdHJpbmcge1xuICAvLyB3ZSBza2lwIGFjY291bnQsIHJlZ2lvbiBhbmQgcmVzb3VyY2VUeXBlIGZvciBTMyByZXNvdXJjZXNcbiAgcmV0dXJuIGBhcm46JHtwYXJ0cy5wYXJ0aXRpb259OiR7cGFydHMuc2VydmljZX06Ojoke3BhcnRzLnJlc291cmNlTmFtZX1gO1xufVxuXG5mdW5jdGlvbiBzdGRDb2xvblJlc291cmNlQXJuRm10KHBhcnRzOiBBcm5QYXJ0cyk6IHN0cmluZyB7XG4gIC8vIHRoaXMgaXMgYSBzdGFuZGFyZCBmb3JtYXQgZm9yIEFSTnMgbGlrZTogYXJuOmF3czpzZXJ2aWNlOnJlZ2lvbjphY2NvdW50OnJlc291cmNlVHlwZTpyZXNvdXJjZU5hbWVcbiAgcmV0dXJuIGBhcm46JHtwYXJ0cy5wYXJ0aXRpb259OiR7cGFydHMuc2VydmljZX06JHtwYXJ0cy5yZWdpb259OiR7cGFydHMuYWNjb3VudH06JHtwYXJ0cy5yZXNvdXJjZVR5cGV9OiR7cGFydHMucmVzb3VyY2VOYW1lfWA7XG59XG5cbmZ1bmN0aW9uIHN0ZFNsYXNoUmVzb3VyY2VBcm5GbXQocGFydHM6IEFyblBhcnRzKTogc3RyaW5nIHtcbiAgLy8gdGhpcyBpcyBhIHN0YW5kYXJkIGZvcm1hdCBmb3IgQVJOcyBsaWtlOiBhcm46YXdzOnNlcnZpY2U6cmVnaW9uOmFjY291bnQ6cmVzb3VyY2VUeXBlL3Jlc291cmNlTmFtZVxuICByZXR1cm4gYGFybjoke3BhcnRzLnBhcnRpdGlvbn06JHtwYXJ0cy5zZXJ2aWNlfToke3BhcnRzLnJlZ2lvbn06JHtwYXJ0cy5hY2NvdW50fToke3BhcnRzLnJlc291cmNlVHlwZX0vJHtwYXJ0cy5yZXNvdXJjZU5hbWV9YDtcbn1cblxuZnVuY3Rpb24gYXBwc3luY0dyYXBoUWxBcGlBcGlJZEZtdChwYXJ0czogQXJuUGFydHMpOiBzdHJpbmcge1xuICAvLyBhcm46YXdzOmFwcHN5bmM6dXMtZWFzdC0xOjExMTExMTExMTExMTphcGlzLzxhcGlJZD5cbiAgcmV0dXJuIHBhcnRzLnJlc291cmNlTmFtZS5zcGxpdCgnLycpWzFdO1xufVxuXG5mdW5jdGlvbiBhcHBzeW5jR3JhcGhRbEZ1bmN0aW9uSURGbXQocGFydHM6IEFyblBhcnRzKTogc3RyaW5nIHtcbiAgLy8gYXJuOmF3czphcHBzeW5jOnVzLWVhc3QtMToxMTExMTExMTExMTE6YXBpcy88YXBpSWQ+L2Z1bmN0aW9ucy88ZnVuY3Rpb25JZD5cbiAgcmV0dXJuIHBhcnRzLnJlc291cmNlTmFtZS5zcGxpdCgnLycpWzNdO1xufVxuXG5mdW5jdGlvbiBhcHBzeW5jR3JhcGhRbERhdGFTb3VyY2VOYW1lRm10KHBhcnRzOiBBcm5QYXJ0cyk6IHN0cmluZyB7XG4gIC8vIGFybjphd3M6YXBwc3luYzp1cy1lYXN0LTE6MTExMTExMTExMTExOmFwaXMvPGFwaUlkPi9kYXRhc291cmNlcy88bmFtZT5cbiAgcmV0dXJuIHBhcnRzLnJlc291cmNlTmFtZS5zcGxpdCgnLycpWzNdO1xufVxuXG5pbnRlcmZhY2UgSW50cmluc2ljIHtcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICByZWFkb25seSBhcmdzOiBhbnk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGFzeW5jR2xvYmFsUmVwbGFjZShzdHI6IHN0cmluZywgcmVnZXg6IFJlZ0V4cCwgY2I6ICh4OiBzdHJpbmcpID0+IFByb21pc2U8c3RyaW5nPik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmICghcmVnZXguZ2xvYmFsKSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignUmVnZXggbXVzdCBiZSBjcmVhdGVkIHdpdGggL2cgZmxhZycpO1xuICB9XG5cbiAgY29uc3QgcmV0ID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgbGV0IHN0YXJ0ID0gMDtcbiAgd2hpbGUgKHRydWUpIHtcbiAgICBjb25zdCBtYXRjaCA9IHJlZ2V4LmV4ZWMoc3RyKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICByZXQucHVzaChzdHIuc3Vic3RyaW5nKHN0YXJ0LCBtYXRjaC5pbmRleCkpO1xuICAgIHJldC5wdXNoKGF3YWl0IGNiKG1hdGNoWzFdKSk7XG5cbiAgICBzdGFydCA9IHJlZ2V4Lmxhc3RJbmRleDtcbiAgfVxuICByZXQucHVzaChzdHIuc2xpY2Uoc3RhcnQpKTtcblxuICByZXR1cm4gcmV0LmpvaW4oJycpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.d.ts new file mode 100644 index 000000000..5a88aed86 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.d.ts @@ -0,0 +1,4 @@ +export * from './evaluate-cloudformation-template'; +export * from './template-body-parameter'; +export * from './nested-stack-helpers'; +export * from './stack-helpers'; diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.js b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.js new file mode 100644 index 000000000..aeec18e19 --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/index.js @@ -0,0 +1,21 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./evaluate-cloudformation-template"), exports); +__exportStar(require("./template-body-parameter"), exports); +__exportStar(require("./nested-stack-helpers"), exports); +__exportStar(require("./stack-helpers"), exports); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2Nsb3VkZm9ybWF0aW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxRUFBbUQ7QUFDbkQsNERBQTBDO0FBQzFDLHlEQUF1QztBQUN2QyxrREFBZ0MiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2V2YWx1YXRlLWNsb3VkZm9ybWF0aW9uLXRlbXBsYXRlJztcbmV4cG9ydCAqIGZyb20gJy4vdGVtcGxhdGUtYm9keS1wYXJhbWV0ZXInO1xuZXhwb3J0ICogZnJvbSAnLi9uZXN0ZWQtc3RhY2staGVscGVycyc7XG5leHBvcnQgKiBmcm9tICcuL3N0YWNrLWhlbHBlcnMnO1xuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/nested-stack-helpers.d.ts b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/nested-stack-helpers.d.ts new file mode 100644 index 000000000..495da00dc --- /dev/null +++ b/packages/@aws-cdk/tmp-toolkit-helpers/lib/api/cloudformation/nested-stack-helpers.d.ts @@ -0,0 +1,25 @@ +import type { CloudFormationStackArtifact } from '@aws-cdk/cx-api'; +import type { SDK } from '../aws-auth'; +import { type Template } from './stack-helpers'; +export interface RootTemplateWithNestedStacks { + readonly deployedRootTemplate: Template; + readonly nestedStacks: { + [nestedStackLogicalId: string]: NestedStackTemplates; + }; +} +/** + * Reads the currently deployed template and all of its nested stack templates from CloudFormation. + */ +export declare function loadCurrentTemplateWithNestedStacks(rootStackArtifact: CloudFormationStackArtifact, sdk: SDK, retrieveProcessedTemplate?: boolean): Promise; +/** + * Returns the currently deployed template from CloudFormation that corresponds to `stackArtifact`. + */ +export declare function loadCurrentTemplate(stackArtifact: CloudFormationStackArtifact, sdk: SDK, retrieveProcessedTemplate?: boolean): Promise