bootstrap.test.js
1 "use strict"; 2 Object.defineProperty(exports, "__esModule", { value: true }); 3 const bootstrap_1 = require("../../lib/api/bootstrap"); 4 const serialize_1 = require("../../lib/serialize"); 5 const mock_sdk_1 = require("../util/mock-sdk"); 6 const env = { 7 account: '123456789012', 8 region: 'us-east-1', 9 name: 'mock', 10 }; 11 let sdk; 12 let executed; 13 let protectedTermination; 14 let cfnMocks; 15 let changeSetTemplate; 16 let bootstrapper; 17 beforeEach(() => { 18 sdk = new mock_sdk_1.MockSdkProvider(); 19 executed = false; 20 protectedTermination = false; 21 bootstrapper = new bootstrap_1.Bootstrapper({ source: 'legacy' }); 22 cfnMocks = { 23 describeStackEvents: jest.fn().mockReturnValue({}), 24 describeStacks: jest.fn() 25 // First two calls, no stacks exist (first is for version checking, second is in deploy-stack.ts) 26 .mockImplementationOnce(() => ({ Stacks: [] })) 27 .mockImplementationOnce(() => ({ Stacks: [] })) 28 // Second call, stack has been created 29 .mockImplementationOnce(() => ({ 30 Stacks: [ 31 { 32 StackStatus: 'CREATE_COMPLETE', 33 StackStatusReason: 'It is magic', 34 EnableTerminationProtection: false, 35 }, 36 ], 37 })), 38 createChangeSet: jest.fn((info) => { 39 changeSetTemplate = serialize_1.deserializeStructure(info.TemplateBody); 40 return {}; 41 }), 42 describeChangeSet: jest.fn(() => ({ 43 Status: 'CREATE_COMPLETE', 44 Changes: [], 45 })), 46 executeChangeSet: jest.fn(() => { 47 executed = true; 48 return {}; 49 }), 50 deleteChangeSet: jest.fn(), 51 getTemplate: jest.fn(() => { 52 executed = true; 53 return {}; 54 }), 55 deleteStack: jest.fn(), 56 updateTerminationProtection: jest.fn(() => { 57 protectedTermination = true; 58 return {}; 59 }), 60 }; 61 sdk.stubCloudFormation(cfnMocks); 62 }); 63 test('do bootstrap', async () => { 64 // WHEN 65 const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack' }); 66 // THEN 67 const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; 68 expect(bucketProperties.BucketName).toBeUndefined(); 69 expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) 70 .toBeUndefined(); 71 expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); 72 expect(ret.noOp).toBeFalsy(); 73 expect(executed).toBeTruthy(); 74 }); 75 test('do bootstrap using custom bucket name', async () => { 76 // WHEN 77 const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { 78 toolkitStackName: 'mockStack', 79 parameters: { 80 bucketName: 'foobar', 81 }, 82 }); 83 // THEN 84 const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; 85 expect(bucketProperties.BucketName).toBe('foobar'); 86 expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) 87 .toBeUndefined(); 88 expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); 89 expect(ret.noOp).toBeFalsy(); 90 expect(executed).toBeTruthy(); 91 }); 92 test('do bootstrap using KMS CMK', async () => { 93 // WHEN 94 const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { 95 toolkitStackName: 'mockStack', 96 parameters: { 97 kmsKeyId: 'myKmsKey', 98 }, 99 }); 100 // THEN 101 const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; 102 expect(bucketProperties.BucketName).toBeUndefined(); 103 expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) 104 .toBe('myKmsKey'); 105 expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); 106 expect(ret.noOp).toBeFalsy(); 107 expect(executed).toBeTruthy(); 108 }); 109 test('bootstrap disable bucket Public Access Block Configuration', async () => { 110 // WHEN 111 const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { 112 toolkitStackName: 'mockStack', 113 parameters: { 114 publicAccessBlockConfiguration: false, 115 }, 116 }); 117 // THEN 118 const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; 119 expect(bucketProperties.BucketName).toBeUndefined(); 120 expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) 121 .toBeUndefined(); 122 expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('false'); 123 expect(ret.noOp).toBeFalsy(); 124 expect(executed).toBeTruthy(); 125 }); 126 test('do bootstrap with custom tags for toolkit stack', async () => { 127 // WHEN 128 const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { 129 toolkitStackName: 'mockStack', 130 tags: [{ Key: 'Foo', Value: 'Bar' }], 131 }); 132 // THEN 133 const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; 134 expect(bucketProperties.BucketName).toBeUndefined(); 135 expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) 136 .toBeUndefined(); 137 expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); 138 expect(ret.noOp).toBeFalsy(); 139 expect(executed).toBeTruthy(); 140 }); 141 test('passing trusted accounts to the old bootstrapping results in an error', async () => { 142 await expect(bootstrapper.bootstrapEnvironment(env, sdk, { 143 toolkitStackName: 'mockStack', 144 parameters: { 145 trustedAccounts: ['0123456789012'], 146 }, 147 })) 148 .rejects 149 .toThrow('--trust can only be passed for the modern bootstrap experience.'); 150 }); 151 test('passing CFN execution policies to the old bootstrapping results in an error', async () => { 152 await expect(bootstrapper.bootstrapEnvironment(env, sdk, { 153 toolkitStackName: 'mockStack', 154 parameters: { 155 cloudFormationExecutionPolicies: ['arn:aws:iam::aws:policy/AdministratorAccess'], 156 }, 157 })) 158 .rejects 159 .toThrow('--cloudformation-execution-policies can only be passed for the modern bootstrap experience.'); 160 }); 161 test('even if the bootstrap stack is in a rollback state, can still retry bootstrapping it', async () => { 162 cfnMocks.describeStacks 163 .mockReset() 164 // First two calls, the stack exists with a 'rollback complete' status 165 // (first is for version checking, second is in deploy-stack.ts) 166 .mockImplementationOnce(() => ({ 167 Stacks: [ 168 { 169 StackStatus: 'UPDATE_ROLLBACK_COMPLETE', 170 StackStatusReason: 'It is magic', 171 Outputs: [ 172 { OutputKey: 'BucketName', OutputValue: 'bucket' }, 173 { OutputKey: 'BucketDomainName', OutputValue: 'aws.com' }, 174 ], 175 }, 176 ], 177 })) 178 .mockImplementationOnce(() => ({ 179 Stacks: [ 180 { 181 StackStatus: 'UPDATE_ROLLBACK_COMPLETE', 182 StackStatusReason: 'It is magic', 183 Outputs: [ 184 { OutputKey: 'BucketName', OutputValue: 'bucket' }, 185 { OutputKey: 'BucketDomainName', OutputValue: 'aws.com' }, 186 ], 187 }, 188 ], 189 })) 190 // Third call, stack has been created 191 .mockImplementationOnce(() => ({ 192 Stacks: [ 193 { 194 StackStatus: 'CREATE_COMPLETE', 195 StackStatusReason: 'It is magic', 196 EnableTerminationProtection: false, 197 }, 198 ], 199 })); 200 // WHEN 201 const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack' }); 202 // THEN 203 const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; 204 expect(bucketProperties.BucketName).toBeUndefined(); 205 expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) 206 .toBeUndefined(); 207 expect(ret.noOp).toBeFalsy(); 208 expect(executed).toBeTruthy(); 209 }); 210 test('even if the bootstrap stack failed to create, can still retry bootstrapping it', async () => { 211 cfnMocks.describeStacks 212 .mockReset() 213 // First two calls, the stack exists with a 'rollback complete' status 214 // (first is for version checking, second is in deploy-stack.ts) 215 .mockImplementationOnce(() => ({ 216 Stacks: [ 217 { 218 StackStatus: 'ROLLBACK_COMPLETE', 219 StackStatusReason: 'It is magic', 220 Outputs: [ 221 { OutputKey: 'BucketName', OutputValue: 'bucket' }, 222 ], 223 }, 224 ], 225 })) 226 .mockImplementationOnce(() => ({ 227 Stacks: [ 228 { 229 StackStatus: 'ROLLBACK_COMPLETE', 230 StackStatusReason: 'It is magic', 231 Outputs: [ 232 { OutputKey: 'BucketName', OutputValue: 'bucket' }, 233 ], 234 }, 235 ], 236 })) 237 // Third call, we just did a delete and want to see it gone 238 .mockImplementationOnce(() => ({ Stacks: [] })) 239 // Fourth call, stack has been created 240 .mockImplementationOnce(() => ({ 241 Stacks: [ 242 { 243 StackStatus: 'CREATE_COMPLETE', 244 StackStatusReason: 'It is magic', 245 EnableTerminationProtection: false, 246 }, 247 ], 248 })); 249 // WHEN 250 const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack' }); 251 // THEN 252 const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; 253 expect(bucketProperties.BucketName).toBeUndefined(); 254 expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) 255 .toBeUndefined(); 256 expect(ret.noOp).toBeFalsy(); 257 expect(executed).toBeTruthy(); 258 expect(cfnMocks.deleteStack).toHaveBeenCalled(); 259 }); 260 test('stack is not termination protected by default', async () => { 261 // WHEN 262 await bootstrapper.bootstrapEnvironment(env, sdk); 263 // THEN 264 expect(executed).toBeTruthy(); 265 expect(protectedTermination).toBeFalsy(); 266 }); 267 test('stack is termination protected when set', async () => { 268 // WHEN 269 await bootstrapper.bootstrapEnvironment(env, sdk, { 270 terminationProtection: true, 271 }); 272 // THEN 273 expect(executed).toBeTruthy(); 274 expect(protectedTermination).toBeTruthy(); 275 }); 276 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJib290c3RyYXAudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUNBLHVEQUF1RDtBQUN2RCxtREFBMkQ7QUFDM0QsK0NBQXdFO0FBRXhFLE1BQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxFQUFFLGNBQWM7SUFDdkIsTUFBTSxFQUFFLFdBQVc7SUFDbkIsSUFBSSxFQUFFLE1BQU07Q0FDYixDQUFDO0FBRUYsSUFBSSxHQUFvQixDQUFDO0FBQ3pCLElBQUksUUFBaUIsQ0FBQztBQUN0QixJQUFJLG9CQUE2QixDQUFDO0FBQ2xDLElBQUksUUFBOEQsQ0FBQztBQUNuRSxJQUFJLGlCQUFrQyxDQUFDO0FBQ3ZDLElBQUksWUFBMEIsQ0FBQztBQUMvQixVQUFVLENBQUMsR0FBRyxFQUFFO0lBQ2QsR0FBRyxHQUFHLElBQUksMEJBQWUsRUFBRSxDQUFDO0lBQzVCLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDakIsb0JBQW9CLEdBQUcsS0FBSyxDQUFDO0lBQzdCLFlBQVksR0FBRyxJQUFJLHdCQUFZLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUV0RCxRQUFRLEdBQUc7UUFDVCxtQkFBbUIsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQztRQUNsRCxjQUFjLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUN2QixpR0FBaUc7YUFDaEcsc0JBQXNCLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2FBQzlDLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMvQyxzQ0FBc0M7YUFDckMsc0JBQXNCLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUM3QixNQUFNLEVBQUU7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RUFBRSxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUM5QixNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFDbEQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsK0NBQStDLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDL0QsT0FBTztJQUNQLE1BQU0sWUFBWSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUVsRCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzlCLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0FBQzNDLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHlDQUF5QyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3pELE9BQU87SUFDUCxNQUFNLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO1FBQ2hELHFCQUFxQixFQUFFLElBQUk7S0FDNUIsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUM5QixNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUM1QyxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENyZWF0ZUNoYW5nZVNldElucHV0IH0gZnJvbSAnYXdzLXNkay9jbGllbnRzL2Nsb3VkZm9ybWF0aW9uJztcbmltcG9ydCB7IEJvb3RzdHJhcHBlciB9IGZyb20gJy4uLy4uL2xpYi9hcGkvYm9vdHN0cmFwJztcbmltcG9ydCB7IGRlc2VyaWFsaXplU3RydWN0dXJlIH0gZnJvbSAnLi4vLi4vbGliL3NlcmlhbGl6ZSc7XG5pbXBvcnQgeyBNb2NrU2RrUHJvdmlkZXIsIFN5bmNIYW5kbGVyU3Vic2V0T2YgfSBmcm9tICcuLi91dGlsL21vY2stc2RrJztcblxuY29uc3QgZW52ID0ge1xuICBhY2NvdW50OiAnMTIzNDU2Nzg5MDEyJyxcbiAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbiAgbmFtZTogJ21vY2snLFxufTtcblxubGV0IHNkazogTW9ja1Nka1Byb3ZpZGVyO1xubGV0IGV4ZWN1dGVkOiBib29sZWFuO1xubGV0IHByb3RlY3RlZFRlcm1pbmF0aW9uOiBib29sZWFuO1xubGV0IGNmbk1vY2tzOiBqZXN0Lk1vY2tlZDxTeW5jSGFuZGxlclN1YnNldE9mPEFXUy5DbG91ZEZvcm1hdGlvbj4+O1xubGV0IGNoYW5nZVNldFRlbXBsYXRlOiBhbnkgfCB1bmRlZmluZWQ7XG5sZXQgYm9vdHN0cmFwcGVyOiBCb290c3RyYXBwZXI7XG5iZWZvcmVFYWNoKCgpID0+IHtcbiAgc2RrID0gbmV3IE1vY2tTZGtQcm92aWRlcigpO1xuICBleGVjdXRlZCA9IGZhbHNlO1xuICBwcm90ZWN0ZWRUZXJtaW5hdGlvbiA9IGZhbHNlO1xuICBib290c3RyYXBwZXIgPSBuZXcgQm9vdHN0cmFwcGVyKHsgc291cmNlOiAnbGVnYWN5JyB9KTtcblxuICBjZm5Nb2NrcyA9IHtcbiAgICBkZXNjcmliZVN0YWNrRXZlbnRzOiBqZXN0LmZuKCkubW9ja1JldHVyblZhbHVlKHt9KSxcbiAgICBkZXNjcmliZVN0YWNrczogamVzdC5mbigpXG4gICAgICAvLyBGaXJzdCB0d28gY2FsbHMsIG5vIHN0YWNrcyBleGlzdCAoZmlyc3QgaXMgZm9yIHZlcnNpb24gY2hlY2tpbmcsIHNlY29uZCBpcyBpbiBkZXBsb3ktc3RhY2sudHMpXG4gICAgICAubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoeyBTdGFja3M6IFtdIH0pKVxuICAgICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHsgU3RhY2tzOiBbXSB9KSlcbiAgICAgIC8vIFNlY29uZCBjYWxsLCBzdGFjayBoYXMgYmVlbiBjcmVhdGVkXG4gICAgICAubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoe1xuICAgICAgICBTdGFja3M6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBTdGFja1N0YXR1czogJ0NSRUFURV9DT01QTEVURScsXG4gICAgICAgICAgICBTdGFja1N0YXR1c1JlYXNvbjogJ0l0IGlzIG1hZ2ljJyxcbiAgICAgICAgICAgIEVuYWJsZVRlcm1pbmF0aW9uUHJvdGVjdGlvbjogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pKSxcbiAgICBjcmVhdGVDaGFuZ2VTZXQ6IGplc3QuZm4oKGluZm86IENyZWF0ZUNoYW5nZVNldElucHV0KSA9PiB7XG4gICAgICBjaGFuZ2VTZXRUZW1wbGF0ZSA9IGRlc2VyaWFsaXplU3RydWN0dXJlKGluZm8uVGVtcGxhdGVCb2R5IGFzIHN0cmluZyk7XG4gICAgICByZXR1cm4ge307XG4gICAgfSksXG4gICAgZGVzY3JpYmVDaGFuZ2VTZXQ6IGplc3QuZm4oKCkgPT4gKHtcbiAgICAgIFN0YXR1czogJ0NSRUFURV9DT01QTEVURScsXG4gICAgICBDaGFuZ2VzOiBbXSxcbiAgICB9KSksXG4gICAgZXhlY3V0ZUNoYW5nZVNldDogamVzdC5mbigoKSA9PiB7XG4gICAgICBleGVjdXRlZCA9IHRydWU7XG4gICAgICByZXR1cm4ge307XG4gICAgfSksXG4gICAgZGVsZXRlQ2hhbmdlU2V0OiBqZXN0LmZuKCksXG4gICAgZ2V0VGVtcGxhdGU6IGplc3QuZm4oKCkgPT4ge1xuICAgICAgZXhlY3V0ZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH0pLFxuICAgIGRlbGV0ZVN0YWNrOiBqZXN0LmZuKCksXG4gICAgdXBkYXRlVGVybWluYXRpb25Qcm90ZWN0aW9uOiBqZXN0LmZuKCgpID0+IHtcbiAgICAgIHByb3RlY3RlZFRlcm1pbmF0aW9uID0gdHJ1ZTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9KSxcbiAgfTtcbiAgc2RrLnN0dWJDbG91ZEZvcm1hdGlvbihjZm5Nb2Nrcyk7XG59KTtcblxudGVzdCgnZG8gYm9vdHN0cmFwJywgYXN5bmMgKCkgPT4ge1xuICAvLyBXSEVOXG4gIGNvbnN0IHJldCA9IGF3YWl0IGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnYsIHNkaywgeyB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyB9KTtcblxuICAvLyBUSEVOXG4gIGNvbnN0IGJ1Y2tldFByb3BlcnRpZXMgPSBjaGFuZ2VTZXRUZW1wbGF0ZS5SZXNvdXJjZXMuU3RhZ2luZ0J1Y2tldC5Qcm9wZXJ0aWVzO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXROYW1lKS50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldEVuY3J5cHRpb24uU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uWzBdLlNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0LktNU01hc3RlcktleUlEKVxuICAgIC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChjaGFuZ2VTZXRUZW1wbGF0ZS5Db25kaXRpb25zLlVzZVB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvblsnRm46OkVxdWFscyddWzBdKS50b0JlKCd0cnVlJyk7XG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xufSk7XG5cbnRlc3QoJ2RvIGJvb3RzdHJhcCB1c2luZyBjdXN0b20gYnVja2V0IG5hbWUnLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgY29uc3QgcmV0ID0gYXdhaXQgYm9vdHN0cmFwcGVyLmJvb3RzdHJhcEVudmlyb25tZW50KGVudiwgc2RrLCB7XG4gICAgdG9vbGtpdFN0YWNrTmFtZTogJ21vY2tTdGFjaycsXG4gICAgcGFyYW1ldGVyczoge1xuICAgICAgYnVja2V0TmFtZTogJ2Zvb2JhcicsXG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBjb25zdCBidWNrZXRQcm9wZXJ0aWVzID0gY2hhbmdlU2V0VGVtcGxhdGUuUmVzb3VyY2VzLlN0YWdpbmdCdWNrZXQuUHJvcGVydGllcztcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0TmFtZSkudG9CZSgnZm9vYmFyJyk7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldEVuY3J5cHRpb24uU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uWzBdLlNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0LktNU01hc3RlcktleUlEKVxuICAgIC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChjaGFuZ2VTZXRUZW1wbGF0ZS5Db25kaXRpb25zLlVzZVB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvblsnRm46OkVxdWFscyddWzBdKS50b0JlKCd0cnVlJyk7XG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xufSk7XG5cbnRlc3QoJ2RvIGJvb3RzdHJhcCB1c2luZyBLTVMgQ01LJywgYXN5bmMgKCkgPT4ge1xuICAvLyBXSEVOXG4gIGNvbnN0IHJldCA9IGF3YWl0IGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnYsIHNkaywge1xuICAgIHRvb2xraXRTdGFja05hbWU6ICdtb2NrU3RhY2snLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIGttc0tleUlkOiAnbXlLbXNLZXknLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgY29uc3QgYnVja2V0UHJvcGVydGllcyA9IGNoYW5nZVNldFRlbXBsYXRlLlJlc291cmNlcy5TdGFnaW5nQnVja2V0LlByb3BlcnRpZXM7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldE5hbWUpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0RW5jcnlwdGlvbi5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb25bMF0uU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQuS01TTWFzdGVyS2V5SUQpXG4gICAgLnRvQmUoJ215S21zS2V5Jyk7XG4gIGV4cGVjdChjaGFuZ2VTZXRUZW1wbGF0ZS5Db25kaXRpb25zLlVzZVB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvblsnRm46OkVxdWFscyddWzBdKS50b0JlKCd0cnVlJyk7XG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xufSk7XG5cbnRlc3QoJ2Jvb3RzdHJhcCBkaXNhYmxlIGJ1Y2tldCBQdWJsaWMgQWNjZXNzIEJsb2NrIENvbmZpZ3VyYXRpb24nLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgY29uc3QgcmV0ID0gYXdhaXQgYm9vdHN0cmFwcGVyLmJvb3RzdHJhcEVudmlyb25tZW50KGVudiwgc2RrLCB7XG4gICAgdG9vbGtpdFN0YWNrTmFtZTogJ21vY2tTdGFjaycsXG4gICAgcGFyYW1ldGVyczoge1xuICAgICAgcHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uOiBmYWxzZSxcbiAgICB9LFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGNvbnN0IGJ1Y2tldFByb3BlcnRpZXMgPSBjaGFuZ2VTZXRUZW1wbGF0ZS5SZXNvdXJjZXMuU3RhZ2luZ0J1Y2tldC5Qcm9wZXJ0aWVzO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXROYW1lKS50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldEVuY3J5cHRpb24uU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uWzBdLlNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0LktNU01hc3RlcktleUlEKVxuICAgIC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChjaGFuZ2VTZXRUZW1wbGF0ZS5Db25kaXRpb25zLlVzZVB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvblsnRm46OkVxdWFscyddWzBdKS50b0JlKCdmYWxzZScpO1xuICBleHBlY3QocmV0Lm5vT3ApLnRvQmVGYWxzeSgpO1xuICBleHBlY3QoZXhlY3V0ZWQpLnRvQmVUcnV0aHkoKTtcbn0pO1xuXG50ZXN0KCdkbyBib290c3RyYXAgd2l0aCBjdXN0b20gdGFncyBmb3IgdG9vbGtpdCBzdGFjaycsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBjb25zdCByZXQgPSBhd2FpdCBib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHtcbiAgICB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyxcbiAgICB0YWdzOiBbeyBLZXk6ICdGb28nLCBWYWx1ZTogJ0JhcicgfV0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgY29uc3QgYnVja2V0UHJvcGVydGllcyA9IGNoYW5nZVNldFRlbXBsYXRlLlJlc291cmNlcy5TdGFnaW5nQnVja2V0LlByb3BlcnRpZXM7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldE5hbWUpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0RW5jcnlwdGlvbi5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb25bMF0uU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQuS01TTWFzdGVyS2V5SUQpXG4gICAgLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGNoYW5nZVNldFRlbXBsYXRlLkNvbmRpdGlvbnMuVXNlUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uWydGbjo6RXF1YWxzJ11bMF0pLnRvQmUoJ3RydWUnKTtcbiAgZXhwZWN0KHJldC5ub09wKS50b0JlRmFsc3koKTtcbiAgZXhwZWN0KGV4ZWN1dGVkKS50b0JlVHJ1dGh5KCk7XG59KTtcblxudGVzdCgncGFzc2luZyB0cnVzdGVkIGFjY291bnRzIHRvIHRoZSBvbGQgYm9vdHN0cmFwcGluZyByZXN1bHRzIGluIGFuIGVycm9yJywgYXN5bmMgKCkgPT4ge1xuICBhd2FpdCBleHBlY3QoYm9vdHN0cmFwcGVyLmJvb3RzdHJhcEVudmlyb25tZW50KGVudiwgc2RrLCB7XG4gICAgdG9vbGtpdFN0YWNrTmFtZTogJ21vY2tTdGFjaycsXG4gICAgcGFyYW1ldGVyczoge1xuICAgICAgdHJ1c3RlZEFjY291bnRzOiBbJzAxMjM0NTY3ODkwMTInXSxcbiAgICB9LFxuICB9KSlcbiAgICAucmVqZWN0c1xuICAgIC50b1Rocm93KCctLXRydXN0IGNhbiBvbmx5IGJlIHBhc3NlZCBmb3IgdGhlIG1vZGVybiBib290c3RyYXAgZXhwZXJpZW5jZS4nKTtcbn0pO1xuXG50ZXN0KCdwYXNzaW5nIENGTiBleGVjdXRpb24gcG9saWNpZXMgdG8gdGhlIG9sZCBib290c3RyYXBwaW5nIHJlc3VsdHMgaW4gYW4gZXJyb3InLCBhc3luYyAoKSA9PiB7XG4gIGF3YWl0IGV4cGVjdChib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHtcbiAgICB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICBjbG91ZEZvcm1hdGlvbkV4ZWN1dGlvblBvbGljaWVzOiBbJ2Fybjphd3M6aWFtOjphd3M6cG9saWN5L0FkbWluaXN0cmF0b3JBY2Nlc3MnXSxcbiAgICB9LFxuICB9KSlcbiAgICAucmVqZWN0c1xuICAgIC50b1Rocm93KCctLWNsb3VkZm9ybWF0aW9uLWV4ZWN1dGlvbi1wb2xpY2llcyBjYW4gb25seSBiZSBwYXNzZWQgZm9yIHRoZSBtb2Rlcm4gYm9vdHN0cmFwIGV4cGVyaWVuY2UuJyk7XG59KTtcblxudGVzdCgnZXZlbiBpZiB0aGUgYm9vdHN0cmFwIHN0YWNrIGlzIGluIGEgcm9sbGJhY2sgc3RhdGUsIGNhbiBzdGlsbCByZXRyeSBib290c3RyYXBwaW5nIGl0JywgYXN5bmMgKCkgPT4ge1xuICAoY2ZuTW9ja3MuZGVzY3JpYmVTdGFja3MhIGFzIGplc3QuTW9jaylcbiAgICAubW9ja1Jlc2V0KClcbiAgICAvLyBGaXJzdCB0d28gY2FsbHMsIHRoZSBzdGFjayBleGlzdHMgd2l0aCBhICdyb2xsYmFjayBjb21wbGV0ZScgc3RhdHVzXG4gICAgLy8gKGZpcnN0IGlzIGZvciB2ZXJzaW9uIGNoZWNraW5nLCBzZWNvbmQgaXMgaW4gZGVwbG95LXN0YWNrLnRzKVxuICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7XG4gICAgICBTdGFja3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIFN0YWNrU3RhdHVzOiAnVVBEQVRFX1JPTExCQUNLX0NPTVBMRVRFJyxcbiAgICAgICAgICBTdGFja1N0YXR1c1JlYXNvbjogJ0l0IGlzIG1hZ2ljJyxcbiAgICAgICAgICBPdXRwdXRzOiBbXG4gICAgICAgICAgICB7IE91dHB1dEtleTogJ0J1Y2tldE5hbWUnLCBPdXRwdXRWYWx1ZTogJ2J1Y2tldCcgfSxcbiAgICAgICAgICAgIHsgT3V0cHV0S2V5OiAnQnVja2V0RG9tYWluTmFtZScsIE91dHB1dFZhbHVlOiAnYXdzLmNvbScgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KSlcbiAgICAubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoe1xuICAgICAgU3RhY2tzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBTdGFja1N0YXR1czogJ1VQREFURV9ST0xMQkFDS19DT01QTEVURScsXG4gICAgICAgICAgU3RhY2tTdGF0dXNSZWFzb246ICdJdCBpcyBtYWdpYycsXG4gICAgICAgICAgT3V0cHV0czogW1xuICAgICAgICAgICAgeyBPdXRwdXRLZXk6ICdCdWNrZXROYW1lJywgT3V0cHV0VmFsdWU6ICdidWNrZXQnIH0sXG4gICAgICAgICAgICB7IE91dHB1dEtleTogJ0J1Y2tldERvbWFpbk5hbWUnLCBPdXRwdXRWYWx1ZTogJ2F3cy5jb20nIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSkpXG4gICAgLy8gVGhpcmQgY2FsbCwgc3RhY2sgaGFzIGJlZW4gY3JlYXRlZFxuICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7XG4gICAgICBTdGFja3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIFN0YWNrU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyxcbiAgICAgICAgICBTdGFja1N0YXR1c1JlYXNvbjogJ0l0IGlzIG1hZ2ljJyxcbiAgICAgICAgICBFbmFibGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCByZXQgPSBhd2FpdCBib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHsgdG9vbGtpdFN0YWNrTmFtZTogJ21vY2tTdGFjaycgfSk7XG5cbiAgLy8gVEhFTlxuICBjb25zdCBidWNrZXRQcm9wZXJ0aWVzID0gY2hhbmdlU2V0VGVtcGxhdGUuUmVzb3VyY2VzLlN0YWdpbmdCdWNrZXQuUHJvcGVydGllcztcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0TmFtZSkudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXRFbmNyeXB0aW9uLlNlcnZlclNpZGVFbmNyeXB0aW9uQ29uZmlndXJhdGlvblswXS5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdC5LTVNNYXN0ZXJLZXlJRClcbiAgICAudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QocmV0Lm5vT3ApLnRvQmVGYWxzeSgpO1xuICBleHBlY3QoZXhlY3V0ZWQpLnRvQmVUcnV0aHkoKTtcbn0pO1xuXG50ZXN0KCdldmVuIGlmIHRoZSBib290c3RyYXAgc3RhY2sgZmFpbGVkIHRvIGNyZWF0ZSwgY2FuIHN0aWxsIHJldHJ5IGJvb3RzdHJhcHBpbmcgaXQnLCBhc3luYyAoKSA9PiB7XG4gIChjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEgYXMgamVzdC5Nb2NrKVxuICAgIC5tb2NrUmVzZXQoKVxuICAgIC8vIEZpcnN0IHR3byBjYWxscywgdGhlIHN0YWNrIGV4aXN0cyB3aXRoIGEgJ3JvbGxiYWNrIGNvbXBsZXRlJyBzdGF0dXNcbiAgICAvLyAoZmlyc3QgaXMgZm9yIHZlcnNpb24gY2hlY2tpbmcsIHNlY29uZCBpcyBpbiBkZXBsb3ktc3RhY2sudHMpXG4gICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgIFN0YWNrczogW1xuICAgICAgICB7XG4gICAgICAgICAgU3RhY2tTdGF0dXM6ICdST0xMQkFDS19DT01QTEVURScsXG4gICAgICAgICAgU3RhY2tTdGF0dXNSZWFzb246ICdJdCBpcyBtYWdpYycsXG4gICAgICAgICAgT3V0cHV0czogW1xuICAgICAgICAgICAgeyBPdXRwdXRLZXk6ICdCdWNrZXROYW1lJywgT3V0cHV0VmFsdWU6ICdidWNrZXQnIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSBhcyBBV1MuQ2xvdWRGb3JtYXRpb24uU3RhY2ssXG4gICAgICBdLFxuICAgIH0pKVxuICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7XG4gICAgICBTdGFja3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIFN0YWNrU3RhdHVzOiAnUk9MTEJBQ0tfQ09NUExFVEUnLFxuICAgICAgICAgIFN0YWNrU3RhdHVzUmVhc29uOiAnSXQgaXMgbWFnaWMnLFxuICAgICAgICAgIE91dHB1dHM6IFtcbiAgICAgICAgICAgIHsgT3V0cHV0S2V5OiAnQnVja2V0TmFtZScsIE91dHB1dFZhbHVlOiAnYnVja2V0JyB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pKVxuICAgIC8vIFRoaXJkIGNhbGwsIHdlIGp1c3QgZGlkIGEgZGVsZXRlIGFuZCB3YW50IHRvIHNlZSBpdCBnb25lXG4gICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHsgU3RhY2tzOiBbXSB9KSlcbiAgICAvLyBGb3VydGggY2FsbCwgc3RhY2sgaGFzIGJlZW4gY3JlYXRlZFxuICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7XG4gICAgICBTdGFja3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIFN0YWNrU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyxcbiAgICAgICAgICBTdGFja1N0YXR1c1JlYXNvbjogJ0l0IGlzIG1hZ2ljJyxcbiAgICAgICAgICBFbmFibGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCByZXQgPSBhd2FpdCBib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHsgdG9vbGtpdFN0YWNrTmFtZTogJ21vY2tTdGFjaycgfSk7XG5cbiAgLy8gVEhFTlxuICBjb25zdCBidWNrZXRQcm9wZXJ0aWVzID0gY2hhbmdlU2V0VGVtcGxhdGUuUmVzb3VyY2VzLlN0YWdpbmdCdWNrZXQuUHJvcGVydGllcztcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0TmFtZSkudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXRFbmNyeXB0aW9uLlNlcnZlclNpZGVFbmNyeXB0aW9uQ29uZmlndXJhdGlvblswXS5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdC5LTVNNYXN0ZXJLZXlJRClcbiAgICAudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QocmV0Lm5vT3ApLnRvQmVGYWxzeSgpO1xuICBleHBlY3QoZXhlY3V0ZWQpLnRvQmVUcnV0aHkoKTtcbiAgZXhwZWN0KGNmbk1vY2tzLmRlbGV0ZVN0YWNrKS50b0hhdmVCZWVuQ2FsbGVkKCk7XG59KTtcblxudGVzdCgnc3RhY2sgaXMgbm90IHRlcm1pbmF0aW9uIHByb3RlY3RlZCBieSBkZWZhdWx0JywgYXN5bmMgKCkgPT4ge1xuICAvLyBXSEVOXG4gIGF3YWl0IGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnYsIHNkayk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoZXhlY3V0ZWQpLnRvQmVUcnV0aHkoKTtcbiAgZXhwZWN0KHByb3RlY3RlZFRlcm1pbmF0aW9uKS50b0JlRmFsc3koKTtcbn0pO1xuXG50ZXN0KCdzdGFjayBpcyB0ZXJtaW5hdGlvbiBwcm90ZWN0ZWQgd2hlbiBzZXQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgYXdhaXQgYm9vdHN0cmFwcGVyLmJvb3RzdHJhcEVudmlyb25tZW50KGVudiwgc2RrLCB7XG4gICAgdGVybWluYXRpb25Qcm90ZWN0aW9uOiB0cnVlLFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xuICBleHBlY3QocHJvdGVjdGVkVGVybWluYXRpb24pLnRvQmVUcnV0aHkoKTtcbn0pO1xuIl19