aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
592 lines • 69.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const setup = require("./hotswap-test-setup");
const common_1 = require("../../../lib/api/hotswap/common");
let hotswapMockSdkProvider;
let mockRegisterTaskDef;
let mockUpdateService;
beforeEach(() => {
hotswapMockSdkProvider = setup.setupHotswapTests();
mockRegisterTaskDef = jest.fn();
mockUpdateService = jest.fn();
hotswapMockSdkProvider.stubEcs({
registerTaskDefinition: mockRegisterTaskDef,
updateService: mockUpdateService,
}, {
// these are needed for the waiter API that the ECS service hotswap uses
api: {
waiters: {},
},
makeRequest() {
return {
promise: () => Promise.resolve({}),
response: {},
addListeners: () => { },
};
},
});
});
describe.each([common_1.HotswapMode.FALL_BACK, common_1.HotswapMode.HOTSWAP_ONLY])('%p mode', (hotswapMode) => {
test('should call registerTaskDefinition and updateService for a difference only in the TaskDefinition with a Family property', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image1' },
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
});
setup.pushStackResourceSummaries(setup.stackSummaryOf('Service', 'AWS::ECS::Service', 'arn:aws:ecs:region:account:service/my-cluster/my-service'));
mockRegisterTaskDef.mockReturnValue({
taskDefinition: {
taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image2' },
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
},
});
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockRegisterTaskDef).toBeCalledWith({
family: 'my-task-def',
containerDefinitions: [
{ image: 'image2' },
],
});
expect(mockUpdateService).toBeCalledWith({
service: 'arn:aws:ecs:region:account:service/my-cluster/my-service',
cluster: 'my-cluster',
taskDefinition: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
deploymentConfiguration: {
minimumHealthyPercent: 0,
},
forceNewDeployment: true,
});
});
test('any other TaskDefinition property change besides ContainerDefinition cannot be hotswapped in CLASSIC mode but does not block HOTSWAP_ONLY mode deployments', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image1' },
],
Cpu: '256',
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
});
setup.pushStackResourceSummaries(setup.stackSummaryOf('Service', 'AWS::ECS::Service', 'arn:aws:ecs:region:account:service/my-cluster/my-service'));
mockRegisterTaskDef.mockReturnValue({
taskDefinition: {
taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image2' },
],
Cpu: '512',
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockRegisterTaskDef).not.toHaveBeenCalled();
expect(mockUpdateService).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockRegisterTaskDef).toBeCalledWith({
family: 'my-task-def',
containerDefinitions: [
{ image: 'image2' },
],
cpu: '256', // this uses the old value because a new value could cause a service replacement
});
expect(mockUpdateService).toBeCalledWith({
service: 'arn:aws:ecs:region:account:service/my-cluster/my-service',
cluster: 'my-cluster',
taskDefinition: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
deploymentConfiguration: {
minimumHealthyPercent: 0,
},
forceNewDeployment: true,
});
}
});
test('deleting any other TaskDefinition property besides ContainerDefinition results in a full deployment in CLASSIC mode and a hotswap deployment in HOTSWAP_ONLY mode', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image1' },
],
Cpu: '256',
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
});
setup.pushStackResourceSummaries(setup.stackSummaryOf('Service', 'AWS::ECS::Service', 'arn:aws:ecs:region:account:service/my-cluster/my-service'));
mockRegisterTaskDef.mockReturnValue({
taskDefinition: {
taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image2' },
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockRegisterTaskDef).not.toHaveBeenCalled();
expect(mockUpdateService).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockRegisterTaskDef).toBeCalledWith({
family: 'my-task-def',
containerDefinitions: [
{ image: 'image2' },
],
cpu: '256', // this uses the old value because a new value could cause a service replacement
});
expect(mockUpdateService).toBeCalledWith({
service: 'arn:aws:ecs:region:account:service/my-cluster/my-service',
cluster: 'my-cluster',
taskDefinition: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
deploymentConfiguration: {
minimumHealthyPercent: 0,
},
forceNewDeployment: true,
});
}
});
test('should call registerTaskDefinition and updateService for a difference only in the TaskDefinition without a Family property', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
ContainerDefinitions: [
{ Image: 'image1' },
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
});
setup.pushStackResourceSummaries(setup.stackSummaryOf('TaskDef', 'AWS::ECS::TaskDefinition', 'arn:aws:ecs:region:account:task-definition/my-task-def:2'), setup.stackSummaryOf('Service', 'AWS::ECS::Service', 'arn:aws:ecs:region:account:service/my-cluster/my-service'));
mockRegisterTaskDef.mockReturnValue({
taskDefinition: {
taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
ContainerDefinitions: [
{ Image: 'image2' },
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
},
});
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockRegisterTaskDef).toBeCalledWith({
family: 'my-task-def',
containerDefinitions: [
{ image: 'image2' },
],
});
expect(mockUpdateService).toBeCalledWith({
service: 'arn:aws:ecs:region:account:service/my-cluster/my-service',
cluster: 'my-cluster',
taskDefinition: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
deploymentConfiguration: {
minimumHealthyPercent: 0,
},
forceNewDeployment: true,
});
});
test('a difference just in a TaskDefinition, without any services using it, is not hotswappable in FALL_BACK mode', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
ContainerDefinitions: [
{ Image: 'image1' },
],
},
},
},
});
setup.pushStackResourceSummaries(setup.stackSummaryOf('TaskDef', 'AWS::ECS::TaskDefinition', 'arn:aws:ecs:region:account:task-definition/my-task-def:2'));
mockRegisterTaskDef.mockReturnValue({
taskDefinition: {
taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
ContainerDefinitions: [
{ Image: 'image2' },
],
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockRegisterTaskDef).not.toHaveBeenCalled();
expect(mockUpdateService).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockRegisterTaskDef).toBeCalledWith({
family: 'my-task-def',
containerDefinitions: [
{ image: 'image2' },
],
});
expect(mockUpdateService).not.toHaveBeenCalledWith();
}
});
test('if anything besides an ECS Service references the changed TaskDefinition, hotswapping is not possible in CLASSIC mode but is possible in HOTSWAP_ONLY', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image1' },
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
Function: {
Type: 'AWS::Lambda::Function',
Properties: {
Environment: {
Variables: {
TaskDefRevArn: { Ref: 'TaskDef' },
},
},
},
},
},
});
setup.pushStackResourceSummaries(setup.stackSummaryOf('Service', 'AWS::ECS::Service', 'arn:aws:ecs:region:account:service/my-cluster/my-service'));
mockRegisterTaskDef.mockReturnValue({
taskDefinition: {
taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image2' },
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
Function: {
Type: 'AWS::Lambda::Function',
Properties: {
Environment: {
Variables: {
TaskDefRevArn: { Ref: 'TaskDef' },
},
},
},
},
},
},
});
if (hotswapMode === common_1.HotswapMode.FALL_BACK) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).toBeUndefined();
expect(mockRegisterTaskDef).not.toHaveBeenCalled();
expect(mockUpdateService).not.toHaveBeenCalled();
}
else if (hotswapMode === common_1.HotswapMode.HOTSWAP_ONLY) {
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockRegisterTaskDef).toBeCalledWith({
family: 'my-task-def',
containerDefinitions: [
{ image: 'image2' },
],
});
expect(mockUpdateService).toBeCalledWith({
service: 'arn:aws:ecs:region:account:service/my-cluster/my-service',
cluster: 'my-cluster',
taskDefinition: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
deploymentConfiguration: {
minimumHealthyPercent: 0,
},
forceNewDeployment: true,
});
}
});
test('should call registerTaskDefinition with certain properties not lowercased', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{ Image: 'image1' },
],
Volumes: [
{
DockerVolumeConfiguration: {
DriverOpts: { Option1: 'option1' },
Labels: { Label1: 'label1' },
},
},
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
});
setup.pushStackResourceSummaries(setup.stackSummaryOf('Service', 'AWS::ECS::Service', 'arn:aws:ecs:region:account:service/my-cluster/my-service'));
mockRegisterTaskDef.mockReturnValue({
taskDefinition: {
taskDefinitionArn: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
},
});
const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
TaskDef: {
Type: 'AWS::ECS::TaskDefinition',
Properties: {
Family: 'my-task-def',
ContainerDefinitions: [
{
Image: 'image2',
DockerLabels: { Label1: 'label1' },
FirelensConfiguration: {
Options: { Name: 'cloudwatch' },
},
LogConfiguration: {
Options: { Option1: 'option1' },
},
},
],
Volumes: [
{
DockerVolumeConfiguration: {
DriverOpts: { Option1: 'option1' },
Labels: { Label1: 'label1' },
},
},
],
},
},
Service: {
Type: 'AWS::ECS::Service',
Properties: {
TaskDefinition: { Ref: 'TaskDef' },
},
},
},
},
});
// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockRegisterTaskDef).toBeCalledWith({
family: 'my-task-def',
containerDefinitions: [
{
image: 'image2',
dockerLabels: { Label1: 'label1' },
firelensConfiguration: {
options: {
Name: 'cloudwatch',
},
},
logConfiguration: {
options: { Option1: 'option1' },
},
},
],
volumes: [
{
dockerVolumeConfiguration: {
driverOpts: { Option1: 'option1' },
labels: { Label1: 'label1' },
},
},
],
});
expect(mockUpdateService).toBeCalledWith({
service: 'arn:aws:ecs:region:account:service/my-cluster/my-service',
cluster: 'my-cluster',
taskDefinition: 'arn:aws:ecs:region:account:task-definition/my-task-def:3',
deploymentConfiguration: {
minimumHealthyPercent: 0,
},
forceNewDeployment: true,
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNzLXNlcnZpY2VzLWhvdHN3YXAtZGVwbG95bWVudHMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImVjcy1zZXJ2aWNlcy1ob3Rzd2FwLWRlcGxveW1lbnRzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSw4Q0FBOEM7QUFDOUMsNERBQThEO0FBRTlELElBQUksc0JBQW9ELENBQUM7QUFDekQsSUFBSSxtQkFBK0csQ0FBQztBQUNwSCxJQUFJLGlCQUEwRixDQUFDO0FBRS9GLFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDZCxzQkFBc0IsR0FBRyxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUVuRCxtQkFBbUIsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDaEMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQzlCLHNCQUFzQixDQUFDLE9BQU8sQ0FBQztRQUM3QixzQkFBc0IsRUFBRSxtQkFBbUI7UUFDM0MsYUFBYSxFQUFFLGlCQUFpQjtLQUNqQyxFQUFFO1FBQ0Qsd0VBQXdFO1FBQ3hFLEdBQUcsRUFBRTtZQUNILE9BQU8sRUFBRSxFQUFFO1NBQ1o7UUFDRCxXQUFXO1lBQ1QsT0FBTztnQkFDTCxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ2xDLFFBQVEsRUFBRSxFQUFFO2dCQUNaLFlBQVksRUFBRSxHQUFHLEVBQUUsR0FBRSxDQUFDO2FBQ3ZCLENBQUM7UUFDSixDQUFDO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsb0JBQVcsQ0FBQyxTQUFTLEVBQUUsb0JBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFO0lBQzFGLElBQUksQ0FBQyx5SEFBeUgsRUFBRSxLQUFLLElBQUksRUFBRTtR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QkFDbEMscUJBQXFCLEVBQUU7d0JBQ3JCLE9BQU8sRUFBRTs0QkFDUCxJQUFJLEVBQUUsWUFBWTt5QkFDbkI7cUJBQ0Y7b0JBQ0QsZ0JBQWdCLEVBQUU7d0JBQ2hCLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUU7cUJBQ2hDO2lCQUNGO2FBQ0Y7WUFDRCxPQUFPLEVBQUU7Z0JBQ1A7b0JBQ0UseUJBQXlCLEVBQUU7d0JBQ3pCLFVBQVUsRUFBRSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUU7d0JBQ2xDLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUU7cUJBQzdCO2lCQUNGO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxjQUFjLENBQUM7WUFDdkMsT0FBTyxFQUFFLDBEQUEwRDtZQUNuRSxPQUFPLEVBQUUsWUFBWTtZQUNyQixjQUFjLEVBQUUsMERBQTBEO1lBQzFFLHVCQUF1QixFQUFFO2dCQUN2QixxQkFBcUIsRUFBRSxDQUFDO2FBQ3pCO1lBQ0Qsa0JBQWtCLEVBQUUsSUFBSTtTQUN6QixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L29yZGVyICovXG5pbXBvcnQgKiBhcyBBV1MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgKiBhcyBzZXR1cCBmcm9tICcuL2hvdHN3YXAtdGVzdC1zZXR1cCc7XG5pbXBvcnQgeyBIb3Rzd2FwTW9kZSB9IGZyb20gJy4uLy4uLy4uL2xpYi9hcGkvaG90c3dhcC9jb21tb24nO1xuXG5sZXQgaG90c3dhcE1vY2tTZGtQcm92aWRlcjogc2V0dXAuSG90c3dhcE1vY2tTZGtQcm92aWRlcjtcbmxldCBtb2NrUmVnaXN0ZXJUYXNrRGVmOiBqZXN0Lk1vY2s8QVdTLkVDUy5SZWdpc3RlclRhc2tEZWZpbml0aW9uUmVzcG9uc2UsIEFXUy5FQ1MuUmVnaXN0ZXJUYXNrRGVmaW5pdGlvblJlcXVlc3RbXT47XG5sZXQgbW9ja1VwZGF0ZVNlcnZpY2U6IChwYXJhbXM6IEFXUy5FQ1MuVXBkYXRlU2VydmljZVJlcXVlc3QpID0+IEFXUy5FQ1MuVXBkYXRlU2VydmljZVJlc3BvbnNlO1xuXG5iZWZvcmVFYWNoKCgpID0+IHtcbiAgaG90c3dhcE1vY2tTZGtQcm92aWRlciA9IHNldHVwLnNldHVwSG90c3dhcFRlc3RzKCk7XG5cbiAgbW9ja1JlZ2lzdGVyVGFza0RlZiA9IGplc3QuZm4oKTtcbiAgbW9ja1VwZGF0ZVNlcnZpY2UgPSBqZXN0LmZuKCk7XG4gIGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIuc3R1YkVjcyh7XG4gICAgcmVnaXN0ZXJUYXNrRGVmaW5pdGlvbjogbW9ja1JlZ2lzdGVyVGFza0RlZixcbiAgICB1cGRhdGVTZXJ2aWNlOiBtb2NrVXBkYXRlU2VydmljZSxcbiAgfSwge1xuICAgIC8vIHRoZXNlIGFyZSBuZWVkZWQgZm9yIHRoZSB3YWl0ZXIgQVBJIHRoYXQgdGhlIEVDUyBzZXJ2aWNlIGhvdHN3YXAgdXNlc1xuICAgIGFwaToge1xuICAgICAgd2FpdGVyczoge30sXG4gICAgfSxcbiAgICBtYWtlUmVxdWVzdCgpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHByb21pc2U6ICgpID0+IFByb21pc2UucmVzb2x2ZSh7fSksXG4gICAgICAgIHJlc3BvbnNlOiB7fSxcbiAgICAgICAgYWRkTGlzdGVuZXJzOiAoKSA9PiB7fSxcbiAgICAgIH07XG4gICAgfSxcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUuZWFjaChbSG90c3dhcE1vZGUuRkFMTF9CQUNLLCBIb3Rzd2FwTW9kZS5IT1RTV0FQX09OTFldKSgnJXAgbW9kZScsIChob3Rzd2FwTW9kZSkgPT4ge1xuICB0ZXN0KCdzaG91bGQgY2FsbCByZWdpc3RlclRhc2tEZWZpbml0aW9uIGFuZCB1cGRhdGVTZXJ2aWNlIGZvciBhIGRpZmZlcmVuY2Ugb25seSBpbiB0aGUgVGFza0RlZmluaXRpb24gd2l0aCBhIEZhbWlseSBwcm9wZXJ0eScsIGFzeW5jICgpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIHNldHVwLnNldEN1cnJlbnRDZm5TdGFja1RlbXBsYXRlKHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBUYXNrRGVmOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6RUNTOjpUYXNrRGVmaW5pdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgRmFtaWx5OiAnbXktdGFzay1kZWYnLFxuICAgICAgICAgICAgQ29udGFpbmVyRGVmaW5pdGlvbnM6IFtcbiAgICAgICAgICAgICAgeyBJbWFnZTogJ2ltYWdlMScgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgU2VydmljZToge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkVDUzo6U2VydmljZScsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgVGFza0RlZmluaXRpb246IHsgUmVmOiAnVGFza0RlZicgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBzZXR1cC5wdXNoU3RhY2tSZXNvdXJjZVN1bW1hcmllcyhcbiAgICAgIHNldHVwLnN0YWNrU3VtbWFyeU9mKCdTZXJ2aWNlJywgJ0FXUzo6RUNTOjpTZXJ2aWNlJyxcbiAgICAgICAgJ2Fybjphd3M6ZWNzOnJlZ2lvbjphY2NvdW50OnNlcnZpY2UvbXktY2x1c3Rlci9teS1zZXJ2aWNlJyksXG4gICAgKTtcbiAgICBtb2NrUmVnaXN0ZXJUYXNrRGVmLm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICB0YXNrRGVmaW5pdGlvbjoge1xuICAgICAgICB0YXNrRGVmaW5pdGlvbkFybjogJ2Fybjphd3M6ZWNzOnJlZ2lvbjphY2NvdW50OnRhc2stZGVmaW5pdGlvbi9teS10YXNrLWRlZjozJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgY2RrU3RhY2tBcnRpZmFjdCA9IHNldHVwLmNka1N0YWNrQXJ0aWZhY3RPZih7XG4gICAgICB0ZW1wbGF0ZToge1xuICAgICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgICBUYXNrRGVmOiB7XG4gICAgICAgICAgICBUeXBlOiAnQVdTOjpFQ1M6OlRhc2tEZWZpbml0aW9uJyxcbiAgICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgRmFtaWx5OiAnbXktdGFzay1kZWYnLFxuICAgICAgICAgICAgICBDb250YWluZXJEZWZpbml0aW9uczogW1xuICAgICAgICAgICAgICAgIHsgSW1hZ2U6ICdpbWFnZTInIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgU2VydmljZToge1xuICAgICAgICAgICAgVHlwZTogJ0FXUzo6RUNTOjpTZXJ2aWNlJyxcbiAgICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgVGFza0RlZmluaXRpb246IHsgUmVmOiAnVGFza0RlZicgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBXSEVOXG4gICAgY29uc3QgZGVwbG95U3RhY2tSZXN1bHQgPSBhd2FpdCBob3Rzd2FwTW9ja1Nka1Byb3ZpZGVyLnRyeUhvdHN3YXBEZXBsb3ltZW50KGhvdHN3YXBNb2RlLCBjZGtTdGFja0FydGlmYWN0KTtcblxuICAgIC8vIFRIRU5cbiAgICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KG1vY2tSZWdpc3RlclRhc2tEZWYpLnRvQmVDYWxsZWRXaXRoKHtcbiAgICAgIGZhbWlseTogJ215LXRhc2stZGVmJyxcbiAgICAgIGNvbnRhaW5lckRlZmluaXRpb25zOiBbXG4gICAgICAgIHsgaW1hZ2U6ICdpbWFnZTInIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICAgIGV4cGVjdChtb2NrVXBkYXRlU2VydmljZSkudG9CZUNhbGxlZFdpdGgoe1xuICAgICAgc2VydmljZTogJ2Fybjphd3M6ZWNzOnJlZ2lvbjphY2NvdW50OnNlcnZpY2UvbXktY2x1c3Rlci9teS1zZXJ2aWNlJyxcbiAgICAgIGNsdXN0ZXI6ICdteS1jbHVzdGVyJyxcbiAgICAgIHRhc2tEZWZpbml0aW9uOiAnYXJuOmF3czplY3M6cmVnaW9uOmFjY291bnQ6dGFzay1kZWZpbml0aW9uL215LXRhc2stZGVmOjMnLFxuICAgICAgZGVwbG95bWVudENvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgbWluaW11bUhlYWx0aHlQZXJjZW50OiAwLFxuICAgICAgfSxcbiAgICAgIGZvcmNlTmV3RGVwbG95bWVudDogdHJ1ZSxcbiAgICB9KTtcbiAgfSk7XG5cbiAgdGVzdCgnYW55IG90aGVyIFRhc2tEZWZpbml0aW9uIHByb3BlcnR5IGNoYW5nZSBiZXNpZGVzIENvbnRhaW5lckRlZmluaXRpb24gY2Fubm90IGJlIGhvdHN3YXBwZWQgaW4gQ0xBU1NJQyBtb2RlIGJ1dCBkb2VzIG5vdCBibG9jayBIT1RTV0FQX09OTFkgbW9kZSBkZXBsb3ltZW50cycsIGFzeW5jICgpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIHNldHVwLnNldEN1cnJlbnRDZm5TdGFja1RlbXBsYXRlKHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBUYXNrRGVmOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6RUNTOjpUYXNrRGVmaW5pdGlvbicsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgRmFtaWx5OiAnbXktdGFzay1kZWYnLFxuICAgICAgICAgICAgQ29udGFpbmVyRGVmaW5pdGlvbnM6IFtcbiAgICAgICAgICAgICAgeyBJbWFnZTogJ2ltYWdlMScgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBDcHU6ICcyNTYnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIFNlcnZpY2U6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpFQ1M6OlNlcnZpY2UnLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIFRhc2tEZWZpbml0aW9uOiB7IFJlZjogJ1Rhc2tEZWYnIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgc2V0dXAucHVzaFN0YWNrUmVzb3VyY2VTdW1tYXJpZXMoXG4gICAgICBzZXR1cC5zdGFja1N1bW1hcnlPZignU2VydmljZScsICdBV1M6OkVDUzo6U2VydmljZScsXG4gICAgICAgICdhcm46YXdzOmVjczpyZWdpb246YWNjb3VudDpzZXJ2aWNlL215LWNsdXN0ZXIvbXktc2VydmljZScpLFxuICAgICk7XG4gICAgbW9ja1JlZ2lzdGVyVGFza0RlZi5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgdGFza0RlZmluaXRpb246IHtcbiAgICAgICAgdGFza0RlZmluaXRpb25Bcm46ICdhcm46YXdzOmVjczpyZWdpb246YWNjb3VudDp0YXNrLWRlZmluaXRpb24vbXktdGFzay1kZWY6MycsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGNvbnN0IGNka1N0YWNrQXJ0aWZhY3QgPSBzZXR1cC5jZGtTdGFja0FydGlmYWN0T2Yoe1xuICAgICAgdGVtcGxhdGU6IHtcbiAgICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgICAgVGFza0RlZjoge1xuICAgICAgICAgICAgVHlwZTogJ0FXUzo6RUNTOjpUYXNrRGVmaW5pdGlvbicsXG4gICAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgIEZhbWlseTogJ215LXRhc2stZGVmJyxcbiAgICAgICAgICAgICAgQ29udGFpbmVyRGVmaW5pdGlvbnM6IFtcbiAgICAgICAgICAgICAgICB7IEltYWdlOiAnaW1hZ2UyJyB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICBDcHU6ICc1MTInLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIFNlcnZpY2U6IHtcbiAgICAgICAgICAgIFR5cGU6ICdBV1M6OkVDUzo6U2VydmljZScsXG4gICAgICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgIFRhc2tEZWZpbml0aW9uOiB7IFJlZjogJ1Rhc2tEZWYnIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKGhvdHN3YXBNb2RlID09PSBIb3Rzd2FwTW9kZS5GQUxMX0JBQ0spIHtcbiAgICAgIC8vIFdIRU5cbiAgICAgIGNvbnN0IGRlcGxveVN0YWNrUmVzdWx0ID0gYXdhaXQgaG90c3dhcE1vY2tTZGtQcm92aWRlci50cnlIb3Rzd2FwRGVwbG95bWVudChob3Rzd2FwTW9kZSwgY2RrU3RhY2tBcnRpZmFjdCk7XG5cbiAgICAgIC8vIFRIRU5cbiAgICAgIGV4cGVjdChkZXBsb3lTdGFja1Jlc3VsdCkudG9CZVVuZGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KG1vY2tSZWdpc3RlclRhc2tEZWYpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja1VwZGF0ZVNlcnZpY2UpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSBlbHNlIGlmIChob3Rzd2FwTW9kZSA9PT0gSG90c3dhcE1vZGUuSE9UU1dBUF9PTkxZKSB7XG4gICAgICAvLyBXSEVOXG4gICAgICBjb25zdCBkZXBsb3lTdGFja1Jlc3VsdCA9IGF3YWl0IGhvdHN3YXBNb2NrU2RrUHJvdmlkZXIudHJ5SG90c3dhcERlcGxveW1lbnQoaG90c3dhcE1vZGUsIGNka1N0YWNrQXJ0aWZhY3QpO1xuXG4gICAgICAvLyBUSEVOXG4gICAgICBleHBlY3QoZGVwbG95U3RhY2tSZXN1bHQpLm5vdC50b0JlVW5kZWZpbmVkKCk7XG4gICAgICBleHBlY3QobW9ja1JlZ2lzdGVyVGFza0RlZikudG9CZUNhbGxlZFdpdGgoe1xuICAgICAgICBmYW1pbHk6ICdteS10YXNrLWRlZicsXG4gICAgICAgIGNvbnRhaW5lckRlZmluaXRpb25zOiBbXG4gICAgICAgICAgeyBpbWFnZTogJ2ltYWdlMicgfSxcbiAgICAgICAgXSxcbiAgICAgICAgY3B1OiAnMjU2JywgLy8gdGhpcyB1c2VzIHRoZSBvbGQgdmFsdWUgYmVjYXVzZSBhIG5ldyB2YWx1ZSBjb3VsZCBjYXVzZSBhIHNlcnZpY2UgcmVwbGFjZW1lbnRcbiAgICAgIH0pO1xuICAgICAgZXhwZWN0KG1vY2tVcGRhdGVTZXJ2aWNlKS50b0JlQ2FsbGVkV2l0aCh7XG4gICAgICAgIHNlcnZpY2U6ICdhcm46YXdzOmVjczpyZWdpb246YWNjb3VudDpzZXJ2aWNlL2