UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

592 lines 69.2 kB
"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