deploy-stack.test.js
1 "use strict"; 2 Object.defineProperty(exports, "__esModule", { value: true }); 3 const api_1 = require("../../lib/api"); 4 const util_1 = require("../util"); 5 const mock_sdk_1 = require("../util/mock-sdk"); 6 const FAKE_STACK = util_1.testStack({ 7 stackName: 'withouterrors', 8 }); 9 const FAKE_STACK_WITH_PARAMETERS = util_1.testStack({ 10 stackName: 'withparameters', 11 template: { 12 Parameters: { 13 HasValue: { Type: 'String' }, 14 HasDefault: { Type: 'String', Default: 'TheDefault' }, 15 OtherParameter: { Type: 'String' }, 16 }, 17 }, 18 }); 19 const FAKE_STACK_TERMINATION_PROTECTION = util_1.testStack({ 20 stackName: 'termination-protection', 21 template: util_1.DEFAULT_FAKE_TEMPLATE, 22 terminationProtection: true, 23 }); 24 let sdk; 25 let sdkProvider; 26 let cfnMocks; 27 beforeEach(() => { 28 sdkProvider = new mock_sdk_1.MockSdkProvider(); 29 sdk = new mock_sdk_1.MockSdk(); 30 cfnMocks = { 31 describeStackEvents: jest.fn().mockReturnValue({}), 32 describeStacks: jest.fn() 33 // First call, no stacks exist 34 .mockImplementationOnce(() => ({ Stacks: [] })) 35 // Second call, stack has been created 36 .mockImplementationOnce(() => ({ 37 Stacks: [ 38 { 39 StackStatus: 'CREATE_COMPLETE', 40 StackStatusReason: 'It is magic', 41 EnableTerminationProtection: false, 42 }, 43 ], 44 })), 45 createChangeSet: jest.fn((_o) => ({})), 46 deleteChangeSet: jest.fn((_o) => ({})), 47 describeChangeSet: jest.fn((_o) => ({ 48 Status: 'CREATE_COMPLETE', 49 Changes: [], 50 })), 51 executeChangeSet: jest.fn((_o) => ({})), 52 deleteStack: jest.fn((_o) => ({})), 53 getTemplate: jest.fn((_o) => ({ TemplateBody: JSON.stringify(util_1.DEFAULT_FAKE_TEMPLATE) })), 54 updateTerminationProtection: jest.fn((_o) => ({ StackId: 'stack-id' })), 55 }; 56 sdk.stubCloudFormation(cfnMocks); 57 }); 58 function standardDeployStackArguments() { 59 return { 60 stack: FAKE_STACK, 61 sdk, 62 sdkProvider, 63 resolvedEnvironment: mock_sdk_1.mockResolvedEnvironment(), 64 toolkitInfo: api_1.ToolkitInfo.bootstraplessDeploymentsOnly(sdk), 65 }; 66 } 67 test('do deploy executable change set with 0 changes', async () => { 68 // WHEN 69 const ret = await api_1.deployStack({ 70 ...standardDeployStackArguments(), 71 }); 72 // THEN 73 expect(ret.noOp).toBeFalsy(); 74 expect(cfnMocks.executeChangeSet).toHaveBeenCalled(); 75 }); 76 test('correctly passes CFN parameters, ignoring ones with empty values', async () => { 77 // WHEN 78 await api_1.deployStack({ 79 ...standardDeployStackArguments(), 80 parameters: { 81 A: 'A-value', 82 B: 'B=value', 83 C: undefined, 84 D: '', 85 }, 86 }); 87 // THEN 88 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 89 Parameters: [ 90 { ParameterKey: 'A', ParameterValue: 'A-value' }, 91 { ParameterKey: 'B', ParameterValue: 'B=value' }, 92 ], 93 })); 94 }); 95 test('reuse previous parameters if requested', async () => { 96 // GIVEN 97 givenStackExists({ 98 Parameters: [ 99 { ParameterKey: 'HasValue', ParameterValue: 'TheValue' }, 100 { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' }, 101 ], 102 }); 103 // WHEN 104 await api_1.deployStack({ 105 ...standardDeployStackArguments(), 106 stack: FAKE_STACK_WITH_PARAMETERS, 107 parameters: { 108 OtherParameter: 'SomeValue', 109 }, 110 usePreviousParameters: true, 111 }); 112 // THEN 113 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 114 Parameters: [ 115 { ParameterKey: 'HasValue', UsePreviousValue: true }, 116 { ParameterKey: 'HasDefault', UsePreviousValue: true }, 117 { ParameterKey: 'OtherParameter', ParameterValue: 'SomeValue' }, 118 ], 119 })); 120 }); 121 test('do not reuse previous parameters if not requested', async () => { 122 // GIVEN 123 givenStackExists({ 124 Parameters: [ 125 { ParameterKey: 'HasValue', ParameterValue: 'TheValue' }, 126 { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' }, 127 ], 128 }); 129 // WHEN 130 await api_1.deployStack({ 131 ...standardDeployStackArguments(), 132 stack: FAKE_STACK_WITH_PARAMETERS, 133 parameters: { 134 HasValue: 'SomeValue', 135 OtherParameter: 'SomeValue', 136 }, 137 }); 138 // THEN 139 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 140 Parameters: [ 141 { ParameterKey: 'HasValue', ParameterValue: 'SomeValue' }, 142 { ParameterKey: 'OtherParameter', ParameterValue: 'SomeValue' }, 143 ], 144 })); 145 }); 146 test('throw exception if not enough parameters supplied', async () => { 147 // GIVEN 148 givenStackExists({ 149 Parameters: [ 150 { ParameterKey: 'HasValue', ParameterValue: 'TheValue' }, 151 { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' }, 152 ], 153 }); 154 // WHEN 155 await expect(api_1.deployStack({ 156 ...standardDeployStackArguments(), 157 stack: FAKE_STACK_WITH_PARAMETERS, 158 parameters: { 159 OtherParameter: 'SomeValue', 160 }, 161 })).rejects.toThrow(/CloudFormation Parameters are missing a value/); 162 }); 163 test('deploy is skipped if template did not change', async () => { 164 // GIVEN 165 givenStackExists(); 166 // WHEN 167 await api_1.deployStack({ 168 ...standardDeployStackArguments(), 169 }); 170 // THEN 171 expect(cfnMocks.executeChangeSet).not.toBeCalled(); 172 }); 173 test('deploy is skipped if parameters are the same', async () => { 174 // GIVEN 175 givenTemplateIs(FAKE_STACK_WITH_PARAMETERS.template); 176 givenStackExists({ 177 Parameters: [ 178 { ParameterKey: 'HasValue', ParameterValue: 'HasValue' }, 179 { ParameterKey: 'HasDefault', ParameterValue: 'HasDefault' }, 180 { ParameterKey: 'OtherParameter', ParameterValue: 'OtherParameter' }, 181 ], 182 }); 183 // WHEN 184 await api_1.deployStack({ 185 ...standardDeployStackArguments(), 186 stack: FAKE_STACK_WITH_PARAMETERS, 187 parameters: {}, 188 usePreviousParameters: true, 189 }); 190 // THEN 191 expect(cfnMocks.createChangeSet).not.toHaveBeenCalled(); 192 }); 193 test('deploy is not skipped if parameters are different', async () => { 194 // GIVEN 195 givenTemplateIs(FAKE_STACK_WITH_PARAMETERS.template); 196 givenStackExists({ 197 Parameters: [ 198 { ParameterKey: 'HasValue', ParameterValue: 'HasValue' }, 199 { ParameterKey: 'HasDefault', ParameterValue: 'HasDefault' }, 200 { ParameterKey: 'OtherParameter', ParameterValue: 'OtherParameter' }, 201 ], 202 }); 203 // WHEN 204 await api_1.deployStack({ 205 ...standardDeployStackArguments(), 206 stack: FAKE_STACK_WITH_PARAMETERS, 207 parameters: { 208 HasValue: 'NewValue', 209 }, 210 usePreviousParameters: true, 211 }); 212 // THEN 213 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 214 Parameters: [ 215 { ParameterKey: 'HasValue', ParameterValue: 'NewValue' }, 216 { ParameterKey: 'HasDefault', UsePreviousValue: true }, 217 { ParameterKey: 'OtherParameter', UsePreviousValue: true }, 218 ], 219 })); 220 }); 221 test('if existing stack failed to create, it is deleted and recreated', async () => { 222 // GIVEN 223 givenStackExists({ StackStatus: 'ROLLBACK_COMPLETE' }, // This is for the initial check 224 { StackStatus: 'DELETE_COMPLETE' }, // Poll the successful deletion 225 { StackStatus: 'CREATE_COMPLETE' }); 226 givenTemplateIs({ 227 DifferentThan: 'TheDefault', 228 }); 229 // WHEN 230 await api_1.deployStack({ 231 ...standardDeployStackArguments(), 232 }); 233 // THEN 234 expect(cfnMocks.deleteStack).toHaveBeenCalled(); 235 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 236 ChangeSetType: 'CREATE', 237 })); 238 }); 239 test('if existing stack failed to create, it is deleted and recreated even if the template did not change', async () => { 240 // GIVEN 241 givenStackExists({ StackStatus: 'ROLLBACK_COMPLETE' }, // This is for the initial check 242 { StackStatus: 'DELETE_COMPLETE' }, // Poll the successful deletion 243 { StackStatus: 'CREATE_COMPLETE' }); 244 // WHEN 245 await api_1.deployStack({ 246 ...standardDeployStackArguments(), 247 }); 248 // THEN 249 expect(cfnMocks.deleteStack).toHaveBeenCalled(); 250 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 251 ChangeSetType: 'CREATE', 252 })); 253 }); 254 test('deploy not skipped if template did not change and --force is applied', async () => { 255 // GIVEN 256 givenStackExists(); 257 // WHEN 258 await api_1.deployStack({ 259 ...standardDeployStackArguments(), 260 force: true, 261 }); 262 // THEN 263 expect(cfnMocks.executeChangeSet).toHaveBeenCalled(); 264 }); 265 test('deploy is skipped if template and tags did not change', async () => { 266 // GIVEN 267 givenStackExists({ 268 Tags: [ 269 { Key: 'Key1', Value: 'Value1' }, 270 { Key: 'Key2', Value: 'Value2' }, 271 ], 272 }); 273 // WHEN 274 await api_1.deployStack({ 275 ...standardDeployStackArguments(), 276 tags: [ 277 { Key: 'Key1', Value: 'Value1' }, 278 { Key: 'Key2', Value: 'Value2' }, 279 ], 280 }); 281 // THEN 282 expect(cfnMocks.createChangeSet).not.toBeCalled(); 283 expect(cfnMocks.executeChangeSet).not.toBeCalled(); 284 expect(cfnMocks.describeStacks).toHaveBeenCalledWith({ StackName: 'withouterrors' }); 285 expect(cfnMocks.getTemplate).toHaveBeenCalledWith({ StackName: 'withouterrors', TemplateStage: 'Original' }); 286 }); 287 test('deploy not skipped if template did not change but tags changed', async () => { 288 // GIVEN 289 givenStackExists({ 290 Tags: [ 291 { Key: 'Key', Value: 'Value' }, 292 ], 293 }); 294 // WHEN 295 await api_1.deployStack({ 296 stack: FAKE_STACK, 297 sdk, 298 sdkProvider, 299 resolvedEnvironment: mock_sdk_1.mockResolvedEnvironment(), 300 tags: [ 301 { 302 Key: 'Key', 303 Value: 'NewValue', 304 }, 305 ], 306 toolkitInfo: api_1.ToolkitInfo.bootstraplessDeploymentsOnly(sdk), 307 }); 308 // THEN 309 expect(cfnMocks.createChangeSet).toHaveBeenCalled(); 310 expect(cfnMocks.executeChangeSet).toHaveBeenCalled(); 311 expect(cfnMocks.describeChangeSet).toHaveBeenCalled(); 312 expect(cfnMocks.describeStacks).toHaveBeenCalledWith({ StackName: 'withouterrors' }); 313 expect(cfnMocks.getTemplate).toHaveBeenCalledWith({ StackName: 'withouterrors', TemplateStage: 'Original' }); 314 }); 315 test('deployStack reports no change if describeChangeSet returns specific error', async () => { 316 var _a; 317 (_a = cfnMocks.describeChangeSet) === null || _a === void 0 ? void 0 : _a.mockImplementation(() => ({ 318 Status: 'FAILED', 319 StatusReason: 'No updates are to be performed.', 320 })); 321 // WHEN 322 const deployResult = await api_1.deployStack({ 323 ...standardDeployStackArguments(), 324 }); 325 // THEN 326 expect(deployResult.noOp).toEqual(true); 327 }); 328 test('deploy not skipped if template did not change but one tag removed', async () => { 329 // GIVEN 330 givenStackExists({ 331 Tags: [ 332 { Key: 'Key1', Value: 'Value1' }, 333 { Key: 'Key2', Value: 'Value2' }, 334 ], 335 }); 336 // WHEN 337 await api_1.deployStack({ 338 ...standardDeployStackArguments(), 339 tags: [ 340 { Key: 'Key1', Value: 'Value1' }, 341 ], 342 }); 343 // THEN 344 expect(cfnMocks.createChangeSet).toHaveBeenCalled(); 345 expect(cfnMocks.executeChangeSet).toHaveBeenCalled(); 346 expect(cfnMocks.describeChangeSet).toHaveBeenCalled(); 347 expect(cfnMocks.describeStacks).toHaveBeenCalledWith({ StackName: 'withouterrors' }); 348 expect(cfnMocks.getTemplate).toHaveBeenCalledWith({ StackName: 'withouterrors', TemplateStage: 'Original' }); 349 }); 350 test('deploy is not skipped if stack is in a _FAILED state', async () => { 351 // GIVEN 352 givenStackExists({ 353 StackStatus: 'DELETE_FAILED', 354 }); 355 // WHEN 356 await api_1.deployStack({ 357 ...standardDeployStackArguments(), 358 usePreviousParameters: true, 359 }).catch(() => { }); 360 // THEN 361 expect(cfnMocks.createChangeSet).toHaveBeenCalled(); 362 }); 363 test('existing stack in UPDATE_ROLLBACK_COMPLETE state can be updated', async () => { 364 // GIVEN 365 givenStackExists({ StackStatus: 'UPDATE_ROLLBACK_COMPLETE' }, // This is for the initial check 366 { StackStatus: 'UPDATE_COMPLETE' }); 367 givenTemplateIs({ changed: 123 }); 368 // WHEN 369 await api_1.deployStack({ 370 ...standardDeployStackArguments(), 371 }); 372 // THEN 373 expect(cfnMocks.deleteStack).not.toHaveBeenCalled(); 374 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 375 ChangeSetType: 'UPDATE', 376 })); 377 }); 378 test('deploy not skipped if template changed', async () => { 379 // GIVEN 380 givenStackExists(); 381 givenTemplateIs({ changed: 123 }); 382 // WHEN 383 await api_1.deployStack({ 384 ...standardDeployStackArguments(), 385 }); 386 // THEN 387 expect(cfnMocks.executeChangeSet).toHaveBeenCalled(); 388 }); 389 test('not executed and no error if --no-execute is given', async () => { 390 // WHEN 391 await api_1.deployStack({ 392 ...standardDeployStackArguments(), 393 execute: false, 394 }); 395 // THEN 396 expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled(); 397 }); 398 test('empty change set is deleted if --execute is given', async () => { 399 var _a; 400 (_a = cfnMocks.describeChangeSet) === null || _a === void 0 ? void 0 : _a.mockImplementation(() => ({ 401 Status: 'FAILED', 402 StatusReason: 'No updates are to be performed.', 403 })); 404 // GIVEN 405 givenStackExists(); 406 // WHEN 407 await api_1.deployStack({ 408 ...standardDeployStackArguments(), 409 execute: true, 410 force: true, 411 }); 412 // THEN 413 expect(cfnMocks.createChangeSet).toHaveBeenCalled(); 414 expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled(); 415 //the first deletion is for any existing cdk change sets, the second is for the deleting the new empty change set 416 expect(cfnMocks.deleteChangeSet).toHaveBeenCalledTimes(2); 417 }); 418 test('empty change set is not deleted if --no-execute is given', async () => { 419 var _a; 420 (_a = cfnMocks.describeChangeSet) === null || _a === void 0 ? void 0 : _a.mockImplementation(() => ({ 421 Status: 'FAILED', 422 StatusReason: 'No updates are to be performed.', 423 })); 424 // GIVEN 425 givenStackExists(); 426 // WHEN 427 await api_1.deployStack({ 428 ...standardDeployStackArguments(), 429 execute: false, 430 }); 431 // THEN 432 expect(cfnMocks.createChangeSet).toHaveBeenCalled(); 433 expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled(); 434 //the first deletion is for any existing cdk change sets 435 expect(cfnMocks.deleteChangeSet).toHaveBeenCalledTimes(1); 436 }); 437 test('use S3 url for stack deployment if present in Stack Artifact', async () => { 438 // WHEN 439 await api_1.deployStack({ 440 ...standardDeployStackArguments(), 441 stack: util_1.testStack({ 442 stackName: 'withouterrors', 443 properties: { 444 stackTemplateAssetObjectUrl: 'https://use-me-use-me/', 445 }, 446 }), 447 }); 448 // THEN 449 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 450 TemplateURL: 'https://use-me-use-me/', 451 })); 452 expect(cfnMocks.executeChangeSet).toHaveBeenCalled(); 453 }); 454 test('use REST API S3 url with substituted placeholders if manifest url starts with s3://', async () => { 455 // WHEN 456 await api_1.deployStack({ 457 ...standardDeployStackArguments(), 458 stack: util_1.testStack({ 459 stackName: 'withouterrors', 460 properties: { 461 stackTemplateAssetObjectUrl: 's3://use-me-use-me-${AWS::AccountId}/object', 462 }, 463 }), 464 }); 465 // THEN 466 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 467 TemplateURL: 'https://s3.bermuda-triangle-1337.amazonaws.com/use-me-use-me-123456789/object', 468 })); 469 expect(cfnMocks.executeChangeSet).toHaveBeenCalled(); 470 }); 471 test('changeset is created when stack exists in REVIEW_IN_PROGRESS status', async () => { 472 // GIVEN 473 givenStackExists({ 474 StackStatus: 'REVIEW_IN_PROGRESS', 475 Tags: [ 476 { Key: 'Key1', Value: 'Value1' }, 477 { Key: 'Key2', Value: 'Value2' }, 478 ], 479 }); 480 // WHEN 481 await api_1.deployStack({ 482 ...standardDeployStackArguments(), 483 execute: false, 484 }); 485 // THEN 486 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 487 ChangeSetType: 'CREATE', 488 StackName: 'withouterrors', 489 })); 490 expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled(); 491 }); 492 test('changeset is updated when stack exists in CREATE_COMPLETE status', async () => { 493 // GIVEN 494 givenStackExists({ 495 Tags: [ 496 { Key: 'Key1', Value: 'Value1' }, 497 { Key: 'Key2', Value: 'Value2' }, 498 ], 499 }); 500 // WHEN 501 await api_1.deployStack({ 502 ...standardDeployStackArguments(), 503 execute: false, 504 }); 505 // THEN 506 expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 507 ChangeSetType: 'UPDATE', 508 StackName: 'withouterrors', 509 })); 510 expect(cfnMocks.executeChangeSet).not.toHaveBeenCalled(); 511 }); 512 test('deploy with termination protection enabled', async () => { 513 // WHEN 514 await api_1.deployStack({ 515 ...standardDeployStackArguments(), 516 stack: FAKE_STACK_TERMINATION_PROTECTION, 517 }); 518 // THEN 519 expect(cfnMocks.updateTerminationProtection).toHaveBeenCalledWith(expect.objectContaining({ 520 EnableTerminationProtection: true, 521 })); 522 }); 523 test('updateTerminationProtection not called when termination protection is undefined', async () => { 524 // WHEN 525 await api_1.deployStack({ 526 ...standardDeployStackArguments(), 527 }); 528 // THEN 529 expect(cfnMocks.updateTerminationProtection).not.toHaveBeenCalled(); 530 }); 531 test('updateTerminationProtection called when termination protection is undefined and stack has termination protection', async () => { 532 // GIVEN 533 givenStackExists({ 534 EnableTerminationProtection: true, 535 }); 536 // WHEN 537 await api_1.deployStack({ 538 ...standardDeployStackArguments(), 539 }); 540 // THEN 541 expect(cfnMocks.updateTerminationProtection).toHaveBeenCalledWith(expect.objectContaining({ 542 EnableTerminationProtection: false, 543 })); 544 }); 545 describe('disable rollback', () => { 546 test('by default, we do not disable rollback (and also do not pass the flag)', async () => { 547 // WHEN 548 await api_1.deployStack({ 549 ...standardDeployStackArguments(), 550 }); 551 // THEN 552 expect(cfnMocks.executeChangeSet).toHaveBeenCalledTimes(1); 553 expect(cfnMocks.executeChangeSet).not.toHaveBeenCalledWith(expect.objectContaining({ 554 DisableRollback: expect.anything(), 555 })); 556 }); 557 test('rollback can be disabled by setting rollback: false', async () => { 558 // WHEN 559 await api_1.deployStack({ 560 ...standardDeployStackArguments(), 561 rollback: false, 562 }); 563 // THEN 564 expect(cfnMocks.executeChangeSet).toHaveBeenCalledWith(expect.objectContaining({ 565 DisableRollback: true, 566 })); 567 }); 568 }); 569 /** 570 * Set up the mocks so that it looks like the stack exists to start with 571 * 572 * The last element of this array will be continuously repeated. 573 */ 574 function givenStackExists(...overrides) { 575 cfnMocks.describeStacks.mockReset(); 576 if (overrides.length === 0) { 577 overrides = [{}]; 578 } 579 const baseResponse = { 580 StackName: 'mock-stack-name', 581 StackId: 'mock-stack-id', 582 CreationTime: new Date(), 583 StackStatus: 'CREATE_COMPLETE', 584 EnableTerminationProtection: false, 585 }; 586 for (const override of overrides.slice(0, overrides.length - 1)) { 587 cfnMocks.describeStacks.mockImplementationOnce(() => ({ 588 Stacks: [{ ...baseResponse, ...override }], 589 })); 590 } 591 cfnMocks.describeStacks.mockImplementation(() => ({ 592 Stacks: [{ ...baseResponse, ...overrides[overrides.length - 1] }], 593 })); 594 } 595 function givenTemplateIs(template) { 596 cfnMocks.getTemplate.mockReset(); 597 cfnMocks.getTemplate.mockReturnValue({ 598 TemplateBody: JSON.stringify(template), 599 }); 600 } 601 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95LXN0YWNrLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZXBsb3ktc3RhY2sudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHVDQUF5RDtBQUN6RCxrQ0FBMkQ7QUFDM0QsK0NBQXdIO0FBRXhILE1BQU0sVUFBVSxHQUFHLGdCQUFTLENBQUM7SUFDM0IsU0FBUyxFQUFFLGVBQWU7Q0FDM0IsQ0FBQyxDQUFDO0FBRUgsTUFBTSwwQkFBMEIsR0FBRyxnQkFBUyxDQUFDO0lBQzNDLFNBQVMsRUFBRSxnQkFBZ0I7SUFDM0IsUUFBUSxFQUFFO1FBQ1IsVUFBVSxFQUFFO1lBQ1YsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtZQUM1QixVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUU7WUFDckQsY0FBYyxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtTQUNuQztLQUNGO0NBQ0YsQ0FBQyxDQUFDO0FBRUgsTUFBTSxpQ0FBaUMsR0FBRyxnQkFBUyxDQUFDO0lBQ2xELFNBQVMsRUFBRSx3QkFBd0I7SUFDbkMsUUFBUSxFQUFFLDRCQUFxQjtJQUMvQixxQkFBcUIsRUFBRSxJQUFJO0NBQzVCLENBQUMsQ0FBQztBQUVILElBQUksR0FBWSxDQUFDO0FBQ2pCLElBQUksV0FBNEIsQ0FBQztBQUNqQyxJQUFJLFFBQStELENBQUM7QUFDcEUsVUFBVSxDQUFDLEdBQUcsRUFBRTtJQUNkLFdBQVcsR0FBRyxJQUFJLDBCQUFlLEVBQUUsQ0FBQztJQUNwQyxHQUFHLEdBQUcsSUFBSSxrQkFBTyxFQUFFLENBQUM7SUFFcEIsUUFBUSxHQUFHO1FBQ1QsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7UUFDbEQsY0FBYyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDdkIsOEJBQThCO2FBQzdCLHNCQUFz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QUFFLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUU7UUFDL0QsUUFBUSxDQUFDLGNBQWUsQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ3JELE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxZQUFZLEVBQUUsR0FBRyxRQUFRLEVBQUUsQ0FBQztTQUMzQyxDQUFDLENBQUMsQ0FBQztLQUNMO0lBQ0QsUUFBUSxDQUFDLGNBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxZQUFZLEVBQUUsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQ2xFLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLFFBQWE7SUFDcEMsUUFBUSxDQUFDLFdBQVksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNsQyxRQUFRLENBQUMsV0FBWSxDQUFDLGVBQWUsQ0FBQztRQUNwQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7S0FDdkMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRlcGxveVN0YWNrLCBUb29sa2l0SW5mbyB9IGZyb20gJy4uLy4uL2xpYi9hcGknO1xuaW1wb3J0IHsgREVGQVVMVF9GQUtFX1RFTVBMQVRFLCB0ZXN0U3RhY2sgfSBmcm9tICcuLi91dGlsJztcbmltcG9ydCB7IE1vY2tlZE9iamVjdCwgbW9ja1Jlc29sdmVkRW52aXJvbm1lbnQsIE1vY2tTZGssIE1vY2tTZGtQcm92aWRlciwgU3luY0hhbmRsZXJTdWJzZXRPZiB9IGZyb20gJy4uL3V0aWwvbW9jay1zZGsnO1xuXG5jb25zdCBGQUtFX1NUQUNLID0gdGVzdFN0YWNrKHtcbiAgc3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsXG59KTtcblxuY29uc3QgRkFLRV9TVEFDS19XSVRIX1BBUkFNRVRFUlMgPSB0ZXN0U3RhY2soe1xuICBzdGFja05hbWU6ICd3aXRocGFyYW1ldGVycycsXG4gIHRlbXBsYXRlOiB7XG4gICAgUGFyYW1ldGVyczoge1xuICAgICAgSGFzVmFsdWU6IHsgVHlwZTogJ1N0cmluZycgfSxcbiAgICAgIEhhc0RlZmF1bHQ6IHsgVHlwZTogJ1N0cmluZycsIERlZmF1bHQ6ICdUaGVEZWZhdWx0JyB9LFxuICAgICAgT3RoZXJQYXJhbWV0ZXI6IHsgVHlwZTogJ1N0cmluZycgfSxcbiAgICB9LFxuICB9LFxufSk7XG5cbmNvbnN0IEZBS0VfU1RBQ0tfVEVSTUlOQVRJT05fUFJPVEVDVElPTiA9IHRlc3RTdGFjayh7XG4gIHN0YWNrTmFtZTogJ3Rlcm1pbmF0aW9uLXByb3RlY3Rpb24nLFxuICB0ZW1wbGF0ZTogREVGQVVMVF9GQUtFX1RFTVBMQVRFLFxuICB0ZXJtaW5hdGlvblByb3RlY3Rpb246IHRydWUsXG59KTtcblxubGV0IHNkazogTW9ja1NkaztcbmxldCBzZGtQcm92aWRlcjogTW9ja1Nka1Byb3ZpZGVyO1xubGV0IGNmbk1vY2tzOiBNb2NrZWRPYmplY3Q8U3luY0hhbmRsZXJTdWJzZXRPZjxBV1MuQ2xvdWRGb3JtYXRpb24+PjtcbmJlZm9yZUVhY2goKCkgPT4ge1xuICBzZGtQcm92aWRlciA9IG5ldyBNb2NrU2RrUHJvdmlkZXIoKTtcbiAgc2RrID0gbmV3IE1vY2tTZGsoKTtcblxuICBjZm5Nb2NrcyA9IHtcbiAgICBkZXNjcmliZVN0YWNrRXZlbnRzOiBqZXN0LmZuKCkubW9ja1JldHVyblZhbHVlKHt9KSxcbiAgICBkZXNjcmliZVN0YWNrczogamVzdC5mbigpXG4gICAgICAvLyBGaXJzdCBjYWxsLCBubyBzdGFja3MgZXhpc3RcbiAgICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7IFN0YWNrczogW10gfSkpXG4gICAgICAvLyBTZWNvbmQgY2FsbCwgc3RhY2sgaGFzIGJlZW4gY3JlYXRlZFxuICAgICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgICAgU3RhY2tzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgU3RhY2tTdGF0dXM6ICdDUkVBVEVfQ09NUExFVEUnLFxuICAgICAgICAgICAgU3RhY2tTdGF0dXNSZWFzb246ICdJdCBpcyBtYWdpYycsXG4gICAgICAgICAgICBFbmFibGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KSksXG4gICAgY3JlYXRlQ2hhbmdlU2V0OiBqZXN0LmZuKChfbykgPT4gKHt9KSksXG4gICAgZGVsZXRlQ2hhbmdlU2V0OiBqZXN0LmZuKChfbykgPT4gKHt9KSksXG4gICAgZGVzY3JpYmVDaGFuZ2VTZXQ6IGplc3QuZm4oKF9vKSA9PiAoe1xuICAgICAgU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyxcbiAgICAgIENoYW5nZXM6IFtdLFxuICAgIH0pKSxcbiAgICBleGVjdXRlQ2hhbmdlU2V0OiBqZXN0LmZuKChfbykgPT4gKHt9KSksXG4gICAgZGVsZXRlU3RhY2s6IGplc3QuZm4oKF9vKSA9PiAoe30pKSxcbiAgICBnZXRUZW1wbGF0ZTogamVzdC5mbigoX28pID0+ICh7IFRlbXBsYXRlQm9keTogSlNPTi5zdHJpbmdpZnkoREVGQVVMVF9GQUtFX1RFTVBMQVRFKSB9KSksXG4gICAgdXBkYXRlVGVybWluYXRpb25Qcm90ZWN0aW9uOiBqZXN0LmZuKChfbykgPT4gKHsgU3RhY2tJZDogJ3N0YWNrLWlkJyB9KSksXG4gIH07XG4gIHNkay5zdHViQ2xvdWRGb3JtYXRpb24oY2ZuTW9ja3MgYXMgYW55KTtcblxufSk7XG5cbmZ1bmN0aW9uIHN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSB7XG4gIHJldHVybiB7XG4gICAgc3RhY2s6IEZBS0VfU1RBQ0ssXG4gICAgc2RrLFxuICAgIHNka1Byb3ZpZGVyLFxuICAgIHJlc29sdmVkRW52aXJvbm1lbnQ6IG1vY2tSZXNvbHZlZEVudmlyb25tZW50KCksXG4gICAgdG9vbGtpdEluZm86IFRvb2xraXRJbmZvLmJvb3RzdHJhcGxlc3NEZXBsb3ltZW50c09ubHkoc2RrKSxcbiAgfTtcbn1cblxudGVzdCgnZG8gZGVwbG95IGV4ZWN1dGFibGUgY2hhbmdlIHNldCB3aXRoIDAgY2hhbmdlcycsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBjb25zdCByZXQgPSBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgnY29ycmVjdGx5IHBhc3NlcyBDRk4gcGFyYW1ldGVycywgaWdub3Jpbmcgb25lcyB3aXRoIGVtcHR5IHZhbHVlcycsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIEE6ICdBLXZhbHVlJyxcbiAgICAgIEI6ICdCPXZhbHVlJyxcbiAgICAgIEM6IHVuZGVmaW5lZCxcbiAgICAgIEQ6ICcnLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnQScsIFBhcmFtZXRlclZhbHVlOiAnQS12YWx1ZScgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnQicsIFBhcmFtZXRlclZhbHVlOiAnQj12YWx1ZScgfSxcbiAgICBdLFxuICB9KSk7XG59KTtcblxudGVzdCgncmV1c2UgcHJldmlvdXMgcGFyYW1ldGVycyBpZiByZXF1ZXN0ZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzVmFsdWUnLCBQYXJhbWV0ZXJWYWx1ZTogJ1RoZVZhbHVlJyB9LFxuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNEZWZhdWx0JywgUGFyYW1ldGVyVmFsdWU6ICdUaGVPbGRWYWx1ZScgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIE90aGVyUGFyYW1ldGVyOiAnU29tZVZhbHVlJyxcbiAgICB9LFxuICAgIHVzZVByZXZpb3VzUGFyYW1ldGVyczogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFVzZVByZXZpb3VzVmFsdWU6IHRydWUgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzRGVmYXVsdCcsIFVzZVByZXZpb3VzVmFsdWU6IHRydWUgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnT3RoZXJQYXJhbWV0ZXInLCBQYXJhbWV0ZXJWYWx1ZTogJ1NvbWVWYWx1ZScgfSxcbiAgICBdLFxuICB9KSk7XG59KTtcblxudGVzdCgnZG8gbm90IHJldXNlIHByZXZpb3VzIHBhcmFtZXRlcnMgaWYgbm90IHJlcXVlc3RlZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnVGhlVmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBQYXJhbWV0ZXJWYWx1ZTogJ1RoZU9sZFZhbHVlJyB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICBzdGFjazogRkFLRV9TVEFDS19XSVRIX1BBUkFNRVRFUlMsXG4gICAgcGFyYW1ldGVyczoge1xuICAgICAgSGFzVmFsdWU6ICdTb21lVmFsdWUnLFxuICAgICAgT3RoZXJQYXJhbWV0ZXI6ICdTb21lVmFsdWUnLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzVmFsdWUnLCBQYXJhbWV0ZXJWYWx1ZTogJ1NvbWVWYWx1ZScgfSxcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnT3RoZXJQYXJhbWV0ZXInLCBQYXJhbWV0ZXJWYWx1ZTogJ1NvbWVWYWx1ZScgfSxcbiAgICBdLFxuICB9KSk7XG59KTtcblxudGVzdCgndGhyb3cgZXhjZXB0aW9uIGlmIG5vdCBlbm91Z2ggcGFyYW1ldGVycyBzdXBwbGllZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnVGhlVmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBQYXJhbWV0ZXJWYWx1ZTogJ1RoZU9sZFZhbHVlJyB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZXhwZWN0KGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIE90aGVyUGFyYW1ldGVyOiAnU29tZVZhbHVlJyxcbiAgICB9LFxuICB9KSkucmVqZWN0cy50b1Rocm93KC9DbG91ZEZvcm1hdGlvbiBQYXJhbWV0ZXJzIGFyZSBtaXNzaW5nIGEgdmFsdWUvKTtcbn0pO1xuXG50ZXN0KCdkZXBsb3kgaXMgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cygpO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkubm90LnRvQmVDYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdkZXBsb3kgaXMgc2tpcHBlZCBpZiBwYXJhbWV0ZXJzIGFyZSB0aGUgc2FtZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5UZW1wbGF0ZUlzKEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLnRlbXBsYXRlKTtcbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnSGFzVmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBQYXJhbWV0ZXJWYWx1ZTogJ0hhc0RlZmF1bHQnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ090aGVyUGFyYW1ldGVyJywgUGFyYW1ldGVyVmFsdWU6ICdPdGhlclBhcmFtZXRlcicgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IEZBS0VfU1RBQ0tfV0lUSF9QQVJBTUVURVJTLFxuICAgIHBhcmFtZXRlcnM6IHt9LFxuICAgIHVzZVByZXZpb3VzUGFyYW1ldGVyczogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBpcyBub3Qgc2tpcHBlZCBpZiBwYXJhbWV0ZXJzIGFyZSBkaWZmZXJlbnQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuVGVtcGxhdGVJcyhGQUtFX1NUQUNLX1dJVEhfUEFSQU1FVEVSUy50ZW1wbGF0ZSk7XG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFBhcmFtZXRlcnM6IFtcbiAgICAgIHsgUGFyYW1ldGVyS2V5OiAnSGFzVmFsdWUnLCBQYXJhbWV0ZXJWYWx1ZTogJ0hhc1ZhbHVlJyB9LFxuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNEZWZhdWx0JywgUGFyYW1ldGVyVmFsdWU6ICdIYXNEZWZhdWx0JyB9LFxuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdPdGhlclBhcmFtZXRlcicsIFBhcmFtZXRlclZhbHVlOiAnT3RoZXJQYXJhbWV0ZXInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHN0YWNrOiBGQUtFX1NUQUNLX1dJVEhfUEFSQU1FVEVSUyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICBIYXNWYWx1ZTogJ05ld1ZhbHVlJyxcbiAgICB9LFxuICAgIHVzZVByZXZpb3VzUGFyYW1ldGVyczogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgUGFyYW1ldGVyczogW1xuICAgICAgeyBQYXJhbWV0ZXJLZXk6ICdIYXNWYWx1ZScsIFBhcmFtZXRlclZhbHVlOiAnTmV3VmFsdWUnIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ0hhc0RlZmF1bHQnLCBVc2VQcmV2aW91c1ZhbHVlOiB0cnVlIH0sXG4gICAgICB7IFBhcmFtZXRlcktleTogJ090aGVyUGFyYW1ldGVyJywgVXNlUHJldmlvdXNWYWx1ZTogdHJ1ZSB9LFxuICAgIF0sXG4gIH0pKTtcbn0pO1xuXG50ZXN0KCdpZiBleGlzdGluZyBzdGFjayBmYWlsZWQgdG8gY3JlYXRlLCBpdCBpcyBkZWxldGVkIGFuZCByZWNyZWF0ZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoXG4gICAgeyBTdGFja1N0YXR1czogJ1JPTExCQUNLX0NPTVBMRVRFJyB9LCAvLyBUaGlzIGlzIGZvciB0aGUgaW5pdGlhbCBjaGVja1xuICAgIHsgU3RhY2tTdGF0dXM6ICdERUxFVEVfQ09NUExFVEUnIH0sIC8vIFBvbGwgdGhlIHN1Y2Nlc3NmdWwgZGVsZXRpb25cbiAgICB7IFN0YWNrU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyB9LCAvLyBQb2xsIHRoZSByZWNyZWF0aW9uXG4gICk7XG4gIGdpdmVuVGVtcGxhdGVJcyh7XG4gICAgRGlmZmVyZW50VGhhbjogJ1RoZURlZmF1bHQnLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmRlbGV0ZVN0YWNrKS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBDaGFuZ2VTZXRUeXBlOiAnQ1JFQVRFJyxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ2lmIGV4aXN0aW5nIHN0YWNrIGZhaWxlZCB0byBjcmVhdGUsIGl0IGlzIGRlbGV0ZWQgYW5kIHJlY3JlYXRlZCBldmVuIGlmIHRoZSB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyhcbiAgICB7IFN0YWNrU3RhdHVzOiAnUk9MTEJBQ0tfQ09NUExFVEUnIH0sIC8vIFRoaXMgaXMgZm9yIHRoZSBpbml0aWFsIGNoZWNrXG4gICAgeyBTdGFja1N0YXR1czogJ0RFTEVURV9DT01QTEVURScgfSwgLy8gUG9sbCB0aGUgc3VjY2Vzc2Z1bCBkZWxldGlvblxuICAgIHsgU3RhY2tTdGF0dXM6ICdDUkVBVEVfQ09NUExFVEUnIH0sIC8vIFBvbGwgdGhlIHJlY3JlYXRpb25cbiAgKTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmRlbGV0ZVN0YWNrKS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBDaGFuZ2VTZXRUeXBlOiAnQ1JFQVRFJyxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBub3Qgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZSBhbmQgLS1mb3JjZSBpcyBhcHBsaWVkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlblN0YWNrRXhpc3RzKCk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGZvcmNlOiB0cnVlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgnZGVwbG95IGlzIHNraXBwZWQgaWYgdGVtcGxhdGUgYW5kIHRhZ3MgZGlkIG5vdCBjaGFuZ2UnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuY3JlYXRlQ2hhbmdlU2V0KS5ub3QudG9CZUNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkubm90LnRvQmVDYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmRlc2NyaWJlU3RhY2tzKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7IFN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnIH0pO1xuICBleHBlY3QoY2ZuTW9ja3MuZ2V0VGVtcGxhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHsgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsIFRlbXBsYXRlU3RhZ2U6ICdPcmlnaW5hbCcgfSk7XG59KTtcblxudGVzdCgnZGVwbG95IG5vdCBza2lwcGVkIGlmIHRlbXBsYXRlIGRpZCBub3QgY2hhbmdlIGJ1dCB0YWdzIGNoYW5nZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5JywgVmFsdWU6ICdWYWx1ZScgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICBzdGFjazogRkFLRV9TVEFDSyxcbiAgICBzZGssXG4gICAgc2RrUHJvdmlkZXIsXG4gICAgcmVzb2x2ZWRFbnZpcm9ubWVudDogbW9ja1Jlc29sdmVkRW52aXJvbm1lbnQoKSxcbiAgICB0YWdzOiBbXG4gICAgICB7XG4gICAgICAgIEtleTogJ0tleScsXG4gICAgICAgIFZhbHVlOiAnTmV3VmFsdWUnLFxuICAgICAgfSxcbiAgICBdLFxuICAgIHRvb2xraXRJbmZvOiBUb29sa2l0SW5mby5ib290c3RyYXBsZXNzRGVwbG95bWVudHNPbmx5KHNkayksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZGVzY3JpYmVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmRlc2NyaWJlU3RhY2tzKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7IFN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnIH0pO1xuICBleHBlY3QoY2ZuTW9ja3MuZ2V0VGVtcGxhdGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHsgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsIFRlbXBsYXRlU3RhZ2U6ICdPcmlnaW5hbCcgfSk7XG59KTtcblxudGVzdCgnZGVwbG95U3RhY2sgcmVwb3J0cyBubyBjaGFuZ2UgaWYgZGVzY3JpYmVDaGFuZ2VTZXQgcmV0dXJucyBzcGVjaWZpYyBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgY2ZuTW9ja3MuZGVzY3JpYmVDaGFuZ2VTZXQ/Lm1vY2tJbXBsZW1lbnRhdGlvbigoKSA9PiAoe1xuICAgIFN0YXR1czogJ0ZBSUxFRCcsXG4gICAgU3RhdHVzUmVhc29uOiAnTm8gdXBkYXRlcyBhcmUgdG8gYmUgcGVyZm9ybWVkLicsXG4gIH0pKTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IGRlcGxveVJlc3VsdCA9IGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGRlcGxveVJlc3VsdC5ub09wKS50b0VxdWFsKHRydWUpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBub3Qgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBkaWQgbm90IGNoYW5nZSBidXQgb25lIHRhZyByZW1vdmVkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlblN0YWNrRXhpc3RzKHtcbiAgICBUYWdzOiBbXG4gICAgICB7IEtleTogJ0tleTEnLCBWYWx1ZTogJ1ZhbHVlMScgfSxcbiAgICAgIHsgS2V5OiAnS2V5MicsIFZhbHVlOiAnVmFsdWUyJyB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICB0YWdzOiBbXG4gICAgICB7IEtleTogJ0tleTEnLCBWYWx1ZTogJ1ZhbHVlMScgfSxcbiAgICBdLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmV4ZWN1dGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmRlc2NyaWJlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcykudG9IYXZlQmVlbkNhbGxlZFdpdGgoeyBTdGFja05hbWU6ICd3aXRob3V0ZXJyb3JzJyB9KTtcbiAgZXhwZWN0KGNmbk1vY2tzLmdldFRlbXBsYXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7IFN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnLCBUZW1wbGF0ZVN0YWdlOiAnT3JpZ2luYWwnIH0pO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBpcyBub3Qgc2tpcHBlZCBpZiBzdGFjayBpcyBpbiBhIF9GQUlMRUQgc3RhdGUnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFN0YWNrU3RhdHVzOiAnREVMRVRFX0ZBSUxFRCcsXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICB1c2VQcmV2aW91c1BhcmFtZXRlcnM6IHRydWUsXG4gIH0pLmNhdGNoKCgpID0+IHt9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdleGlzdGluZyBzdGFjayBpbiBVUERBVEVfUk9MTEJBQ0tfQ09NUExFVEUgc3RhdGUgY2FuIGJlIHVwZGF0ZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoXG4gICAgeyBTdGFja1N0YXR1czogJ1VQREFURV9ST0xMQkFDS19DT01QTEVURScgfSwgLy8gVGhpcyBpcyBmb3IgdGhlIGluaXRpYWwgY2hlY2tcbiAgICB7IFN0YWNrU3RhdHVzOiAnVVBEQVRFX0NPTVBMRVRFJyB9LCAvLyBQb2xsIHRoZSB1cGRhdGVcbiAgKTtcbiAgZ2l2ZW5UZW1wbGF0ZUlzKHsgY2hhbmdlZDogMTIzIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MuZGVsZXRlU3RhY2spLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBDaGFuZ2VTZXRUeXBlOiAnVVBEQVRFJyxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSBub3Qgc2tpcHBlZCBpZiB0ZW1wbGF0ZSBjaGFuZ2VkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlblN0YWNrRXhpc3RzKCk7XG4gIGdpdmVuVGVtcGxhdGVJcyh7IGNoYW5nZWQ6IDEyMyB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmV4ZWN1dGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdub3QgZXhlY3V0ZWQgYW5kIG5vIGVycm9yIGlmIC0tbm8tZXhlY3V0ZSBpcyBnaXZlbicsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGV4ZWN1dGU6IGZhbHNlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2VtcHR5IGNoYW5nZSBzZXQgaXMgZGVsZXRlZCBpZiAtLWV4ZWN1dGUgaXMgZ2l2ZW4nLCBhc3luYyAoKSA9PiB7XG4gIGNmbk1vY2tzLmRlc2NyaWJlQ2hhbmdlU2V0Py5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4gKHtcbiAgICBTdGF0dXM6ICdGQUlMRUQnLFxuICAgIFN0YXR1c1JlYXNvbjogJ05vIHVwZGF0ZXMgYXJlIHRvIGJlIHBlcmZvcm1lZC4nLFxuICB9KSk7XG5cbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cygpO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICBleGVjdXRlOiB0cnVlLFxuICAgIGZvcmNlOiB0cnVlLCAvLyBOZWNlc3NhcnkgdG8gYnlwYXNzIFwic2tpcCBkZXBsb3lcIlxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmV4ZWN1dGVDaGFuZ2VTZXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG5cbiAgLy90aGUgZmlyc3QgZGVsZXRpb24gaXMgZm9yIGFueSBleGlzdGluZyBjZGsgY2hhbmdlIHNldHMsIHRoZSBzZWNvbmQgaXMgZm9yIHRoZSBkZWxldGluZyB0aGUgbmV3IGVtcHR5IGNoYW5nZSBzZXRcbiAgZXhwZWN0KGNmbk1vY2tzLmRlbGV0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDIpO1xufSk7XG5cbnRlc3QoJ2VtcHR5IGNoYW5nZSBzZXQgaXMgbm90IGRlbGV0ZWQgaWYgLS1uby1leGVjdXRlIGlzIGdpdmVuJywgYXN5bmMgKCkgPT4ge1xuICBjZm5Nb2Nrcy5kZXNjcmliZUNoYW5nZVNldD8ubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+ICh7XG4gICAgU3RhdHVzOiAnRkFJTEVEJyxcbiAgICBTdGF0dXNSZWFzb246ICdObyB1cGRhdGVzIGFyZSB0byBiZSBwZXJmb3JtZWQuJyxcbiAgfSkpO1xuXG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoKTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgZXhlY3V0ZTogZmFsc2UsXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcblxuICAvL3RoZSBmaXJzdCBkZWxldGlvbiBpcyBmb3IgYW55IGV4aXN0aW5nIGNkayBjaGFuZ2Ugc2V0c1xuICBleHBlY3QoY2ZuTW9ja3MuZGVsZXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkVGltZXMoMSk7XG59KTtcblxudGVzdCgndXNlIFMzIHVybCBmb3Igc3RhY2sgZGVwbG95bWVudCBpZiBwcmVzZW50IGluIFN0YWNrIEFydGlmYWN0JywgYXN5bmMgKCkgPT4ge1xuICAvLyBXSEVOXG4gIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAuLi5zdGFuZGFyZERlcGxveVN0YWNrQXJndW1lbnRzKCksXG4gICAgc3RhY2s6IHRlc3RTdGFjayh7XG4gICAgICBzdGFja05hbWU6ICd3aXRob3V0ZXJyb3JzJyxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgc3RhY2tUZW1wbGF0ZUFzc2V0T2JqZWN0VXJsOiAnaHR0cHM6Ly91c2UtbWUtdXNlLW1lLycsXG4gICAgICB9LFxuICAgIH0pLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBUZW1wbGF0ZVVSTDogJ2h0dHBzOi8vdXNlLW1lLXVzZS1tZS8nLFxuICB9KSk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgndXNlIFJFU1QgQVBJIFMzIHVybCB3aXRoIHN1YnN0aXR1dGVkIHBsYWNlaG9sZGVycyBpZiBtYW5pZmVzdCB1cmwgc3RhcnRzIHdpdGggczM6Ly8nLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICBzdGFjazogdGVzdFN0YWNrKHtcbiAgICAgIHN0YWNrTmFtZTogJ3dpdGhvdXRlcnJvcnMnLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBzdGFja1RlbXBsYXRlQXNzZXRPYmplY3RVcmw6ICdzMzovL3VzZS1tZS11c2UtbWUtJHtBV1M6OkFjY291bnRJZH0vb2JqZWN0JyxcbiAgICAgIH0sXG4gICAgfSksXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLmNyZWF0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIFRlbXBsYXRlVVJMOiAnaHR0cHM6Ly9zMy5iZXJtdWRhLXRyaWFuZ2xlLTEzMzcuYW1hem9uYXdzLmNvbS91c2UtbWUtdXNlLW1lLTEyMzQ1Njc4OS9vYmplY3QnLFxuICB9KSk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgnY2hhbmdlc2V0IGlzIGNyZWF0ZWQgd2hlbiBzdGFjayBleGlzdHMgaW4gUkVWSUVXX0lOX1BST0dSRVNTIHN0YXR1cycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgZ2l2ZW5TdGFja0V4aXN0cyh7XG4gICAgU3RhY2tTdGF0dXM6ICdSRVZJRVdfSU5fUFJPR1JFU1MnLFxuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGV4ZWN1dGU6IGZhbHNlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgIENoYW5nZVNldFR5cGU6ICdDUkVBVEUnLFxuICAgICAgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsXG4gICAgfSksXG4gICk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2NoYW5nZXNldCBpcyB1cGRhdGVkIHdoZW4gc3RhY2sgZXhpc3RzIGluIENSRUFURV9DT01QTEVURSBzdGF0dXMnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIFRhZ3M6IFtcbiAgICAgIHsgS2V5OiAnS2V5MScsIFZhbHVlOiAnVmFsdWUxJyB9LFxuICAgICAgeyBLZXk6ICdLZXkyJywgVmFsdWU6ICdWYWx1ZTInIH0sXG4gICAgXSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIGV4ZWN1dGU6IGZhbHNlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy5jcmVhdGVDaGFuZ2VTZXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgIENoYW5nZVNldFR5cGU6ICdVUERBVEUnLFxuICAgICAgU3RhY2tOYW1lOiAnd2l0aG91dGVycm9ycycsXG4gICAgfSksXG4gICk7XG4gIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ2RlcGxveSB3aXRoIHRlcm1pbmF0aW9uIHByb3RlY3Rpb24gZW5hYmxlZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgIHN0YWNrOiBGQUtFX1NUQUNLX1RFUk1JTkFUSU9OX1BST1RFQ1RJT04sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGNmbk1vY2tzLnVwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbikudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgIEVuYWJsZVRlcm1pbmF0aW9uUHJvdGVjdGlvbjogdHJ1ZSxcbiAgfSkpO1xufSk7XG5cbnRlc3QoJ3VwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbiBub3QgY2FsbGVkIHdoZW4gdGVybWluYXRpb24gcHJvdGVjdGlvbiBpcyB1bmRlZmluZWQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY2ZuTW9ja3MudXBkYXRlVGVybWluYXRpb25Qcm90ZWN0aW9uKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xufSk7XG5cbnRlc3QoJ3VwZGF0ZVRlcm1pbmF0aW9uUHJvdGVjdGlvbiBjYWxsZWQgd2hlbiB0ZXJtaW5hdGlvbiBwcm90ZWN0aW9uIGlzIHVuZGVmaW5lZCBhbmQgc3RhY2sgaGFzIHRlcm1pbmF0aW9uIHByb3RlY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuU3RhY2tFeGlzdHMoe1xuICAgIEVuYWJsZVRlcm1pbmF0aW9uUHJvdGVjdGlvbjogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBkZXBsb3lTdGFjayh7XG4gICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjZm5Nb2Nrcy51cGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb24pLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICBFbmFibGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICB9KSk7XG59KTtcblxuZGVzY3JpYmUoJ2Rpc2FibGUgcm9sbGJhY2snLCAoKSA9PiB7XG4gIHRlc3QoJ2J5IGRlZmF1bHQsIHdlIGRvIG5vdCBkaXNhYmxlIHJvbGxiYWNrIChhbmQgYWxzbyBkbyBub3QgcGFzcyB0aGUgZmxhZyknLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gV0hFTlxuICAgIGF3YWl0IGRlcGxveVN0YWNrKHtcbiAgICAgIC4uLnN0YW5kYXJkRGVwbG95U3RhY2tBcmd1bWVudHMoKSxcbiAgICB9KTtcblxuICAgIC8vIFRIRU5cbiAgICBleHBlY3QoY2ZuTW9ja3MuZXhlY3V0ZUNoYW5nZVNldCkudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDEpO1xuICAgIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgICAgRGlzYWJsZVJvbGxiYWNrOiBleHBlY3QuYW55dGhpbmcoKSxcbiAgICB9KSk7XG4gIH0pO1xuXG4gIHRlc3QoJ3JvbGxiYWNrIGNhbiBiZSBkaXNhYmxlZCBieSBzZXR0aW5nIHJvbGxiYWNrOiBmYWxzZScsIGFzeW5jICgpID0+IHtcbiAgICAvLyBXSEVOXG4gICAgYXdhaXQgZGVwbG95U3RhY2soe1xuICAgICAgLi4uc3RhbmRhcmREZXBsb3lTdGFja0FyZ3VtZW50cygpLFxuICAgICAgcm9sbGJhY2s6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgLy8gVEhFTlxuICAgIGV4cGVjdChjZm5Nb2Nrcy5leGVjdXRlQ2hhbmdlU2V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgICBEaXNhYmxlUm9sbGJhY2s6IHRydWUsXG4gICAgfSkpO1xuICB9KTtcblxufSk7XG5cbi8qKlxuICogU2V0IHVwIHRoZSBtb2NrcyBzbyB0aGF0IGl0IGxvb2tzIGxpa2UgdGhlIHN0YWNrIGV4aXN0cyB0byBzdGFydCB3aXRoXG4gKlxuICogVGhlIGxhc3QgZWxlbWVudCBvZiB0aGlzIGFycmF5IHdpbGwgYmUgY29udGludW91c2x5IHJlcGVhdGVkLlxuICovXG5mdW5jdGlvbiBnaXZlblN0YWNrRXhpc3RzKC4uLm92ZXJyaWRlczogQXJyYXk8UGFydGlhbDxBV1MuQ2xvdWRGb3JtYXRpb24uU3RhY2s+Pikge1xuICBjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEubW9ja1Jlc2V0KCk7XG5cbiAgaWYgKG92ZXJyaWRlcy5sZW5ndGggPT09IDApIHtcbiAgICBvdmVycmlkZXMgPSBbe31dO1xuICB9XG5cbiAgY29uc3QgYmFzZVJlc3BvbnNlID0ge1xuICAgIFN0YWNrTmFtZTogJ21vY2stc3RhY2stbmFtZScsXG4gICAgU3RhY2tJZDogJ21vY2stc3RhY2staWQnLFxuICAgIENyZWF0aW9uVGltZTogbmV3IERhdGUoKSxcbiAgICBTdGFja1N0YXR1czogJ0NSRUFURV9DT01QTEVURScsXG4gICAgRW5hYmxlVGVybWluYXRpb25Qcm90ZWN0aW9uOiBmYWxzZSxcbiAgfTtcblxuICBmb3IgKGNvbnN0IG92ZXJyaWRlIG9mIG92ZXJyaWRlcy5zbGljZSgwLCBvdmVycmlkZXMubGVuZ3RoIC0gMSkpIHtcbiAgICBjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoe1xuICAgICAgU3RhY2tzOiBbeyAuLi5iYXNlUmVzcG9uc2UsIC4uLm92ZXJyaWRlIH1dLFxuICAgIH0pKTtcbiAgfVxuICBjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+ICh7XG4gICAgU3RhY2tzOiBbeyAuLi5iYXNlUmVzcG9uc2UsIC4uLm92ZXJyaWRlc1tvdmVycmlkZXMubGVuZ3RoIC0gMV0gfV0sXG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZ2l2ZW5UZW1wbGF0ZUlzKHRlbXBsYXRlOiBhbnkpIHtcbiAgY2ZuTW9ja3MuZ2V0VGVtcGxhdGUhLm1vY2tSZXNldCgpO1xuICBjZm5Nb2Nrcy5nZXRUZW1wbGF0ZSEubW9ja1JldHVyblZhbHVlKHtcbiAgICBUZW1wbGF0ZUJvZHk6IEpTT04uc3RyaW5naWZ5KHRlbXBsYXRlKSxcbiAgfSk7XG59Il19