aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
661 lines • 76.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const setup = require("./hotswap-test-setup");
const evaluate_cloudformation_template_1 = require("../../../lib/api/evaluate-cloudformation-template");
const common_1 = require("../../../lib/api/hotswap/common");
let hotswapMockSdkProvider;
let mockUpdateLambdaCode;
let mockUpdateMachineDefinition;
let mockGetEndpointSuffix;
beforeEach(() => {
hotswapMockSdkProvider = setup.setupHotswapTests();
mockUpdateLambdaCode = jest.fn().mockReturnValue({});
mockUpdateMachineDefinition = jest.fn();
mockGetEndpointSuffix = jest.fn(() => 'amazonaws.com');
hotswapMockSdkProvider.stubLambda({
updateFunctionCode: mockUpdateLambdaCode,
});
hotswapMockSdkProvider.setUpdateStateMachineMock(mockUpdateMachineDefinition);
hotswapMockSdkProvider.stubGetEndpointSuffix(mockGetEndpointSuffix);
});
describe.each([common_1.HotswapMode.FALL_BACK, common_1.HotswapMode.HOTSWAP_ONLY])('%p mode', (hotswapMode) => {
test('returns a deployStackResult with noOp=true when it receives an empty set of changes', async () => {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, setup.cdkStackArtifactOf());
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(deployStackResult?.noOp).toBeTruthy();
expect(deployStackResult?.stackArn).toEqual(setup.STACK_ID);
});
test('A change to only a non-hotswappable resource results in a full deployment for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
SomethingElse: {
Type: 'AWS::CloudFormation::SomethingElse',
Properties: {
Prop: 'old-value',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
SomethingElse: {
Type: 'AWS::CloudFormation::SomethingElse',
Properties: {
Prop: 'new-value',
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(deployStackResult?.noOp).toEqual(true);
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
});
test('A change to both a hotswappable resource and a non-hotswappable resource results in a full deployment for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'old-path',
},
},
SomethingElse: {
Type: 'AWS::CloudFormation::SomethingElse',
Properties: {
Prop: 'old-value',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'new-key',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
SomethingElse: {
Type: 'AWS::CloudFormation::SomethingElse',
Properties: {
Prop: 'new-value',
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
FunctionName: 'my-function',
S3Bucket: 'current-bucket',
S3Key: 'new-key',
});
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
}
});
test('changes only to CDK::Metadata result in a noOp', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
MetaData: {
Type: 'AWS::CDK::Metadata',
Properties: {
Prop: 'old-value',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
MetaData: {
Type: 'AWS::CDK::Metadata',
Properties: {
Prop: 'new-value',
},
},
},
},
});
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(deployStackResult?.noOp).toEqual(true);
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
});
test('resource deletions require full deployments for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Machine: {
Type: 'AWS::StepFunctions::StateMachine',
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf();
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(deployStackResult?.noOp).toEqual(true);
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
});
test('can correctly reference AWS::Partition in hotswappable changes', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
FunctionName: {
'Fn::Join': [
'',
[
{ Ref: 'AWS::Partition' },
'-',
'my-function',
],
],
},
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'new-key',
},
FunctionName: {
'Fn::Join': [
'',
[
{ Ref: 'AWS::Partition' },
'-',
'my-function',
],
],
},
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
},
});
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
FunctionName: 'aws-my-function',
S3Bucket: 'current-bucket',
S3Key: 'new-key',
});
});
test('can correctly reference AWS::URLSuffix in hotswappable changes', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
FunctionName: {
'Fn::Join': ['', [
'my-function-',
{ Ref: 'AWS::URLSuffix' },
'-',
{ Ref: 'AWS::URLSuffix' },
]],
},
},
Metadata: {
'aws:asset:path': 'old-path',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'new-key',
},
FunctionName: {
'Fn::Join': ['', [
'my-function-',
{ Ref: 'AWS::URLSuffix' },
'-',
{ Ref: 'AWS::URLSuffix' },
]],
},
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
},
});
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
FunctionName: 'my-function-amazonaws.com-amazonaws.com',
S3Bucket: 'current-bucket',
S3Key: 'new-key',
});
expect(mockGetEndpointSuffix).toHaveBeenCalledTimes(1);
// the User-Agent is set correctly
expect(hotswapMockSdkProvider.mockSdkProvider.sdk.appendCustomUserAgent)
.toHaveBeenCalledWith('cdk-hotswap/success-lambda');
expect(hotswapMockSdkProvider.mockSdkProvider.sdk.removeCustomUserAgent)
.toHaveBeenCalledWith('cdk-hotswap/success-lambda');
});
test('changing the type of a deployed resource always results in a full deployment for HOTSWAP and a noOp for HOTSWAP_ONLY', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
SharedLogicalId: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'new-key',
},
FunctionName: 'my-function',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
SharedLogicalId: {
Type: 'AWS::StepFunctions::StateMachine',
Properties: {
DefinitionString: '{ Prop: "new-value" }',
StateMachineName: 'my-machine',
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(deployStackResult?.noOp).toEqual(true);
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
});
test('A change to both a hotswappable resource and a stack output results in a full deployment for HOTSWAP and a hotswap deployment for HOTSWAP_ONLY', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'old-path',
},
},
},
Outputs: {
SomeOutput: {
Value: 'old-value',
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'new-key',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
Outputs: {
SomeOutput: {
Value: 'new-value',
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
FunctionName: 'my-function',
S3Bucket: 'current-bucket',
S3Key: 'new-key',
});
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
}
});
test('Multiple CfnEvaluationException will not cause unhandled rejections', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Func1: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
Environment: {
key: 'old',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'old-path',
},
},
Func2: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
Environment: {
key: 'old',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'old-path',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
Func1: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
Environment: {
key: { Ref: 'ErrorResource' },
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
Func2: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
Environment: {
key: { Ref: 'ErrorResource' },
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
},
});
// WHEN
const deployStackResult = hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
await expect(deployStackResult).rejects.toThrowError(evaluate_cloudformation_template_1.CfnEvaluationException);
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
});
test('deleting a resource and making a hotswappable change results in full deployments for HOTSWAP and a hotswap deployment for HOTSWAP_ONLY', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Machine: {
Type: 'AWS::StepFunctions::StateMachine',
},
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'current-key',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'old-path',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'new-key',
},
FunctionName: 'my-function',
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockUpdateMachineDefinition).not.toHaveBeenCalled();
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
FunctionName: 'my-function',
S3Bucket: 'current-bucket',
S3Key: 'new-key',
});
}
});
test('can correctly reference Fn::ImportValue in hotswappable changes', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: 'old-key',
},
FunctionName: 'aws-my-function',
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'current-bucket',
S3Key: {
'Fn::ImportValue': 'test-import',
},
},
FunctionName: 'aws-my-function',
},
Metadata: {
'aws:asset:path': 'new-path',
},
},
},
},
});
const listExports = jest.fn().mockReturnValue({
Exports: [
{
ExportingStackId: 'test-exporting-stack-id',
Name: 'test-import',
Value: 'new-key',
},
],
});
hotswapMockSdkProvider.mockSdkProvider.stubCloudFormation({
listExports,
});
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockUpdateLambdaCode).toHaveBeenCalledWith({
FunctionName: 'aws-my-function',
S3Bucket: 'current-bucket',
S3Key: 'new-key',
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG90c3dhcC1kZXBsb3ltZW50cy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaG90c3dhcC1kZXBsb3ltZW50cy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBRUEsOENBQThDO0FBQzlDLHdHQUEyRjtBQUMzRiw0REFBOEQ7QUFFOUQsSUFBSSxzQkFBb0QsQ0FBQztBQUN6RCxJQUFJLG9CQUE0RyxDQUFDO0FBQ2pILElBQUksMkJBQWtJLENBQUM7QUFDdkksSUFBSSxxQkFBbUMsQ0FBQztBQUV4QyxVQUFVLENBQUMsR0FBRyxFQUFFO0lBQ2Qsc0JBQXNCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDbkQsb0JBQW9CLEdBQUcsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyRCwyQkFBMkIsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDeEMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUN2RCxzQkFBc0IsQ0FBQyxVQUFVLENBQUM7UUFDaEMsa0JBQWtCLEVBQUUsb0JBQW9CO0tBQ3pDLENBQUMsQ0FBQztJQUNILHNCQUFzQixDQUFDLHlCQUF5QixDQUFDLDJCQUEyQixDQUFDLENBQUM7SUFDOUUsc0JBQXNCLENBQUMscUJBQXFCLENBQUMscUJBQXFCLENBQUMsQ0FBQztBQUN0RSxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxvQkFBVyxDQUFDLFNBQVMsRUFBRSxvQkFBVyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsV0FBVyxFQUFFLEVBQUU7SUFDMUYsSUFBSSxDQUFDLHFGQUFxRixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JHLE9BQU87UUFDUCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sc0JBQXNCLENBQUMs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QzdCO3FCQUNGO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDO1lBQzVDLE9BQU8sRUFBRTtnQkFDUDtvQkFDRSxnQkFBZ0IsRUFBRSx5QkFBeUI7b0JBQzNDLElBQUksRUFBRSxhQUFhO29CQUNuQixLQUFLLEVBQUUsU0FBUztpQkFDakI7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILHNCQUFzQixDQUFDLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQztZQUN4RCxXQUFXO1NBQ1osQ0FBQyxDQUFDO1FBRUgsT0FBTztRQUNQLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUUzRyxPQUFPO1FBQ1AsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzlDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLG9CQUFvQixDQUFDO1lBQ2hELFlBQVksRUFBRSxpQkFBaUI7WUFDL0IsUUFBUSxFQUFFLGdCQUFnQjtZQUMxQixLQUFLLEVBQUUsU0FBUztTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L29yZGVyICovXG5pbXBvcnQgeyBMYW1iZGEsIFN0ZXBGdW5jdGlvbnMgfSBmcm9tICdhd3Mtc2RrJztcbmltcG9ydCAqIGFzIHNldHVwIGZyb20gJy4vaG90c3dhcC10ZXN0LXNldHVwJztcbmltcG9ydCB7IENmbkV2YWx1YXRpb25FeGNlcHRpb24gfSBmcm9tICcuLi8uLi8uLi9saWIvYXBpL2V2YWx1YXRlLWNsb3VkZm9ybWF0aW9uLXRlbXBsYXRlJztcbmltcG9ydCB7IEhvdHN3YXBNb2RlIH0gZnJvbSAnLi4vLi4vLi4vbGliL2FwaS9ob3Rzd2FwL2NvbW1vbic7XG5cbmxldCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyOiBzZXR1cC5Ib3Rzd2FwTW9ja1Nka1Byb3ZpZGVyO1xubGV0IG1vY2tVcGRhdGVMYW1iZGFDb2RlOiAocGFyYW1zOiBMYW1iZGEuVHlwZXMuVXBkYXRlRnVuY3Rpb25Db2RlUmVxdWVzdCkgPT4gTGFtYmRhLlR5cGVzLkZ1bmN0aW9uQ29uZmlndXJhdGlvbjtcbmxldCBtb2NrVXBkYXRlTWFjaGluZURlZmluaXRpb246IChwYXJhbXM6IFN0ZXBGdW5jdGlvbnMuVHlwZXMuVXBkYXRlU3RhdGVNYWNoaW5lSW5wdXQpID0+IFN0ZXBGdW5jdGlvbnMuVHlwZXMuVXBkYXRlU3RhdGVNYWNoaW5lT3V0cHV0O1xubGV0IG1vY2tHZXRFbmRwb2ludFN1ZmZpeDogKCkgPT4gc3RyaW5nO1xuXG5iZWZvcmVFYWNoKCgpID0+IHtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcFRlc3RzKCk7XG4gIG1vY2tVcGRhdGVMYW1iZGFDb2RlID0gamVzdC5mbigpLm1vY2tSZXR1cm5WYWx1ZSh7fSk7XG4gIG1vY2tVcGRhdGVNYWNoaW5lRGVmaW5pdGlvbiA9IGplc3QuZm4oKTtcbiAgbW9ja0dldEVuZHBvaW50U3VmZml4ID0gamVzdC5mbigoKSA9PiAnYW1hem9uYXdzLmNvbScpO1xuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnN0dWJMYW1iZGEoe1xuICAgIHVwZGF0ZUZ1bmN0aW9uQ29kZTogbW9ja1VwZGF0ZUxhbWJkYUNvZGUsXG4gIH0pO1xuICBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnNldFVwZGF0ZVN0YXRlTWFjaGluZU1vY2sobW9ja1VwZGF0ZU1hY2hpbmVEZWZpbml0aW9uKTtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlci5zdHViR2V0RW5kcG9pbnRTdWZmaXgobW9ja0dldEVuZHBvaW50U3VmZml4KTtcbn0pO1xuXG5kZXNjcmliZS5lYWNoKFtIb3Rzd2FwTW9kZS5GQUxMX0JBQ0ssIEhvdHN3YXBNb2RlLkhPVFNXQVBfT05MWV0pKCclcCBtb2RlJywgKGhvdHN3YXBNb2RlKSA9PiB7XG4gIHRlc3QoJ3JldHVybnMgYSBkZXBsb3lTdGFja1Jlc3VsdCB3aXRoIG5vT3A9dHJ1ZSB3aGVuIGl0IHJlY2VpdmVzIGFuIGVtcHR5IHNldCBvZiBjaGFuZ2VzJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIFdIRU5cbiAgICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoaG90c3dhcE1vZGUsIHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZigpKTtcblxuICAgIC8vIFRIRU5cbiAgICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0Py5ub09wKS50b0JlVHJ1dGh5KCk7XG4gICAgZXhwZWN0KGRlcGxveVN0YWNrUmVzdWx0Py5zdGFja0FybikudG9FcXVhbChzZXR1cC5TVEFDS19JRCk7XG4gIH0pO1xuXG4gIHRlc3QoJ0EgY2hhbmdlIHRvIG9ubHkgYSBub24taG90c3dhcHBhYmxlIHJlc291cmNlIHJlc3VsdHMgaW4gYSBmdWxsIGRlcGxveW1lbnQgZm9yIEhPVFNXQVAgYW5kIGEgbm9PcCBmb3IgSE9UU1dBUF9PTkxZJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEdJVkVOXG4gICAgc2V0dXAuc2V0Q3VycmVudENmblN0YWNrVGVtcGxhdGUoe1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIFNvbWV0aGluZ0Vsc2U6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U29tZXRoaW5nRWxzZScsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgUHJvcDogJ29sZC12YWx1ZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZih7XG4gICAgICB0ZW1wbGF0ZToge1xuICAgICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgICBTb21ldGhpbmdFbHNlOiB7XG4gICAgICAgICAgICBUeXBlOiAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U29tZXRoaW5nRWxzZScsXG4gICAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgIFByb3A6ICduZXctdmFsdWUnLFxuICAgICAgICAgICAgfSxcbiAgICA