aws-cdk 2.5.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/bin/cdk.js +22 -6
- package/build-info.json +2 -2
- package/lib/api/aws-auth/sdk-provider.d.ts +26 -1
- package/lib/api/aws-auth/sdk-provider.js +4 -4
- package/lib/api/aws-auth/sdk.d.ts +2 -0
- package/lib/api/aws-auth/sdk.js +4 -1
- package/lib/api/bootstrap/deploy-bootstrap.js +14 -3
- package/lib/api/cloudformation-deployments.d.ts +63 -1
- package/lib/api/cloudformation-deployments.js +74 -4
- package/lib/api/cxapp/cloud-assembly.js +5 -5
- package/lib/api/deploy-stack.d.ts +0 -1
- package/lib/api/deploy-stack.js +8 -9
- package/lib/api/{hotswap/evaluate-cloudformation-template.d.ts → evaluate-cloudformation-template.d.ts} +14 -1
- package/lib/api/evaluate-cloudformation-template.js +289 -0
- package/lib/api/hotswap/code-build-projects.d.ts +1 -1
- package/lib/api/hotswap/code-build-projects.js +2 -2
- package/lib/api/hotswap/common.d.ts +0 -6
- package/lib/api/hotswap/common.js +2 -19
- package/lib/api/hotswap/ecs-services.d.ts +1 -1
- package/lib/api/hotswap/ecs-services.js +2 -2
- package/lib/api/hotswap/lambda-functions.d.ts +1 -1
- package/lib/api/hotswap/lambda-functions.js +69 -3
- package/lib/api/hotswap/s3-bucket-deployments.d.ts +1 -1
- package/lib/api/hotswap/s3-bucket-deployments.js +1 -1
- package/lib/api/hotswap/stepfunctions-state-machines.d.ts +1 -1
- package/lib/api/hotswap/stepfunctions-state-machines.js +1 -1
- package/lib/api/hotswap-deployments.js +9 -35
- package/lib/api/logs/find-cloudwatch-logs.d.ts +24 -0
- package/lib/api/logs/find-cloudwatch-logs.js +84 -0
- package/lib/api/logs/logs-monitor.d.ts +53 -0
- package/lib/api/logs/logs-monitor.js +163 -0
- package/lib/api/toolkit-info.d.ts +5 -5
- package/lib/api/toolkit-info.js +10 -10
- package/lib/api/util/cloudformation/stack-activity-monitor.js +22 -22
- package/lib/assets.js +3 -3
- package/lib/cdk-toolkit.d.ts +15 -0
- package/lib/cdk-toolkit.js +30 -20
- package/lib/commands/context.js +7 -7
- package/lib/commands/docs.js +4 -4
- package/lib/commands/doctor.js +6 -6
- package/lib/context-providers/ami.js +2 -2
- package/lib/context-providers/availability-zones.js +2 -2
- package/lib/context-providers/endpoint-service-availability-zones.js +2 -2
- package/lib/context-providers/hosted-zones.js +2 -2
- package/lib/context-providers/keys.js +2 -2
- package/lib/context-providers/load-balancers.js +3 -3
- package/lib/context-providers/security-groups.js +2 -2
- package/lib/context-providers/ssm-parameters.js +2 -2
- package/lib/context-providers/vpcs.js +2 -2
- package/lib/diff.js +3 -3
- package/lib/init.js +14 -14
- package/lib/logging.js +7 -7
- package/lib/os.js +3 -3
- package/lib/plugin.js +4 -4
- package/lib/util/asset-publishing.js +3 -3
- package/lib/util/console-formatters.js +4 -3
- package/lib/version.js +3 -3
- package/npm-shrinkwrap.json +90 -95
- package/package.json +22 -21
- package/test/api/bootstrap2.test.js +2 -3
- package/test/api/cloudformation-deployments.test.js +2 -2
- package/test/api/hotswap/lambda-functions-docker-hotswap-deployments.test.d.ts +1 -0
- package/test/api/hotswap/lambda-functions-docker-hotswap-deployments.test.js +64 -0
- package/test/api/hotswap/lambda-functions-inline-hotswap-deployments.test.d.ts +1 -0
- package/test/api/hotswap/lambda-functions-inline-hotswap-deployments.test.js +139 -0
- package/test/api/logs/find-cloudwatch-logs.test.d.ts +1 -0
- package/test/api/logs/find-cloudwatch-logs.test.js +264 -0
- package/test/api/logs/logs-monitor.test.d.ts +1 -0
- package/test/api/logs/logs-monitor.test.js +59 -0
- package/test/api/sdk-provider.test.js +11 -11
- package/test/api/stack-activity-monitor.test.js +13 -13
- package/test/cdk-toolkit.test.js +271 -10
- package/test/context-providers/load-balancers.test.js +4 -4
- package/test/util/cloudformation.test.js +2 -2
- package/test/util/console-formatters.test.js +6 -6
- package/test/util/mock-sdk.d.ts +8 -2
- package/test/util/mock-sdk.js +12 -2
- package/test/util/mock-toolkitinfo.js +2 -2
- package/lib/api/hotswap/evaluate-cloudformation-template.js +0 -247
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findCloudWatchLogGroups = void 0;
|
|
4
|
+
const aws_auth_1 = require("../aws-auth");
|
|
5
|
+
const cloudformation_deployments_1 = require("../cloudformation-deployments");
|
|
6
|
+
const evaluate_cloudformation_template_1 = require("../evaluate-cloudformation-template");
|
|
7
|
+
// resource types that have associated CloudWatch Log Groups that should _not_ be monitored
|
|
8
|
+
const IGNORE_LOGS_RESOURCE_TYPES = ['AWS::EC2::FlowLog', 'AWS::CloudTrail::Trail', 'AWS::CodeBuild::Project'];
|
|
9
|
+
// Resource types that will create a CloudWatch log group with a specific name if one is not provided.
|
|
10
|
+
// The keys are CFN resource types, and the values are the name of the physical name property of that resource
|
|
11
|
+
// and the service name that is used in the automatically created CloudWatch log group.
|
|
12
|
+
const RESOURCE_TYPES_WITH_IMPLICIT_LOGS = {
|
|
13
|
+
'AWS::Lambda::Function': {
|
|
14
|
+
PhysicalNamePropertyName: 'FunctionName',
|
|
15
|
+
LogGroupServiceName: 'lambda',
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
async function findCloudWatchLogGroups(sdkProvider, stackArtifact) {
|
|
19
|
+
let sdk;
|
|
20
|
+
const resolvedEnv = await sdkProvider.resolveEnvironment(stackArtifact.environment);
|
|
21
|
+
// try to assume the lookup role and fallback to the default credentials
|
|
22
|
+
try {
|
|
23
|
+
sdk = (await cloudformation_deployments_1.prepareSdkWithLookupRoleFor(sdkProvider, stackArtifact)).sdk;
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
sdk = (await sdkProvider.forEnvironment(resolvedEnv, aws_auth_1.Mode.ForReading)).sdk;
|
|
27
|
+
}
|
|
28
|
+
const listStackResources = new evaluate_cloudformation_template_1.LazyListStackResources(sdk, stackArtifact.stackName);
|
|
29
|
+
const evaluateCfnTemplate = new evaluate_cloudformation_template_1.EvaluateCloudFormationTemplate({
|
|
30
|
+
stackArtifact,
|
|
31
|
+
parameters: {},
|
|
32
|
+
account: resolvedEnv.account,
|
|
33
|
+
region: resolvedEnv.region,
|
|
34
|
+
partition: (await sdk.currentAccount()).partition,
|
|
35
|
+
urlSuffix: (region) => sdk.getEndpointSuffix(region),
|
|
36
|
+
listStackResources,
|
|
37
|
+
});
|
|
38
|
+
const stackResources = await listStackResources.listStackResources();
|
|
39
|
+
const logGroupNames = findAllLogGroupNames(stackResources, evaluateCfnTemplate);
|
|
40
|
+
return {
|
|
41
|
+
env: resolvedEnv,
|
|
42
|
+
sdk,
|
|
43
|
+
logGroupNames,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
exports.findCloudWatchLogGroups = findCloudWatchLogGroups;
|
|
47
|
+
/**
|
|
48
|
+
* Determine if a CloudWatch Log Group is associated
|
|
49
|
+
* with an ignored resource
|
|
50
|
+
*/
|
|
51
|
+
function isReferencedFromIgnoredResource(logGroupResource, evaluateCfnTemplate) {
|
|
52
|
+
let foundReference = false;
|
|
53
|
+
const resourcesReferencingLogGroup = evaluateCfnTemplate.findReferencesTo(logGroupResource.LogicalResourceId);
|
|
54
|
+
for (const reference of resourcesReferencingLogGroup) {
|
|
55
|
+
if (IGNORE_LOGS_RESOURCE_TYPES.includes(reference.Type)) {
|
|
56
|
+
foundReference = true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return foundReference;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Find all CloudWatch Log Groups in the deployed template.
|
|
63
|
+
* This will find both explicitely created Log Groups (excluding those associated with ignored resources)
|
|
64
|
+
* as well as Log Groups created implicitely (i.e. Lambda Functions)
|
|
65
|
+
*/
|
|
66
|
+
function findAllLogGroupNames(stackResources, evaluateCfnTemplate) {
|
|
67
|
+
return stackResources.reduce((logGroupNames, resource) => {
|
|
68
|
+
let logGroupName;
|
|
69
|
+
if (resource.ResourceType === 'AWS::Logs::LogGroup') {
|
|
70
|
+
if (!isReferencedFromIgnoredResource(resource, evaluateCfnTemplate)) {
|
|
71
|
+
logGroupName = resource.PhysicalResourceId;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (RESOURCE_TYPES_WITH_IMPLICIT_LOGS[resource.ResourceType]) {
|
|
75
|
+
const servicePart = RESOURCE_TYPES_WITH_IMPLICIT_LOGS[resource.ResourceType].LogGroupServiceName;
|
|
76
|
+
logGroupName = `/aws/${servicePart}/${resource.PhysicalResourceId}`;
|
|
77
|
+
}
|
|
78
|
+
if (logGroupName) {
|
|
79
|
+
logGroupNames.push(logGroupName);
|
|
80
|
+
}
|
|
81
|
+
return logGroupNames;
|
|
82
|
+
}, []);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmluZC1jbG91ZHdhdGNoLWxvZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJmaW5kLWNsb3Vkd2F0Y2gtbG9ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSwwQ0FBc0Q7QUFDdEQsOEVBQTRFO0FBQzVFLDBGQUE2RztBQUU3RywyRkFBMkY7QUFDM0YsTUFBTSwwQkFBMEIsR0FBRyxDQUFDLG1CQUFtQixFQUFFLHdCQUF3QixFQUFFLHlCQUF5QixDQUFDLENBQUM7QUFFOUcsc0dBQXNHO0FBQ3RHLDhHQUE4RztBQUM5Ryx1RkFBdUY7QUFDdkYsTUFBTSxpQ0FBaUMsR0FBNkQ7SUFDbEcsdUJBQXVCLEVBQUU7UUFDdkIsd0JBQXdCLEVBQUUsY0FBYztRQUN4QyxtQkFBbUIsRUFBRSxRQUFRO0tBQzlCO0NBQ0YsQ0FBQztBQTBCSyxLQUFLLFVBQVUsdUJBQXVCLENBQzNDLFdBQXdCLEVBQ3hCLGFBQWdEO0lBRWhELElBQUksR0FBUyxDQUFDO0lBQ2QsTUFBTSxXQUFXLEdBQUcsTUFBTSxXQUFXLENBQUMsa0JBQWtCLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3BGLHdFQUF3RTtJQUN4RSxJQUFJO1FBQ0YsR0FBRyxHQUFHLENBQUMsTUFBTSx3REFBMkIsQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7S0FDM0U7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLEdBQUcsR0FBRyxDQUFDLE1BQU0sV0FBVyxDQUFDLGNBQWMsQ0FBQyxXQUFXLEVBQUUsZUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0tBQzVFO0lBRUQsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLHlEQUFzQixDQUFDLEdBQUcsRUFBRSxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDcEYsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGlFQUE4QixDQUFDO1FBQzdELGFBQWE7UUFDYixVQUFVLEVBQUUsRUFBRTtRQUNkLE9BQU8sRUFBRSxXQUFXLENBQUMsT0FBTztRQUM1QixNQUFNLEVBQUUsV0FBVyxDQUFDLE1BQU07UUFDMUIsU0FBUyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxTQUFTO1FBQ2pELFNBQVMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQztRQUNwRCxrQkFBa0I7S0FDbkIsQ0FBQyxDQUFDO0lBRUgsTUFBTSxjQUFjLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQ3JFLE1BQU0sYUFBYSxHQUFHLG9CQUFvQixDQUFDLGNBQWMsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0lBRWhGLE9BQU87UUFDTCxHQUFHLEVBQUUsV0FBVztRQUNoQixHQUFHO1FBQ0gsYUFBYTtLQUNkLENBQUM7QUFDSixDQUFDO0FBaENELDBEQWdDQztBQUVEOzs7R0FHRztBQUNILFNBQVMsK0JBQStCLENBQ3RDLGdCQUFxRCxFQUNyRCxtQkFBbUQ7SUFFbkQsSUFBSSxjQUFjLEdBQUcsS0FBSyxDQUFDO0lBQzNCLE1BQU0sNEJBQTRCLEdBQUcsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUM5RyxLQUFLLE1BQU0sU0FBUyxJQUFJLDRCQUE0QixFQUFFO1FBQ3BELElBQUksMEJBQTBCLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN2RCxjQUFjLEdBQUcsSUFBSSxDQUFDO1NBQ3ZCO0tBQ0Y7SUFDRCxPQUFPLGNBQWMsQ0FBQztBQUN4QixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsb0JBQW9CLENBQzNCLGNBQXFELEVBQ3JELG1CQUFtRDtJQUVuRCxPQUFPLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxhQUF1QixFQUFFLFFBQVEsRUFBRSxFQUFFO1FBQ2pFLElBQUksWUFBWSxDQUFDO1FBQ2pCLElBQUksUUFBUSxDQUFDLFlBQVksS0FBSyxxQkFBcUIsRUFBRTtZQUNuRCxJQUFJLENBQUMsK0JBQStCLENBQUMsUUFBUSxFQUFFLG1CQUFtQixDQUFDLEVBQUU7Z0JBQ25FLFlBQVksR0FBRyxRQUFRLENBQUMsa0JBQWtCLENBQUM7YUFDNUM7U0FDRjthQUFNLElBQUksaUNBQWlDLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUFFO1lBQ25FLE1BQU0sV0FBVyxHQUFHLGlDQUFpQyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQztZQUNqRyxZQUFZLEdBQUcsUUFBUSxXQUFXLElBQUksUUFBUSxDQUFDLGtCQUFrQixFQUFFLENBQUM7U0FDckU7UUFDRCxJQUFJLFlBQVksRUFBRTtZQUNoQixhQUFhLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ2xDO1FBQ0QsT0FBTyxhQUFhLENBQUM7SUFDdkIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ1QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBDbG91ZEZvcm1hdGlvbiB9IGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgTW9kZSwgU2RrUHJvdmlkZXIsIElTREsgfSBmcm9tICcuLi9hd3MtYXV0aCc7XG5pbXBvcnQgeyBwcmVwYXJlU2RrV2l0aExvb2t1cFJvbGVGb3IgfSBmcm9tICcuLi9jbG91ZGZvcm1hdGlvbi1kZXBsb3ltZW50cyc7XG5pbXBvcnQgeyBFdmFsdWF0ZUNsb3VkRm9ybWF0aW9uVGVtcGxhdGUsIExhenlMaXN0U3RhY2tSZXNvdXJjZXMgfSBmcm9tICcuLi9ldmFsdWF0ZS1jbG91ZGZvcm1hdGlvbi10ZW1wbGF0ZSc7XG5cbi8vIHJlc291cmNlIHR5cGVzIHRoYXQgaGF2ZSBhc3NvY2lhdGVkIENsb3VkV2F0Y2ggTG9nIEdyb3VwcyB0aGF0IHNob3VsZCBfbm90XyBiZSBtb25pdG9yZWRcbmNvbnN0IElHTk9SRV9MT0dTX1JFU09VUkNFX1RZUEVTID0gWydBV1M6OkVDMjo6Rmxvd0xvZycsICdBV1M6OkNsb3VkVHJhaWw6OlRyYWlsJywgJ0FXUzo6Q29kZUJ1aWxkOjpQcm9qZWN0J107XG5cbi8vIFJlc291cmNlIHR5cGVzIHRoYXQgd2lsbCBjcmVhdGUgYSBDbG91ZFdhdGNoIGxvZyBncm91cCB3aXRoIGEgc3BlY2lmaWMgbmFtZSBpZiBvbmUgaXMgbm90IHByb3ZpZGVkLlxuLy8gVGhlIGtleXMgYXJlIENGTiByZXNvdXJjZSB0eXBlcywgYW5kIHRoZSB2YWx1ZXMgYXJlIHRoZSBuYW1lIG9mIHRoZSBwaHlzaWNhbCBuYW1lIHByb3BlcnR5IG9mIHRoYXQgcmVzb3VyY2Vcbi8vIGFuZCB0aGUgc2VydmljZSBuYW1lIHRoYXQgaXMgdXNlZCBpbiB0aGUgYXV0b21hdGljYWxseSBjcmVhdGVkIENsb3VkV2F0Y2ggbG9nIGdyb3VwLlxuY29uc3QgUkVTT1VSQ0VfVFlQRVNfV0lUSF9JTVBMSUNJVF9MT0dTOiB7IFtjZm5SZXNvdXJjZVR5cGU6IHN0cmluZ106IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gfSA9IHtcbiAgJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbic6IHtcbiAgICBQaHlzaWNhbE5hbWVQcm9wZXJ0eU5hbWU6ICdGdW5jdGlvbk5hbWUnLFxuICAgIExvZ0dyb3VwU2VydmljZU5hbWU6ICdsYW1iZGEnLFxuICB9LFxufTtcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIG5lZWRlZCB0byBtb25pdG9yIENsb3VkV2F0Y2ggTG9nIEdyb3Vwc1xuICogZm91bmQgaW4gYSBnaXZlbiBDbG91ZEZvcm1hdGlvbiBTdGFja1xuICovXG5leHBvcnQgaW50ZXJmYWNlIEZvdW5kTG9nR3JvdXBzUmVzdWx0IHtcbiAgLyoqXG4gICAqIFRoZSByZXNvbHZlZCBlbnZpcm9ubWVudCAoYWNjb3VudC9yZWdpb24pIHRoYXQgdGhlIGxvZ1xuICAgKiBncm91cHMgYXJlIGRlcGxveWVkIGluXG4gICAqL1xuICByZWFkb25seSBlbnY6IGN4YXBpLkVudmlyb25tZW50O1xuXG4gIC8qKlxuICAgKiBUaGUgU0RLIHRoYXQgY2FuIGJlIHVzZWQgdG8gcmVhZCBldmVudHMgZnJvbSB0aGUgQ2xvdWRXYXRjaFxuICAgKiBMb2cgR3JvdXBzIGluIHRoZSBnaXZlbiBlbnZpcm9ubWVudFxuICAgKi9cbiAgcmVhZG9ubHkgc2RrOiBJU0RLO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZXMgb2YgdGhlIHJlbGV2YW50IENsb3VkV2F0Y2ggTG9nIEdyb3Vwc1xuICAgKiBpbiB0aGUgZ2l2ZW4gQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGVcbiAgICovXG4gIHJlYWRvbmx5IGxvZ0dyb3VwTmFtZXM6IHN0cmluZ1tdXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmaW5kQ2xvdWRXYXRjaExvZ0dyb3VwcyhcbiAgc2RrUHJvdmlkZXI6IFNka1Byb3ZpZGVyLFxuICBzdGFja0FydGlmYWN0OiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QsXG4pOiBQcm9taXNlPEZvdW5kTG9nR3JvdXBzUmVzdWx0PiB7XG4gIGxldCBzZGs6IElTREs7XG4gIGNvbnN0IHJlc29sdmVkRW52ID0gYXdhaXQgc2RrUHJvdmlkZXIucmVzb2x2ZUVudmlyb25tZW50KHN0YWNrQXJ0aWZhY3QuZW52aXJvbm1lbnQpO1xuICAvLyB0cnkgdG8gYXNzdW1lIHRoZSBsb29rdXAgcm9sZSBhbmQgZmFsbGJhY2sgdG8gdGhlIGRlZmF1bHQgY3JlZGVudGlhbHNcbiAgdHJ5IHtcbiAgICBzZGsgPSAoYXdhaXQgcHJlcGFyZVNka1dpdGhMb29rdXBSb2xlRm9yKHNka1Byb3ZpZGVyLCBzdGFja0FydGlmYWN0KSkuc2RrO1xuICB9IGNhdGNoIChlKSB7XG4gICAgc2RrID0gKGF3YWl0IHNka1Byb3ZpZGVyLmZvckVudmlyb25tZW50KHJlc29sdmVkRW52LCBNb2RlLkZvclJlYWRpbmcpKS5zZGs7XG4gIH1cblxuICBjb25zdCBsaXN0U3RhY2tSZXNvdXJjZXMgPSBuZXcgTGF6eUxpc3RTdGFja1Jlc291cmNlcyhzZGssIHN0YWNrQXJ0aWZhY3Quc3RhY2tOYW1lKTtcbiAgY29uc3QgZXZhbHVhdGVDZm5UZW1wbGF0ZSA9IG5ldyBFdmFsdWF0ZUNsb3VkRm9ybWF0aW9uVGVtcGxhdGUoe1xuICAgIHN0YWNrQXJ0aWZhY3QsXG4gICAgcGFyYW1ldGVyczoge30sXG4gICAgYWNjb3VudDogcmVzb2x2ZWRFbnYuYWNjb3VudCxcbiAgICByZWdpb246IHJlc29sdmVkRW52LnJlZ2lvbixcbiAgICBwYXJ0aXRpb246IChhd2FpdCBzZGsuY3VycmVudEFjY291bnQoKSkucGFydGl0aW9uLFxuICAgIHVybFN1ZmZpeDogKHJlZ2lvbikgPT4gc2RrLmdldEVuZHBvaW50U3VmZml4KHJlZ2lvbiksXG4gICAgbGlzdFN0YWNrUmVzb3VyY2VzLFxuICB9KTtcblxuICBjb25zdCBzdGFja1Jlc291cmNlcyA9IGF3YWl0IGxpc3RTdGFja1Jlc291cmNlcy5saXN0U3RhY2tSZXNvdXJjZXMoKTtcbiAgY29uc3QgbG9nR3JvdXBOYW1lcyA9IGZpbmRBbGxMb2dHcm91cE5hbWVzKHN0YWNrUmVzb3VyY2VzLCBldmFsdWF0ZUNmblRlbXBsYXRlKTtcblxuICByZXR1cm4ge1xuICAgIGVudjogcmVzb2x2ZWRFbnYsXG4gICAgc2RrLFxuICAgIGxvZ0dyb3VwTmFtZXMsXG4gIH07XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgQ2xvdWRXYXRjaCBMb2cgR3JvdXAgaXMgYXNzb2NpYXRlZFxuICogd2l0aCBhbiBpZ25vcmVkIHJlc291cmNlXG4gKi9cbmZ1bmN0aW9uIGlzUmVmZXJlbmNlZEZyb21JZ25vcmVkUmVzb3VyY2UoXG4gIGxvZ0dyb3VwUmVzb3VyY2U6IENsb3VkRm9ybWF0aW9uLlN0YWNrUmVzb3VyY2VTdW1tYXJ5LFxuICBldmFsdWF0ZUNmblRlbXBsYXRlOiBFdmFsdWF0ZUNsb3VkRm9ybWF0aW9uVGVtcGxhdGUsXG4pOiBib29sZWFuIHtcbiAgbGV0IGZvdW5kUmVmZXJlbmNlID0gZmFsc2U7XG4gIGNvbnN0IHJlc291cmNlc1JlZmVyZW5jaW5nTG9nR3JvdXAgPSBldmFsdWF0ZUNmblRlbXBsYXRlLmZpbmRSZWZlcmVuY2VzVG8obG9nR3JvdXBSZXNvdXJjZS5Mb2dpY2FsUmVzb3VyY2VJZCk7XG4gIGZvciAoY29uc3QgcmVmZXJlbmNlIG9mIHJlc291cmNlc1JlZmVyZW5jaW5nTG9nR3JvdXApIHtcbiAgICBpZiAoSUdOT1JFX0xPR1NfUkVTT1VSQ0VfVFlQRVMuaW5jbHVkZXMocmVmZXJlbmNlLlR5cGUpKSB7XG4gICAgICBmb3VuZFJlZmVyZW5jZSA9IHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmb3VuZFJlZmVyZW5jZTtcbn1cblxuLyoqXG4gKiBGaW5kIGFsbCBDbG91ZFdhdGNoIExvZyBHcm91cHMgaW4gdGhlIGRlcGxveWVkIHRlbXBsYXRlLlxuICogVGhpcyB3aWxsIGZpbmQgYm90aCBleHBsaWNpdGVseSBjcmVhdGVkIExvZyBHcm91cHMgKGV4Y2x1ZGluZyB0aG9zZSBhc3NvY2lhdGVkIHdpdGggaWdub3JlZCByZXNvdXJjZXMpXG4gKiBhcyB3ZWxsIGFzIExvZyBHcm91cHMgY3JlYXRlZCBpbXBsaWNpdGVseSAoaS5lLiBMYW1iZGEgRnVuY3Rpb25zKVxuICovXG5mdW5jdGlvbiBmaW5kQWxsTG9nR3JvdXBOYW1lcyhcbiAgc3RhY2tSZXNvdXJjZXM6IENsb3VkRm9ybWF0aW9uLlN0YWNrUmVzb3VyY2VTdW1tYXJ5W10sXG4gIGV2YWx1YXRlQ2ZuVGVtcGxhdGU6IEV2YWx1YXRlQ2xvdWRGb3JtYXRpb25UZW1wbGF0ZSxcbik6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIHN0YWNrUmVzb3VyY2VzLnJlZHVjZSgobG9nR3JvdXBOYW1lczogc3RyaW5nW10sIHJlc291cmNlKSA9PiB7XG4gICAgbGV0IGxvZ0dyb3VwTmFtZTtcbiAgICBpZiAocmVzb3VyY2UuUmVzb3VyY2VUeXBlID09PSAnQVdTOjpMb2dzOjpMb2dHcm91cCcpIHtcbiAgICAgIGlmICghaXNSZWZlcmVuY2VkRnJvbUlnbm9yZWRSZXNvdXJjZShyZXNvdXJjZSwgZXZhbHVhdGVDZm5UZW1wbGF0ZSkpIHtcbiAgICAgICAgbG9nR3JvdXBOYW1lID0gcmVzb3VyY2UuUGh5c2ljYWxSZXNvdXJjZUlkO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoUkVTT1VSQ0VfVFlQRVNfV0lUSF9JTVBMSUNJVF9MT0dTW3Jlc291cmNlLlJlc291cmNlVHlwZV0pIHtcbiAgICAgIGNvbnN0IHNlcnZpY2VQYXJ0ID0gUkVTT1VSQ0VfVFlQRVNfV0lUSF9JTVBMSUNJVF9MT0dTW3Jlc291cmNlLlJlc291cmNlVHlwZV0uTG9nR3JvdXBTZXJ2aWNlTmFtZTtcbiAgICAgIGxvZ0dyb3VwTmFtZSA9IGAvYXdzLyR7c2VydmljZVBhcnR9LyR7cmVzb3VyY2UuUGh5c2ljYWxSZXNvdXJjZUlkfWA7XG4gICAgfVxuICAgIGlmIChsb2dHcm91cE5hbWUpIHtcbiAgICAgIGxvZ0dyb3VwTmFtZXMucHVzaChsb2dHcm91cE5hbWUpO1xuICAgIH1cbiAgICByZXR1cm4gbG9nR3JvdXBOYW1lcztcbiAgfSwgW10pO1xufVxuIl19
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as cxapi from '@aws-cdk/cx-api';
|
|
2
|
+
import { ISDK } from '../aws-auth';
|
|
3
|
+
export declare class CloudWatchLogEventMonitor {
|
|
4
|
+
/**
|
|
5
|
+
* Determines which events not to display
|
|
6
|
+
*/
|
|
7
|
+
private startTime;
|
|
8
|
+
/**
|
|
9
|
+
* Map of environment (account:region) to LogGroupsAccessSettings
|
|
10
|
+
*/
|
|
11
|
+
private readonly envsLogGroupsAccessSettings;
|
|
12
|
+
private active;
|
|
13
|
+
constructor(startTime?: Date);
|
|
14
|
+
/**
|
|
15
|
+
* resume reading/printing events
|
|
16
|
+
*/
|
|
17
|
+
activate(): void;
|
|
18
|
+
/**
|
|
19
|
+
* deactivates the monitor so no new events are read
|
|
20
|
+
* use case for this is when we are in the middle of performing a deployment
|
|
21
|
+
* and don't want to interweave all the logs together with the CFN
|
|
22
|
+
* deployment logs
|
|
23
|
+
*
|
|
24
|
+
* Also resets the start time to be when the new deployment was triggered
|
|
25
|
+
* and clears the list of tracked log groups
|
|
26
|
+
*/
|
|
27
|
+
deactivate(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Adds CloudWatch log groups to read log events from.
|
|
30
|
+
* Since we could be watching multiple stacks that deploy to
|
|
31
|
+
* multiple environments (account+region), we need to store a list of log groups
|
|
32
|
+
* per env along with the SDK object that has access to read from
|
|
33
|
+
* that environment.
|
|
34
|
+
*/
|
|
35
|
+
addLogGroups(env: cxapi.Environment, sdk: ISDK, logGroupNames: string[]): void;
|
|
36
|
+
private scheduleNextTick;
|
|
37
|
+
private tick;
|
|
38
|
+
/**
|
|
39
|
+
* Reads all new log events from a set of CloudWatch Log Groups
|
|
40
|
+
* in parallel
|
|
41
|
+
*/
|
|
42
|
+
private readNewEvents;
|
|
43
|
+
/**
|
|
44
|
+
* Print out a cloudwatch event
|
|
45
|
+
*/
|
|
46
|
+
private print;
|
|
47
|
+
/**
|
|
48
|
+
* Reads all new log events from a CloudWatch Log Group
|
|
49
|
+
* starting at either the time the hotswap was triggered or
|
|
50
|
+
* when the last event was read on the previous tick
|
|
51
|
+
*/
|
|
52
|
+
private readEventsFromLogGroup;
|
|
53
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CloudWatchLogEventMonitor = void 0;
|
|
4
|
+
const util = require("util");
|
|
5
|
+
const chalk = require("chalk");
|
|
6
|
+
const logging_1 = require("../../logging");
|
|
7
|
+
const arrays_1 = require("../../util/arrays");
|
|
8
|
+
/**
|
|
9
|
+
* After reading events from all CloudWatch log groups
|
|
10
|
+
* how long should we wait to read more events.
|
|
11
|
+
*
|
|
12
|
+
* If there is some error with reading events (i.e. Throttle)
|
|
13
|
+
* then this is also how long we wait until we try again
|
|
14
|
+
*/
|
|
15
|
+
const SLEEP = 2000;
|
|
16
|
+
class CloudWatchLogEventMonitor {
|
|
17
|
+
constructor(startTime) {
|
|
18
|
+
var _a;
|
|
19
|
+
/**
|
|
20
|
+
* Map of environment (account:region) to LogGroupsAccessSettings
|
|
21
|
+
*/
|
|
22
|
+
this.envsLogGroupsAccessSettings = new Map();
|
|
23
|
+
this.active = false;
|
|
24
|
+
this.startTime = (_a = startTime === null || startTime === void 0 ? void 0 : startTime.getTime()) !== null && _a !== void 0 ? _a : Date.now();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* resume reading/printing events
|
|
28
|
+
*/
|
|
29
|
+
activate() {
|
|
30
|
+
this.active = true;
|
|
31
|
+
this.scheduleNextTick(0);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* deactivates the monitor so no new events are read
|
|
35
|
+
* use case for this is when we are in the middle of performing a deployment
|
|
36
|
+
* and don't want to interweave all the logs together with the CFN
|
|
37
|
+
* deployment logs
|
|
38
|
+
*
|
|
39
|
+
* Also resets the start time to be when the new deployment was triggered
|
|
40
|
+
* and clears the list of tracked log groups
|
|
41
|
+
*/
|
|
42
|
+
deactivate() {
|
|
43
|
+
this.active = false;
|
|
44
|
+
this.startTime = Date.now();
|
|
45
|
+
this.envsLogGroupsAccessSettings.clear();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Adds CloudWatch log groups to read log events from.
|
|
49
|
+
* Since we could be watching multiple stacks that deploy to
|
|
50
|
+
* multiple environments (account+region), we need to store a list of log groups
|
|
51
|
+
* per env along with the SDK object that has access to read from
|
|
52
|
+
* that environment.
|
|
53
|
+
*/
|
|
54
|
+
addLogGroups(env, sdk, logGroupNames) {
|
|
55
|
+
var _a;
|
|
56
|
+
const awsEnv = `${env.account}:${env.region}`;
|
|
57
|
+
const logGroupsStartTimes = logGroupNames.reduce((acc, groupName) => {
|
|
58
|
+
acc[groupName] = this.startTime;
|
|
59
|
+
return acc;
|
|
60
|
+
}, {});
|
|
61
|
+
this.envsLogGroupsAccessSettings.set(awsEnv, {
|
|
62
|
+
sdk,
|
|
63
|
+
logGroupsStartTimes: {
|
|
64
|
+
...(_a = this.envsLogGroupsAccessSettings.get(awsEnv)) === null || _a === void 0 ? void 0 : _a.logGroupsStartTimes,
|
|
65
|
+
...logGroupsStartTimes,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
scheduleNextTick(sleep) {
|
|
70
|
+
setTimeout(() => void (this.tick()), sleep);
|
|
71
|
+
}
|
|
72
|
+
async tick() {
|
|
73
|
+
if (!this.active) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const events = arrays_1.flatten(await this.readNewEvents());
|
|
78
|
+
events.forEach(event => {
|
|
79
|
+
this.print(event);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
logging_1.error('Error occurred while monitoring logs: %s', e);
|
|
84
|
+
}
|
|
85
|
+
this.scheduleNextTick(SLEEP);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Reads all new log events from a set of CloudWatch Log Groups
|
|
89
|
+
* in parallel
|
|
90
|
+
*/
|
|
91
|
+
async readNewEvents() {
|
|
92
|
+
const promises = [];
|
|
93
|
+
for (const settings of this.envsLogGroupsAccessSettings.values()) {
|
|
94
|
+
for (const group of Object.keys(settings.logGroupsStartTimes)) {
|
|
95
|
+
promises.push(this.readEventsFromLogGroup(settings, group));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return Promise.all(promises);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Print out a cloudwatch event
|
|
102
|
+
*/
|
|
103
|
+
print(event) {
|
|
104
|
+
logging_1.print(util.format('[%s] %s %s', chalk.blue(event.logGroupName), chalk.yellow(event.timestamp.toLocaleTimeString()), event.message.trim()));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Reads all new log events from a CloudWatch Log Group
|
|
108
|
+
* starting at either the time the hotswap was triggered or
|
|
109
|
+
* when the last event was read on the previous tick
|
|
110
|
+
*/
|
|
111
|
+
async readEventsFromLogGroup(logGroupsAccessSettings, logGroupName) {
|
|
112
|
+
var _a, _b;
|
|
113
|
+
const events = [];
|
|
114
|
+
// log events from some service are ingested faster than others
|
|
115
|
+
// so we need to track the start/end time for each log group individually
|
|
116
|
+
// to make sure that we process all events from each log group
|
|
117
|
+
const startTime = (_a = logGroupsAccessSettings.logGroupsStartTimes[logGroupName]) !== null && _a !== void 0 ? _a : this.startTime;
|
|
118
|
+
let endTime = startTime;
|
|
119
|
+
try {
|
|
120
|
+
const response = await logGroupsAccessSettings.sdk.cloudWatchLogs().filterLogEvents({
|
|
121
|
+
logGroupName: logGroupName,
|
|
122
|
+
limit: 100,
|
|
123
|
+
startTime: startTime,
|
|
124
|
+
}).promise();
|
|
125
|
+
const filteredEvents = (_b = response.events) !== null && _b !== void 0 ? _b : [];
|
|
126
|
+
for (const event of filteredEvents) {
|
|
127
|
+
if (event.message) {
|
|
128
|
+
events.push({
|
|
129
|
+
message: event.message,
|
|
130
|
+
logGroupName,
|
|
131
|
+
timestamp: event.timestamp ? new Date(event.timestamp) : new Date(),
|
|
132
|
+
});
|
|
133
|
+
if (event.timestamp && endTime < event.timestamp) {
|
|
134
|
+
endTime = event.timestamp;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// if we have > 100 events let the user know some
|
|
139
|
+
// messages have been supressed. We are essentially
|
|
140
|
+
// showing them a sampling (10000 events printed out is not very useful)
|
|
141
|
+
if (filteredEvents.length > 0 && response.nextToken) {
|
|
142
|
+
events.push({
|
|
143
|
+
message: '>>> `watch` shows only the first 100 log messages - the rest have been truncated...',
|
|
144
|
+
logGroupName,
|
|
145
|
+
timestamp: new Date(endTime),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
// with Lambda functions the CloudWatch is not created
|
|
151
|
+
// until something is logged, so just keep polling until
|
|
152
|
+
// there is somthing to find
|
|
153
|
+
if (e.code === 'ResourceNotFoundException') {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
throw e;
|
|
157
|
+
}
|
|
158
|
+
logGroupsAccessSettings.logGroupsStartTimes[logGroupName] = endTime + 1;
|
|
159
|
+
return events;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.CloudWatchLogEventMonitor = CloudWatchLogEventMonitor;
|
|
163
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9ncy1tb25pdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibG9ncy1tb25pdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE2QjtBQUU3QiwrQkFBK0I7QUFDL0IsMkNBQTZDO0FBQzdDLDhDQUE0QztBQUc1Qzs7Ozs7O0dBTUc7QUFDSCxNQUFNLEtBQUssR0FBRyxJQUFLLENBQUM7QUEwQ3BCLE1BQWEseUJBQXlCO0lBYXBDLFlBQVksU0FBZ0I7O1FBUDVCOztXQUVHO1FBQ2MsZ0NBQTJCLEdBQUcsSUFBSSxHQUFHLEVBQW1DLENBQUM7UUFFbEYsV0FBTSxHQUFHLEtBQUssQ0FBQztRQUdyQixJQUFJLENBQUMsU0FBUyxTQUFHLFNBQVMsYUFBVCxTQUFTLHVCQUFULFNBQVMsQ0FBRSxPQUFPLHFDQUFNLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxRQUFRO1FBQ2IsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDbkIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNJLFVBQVU7UUFDZixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsMkJBQTJCLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDM0MsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLFlBQVksQ0FBQyxHQUFzQixFQUFFLEdBQVMsRUFBRSxhQUF1Qjs7UUFDNUUsTUFBTSxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM5QyxNQUFNLG1CQUFtQixHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsU0FBUyxFQUFFLEVB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QUFNLENBQUM7SUFDaEIsQ0FBQztDQUNGO0FBdEtELDhEQXNLQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHV0aWwgZnJvbSAndXRpbCc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0ICogYXMgY2hhbGsgZnJvbSAnY2hhbGsnO1xuaW1wb3J0IHsgcHJpbnQsIGVycm9yIH0gZnJvbSAnLi4vLi4vbG9nZ2luZyc7XG5pbXBvcnQgeyBmbGF0dGVuIH0gZnJvbSAnLi4vLi4vdXRpbC9hcnJheXMnO1xuaW1wb3J0IHsgSVNESyB9IGZyb20gJy4uL2F3cy1hdXRoJztcblxuLyoqXG4gKiBBZnRlciByZWFkaW5nIGV2ZW50cyBmcm9tIGFsbCBDbG91ZFdhdGNoIGxvZyBncm91cHNcbiAqIGhvdyBsb25nIHNob3VsZCB3ZSB3YWl0IHRvIHJlYWQgbW9yZSBldmVudHMuXG4gKlxuICogSWYgdGhlcmUgaXMgc29tZSBlcnJvciB3aXRoIHJlYWRpbmcgZXZlbnRzIChpLmUuIFRocm90dGxlKVxuICogdGhlbiB0aGlzIGlzIGFsc28gaG93IGxvbmcgd2Ugd2FpdCB1bnRpbCB3ZSB0cnkgYWdhaW5cbiAqL1xuY29uc3QgU0xFRVAgPSAyXzAwMDtcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgQ2xvdWRXYXRjaCBMb2cgRXZlbnQgdGhhdCB3aWxsIGJlXG4gKiBwcmludGVkIHRvIHRoZSB0ZXJtaW5hbFxuICovXG5pbnRlcmZhY2UgQ2xvdWRXYXRjaExvZ0V2ZW50IHtcbiAgLyoqXG4gICAqIFRoZSBsb2cgZXZlbnQgbWVzc2FnZVxuICAgKi9cbiAgcmVhZG9ubHkgbWVzc2FnZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgbG9nIGdyb3VwXG4gICAqL1xuICByZWFkb25seSBsb2dHcm91cE5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHRpbWUgYXQgd2hpY2ggdGhlIGV2ZW50IG9jY3VycmVkXG4gICAqL1xuICByZWFkb25seSB0aW1lc3RhbXA6IERhdGU7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiB0cmFja2luZyBpbmZvcm1hdGlvbiBvbiB0aGUgbG9nIGdyb3VwcyB0aGF0IGFyZVxuICogYmVpbmcgbW9uaXRvcmVkXG4gKi9cbmludGVyZmFjZSBMb2dHcm91cHNBY2Nlc3NTZXR0aW5ncyB7XG4gIC8qKlxuICAgKiBUaGUgU0RLIGZvciBhIGdpdmVuIGVudmlyb25tZW50IChhY2NvdW50L3JlZ2lvbilcbiAgICovXG4gIHJlYWRvbmx5IHNkazogSVNESztcblxuICAvKipcbiAgICogQSBtYXAgb2YgbG9nIGdyb3VwcyBhbmQgYXNzb2NpYXRlZCBzdGFydFRpbWUgaW4gYSBnaXZlbiBhY2NvdW50LlxuICAgKlxuICAgKiBUaGUgbW9uaXRvciB3aWxsIHJlYWQgZXZlbnRzIGZyb20gdGhlIGxvZyBncm91cCBzdGFydGluZyBhdCB0aGVcbiAgICogYXNzb2NpYXRlZCBzdGFydFRpbWVcbiAgICovXG4gIHJlYWRvbmx5IGxvZ0dyb3Vwc1N0YXJ0VGltZXM6IHsgW2xvZ0dyb3VwTmFtZTogc3RyaW5nXTogbnVtYmVyIH07XG59XG5cbmV4cG9ydCBjbGFzcyBDbG91ZFdhdGNoTG9nRXZlbnRNb25pdG9yIHtcbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hpY2ggZXZlbnRzIG5vdCB0byBkaXNwbGF5XG4gICAqL1xuICBwcml2YXRlIHN0YXJ0VGltZTogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBNYXAgb2YgZW52aXJvbm1lbnQgKGFjY291bnQ6cmVnaW9uKSB0byBMb2dHcm91cHNBY2Nlc3NTZXR0aW5nc1xuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBlbnZzTG9nR3JvdXBzQWNjZXNzU2V0dGluZ3MgPSBuZXcgTWFwPHN0cmluZywgTG9nR3JvdXBzQWNjZXNzU2V0dGluZ3M+KCk7XG5cbiAgcHJpdmF0ZSBhY3RpdmUgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihzdGFydFRpbWU/OiBEYXRlKSB7XG4gICAgdGhpcy5zdGFydFRpbWUgPSBzdGFydFRpbWU/LmdldFRpbWUoKSA/PyBEYXRlLm5vdygpO1xuICB9XG5cbiAgLyoqXG4gICAqIHJlc3VtZSByZWFkaW5nL3ByaW50aW5nIGV2ZW50c1xuICAgKi9cbiAgcHVibGljIGFjdGl2YXRlKCk6IHZvaWQge1xuICAgIHRoaXMuYWN0aXZlID0gdHJ1ZTtcbiAgICB0aGlzLnNjaGVkdWxlTmV4dFRpY2soMCk7XG4gIH1cblxuICAvKipcbiAgICogZGVhY3RpdmF0ZXMgdGhlIG1vbml0b3Igc28gbm8gbmV3IGV2ZW50cyBhcmUgcmVhZFxuICAgKiB1c2UgY2FzZSBmb3IgdGhpcyBpcyB3aGVuIHdlIGFyZSBpbiB0aGUgbWlkZGxlIG9mIHBlcmZvcm1pbmcgYSBkZXBsb3ltZW50XG4gICAqIGFuZCBkb24ndCB3YW50IHRvIGludGVyd2VhdmUgYWxsIHRoZSBsb2dzIHRvZ2V0aGVyIHdpdGggdGhlIENGTlxuICAgKiBkZXBsb3ltZW50IGxvZ3NcbiAgICpcbiAgICogQWxzbyByZXNldHMgdGhlIHN0YXJ0IHRpbWUgdG8gYmUgd2hlbiB0aGUgbmV3IGRlcGxveW1lbnQgd2FzIHRyaWdnZXJlZFxuICAgKiBhbmQgY2xlYXJzIHRoZSBsaXN0IG9mIHRyYWNrZWQgbG9nIGdyb3Vwc1xuICAgKi9cbiAgcHVibGljIGRlYWN0aXZhdGUoKTogdm9pZCB7XG4gICAgdGhpcy5hY3RpdmUgPSBmYWxzZTtcbiAgICB0aGlzLnN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgdGhpcy5lbnZzTG9nR3JvdXBzQWNjZXNzU2V0dGluZ3MuY2xlYXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIENsb3VkV2F0Y2ggbG9nIGdyb3VwcyB0byByZWFkIGxvZyBldmVudHMgZnJvbS5cbiAgICogU2luY2Ugd2UgY291bGQgYmUgd2F0Y2hpbmcgbXVsdGlwbGUgc3RhY2tzIHRoYXQgZGVwbG95IHRvXG4gICAqIG11bHRpcGxlIGVudmlyb25tZW50cyAoYWNjb3VudCtyZWdpb24pLCB3ZSBuZWVkIHRvIHN0b3JlIGEgbGlzdCBvZiBsb2cgZ3JvdXBzXG4gICAqIHBlciBlbnYgYWxvbmcgd2l0aCB0aGUgU0RLIG9iamVjdCB0aGF0IGhhcyBhY2Nlc3MgdG8gcmVhZCBmcm9tXG4gICAqIHRoYXQgZW52aXJvbm1lbnQuXG4gICAqL1xuICBwdWJsaWMgYWRkTG9nR3JvdXBzKGVudjogY3hhcGkuRW52aXJvbm1lbnQsIHNkazogSVNESywgbG9nR3JvdXBOYW1lczogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBjb25zdCBhd3NFbnYgPSBgJHtlbnYuYWNjb3VudH06JHtlbnYucmVnaW9ufWA7XG4gICAgY29uc3QgbG9nR3JvdXBzU3RhcnRUaW1lcyA9IGxvZ0dyb3VwTmFtZXMucmVkdWNlKChhY2MsIGdyb3VwTmFtZSkgPT4ge1xuICAgICAgYWNjW2dyb3VwTmFtZV0gPSB0aGlzLnN0YXJ0VGltZTtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwge30gYXMgeyBbbG9nR3JvdXBOYW1lOiBzdHJpbmddOiBudW1iZXIgfSk7XG4gICAgdGhpcy5lbnZzTG9nR3JvdXBzQWNjZXNzU2V0dGluZ3Muc2V0KGF3c0Vudiwge1xuICAgICAgc2RrLFxuICAgICAgbG9nR3JvdXBzU3RhcnRUaW1lczoge1xuICAgICAgICAuLi50aGlzLmVudnNMb2dHcm91cHNBY2Nlc3NTZXR0aW5ncy5nZXQoYXdzRW52KT8ubG9nR3JvdXBzU3RhcnRUaW1lcyxcbiAgICAgICAgLi4ubG9nR3JvdXBzU3RhcnRUaW1lcyxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNjaGVkdWxlTmV4dFRpY2soc2xlZXA6IG51bWJlcik6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gdm9pZCh0aGlzLnRpY2soKSksIHNsZWVwKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdGljaygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuYWN0aXZlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBldmVudHMgPSBmbGF0dGVuKGF3YWl0IHRoaXMucmVhZE5ld0V2ZW50cygpKTtcbiAgICAgIGV2ZW50cy5mb3JFYWNoKGV2ZW50ID0+IHtcbiAgICAgICAgdGhpcy5wcmludChldmVudCk7XG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBlcnJvcignRXJyb3Igb2NjdXJyZWQgd2hpbGUgbW9uaXRvcmluZyBsb2dzOiAlcycsIGUpO1xuICAgIH1cblxuICAgIHRoaXMuc2NoZWR1bGVOZXh0VGljayhTTEVFUCk7XG4gIH1cblxuICAvKipcbiAgICogUmVhZHMgYWxsIG5ldyBsb2cgZXZlbnRzIGZyb20gYSBzZXQgb2YgQ2xvdWRXYXRjaCBMb2cgR3JvdXBzXG4gICAqIGluIHBhcmFsbGVsXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlYWROZXdFdmVudHMoKTogUHJvbWlzZTxBcnJheTxBcnJheTxDbG91ZFdhdGNoTG9nRXZlbnQ+Pj4ge1xuICAgIGNvbnN0IHByb21pc2VzOiBBcnJheTxQcm9taXNlPEFycmF5PENsb3VkV2F0Y2hMb2dFdmVudD4+PiA9IFtdO1xuICAgIGZvciAoY29uc3Qgc2V0dGluZ3Mgb2YgdGhpcy5lbnZzTG9nR3JvdXBzQWNjZXNzU2V0dGluZ3MudmFsdWVzKCkpIHtcbiAgICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgT2JqZWN0LmtleXMoc2V0dGluZ3MubG9nR3JvdXBzU3RhcnRUaW1lcykpIHtcbiAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLnJlYWRFdmVudHNGcm9tTG9nR3JvdXAoc2V0dGluZ3MsIGdyb3VwKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gIH1cblxuICAvKipcbiAgICogUHJpbnQgb3V0IGEgY2xvdWR3YXRjaCBldmVudFxuICAgKi9cbiAgcHJpdmF0ZSBwcmludChldmVudDogQ2xvdWRXYXRjaExvZ0V2ZW50KTogdm9pZCB7XG4gICAgcHJpbnQodXRpbC5mb3JtYXQoJ1slc10gJXMgJXMnLFxuICAgICAgY2hhbGsuYmx1ZShldmVudC5sb2dHcm91cE5hbWUpLFxuICAgICAgY2hhbGsueWVsbG93KGV2ZW50LnRpbWVzdGFtcC50b0xvY2FsZVRpbWVTdHJpbmcoKSksXG4gICAgICBldmVudC5tZXNzYWdlLnRyaW0oKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlYWRzIGFsbCBuZXcgbG9nIGV2ZW50cyBmcm9tIGEgQ2xvdWRXYXRjaCBMb2cgR3JvdXBcbiAgICogc3RhcnRpbmcgYXQgZWl0aGVyIHRoZSB0aW1lIHRoZSBob3Rzd2FwIHdhcyB0cmlnZ2VyZWQgb3JcbiAgICogd2hlbiB0aGUgbGFzdCBldmVudCB3YXMgcmVhZCBvbiB0aGUgcHJldmlvdXMgdGlja1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZWFkRXZlbnRzRnJvbUxvZ0dyb3VwKFxuICAgIGxvZ0dyb3Vwc0FjY2Vzc1NldHRpbmdzOiBMb2dHcm91cHNBY2Nlc3NTZXR0aW5ncyxcbiAgICBsb2dHcm91cE5hbWU6IHN0cmluZyxcbiAgKTogUHJvbWlzZTxBcnJheTxDbG91ZFdhdGNoTG9nRXZlbnQ+PiB7XG4gICAgY29uc3QgZXZlbnRzOiBDbG91ZFdhdGNoTG9nRXZlbnRbXSA9IFtdO1xuXG4gICAgLy8gbG9nIGV2ZW50cyBmcm9tIHNvbWUgc2VydmljZSBhcmUgaW5nZXN0ZWQgZmFzdGVyIHRoYW4gb3RoZXJzXG4gICAgLy8gc28gd2UgbmVlZCB0byB0cmFjayB0aGUgc3RhcnQvZW5kIHRpbWUgZm9yIGVhY2ggbG9nIGdyb3VwIGluZGl2aWR1YWxseVxuICAgIC8vIHRvIG1ha2Ugc3VyZSB0aGF0IHdlIHByb2Nlc3MgYWxsIGV2ZW50cyBmcm9tIGVhY2ggbG9nIGdyb3VwXG4gICAgY29uc3Qgc3RhcnRUaW1lID0gbG9nR3JvdXBzQWNjZXNzU2V0dGluZ3MubG9nR3JvdXBzU3RhcnRUaW1lc1tsb2dHcm91cE5hbWVdID8/IHRoaXMuc3RhcnRUaW1lO1xuICAgIGxldCBlbmRUaW1lID0gc3RhcnRUaW1lO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGxvZ0dyb3Vwc0FjY2Vzc1NldHRpbmdzLnNkay5jbG91ZFdhdGNoTG9ncygpLmZpbHRlckxvZ0V2ZW50cyh7XG4gICAgICAgIGxvZ0dyb3VwTmFtZTogbG9nR3JvdXBOYW1lLFxuICAgICAgICBsaW1pdDogMTAwLFxuICAgICAgICBzdGFydFRpbWU6IHN0YXJ0VGltZSxcbiAgICAgIH0pLnByb21pc2UoKTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkRXZlbnRzID0gcmVzcG9uc2UuZXZlbnRzID8/IFtdO1xuXG4gICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGZpbHRlcmVkRXZlbnRzKSB7XG4gICAgICAgIGlmIChldmVudC5tZXNzYWdlKSB7XG4gICAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgICAgbWVzc2FnZTogZXZlbnQubWVzc2FnZSxcbiAgICAgICAgICAgIGxvZ0dyb3VwTmFtZSxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogZXZlbnQudGltZXN0YW1wID8gbmV3IERhdGUoZXZlbnQudGltZXN0YW1wKSA6IG5ldyBEYXRlKCksXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAoZXZlbnQudGltZXN0YW1wICYmIGVuZFRpbWUgPCBldmVudC50aW1lc3RhbXApIHtcbiAgICAgICAgICAgIGVuZFRpbWUgPSBldmVudC50aW1lc3RhbXA7XG4gICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIGlmIHdlIGhhdmUgPiAxMDAgZXZlbnRzIGxldCB0aGUgdXNlciBrbm93IHNvbWVcbiAgICAgIC8vIG1lc3NhZ2VzIGhhdmUgYmVlbiBzdXByZXNzZWQuIFdlIGFyZSBlc3NlbnRpYWxseVxuICAgICAgLy8gc2hvd2luZyB0aGVtIGEgc2FtcGxpbmcgKDEwMDAwIGV2ZW50cyBwcmludGVkIG91dCBpcyBub3QgdmVyeSB1c2VmdWwpXG4gICAgICBpZiAoZmlsdGVyZWRFdmVudHMubGVuZ3RoID4gMCAmJiByZXNwb25zZS5uZXh0VG9rZW4pIHtcbiAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgIG1lc3NhZ2U6ICc+Pj4gYHdhdGNoYCBzaG93cyBvbmx5IHRoZSBmaXJzdCAxMDAgbG9nIG1lc3NhZ2VzIC0gdGhlIHJlc3QgaGF2ZSBiZWVuIHRydW5jYXRlZC4uLicsXG4gICAgICAgICAgbG9nR3JvdXBOYW1lLFxuICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoZW5kVGltZSksXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIHdpdGggTGFtYmRhIGZ1bmN0aW9ucyB0aGUgQ2xvdWRXYXRjaCBpcyBub3QgY3JlYXRlZFxuICAgICAgLy8gdW50aWwgc29tZXRoaW5nIGlzIGxvZ2dlZCwgc28ganVzdCBrZWVwIHBvbGxpbmcgdW50aWxcbiAgICAgIC8vIHRoZXJlIGlzIHNvbXRoaW5nIHRvIGZpbmRcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICBsb2dHcm91cHNBY2Nlc3NTZXR0aW5ncy5sb2dHcm91cHNTdGFydFRpbWVzW2xvZ0dyb3VwTmFtZV0gPSBlbmRUaW1lICsgMTtcbiAgICByZXR1cm4gZXZlbnRzO1xuICB9XG59XG4iXX0=
|
|
@@ -32,19 +32,19 @@ export declare abstract class ToolkitInfo {
|
|
|
32
32
|
static fromStack(stack: CloudFormationStack, sdk: ISDK): ToolkitInfo;
|
|
33
33
|
static bootstraplessDeploymentsOnly(sdk: ISDK): ToolkitInfo;
|
|
34
34
|
static bootstrapStackNotFoundInfo(sdk: ISDK): ToolkitInfo;
|
|
35
|
+
/**
|
|
36
|
+
* Read a version from an SSM parameter, cached
|
|
37
|
+
*/
|
|
38
|
+
static versionFromSsmParameter(sdk: ISDK, parameterName: string, ssmCache?: Map<string, number>): Promise<number>;
|
|
39
|
+
protected readonly ssmCache: Map<string, number>;
|
|
35
40
|
abstract readonly found: boolean;
|
|
36
41
|
abstract readonly bucketUrl: string;
|
|
37
42
|
abstract readonly bucketName: string;
|
|
38
43
|
abstract readonly version: number;
|
|
39
44
|
abstract readonly bootstrapStack: CloudFormationStack;
|
|
40
|
-
private readonly ssmCache;
|
|
41
45
|
constructor(sdk: ISDK);
|
|
42
46
|
abstract validateVersion(expectedVersion: number, ssmParameterName: string | undefined): Promise<void>;
|
|
43
47
|
abstract prepareEcrRepository(repositoryName: string): Promise<EcrRepositoryInfo>;
|
|
44
|
-
/**
|
|
45
|
-
* Read a version from an SSM parameter, cached
|
|
46
|
-
*/
|
|
47
|
-
protected versionFromSsmParameter(parameterName: string): Promise<number>;
|
|
48
48
|
}
|
|
49
49
|
export interface EcrRepositoryInfo {
|
|
50
50
|
repositoryUri: string;
|
package/lib/api/toolkit-info.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ToolkitInfo = exports.DEFAULT_TOOLKIT_STACK_NAME = void 0;
|
|
4
|
-
const
|
|
4
|
+
const chalk = require("chalk");
|
|
5
5
|
const logging_1 = require("../logging");
|
|
6
6
|
const bootstrap_1 = require("./bootstrap");
|
|
7
7
|
const cloudformation_1 = require("./util/cloudformation");
|
|
@@ -45,12 +45,12 @@ class ToolkitInfo {
|
|
|
45
45
|
const cfn = sdk.cloudFormation();
|
|
46
46
|
const stack = await cloudformation_1.stabilizeStack(cfn, stackName !== null && stackName !== void 0 ? stackName : exports.DEFAULT_TOOLKIT_STACK_NAME);
|
|
47
47
|
if (!stack) {
|
|
48
|
-
logging_1.debug('The environment %s doesn\'t have the CDK toolkit stack (%s) installed. Use %s to setup your environment for use with the toolkit.', environment.name, stackName,
|
|
48
|
+
logging_1.debug('The environment %s doesn\'t have the CDK toolkit stack (%s) installed. Use %s to setup your environment for use with the toolkit.', environment.name, stackName, chalk.blue(`cdk bootstrap "${environment.name}"`));
|
|
49
49
|
return ToolkitInfo.bootstrapStackNotFoundInfo(sdk);
|
|
50
50
|
}
|
|
51
51
|
if (stack.stackStatus.isCreationFailure) {
|
|
52
52
|
// Treat a "failed to create" bootstrap stack as an absent one.
|
|
53
|
-
logging_1.debug('The environment %s has a CDK toolkit stack (%s) that failed to create. Use %s to try provisioning it again.', environment.name, stackName,
|
|
53
|
+
logging_1.debug('The environment %s has a CDK toolkit stack (%s) that failed to create. Use %s to try provisioning it again.', environment.name, stackName, chalk.blue(`cdk bootstrap "${environment.name}"`));
|
|
54
54
|
return ToolkitInfo.bootstrapStackNotFoundInfo(sdk);
|
|
55
55
|
}
|
|
56
56
|
return new ExistingToolkitInfo(stack, sdk);
|
|
@@ -67,20 +67,20 @@ class ToolkitInfo {
|
|
|
67
67
|
/**
|
|
68
68
|
* Read a version from an SSM parameter, cached
|
|
69
69
|
*/
|
|
70
|
-
async versionFromSsmParameter(parameterName) {
|
|
70
|
+
static async versionFromSsmParameter(sdk, parameterName, ssmCache) {
|
|
71
71
|
var _a, _b;
|
|
72
|
-
const existing =
|
|
72
|
+
const existing = ssmCache === null || ssmCache === void 0 ? void 0 : ssmCache.get(parameterName);
|
|
73
73
|
if (existing !== undefined) {
|
|
74
74
|
return existing;
|
|
75
75
|
}
|
|
76
|
-
const ssm =
|
|
76
|
+
const ssm = sdk.ssm();
|
|
77
77
|
try {
|
|
78
78
|
const result = await ssm.getParameter({ Name: parameterName }).promise();
|
|
79
79
|
const asNumber = parseInt(`${(_a = result.Parameter) === null || _a === void 0 ? void 0 : _a.Value}`, 10);
|
|
80
80
|
if (isNaN(asNumber)) {
|
|
81
81
|
throw new Error(`SSM parameter ${parameterName} not a number: ${(_b = result.Parameter) === null || _b === void 0 ? void 0 : _b.Value}`);
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
ssmCache === null || ssmCache === void 0 ? void 0 : ssmCache.set(parameterName, asNumber);
|
|
84
84
|
return asNumber;
|
|
85
85
|
}
|
|
86
86
|
catch (e) {
|
|
@@ -132,7 +132,7 @@ class ExistingToolkitInfo extends ToolkitInfo {
|
|
|
132
132
|
let version = this.version; // Default to the current version, but will be overwritten by a lookup if required.
|
|
133
133
|
if (ssmParameterName !== undefined) {
|
|
134
134
|
try {
|
|
135
|
-
version = await
|
|
135
|
+
version = await ToolkitInfo.versionFromSsmParameter(this.sdk, ssmParameterName, this.ssmCache);
|
|
136
136
|
}
|
|
137
137
|
catch (e) {
|
|
138
138
|
if (e.code !== 'AccessDeniedException') {
|
|
@@ -234,7 +234,7 @@ class BootstrapStackNotFoundInfo extends ToolkitInfo {
|
|
|
234
234
|
}
|
|
235
235
|
let version;
|
|
236
236
|
try {
|
|
237
|
-
version = await
|
|
237
|
+
version = await ToolkitInfo.versionFromSsmParameter(this.sdk, ssmParameterName, this.ssmCache);
|
|
238
238
|
}
|
|
239
239
|
catch (e) {
|
|
240
240
|
if (e.code !== 'AccessDeniedException') {
|
|
@@ -256,4 +256,4 @@ class BootstrapStackNotFoundInfo extends ToolkitInfo {
|
|
|
256
256
|
throw new Error(this.errorMessage);
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbGtpdC1pbmZvLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidG9vbGtpdC1pbmZvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHNDQUFzQztBQUN0Qyx3Q0FBNEM7QUFFNUMsMkNBQXNHO0FBQ3RHLDBEQUE0RTtBQUUvRCxRQUFBLDBCQUEwQixHQUFHLFlBQVksQ0FBQztBQUV2RDs7R0FFRztBQUNILE1BQU0sbURBQW1ELEdBQUcsQ0FBQyxDQUFDO0FBRTlEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBQ0gsTUFBc0IsV0FBVztJQTJDL0IsWUFBK0IsR0FBUztRQUFULFFBQUcsR0FBSCxHQUFHLENBQU07UUFGdkIsYUFBUSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBR3RELENBQUM7SUEzQ00sTUFBTSxDQUFDLGFBQWEsQ0FBQyxZQUFxQjtRQUMvQyxPQUFPLFlBQVksYUFBWixZQUFZLGNBQVosWUFBWSxHQUFJLGtDQUEwQixDQUFDO0lBQ3BELENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUE4QixFQUFFLEdBQVMsRUFBRSxTQUE2QjtRQUNqRyxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDakMsTUFBTSxLQUFLLEdBQUcsTUFBTSwrQkFBYyxDQUFDLEdBQUcsRUFBRSxTQUFTLGFBQVQsU0FBUyxjQUFULFNBQVMsR0FBSSxrQ0FBMEIsQ0FBQyxDQUFDO1FBQ2pGLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixlQUFLLENBQUMsbUlBQW1JLEVBQ3ZJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLFdBQVcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDbkYsT0FBTyxXQUFXLENBQUMsMEJBQTBCLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDcEQ7UUFDRCxJQUFJLEtBQUssQ0FBQyxXQUFX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LENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQsSUFBVyxPQUFPO1FBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTSxLQUFLLENBQUMsZUFBZSxDQUFDLGVBQXVCLEVBQUUsZ0JBQW9DO1FBQ3hGLElBQUksZ0JBQWdCLEtBQUssU0FBUyxFQUFFO1lBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ3BDO1FBRUQsSUFBSSxPQUFlLENBQUM7UUFDcEIsSUFBSTtZQUNGLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1NBQ2hFO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssdUJBQXVCLEVBQUU7Z0JBQUUsTUFBTSxDQUFDLENBQUM7YUFBRTtZQUVwRCx5RkFBeUY7WUFDekYsMkZBQTJGO1lBQzNGLHNGQUFzRjtZQUN0RiwyRkFBMkY7WUFDM0Ysa0RBQWtEO1lBQ2xELGlCQUFPLENBQUMsZ0NBQWdDLGdCQUFnQixLQUFLLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQzFFLE1BQU0sSUFBSSxLQUFLLENBQUMseURBQXlELGVBQWUsd0RBQXdELENBQUMsQ0FBQztTQUNuSjtRQUVELElBQUksZUFBZSxHQUFHLE9BQU8sRUFBRTtZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLHlEQUF5RCxlQUFlLGFBQWEsT0FBTyxnQ0FBZ0MsQ0FBQyxDQUFDO1NBQy9JO0lBQ0gsQ0FBQztJQUVNLG9CQUFvQjtRQUN6QixNQUFNLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNyQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0ICogYXMgY29sb3JzIGZyb20gJ2NvbG9ycy9zYWZlJztcbmltcG9ydCB7IGRlYnVnLCB3YXJuaW5nIH0gZnJvbSAnLi4vbG9nZ2luZyc7XG5pbXBvcnQgeyBJU0RLIH0gZnJvbSAnLi9hd3MtYXV0aCc7XG5pbXBvcnQgeyBCT09UU1RSQVBfVkVSU0lPTl9PVVRQVVQsIEJVQ0tFVF9ET01BSU5fTkFNRV9PVVRQVVQsIEJVQ0tFVF9OQU1FX09VVFBVVCB9IGZyb20gJy4vYm9vdHN0cmFwJztcbmltcG9ydCB7IHN0YWJpbGl6ZVN0YWNrLCBDbG91ZEZvcm1hdGlvblN0YWNrIH0gZnJvbSAnLi91dGlsL2Nsb3VkZm9ybWF0aW9uJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FID0gJ0NES1Rvb2xraXQnO1xuXG4vKipcbiAqIFRoZSBib290c3RyYXAgdGVtcGxhdGUgdmVyc2lvbiB0aGF0IGludHJvZHVjZWQgc3NtOkdldFBhcmFtZXRlclxuICovXG5jb25zdCBCT09UU1RSQVBfVEVNUExBVEVfVkVSU0lPTl9JTlRST0RVQ0lOR19HRVRQQVJBTUVURVIgPSA1O1xuXG4vKipcbiAqIEluZm9ybWF0aW9uIG9uIHRoZSBCb290c3RyYXAgc3RhY2sgb2YgdGhlIGVudmlyb25tZW50IHdlJ3JlIGRlcGxveWluZyB0by5cbiAqXG4gKiBUaGlzIGNsYXNzIHNlcnZlcyB0bzpcbiAqXG4gKiAtIEluc3BlY3QgdGhlIGJvb3RzdHJhcCBzdGFjaywgYW5kIHJldHVybiB2YXJpb3VzIHByb3BlcnRpZXMgb2YgaXQgZm9yIHN1Y2Nlc3NmdWxcbiAqICAgYXNzZXQgZGVwbG95bWVudCAoaW4gY2FzZSBvZiBsZWdhY3ktc3ludGhlc2l6ZWQgc3RhY2tzKS5cbiAqIC0gVmFsaWRhdGUgdGhlIHZlcnNpb24gb2YgdGhlIHRhcmdldCBlbnZpcm9ubWVudCwgYW5kIG5vdGhpbmcgZWxzZSAoaW4gY2FzZSBvZlxuICogICBkZWZhdWx0LXN5bnRoZXNpemVkIHN0YWNrcykuXG4gKlxuICogQW4gb2JqZWN0IG9mIHRoaXMgdHlwZSBtaWdodCByZXByZXNlbnQgYSBib290c3RyYXAgc3RhY2sgdGhhdCBjb3VsZCBub3QgYmUgZm91bmQuXG4gKiBUaGlzIGlzIG5vdCBhbiBpc3N1ZSB1bmxlc3MgYW55IG1lbWJlcnMgYXJlIHVzZWQgdGhhdCByZXF1aXJlIHRoZSBib290c3RyYXAgc3RhY2tcbiAqIHRvIGhhdmUgYmVlbiBmb3VuZCwgaW4gd2hpY2ggY2FzZSBhbiBlcnJvciBpcyB0aHJvd24gKGRlZmF1bHQtc3ludGhlc2l6ZWQgc3RhY2tzXG4gKiBzaG91bGQgbmV2ZXIgcnVuIGludG8gdGhpcyBhcyB0aGV5IGRvbid0IG5lZWQgaW5mb3JtYXRpb24gZnJvbSB0aGUgYm9vdHN0cmFwXG4gKiBzdGFjaywgYWxsIGluZm9ybWF0aW9uIGlzIGFscmVhZHkgZW5jb2RlZCBpbnRvIHRoZSBDbG91ZCBBc3NlbWJseSBNYW5pZmVzdCkuXG4gKlxuICogTmV2ZXJ0aGVsZXNzLCBhbiBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzIGV4aXN0cyB0byBzZXJ2ZSBhcyBhIGNhY2hlIGZvciBTU01cbiAqIHBhcmFtZXRlciBsb29rdXBzIChvdGhlcndpc2UsIHRoZSBcImJvb3RzdHJhcCBzdGFjayB2ZXJzaW9uXCIgcGFyYW1ldGVyIHdvdWxkXG4gKiBuZWVkIHRvIGJlIHJlYWQgcmVwZWF0ZWRseSkuXG4gKlxuICogQ2FsbGVkIFwiVG9vbGtpdEluZm9cIiBmb3IgaGlzdG9yaWNhbCByZWFzb25zLlxuICpcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFRvb2xraXRJbmZvIHtcbiAgcHVibGljIHN0YXRpYyBkZXRlcm1pbmVOYW1lKG92ZXJyaWRlTmFtZT86IHN0cmluZykge1xuICAgIHJldHVybiBvdmVycmlkZU5hbWUgPz8gREVGQVVMVF9UT09MS0lUX1NUQUNLX05BTUU7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGFzeW5jIGxvb2t1cChlbnZpcm9ubWVudDogY3hhcGkuRW52aXJvbm1lbnQsIHNkazogSVNESywgc3RhY2tOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPFRvb2xraXRJbmZvPiB7XG4gICAgY29uc3QgY2ZuID0gc2RrLmNsb3VkRm9ybWF0aW9uKCk7XG4gICAgY29uc3Qgc3RhY2sgPSBhd2FpdCBzdGFiaWxpemVTdGFjayhjZm4sIHN0YWNrTmFtZSA/PyBERUZBVUxUX1RPT0xLSVRfU1RBQ0tfTkFNRSk7XG4gICAgaWYgKCFzdGFjaykge1xuICAgICAgZGVidWcoJ1RoZSBlbnZpcm9ubWVudCAlcyBkb2VzblxcJ3QgaGF2ZSB0aGUgQ0RLIHRvb2xraXQgc3RhY2sgKCVzKSBpbnN0YWxsZWQuIFVzZSAlcyB0byBzZXR1cCB5b3VyIGVudmlyb25tZW50IGZvciB1c2Ugd2l0aCB0aGUgdG9vbGtpdC4nLFxuICAgICAgICBlbnZpcm9ubWVudC5uYW1lLCBzdGFja05hbWUsIGNvbG9ycy5ibHVlKGBjZGsgYm9vdHN0cmFwIFwiJHtlbnZpcm9ubWVudC5uYW1lfVwiYCkpO1xuICAgICAgcmV0dXJuIFRvb2xraXRJbmZvLmJvb3RzdHJhcFN0YWNrTm90Rm91bmRJbmZvKHNkayk7XG4gICAgfVxuICAgIGlmIChzdGFjay5zdGFja1N0YXR1cy5pc0NyZWF0aW9uRmFpbHVyZSkge1xuICAgICAgLy8gVHJlYXQgYSBcImZhaWxlZCB0byBjcmVhdGVcIiBib290c3RyYXAgc3RhY2sgYXMgYW4gYWJzZW50IG9uZS5cbiAgICAgIGRlYnVnKCdUaGUgZW52aXJvbm1lbnQgJXMgaGFzIGEgQ0RLIHRvb2xraXQgc3RhY2sgKCVzKSB0aGF0IGZhaWxlZCB0byBjcmVhdGUuIFVzZSAlcyB0byB0cnkgcHJvdmlzaW9uaW5nIGl0IGFnYWluLicsXG4gICAgICAgIGVudmlyb25tZW50Lm5hbWUsIHN0YWNrTmFtZSwgY29sb3JzLmJsdWUoYGNkayBib290c3RyYXAgXCIke2Vudmlyb25tZW50Lm5hbWV9XCJgKSk7XG4gICAgICByZXR1cm4gVG9vbGtpdEluZm8uYm9vdHN0cmFwU3RhY2tOb3RGb3VuZEluZm8oc2RrKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEV4aXN0aW5nVG9vbGtpdEluZm8oc3RhY2ssIHNkayk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGZyb21TdGFjayhzdGFjazogQ2xvdWRGb3JtYXRpb25TdGFjaywgc2RrOiBJU0RLKTogVG9vbGtpdEluZm8ge1xuICAgIHJldHVybiBuZXcgRXhpc3RpbmdUb29sa2l0SW5mbyhzdGFjaywgc2RrKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgYm9vdHN0cmFwbGVzc0RlcGxveW1lbnRzT25seShzZGs6IElTREspOiBUb29sa2l0SW5mbyB7XG4gICAgcmV0dXJuIG5ldyBCb290c3RyYXBTdGFja05vdEZvdW5kSW5mbyhzZGssICdUcnlpbmcgdG8gcGVyZm9ybSBhbiBvcGVyYXRpb24gdGhhdCByZXF1aXJlcyBhIGJvb3RzdHJhcCBzdGFjazsgeW91IHNob3VsZCBub3Qgc2VlIHRoaXMgZXJyb3IsIHRoaXMgaXMgYSBidWcgaW4gdGhlIENESyBDTEkuJyk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGJvb3RzdHJhcFN0YWNrTm90Rm91bmRJbmZvKHNkazogSVNESyk6IFRvb2xraXRJbmZvIHtcbiAgICByZXR1cm4gbmV3IEJvb3RzdHJhcFN0YWNrTm90Rm91bmRJbmZvKHNkaywgJ1RoaXMgZGVwbG95bWVudCByZXF1aXJlcyBhIGJvb3RzdHJhcCBzdGFjayB3aXRoIGEga25vd24gbmFtZTsgcGFzcyBcXCctLXRvb2xraXQtc3RhY2stbmFtZVxcJyBvciBzd2l0Y2ggdG8gdXNpbmcgdGhlIFxcJ0RlZmF1bHRTdGFja1N5bnRoZXNpemVyXFwnIChzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nkay9sYXRlc3QvZ3VpZGUvYm9vdHN0cmFwcGluZy5odG1sKScpO1xuICB9XG5cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGZvdW5kOiBib29sZWFuO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgYnVja2V0VXJsOiBzdHJpbmc7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBidWNrZXROYW1lOiBzdHJpbmc7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSB2ZXJzaW9uOiBudW1iZXI7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBib290c3RyYXBTdGFjazogQ2xvdWRGb3JtYXRpb25TdGFjaztcblxuICBwcml2YXRlIHJlYWRvbmx5IHNzbUNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgcmVhZG9ubHkgc2RrOiBJU0RLKSB7XG4gIH1cbiAgcHVibGljIGFic3RyYWN0IHZhbGlkYXRlVmVyc2lvbihleHBlY3RlZFZlcnNpb246IG51bWJlciwgc3NtUGFyYW1ldGVyTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogUHJvbWlzZTx2b2lkPjtcbiAgcHVibGljIGFic3RyYWN0IHByZXBhcmVFY3JSZXBvc2l0b3J5KHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcpOiBQcm9taXNlPEVjclJlcG9zaXRvcnlJbmZvPjtcblxuICAvKipcbiAgICogUmVhZCBhIHZlcnNpb24gZnJvbSBhbiBTU00gcGFyYW1ldGVyLCBjYWNoZWRcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyB2ZXJzaW9uRnJvbVNzbVBhcmFtZXRlcihwYXJhbWV0ZXJOYW1lOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5zc21DYWNoZS5nZXQocGFyYW1ldGVyTmFtZSk7XG4gICAgaWYgKGV4aXN0aW5nICE9PSB1bmRlZmluZWQpIHsgcmV0dXJuIGV4aXN0aW5nOyB9XG5cbiAgICBjb25zdCBzc20gPSB0aGlzLnNkay5zc20oKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzc20uZ2V0UGFyYW1ldGVyKHsgTmFtZTogcGFyYW1ldGVyTmFtZSB9KS5wcm9taXNlKCk7XG5cbiAgICAgIGNvbnN0IGFzTnVtYmVyID0gcGFyc2VJbnQoYCR7cmVzdWx0LlBhcmFtZXRlcj8uVmFsdWV9YCwgMTApO1xuICAgICAgaWYgKGlzTmFOKGFzTnVtYmVyKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFNTTSBwYXJhbWV0ZXIgJHtwYXJhbWV0ZXJOYW1lfSBub3QgYSBudW1iZXI6ICR7cmVzdWx0LlBhcmFtZXRlcj8uVmFsdWV9YCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc3NtQ2FjaGUuc2V0KHBhcmFtZXRlck5hbWUsIGFzTnVtYmVyKTtcbiAgICAgIHJldHVybiBhc051bWJlcjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlID09PSAnUGFyYW1ldGVyTm90Rm91bmQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgU1NNIHBhcmFtZXRlciAke3BhcmFtZXRlck5hbWV9IG5vdCBmb3VuZC4gSGFzIHRoZSBlbnZpcm9ubWVudCBiZWVuIGJvb3RzdHJhcHBlZD8gUGxlYXNlIHJ1biBcXCdjZGsgYm9vdHN0cmFwXFwnIChzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nkay9sYXRlc3QvZ3VpZGUvYm9vdHN0cmFwcGluZy5odG1sKWApO1xuICAgICAgfVxuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5lZCB3aGVuIGEgYm9vdHN0cmFwIHN0YWNrIGlzIGZvdW5kXG4gKi9cbmNsYXNzIEV4aXN0aW5nVG9vbGtpdEluZm8gZXh0ZW5kcyBUb29sa2l0SW5mbyB7XG4gIHB1YmxpYyByZWFkb25seSBmb3VuZCA9IHRydWU7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IGJvb3RzdHJhcFN0YWNrOiBDbG91ZEZvcm1hdGlvblN0YWNrLCBzZGs6IElTREspIHtcbiAgICBzdXBlcihzZGspO1xuICB9XG5cbiAgcHVibGljIGdldCBidWNrZXRVcmwoKSB7XG4gICAgcmV0dXJuIGBodHRwczovLyR7dGhpcy5yZXF1aXJlT3V0cHV0KEJVQ0tFVF9ET01BSU5fTkFNRV9PVVRQVVQpfWA7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJ1Y2tldE5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWlyZU91dHB1dChCVUNLRVRfTkFNRV9PVVRQVVQpO1xuICB9XG5cbiAgcHVibGljIGdldCB2ZXJzaW9uKCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLmJvb3RzdHJhcFN0YWNrLm91dHB1dHNbQk9PVFNUUkFQX1ZFUlNJT05fT1VUUFVUXSA/PyAnMCcsIDEwKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgcGFyYW1ldGVycygpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5ib290c3RyYXBTdGFjay5wYXJhbWV0ZXJzID8/IHt9O1xuICB9XG5cbiAgcHVibGljIGdldCB0ZXJtaW5hdGlvblByb3RlY3Rpb24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYm9vdHN0cmFwU3RhY2sudGVybWluYXRpb25Qcm90ZWN0aW9uID8/IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgdGhlIGJvb3RzdHJhcCBzdGFjayB2ZXJzaW9uIG1hdGNoZXMgb3IgZXhjZWVkcyB0aGUgZXhwZWN0ZWQgdmVyc2lvblxuICAgKlxuICAgKiBVc2UgdGhlIFNTTSBwYXJhbWV0ZXIgbmFtZSB0byByZWFkIHRoZSB2ZXJzaW9uIG51bWJlciBpZiBnaXZlbiwgb3RoZXJ3aXNlIHVzZSB0aGUgdmVyc2lvblxuICAgKiBkaXNjb3ZlcmVkIG9uIHRoZSBib290c3RyYXAgc3RhY2suXG4gICAqXG4gICAqIFBhc3MgaW4gdGhlIFNTTSBwYXJhbWV0ZXIgbmFtZSBzbyB3ZSBjYW4gY2FjaGUgdGhlIGxvb2t1cHMgYW4gZG9uJ3QgbmVlZCB0byBkbyB0aGUgc2FtZVxuICAgKiBsb29rdXAgYWdhaW4gYW5kIGFnYWluIGZvciBldmVyeSBhcnRpZmFjdC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB2YWxpZGF0ZVZlcnNpb24oZXhwZWN0ZWRWZXJzaW9uOiBudW1iZXIsIHNzbVBhcmFtZXRlck5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIGxldCB2ZXJzaW9uID0gdGhpcy52ZXJzaW9uOyAvLyBEZWZhdWx0IHRvIHRoZSBjdXJyZW50IHZlcnNpb24sIGJ1dCB3aWxsIGJlIG92ZXJ3cml0dGVuIGJ5IGEgbG9va3VwIGlmIHJlcXVpcmVkLlxuXG4gICAgaWYgKHNzbVBhcmFtZXRlck5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmVyc2lvbiA9IGF3YWl0IHRoaXMudmVyc2lvbkZyb21Tc21QYXJhbWV0ZXIoc3NtUGFyYW1ldGVyTmFtZSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChlLmNvZGUgIT09ICdBY2Nlc3NEZW5pZWRFeGNlcHRpb24nKSB7IHRocm93IGU7IH1cblxuICAgICAgICAvLyBUaGlzIGlzIGEgZmFsbGJhY2shIFRoZSBib290c3RyYXAgdGVtcGxhdGUgdGhhdCBnb2VzIGFsb25nIHdpdGggdGhpcyBjaGFuZ2UgaW50cm9kdWNlc1xuICAgICAgICAvLyBhIG5ldyAnc3NtOkdldFBhcmFtZXRlcicgcGVybWlzc2lvbiwgYnV0IHdoZW4gcnVuIHVzaW5nIHRoZSBwcmV2aW91cyBib290c3RyYXAgdGVtcGxhdGUgd2VcbiAgICAgICAgLy8gd29uJ3QgaGF2ZSB0aGUgcGVybWlzc2lvbnMgeWV0IHRvIHJlYWQgdGhlIHZlcnNpb24sIHNvIHdlIHdvbid0IGJlIGFibGUgdG8gc2hvdyB0aGVcbiAgICAgICAgLy8gbWVzc2FnZSB0ZWxsaW5nIHRoZSB1c2VyIHRoZXkgbmVlZCB0byB1cGRhdGUhIFdoZW4gd2Ugc2VlIGFuIEFjY2Vzc0RlbmllZEV4Y2VwdGlvbiwgZmFsbFxuICAgICAgICAvLyBiYWNrIHRvIHRoZSB2ZXJzaW9uIHdlIHJlYWQgZnJvbSBTdGFjayBPdXRwdXRzOyBidXQgT05MWSBpZiB0aGUgdmVyc2lvbiB3ZSBkaXNjb3ZlcmVkIHZpYVxuICAgICAgICAvLyBvdXRwdXRzIGlzIGxlZ2l0aW1hdGVseSBhbiBvbGQgdmVyc2lvbi4gSWYgaXQncyBuZXdlciB0aGFuIHRoYXQsIHNvbWV0aGluZyBlbHNlIG11c3QgYmUgYnJva2VuLFxuICAgICAgICAvLyBzbyBsZXQgaXQgZmFpbCBhcyBpdCB3b3VsZCBpZiB3ZSBkaWRuJ3QgaGF2ZSB0aGlzIGZhbGxiYWNrLlxuICAgICAgICBpZiAodGhpcy52ZXJzaW9uID49IEJPT1RTVFJBUF9URU1QTEFURV9WRVJTSU9OX0lOVFJPRFVDSU5HX0dFVFBBUkFNRVRFUikge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cblxuICAgICAgICB3YXJuaW5nKGBDb3VsZCBub3QgcmVhZCBTU00gcGFyYW1ldGVyICR7c3NtUGFyYW1ldGVyTmFtZX06ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgICAvLyBGYWxsIHRocm91Z2ggb24gcHVycG9zZVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChleHBlY3RlZFZlcnNpb24gPiB2ZXJzaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgQ0RLIGRlcGxveW1lbnQgcmVxdWlyZXMgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gJyR7ZXhwZWN0ZWRWZXJzaW9ufScsIGZvdW5kICcke3ZlcnNpb259Jy4gUGxlYXNlIHJ1biAnY2RrIGJvb3RzdHJhcCcuYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmUgYW4gRUNSIHJlcG9zaXRvcnkgZm9yIHVwbG9hZGluZyB0byB1c2luZyBEb2NrZXJcbiAgICpcbiAgICovXG4gIHB1YmxpYyBhc3luYyBwcmVwYXJlRWNyUmVwb3NpdG9yeShyZXBvc2l0b3J5TmFtZTogc3RyaW5nKTogUHJvbWlzZTxFY3JSZXBvc2l0b3J5SW5mbz4ge1xuICAgIGlmICghdGhpcy5zZGspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVG9vbGtpdEluZm8gbmVlZHMgdG8gaGF2ZSBiZWVuIGluaXRpYWxpemVkIHdpdGggYW4gc2RrIHRvIGNhbGwgcHJlcGFyZUVjclJlcG9zaXRvcnknKTtcbiAgICB9XG4gICAgY29uc3QgZWNyID0gdGhpcy5zZGsuZWNyKCk7XG5cbiAgICAvLyBjaGVjayBpZiByZXBvIGFscmVhZHkgZXhpc3RzXG4gICAgdHJ5IHtcbiAgICAgIGRlYnVnKGAke3JlcG9zaXRvcnlOYW1lfTogY2hlY2tpbmcgaWYgRUNSIHJlcG9zaXRvcnkgYWxyZWFkeSBleGlzdHNgKTtcbiAgICAgIGNvbnN0IGRlc2NyaWJlUmVzcG9uc2UgPSBhd2FpdCBlY3IuZGVzY3JpYmVSZXBvc2l0b3JpZXMoeyByZXBvc2l0b3J5TmFtZXM6IFtyZXBvc2l0b3J5TmFtZV0gfSkucHJvbWlzZSgpO1xuICAgICAgY29uc3QgZXhpc3RpbmdSZXBvc2l0b3J5VXJpID0gZGVzY3JpYmVSZXNwb25zZS5yZXBvc2l0b3JpZXMhWzBdPy5yZXBvc2l0b3J5VXJpO1xuICAgICAgaWYgKGV4aXN0aW5nUmVwb3NpdG9yeVVyaSkge1xuICAgICAgICByZXR1cm4geyByZXBvc2l0b3J5VXJpOiBleGlzdGluZ1JlcG9zaXRvcnlVcmkgfTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVwb3NpdG9yeU5vdEZvdW5kRXhjZXB0aW9uJykgeyB0aHJvdyBlOyB9XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIHRoZSByZXBvICh0YWcgaXQgc28gaXQgd2lsbCBiZSBlYXNpZXIgdG8gZ2FyYmFnZSBjb2xsZWN0IGluIHRoZSBmdXR1cmUpXG4gICAgZGVidWcoYCR7cmVwb3NpdG9yeU5hbWV9OiBjcmVhdGluZyBFQ1IgcmVwb3NpdG9yeWApO1xuICAgIGNvbnN0IGFzc2V0VGFnID0geyBLZXk6ICdhd3NjZGs6YXNzZXQnLCBWYWx1ZTogJ3RydWUnIH07XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBlY3IuY3JlYXRlUmVwb3NpdG9yeSh7IHJlcG9zaXRvcnlOYW1lLCB0YWdzOiBbYXNzZXRUYWddIH0pLnByb21pc2UoKTtcbiAgICBjb25zdCByZXBvc2l0b3J5VXJpID0gcmVzcG9uc2UucmVwb3NpdG9yeT8ucmVwb3NpdG9yeVVyaTtcbiAgICBpZiAoIXJlcG9zaXRvcnlVcmkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ3JlYXRlUmVwb3NpdG9yeSBkaWQgbm90IHJldHVybiBhIHJlcG9zaXRvcnkgVVJJIGZvciAke3JlcG9zaXRvcnlVcml9YCk7XG4gICAgfVxuXG4gICAgLy8gY29uZmlndXJlIGltYWdlIHNjYW5uaW5nIG9uIHB1c2ggKGhlbHBzIGluIGlkZW50aWZ5aW5nIHNvZnR3YXJlIHZ1bG5lcmFiaWxpdGllcywgbm8gYWRkaXRpb25hbCBjaGFyZ2UpXG4gICAgZGVidWcoYCR7cmVwb3NpdG9yeU5hbWV9OiBlbmFibGUgaW1hZ2Ugc2Nhbm5pbmdgKTtcbiAgICBhd2FpdCBlY3IucHV0SW1hZ2VTY2FubmluZ0NvbmZpZ3VyYXRpb24oeyByZXBvc2l0b3J5TmFtZSwgaW1hZ2VTY2FubmluZ0NvbmZpZ3VyYXRpb246IHsgc2Nhbk9uUHVzaDogdHJ1ZSB9IH0pLnByb21pc2UoKTtcblxuICAgIHJldHVybiB7IHJlcG9zaXRvcnlVcmkgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVxdWlyZU91dHB1dChvdXRwdXQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCEob3V0cHV0IGluIHRoaXMuYm9vdHN0cmFwU3RhY2sub3V0cHV0cykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlIENESyB0b29sa2l0IHN0YWNrICgke3RoaXMuYm9vdHN0cmFwU3RhY2suc3RhY2tOYW1lfSkgZG9lcyBub3QgaGF2ZSBhbiBvdXRwdXQgbmFtZWQgJHtvdXRwdXR9LiBVc2UgJ2NkayBib290c3RyYXAnIHRvIGNvcnJlY3QgdGhpcy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYm9vdHN0cmFwU3RhY2sub3V0cHV0c1tvdXRwdXRdO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJuZWQgd2hlbiBhIGJvb3RzdHJhcCBzdGFjayBjb3VsZCBub3QgYmUgZm91bmRcbiAqXG4gKiBUaGlzIGlzIG5vdCBhbiBlcnJvciBpbiBwcmluY2lwbGUsIFVOVElMIG9uZSBvZiB0aGUgbWVtYmVycyBpcyBjYWxsZWQgdGhhdCByZXF1aXJlc1xuICogdGhlIGJvb3RzdHJhcCBzdGFjayB0byBoYXZlIGJlZW4gZm91bmQsIGluIHdoaWNoIGNhc2UgdGhlIGxvb2t1cCBlcnJvciBpcyBzdGlsbCB0aHJvd25cbiAqIGJlbGF0ZWRseS5cbiAqXG4gKiBUaGUgZXJyb3JzIGJlbG93IHNlcnZlIGFzIGEgbGFzdCBzdG9wLWdhcCBtZXNzYWdlLS1ub3JtYWxseSBjYWxsaW5nIGNvZGUgc2hvdWxkIGhhdmVcbiAqIGNoZWNrZWQgYHRvb2xraXQuZm91bmRgIGFuZCBwcm9kdWNlZCBhbiBhcHByb3ByaWF0ZSBlcnJvciBtZXNzYWdlLlxuICovXG5jbGFzcyBCb290c3RyYXBTdGFja05vdEZvdW5kSW5mbyBleHRlbmRzIFRvb2xraXRJbmZvIHtcbiAgcHVibGljIHJlYWRvbmx5IGZvdW5kID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3Ioc2RrOiBJU0RLLCBwcml2YXRlIHJlYWRvbmx5IGVycm9yTWVzc2FnZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoc2RrKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYm9vdHN0cmFwU3RhY2soKTogQ2xvdWRGb3JtYXRpb25TdGFjayB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHRoaXMuZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYnVja2V0VXJsKCk6IHN0cmluZyB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHRoaXMuZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYnVja2V0TmFtZSgpOiBzdHJpbmcge1xuICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmVycm9yTWVzc2FnZSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHZlcnNpb24oKTogbnVtYmVyIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5lcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHZhbGlkYXRlVmVyc2lvbihleHBlY3RlZFZlcnNpb246IG51bWJlciwgc3NtUGFyYW1ldGVyTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHNzbVBhcmFtZXRlck5hbWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMuZXJyb3JNZXNzYWdlKTtcbiAgICB9XG5cbiAgICBsZXQgdmVyc2lvbjogbnVtYmVyO1xuICAgIHRyeSB7XG4gICAgICB2ZXJzaW9uID0gYXdhaXQgdGhpcy52ZXJzaW9uRnJvbVNzbVBhcmFtZXRlcihzc21QYXJhbWV0ZXJOYW1lKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnQWNjZXNzRGVuaWVkRXhjZXB0aW9uJykgeyB0aHJvdyBlOyB9XG5cbiAgICAgIC8vIFRoaXMgaXMgYSBmYWxsYmFjayEgVGhlIGJvb3RzdHJhcCB0ZW1wbGF0ZSB0aGF0IGdvZXMgYWxvbmcgd2l0aCB0aGlzIGNoYW5nZSBpbnRyb2R1Y2VzXG4gICAgICAvLyBhIG5ldyAnc3NtOkdldFBhcmFtZXRlcicgcGVybWlzc2lvbiwgYnV0IHdoZW4gcnVuIHVzaW5nIGEgcHJldmlvdXMgYm9vdHN0cmFwIHRlbXBsYXRlIHdlXG4gICAgICAvLyB3b24ndCBoYXZlIHRoZSBwZXJtaXNzaW9ucyB5ZXQgdG8gcmVhZCB0aGUgdmVyc2lvbiwgc28gd2Ugd29uJ3QgYmUgYWJsZSB0byBzaG93IHRoZVxuICAgICAgLy8gbWVzc2FnZSB0ZWxsaW5nIHRoZSB1c2VyIHRoZXkgbmVlZCB0byB1cGRhdGUhIFdoZW4gd2Ugc2VlIGFuIEFjY2Vzc0RlbmllZEV4Y2VwdGlvbiwgZmFsbFxuICAgICAgLy8gYmFjayB0byB0aGUgdmVyc2lvbiB3ZSByZWFkIGZyb20gU3RhY2sgT3V0cHV0cy5cbiAgICAgIHdhcm5pbmcoYENvdWxkIG5vdCByZWFkIFNTTSBwYXJhbWV0ZXIgJHtzc21QYXJhbWV0ZXJOYW1lfTogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgQ0RLIGRlcGxveW1lbnQgcmVxdWlyZXMgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gJyR7ZXhwZWN0ZWRWZXJzaW9ufScsIGZvdW5kIGFuIG9sZGVyIHZlcnNpb24uIFBsZWFzZSBydW4gJ2NkayBib290c3RyYXAnLmApO1xuICAgIH1cblxuICAgIGlmIChleHBlY3RlZFZlcnNpb24gPiB2ZXJzaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgQ0RLIGRlcGxveW1lbnQgcmVxdWlyZXMgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gJyR7ZXhwZWN0ZWRWZXJzaW9ufScsIGZvdW5kICcke3ZlcnNpb259Jy4gUGxlYXNlIHJ1biAnY2RrIGJvb3RzdHJhcCcuYCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHByZXBhcmVFY3JSZXBvc2l0b3J5KCk6IFByb21pc2U8RWNyUmVwb3NpdG9yeUluZm8+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5lcnJvck1lc3NhZ2UpO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWNyUmVwb3NpdG9yeUluZm8ge1xuICByZXBvc2l0b3J5VXJpOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWNyQ3JlZGVudGlhbHMge1xuICB1c2VybmFtZTogc3RyaW5nO1xuICBwYXNzd29yZDogc3RyaW5nO1xuICBlbmRwb2ludDogc3RyaW5nO1xufSJdfQ==
|
|
259
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbGtpdC1pbmZvLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidG9vbGtpdC1pbmZvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLCtCQUErQjtBQUMvQix3Q0FBNEM7QUFFNUMsMkNBQXNHO0FBQ3RHLDBEQUE0RTtBQUUvRCxRQUFBLDBCQUEwQixHQUFHLFlBQVksQ0FBQztBQUV2RDs7R0FFRztBQUNILE1BQU0sbURBQW1ELEdBQUcsQ0FBQyxDQUFDO0FBRTlEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBQ0gsTUFBc0IsV0FBVztJQXFFL0IsWUFBK0IsR0FBUztRQUFULFFBQUcsR0FBSCxHQUFHLENBQU07UUFQckIsYUFBUSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBUXhELENBQUM7SUFyRU0sTUFBTSxDQUFDLGFBQWEsQ0FBQyxZQUFxQjtRQUMvQyxPQUFPLFlBQVksYUFBWixZQUFZLGNBQVosWUFBWSxHQUFJLGtDQUEwQixDQUFDO0lBQ3BELENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUE4QixFQUFFLEdBQVMsRUFBRSxTQUE2QjtRQUNqRyxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDakMsTUFBTSxLQUFLLEdBQUcsTUFBTSwrQkFBYyxDQUFDLEdBQUcsRUFBRSxTQUFTLGFBQVQsU0FBUyxjQUFULFNBQVMsR0FBSSxrQ0FBMEIsQ0FBQyxDQUFDO1FBQ2pGLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixlQUFLLENBQUMsbUlBQW1JLEVBQ3ZJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsa0JBQWtCLFdBQVcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDbEYsT0FBTyxXQUFXLENBQUMsMEJBQTBCLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDcEQ7UUFDRCxJQUFJLEtBQUssQ0FBQyxXQUFX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SUFDckMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCB7IGRlYnVnLCB3YXJuaW5nIH0gZnJvbSAnLi4vbG9nZ2luZyc7XG5pbXBvcnQgeyBJU0RLIH0gZnJvbSAnLi9hd3MtYXV0aCc7XG5pbXBvcnQgeyBCT09UU1RSQVBfVkVSU0lPTl9PVVRQVVQsIEJVQ0tFVF9ET01BSU5fTkFNRV9PVVRQVVQsIEJVQ0tFVF9OQU1FX09VVFBVVCB9IGZyb20gJy4vYm9vdHN0cmFwJztcbmltcG9ydCB7IHN0YWJpbGl6ZVN0YWNrLCBDbG91ZEZvcm1hdGlvblN0YWNrIH0gZnJvbSAnLi91dGlsL2Nsb3VkZm9ybWF0aW9uJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FID0gJ0NES1Rvb2xraXQnO1xuXG4vKipcbiAqIFRoZSBib290c3RyYXAgdGVtcGxhdGUgdmVyc2lvbiB0aGF0IGludHJvZHVjZWQgc3NtOkdldFBhcmFtZXRlclxuICovXG5jb25zdCBCT09UU1RSQVBfVEVNUExBVEVfVkVSU0lPTl9JTlRST0RVQ0lOR19HRVRQQVJBTUVURVIgPSA1O1xuXG4vKipcbiAqIEluZm9ybWF0aW9uIG9uIHRoZSBCb290c3RyYXAgc3RhY2sgb2YgdGhlIGVudmlyb25tZW50IHdlJ3JlIGRlcGxveWluZyB0by5cbiAqXG4gKiBUaGlzIGNsYXNzIHNlcnZlcyB0bzpcbiAqXG4gKiAtIEluc3BlY3QgdGhlIGJvb3RzdHJhcCBzdGFjaywgYW5kIHJldHVybiB2YXJpb3VzIHByb3BlcnRpZXMgb2YgaXQgZm9yIHN1Y2Nlc3NmdWxcbiAqICAgYXNzZXQgZGVwbG95bWVudCAoaW4gY2FzZSBvZiBsZWdhY3ktc3ludGhlc2l6ZWQgc3RhY2tzKS5cbiAqIC0gVmFsaWRhdGUgdGhlIHZlcnNpb24gb2YgdGhlIHRhcmdldCBlbnZpcm9ubWVudCwgYW5kIG5vdGhpbmcgZWxzZSAoaW4gY2FzZSBvZlxuICogICBkZWZhdWx0LXN5bnRoZXNpemVkIHN0YWNrcykuXG4gKlxuICogQW4gb2JqZWN0IG9mIHRoaXMgdHlwZSBtaWdodCByZXByZXNlbnQgYSBib290c3RyYXAgc3RhY2sgdGhhdCBjb3VsZCBub3QgYmUgZm91bmQuXG4gKiBUaGlzIGlzIG5vdCBhbiBpc3N1ZSB1bmxlc3MgYW55IG1lbWJlcnMgYXJlIHVzZWQgdGhhdCByZXF1aXJlIHRoZSBib290c3RyYXAgc3RhY2tcbiAqIHRvIGhhdmUgYmVlbiBmb3VuZCwgaW4gd2hpY2ggY2FzZSBhbiBlcnJvciBpcyB0aHJvd24gKGRlZmF1bHQtc3ludGhlc2l6ZWQgc3RhY2tzXG4gKiBzaG91bGQgbmV2ZXIgcnVuIGludG8gdGhpcyBhcyB0aGV5IGRvbid0IG5lZWQgaW5mb3JtYXRpb24gZnJvbSB0aGUgYm9vdHN0cmFwXG4gKiBzdGFjaywgYWxsIGluZm9ybWF0aW9uIGlzIGFscmVhZHkgZW5jb2RlZCBpbnRvIHRoZSBDbG91ZCBBc3NlbWJseSBNYW5pZmVzdCkuXG4gKlxuICogTmV2ZXJ0aGVsZXNzLCBhbiBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzIGV4aXN0cyB0byBzZXJ2ZSBhcyBhIGNhY2hlIGZvciBTU01cbiAqIHBhcmFtZXRlciBsb29rdXBzIChvdGhlcndpc2UsIHRoZSBcImJvb3RzdHJhcCBzdGFjayB2ZXJzaW9uXCIgcGFyYW1ldGVyIHdvdWxkXG4gKiBuZWVkIHRvIGJlIHJlYWQgcmVwZWF0ZWRseSkuXG4gKlxuICogQ2FsbGVkIFwiVG9vbGtpdEluZm9cIiBmb3IgaGlzdG9yaWNhbCByZWFzb25zLlxuICpcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFRvb2xraXRJbmZvIHtcbiAgcHVibGljIHN0YXRpYyBkZXRlcm1pbmVOYW1lKG92ZXJyaWRlTmFtZT86IHN0cmluZykge1xuICAgIHJldHVybiBvdmVycmlkZU5hbWUgPz8gREVGQVVMVF9UT09MS0lUX1NUQUNLX05BTUU7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGFzeW5jIGxvb2t1cChlbnZpcm9ubWVudDogY3hhcGkuRW52aXJvbm1lbnQsIHNkazogSVNESywgc3RhY2tOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPFRvb2xraXRJbmZvPiB7XG4gICAgY29uc3QgY2ZuID0gc2RrLmNsb3VkRm9ybWF0aW9uKCk7XG4gICAgY29uc3Qgc3RhY2sgPSBhd2FpdCBzdGFiaWxpemVTdGFjayhjZm4sIHN0YWNrTmFtZSA/PyBERUZBVUxUX1RPT0xLSVRfU1RBQ0tfTkFNRSk7XG4gICAgaWYgKCFzdGFjaykge1xuICAgICAgZGVidWcoJ1RoZSBlbnZpcm9ubWVudCAlcyBkb2VzblxcJ3QgaGF2ZSB0aGUgQ0RLIHRvb2xraXQgc3RhY2sgKCVzKSBpbnN0YWxsZWQuIFVzZSAlcyB0byBzZXR1cCB5b3VyIGVudmlyb25tZW50IGZvciB1c2Ugd2l0aCB0aGUgdG9vbGtpdC4nLFxuICAgICAgICBlbnZpcm9ubWVudC5uYW1lLCBzdGFja05hbWUsIGNoYWxrLmJsdWUoYGNkayBib290c3RyYXAgXCIke2Vudmlyb25tZW50Lm5hbWV9XCJgKSk7XG4gICAgICByZXR1cm4gVG9vbGtpdEluZm8uYm9vdHN0cmFwU3RhY2tOb3RGb3VuZEluZm8oc2RrKTtcbiAgICB9XG4gICAgaWYgKHN0YWNrLnN0YWNrU3RhdHVzLmlzQ3JlYXRpb25GYWlsdXJlKSB7XG4gICAgICAvLyBUcmVhdCBhIFwiZmFpbGVkIHRvIGNyZWF0ZVwiIGJvb3RzdHJhcCBzdGFjayBhcyBhbiBhYnNlbnQgb25lLlxuICAgICAgZGVidWcoJ1RoZSBlbnZpcm9ubWVudCAlcyBoYXMgYSBDREsgdG9vbGtpdCBzdGFjayAoJXMpIHRoYXQgZmFpbGVkIHRvIGNyZWF0ZS4gVXNlICVzIHRvIHRyeSBwcm92aXNpb25pbmcgaXQgYWdhaW4uJyxcbiAgICAgICAgZW52aXJvbm1lbnQubmFtZSwgc3RhY2tOYW1lLCBjaGFsay5ibHVlKGBjZGsgYm9vdHN0cmFwIFwiJHtlbnZpcm9ubWVudC5uYW1lfVwiYCkpO1xuICAgICAgcmV0dXJuIFRvb2xraXRJbmZvLmJvb3RzdHJhcFN0YWNrTm90Rm91bmRJbmZvKHNkayk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBFeGlzdGluZ1Rvb2xraXRJbmZvKHN0YWNrLCBzZGspO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBmcm9tU3RhY2soc3RhY2s6IENsb3VkRm9ybWF0aW9uU3RhY2ssIHNkazogSVNESyk6IFRvb2xraXRJbmZvIHtcbiAgICByZXR1cm4gbmV3IEV4aXN0aW5nVG9vbGtpdEluZm8oc3RhY2ssIHNkayk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGJvb3RzdHJhcGxlc3NEZXBsb3ltZW50c09ubHkoc2RrOiBJU0RLKTogVG9vbGtpdEluZm8ge1xuICAgIHJldHVybiBuZXcgQm9vdHN0cmFwU3RhY2tOb3RGb3VuZEluZm8oc2RrLCAnVHJ5aW5nIHRvIHBlcmZvcm0gYW4gb3BlcmF0aW9uIHRoYXQgcmVxdWlyZXMgYSBib290c3RyYXAgc3RhY2s7IHlvdSBzaG91bGQgbm90IHNlZSB0aGlzIGVycm9yLCB0aGlzIGlzIGEgYnVnIGluIHRoZSBDREsgQ0xJLicpO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBib290c3RyYXBTdGFja05vdEZvdW5kSW5mbyhzZGs6IElTREspOiBUb29sa2l0SW5mbyB7XG4gICAgcmV0dXJuIG5ldyBCb290c3RyYXBTdGFja05vdEZvdW5kSW5mbyhzZGssICdUaGlzIGRlcGxveW1lbnQgcmVxdWlyZXMgYSBib290c3RyYXAgc3RhY2sgd2l0aCBhIGtub3duIG5hbWU7IHBhc3MgXFwnLS10b29sa2l0LXN0YWNrLW5hbWVcXCcgb3Igc3dpdGNoIHRvIHVzaW5nIHRoZSBcXCdEZWZhdWx0U3RhY2tTeW50aGVzaXplclxcJyAoc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jZGsvbGF0ZXN0L2d1aWRlL2Jvb3RzdHJhcHBpbmcuaHRtbCknKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkIGEgdmVyc2lvbiBmcm9tIGFuIFNTTSBwYXJhbWV0ZXIsIGNhY2hlZFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhc3luYyB2ZXJzaW9uRnJvbVNzbVBhcmFtZXRlcihzZGs6IElTREssIHBhcmFtZXRlck5hbWU6IHN0cmluZywgc3NtQ2FjaGU/OiBNYXA8c3RyaW5nLCBudW1iZXI+KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBleGlzdGluZyA9IHNzbUNhY2hlPy5nZXQocGFyYW1ldGVyTmFtZSk7XG4gICAgaWYgKGV4aXN0aW5nICE9PSB1bmRlZmluZWQpIHsgcmV0dXJuIGV4aXN0aW5nOyB9XG5cbiAgICBjb25zdCBzc20gPSBzZGsuc3NtKCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3NtLmdldFBhcmFtZXRlcih7IE5hbWU6IHBhcmFtZXRlck5hbWUgfSkucHJvbWlzZSgpO1xuXG4gICAgICBjb25zdCBhc051bWJlciA9IHBhcnNlSW50KGAke3Jlc3VsdC5QYXJhbWV0ZXI/LlZhbHVlfWAsIDEwKTtcbiAgICAgIGlmIChpc05hTihhc051bWJlcikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTU00gcGFyYW1ldGVyICR7cGFyYW1ldGVyTmFtZX0gbm90IGEgbnVtYmVyOiAke3Jlc3VsdC5QYXJhbWV0ZXI/LlZhbHVlfWApO1xuICAgICAgfVxuXG4gICAgICBzc21DYWNoZT8uc2V0KHBhcmFtZXRlck5hbWUsIGFzTnVtYmVyKTtcbiAgICAgIHJldHVybiBhc051bWJlcjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlID09PSAnUGFyYW1ldGVyTm90Rm91bmQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgU1NNIHBhcmFtZXRlciAke3BhcmFtZXRlck5hbWV9IG5vdCBmb3VuZC4gSGFzIHRoZSBlbnZpcm9ubWVudCBiZWVuIGJvb3RzdHJhcHBlZD8gUGxlYXNlIHJ1biBcXCdjZGsgYm9vdHN0cmFwXFwnIChzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nkay9sYXRlc3QvZ3VpZGUvYm9vdHN0cmFwcGluZy5odG1sKWApO1xuICAgICAgfVxuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc3NtQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgZm91bmQ6IGJvb2xlYW47XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBidWNrZXRVcmw6IHN0cmluZztcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGJ1Y2tldE5hbWU6IHN0cmluZztcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHZlcnNpb246IG51bWJlcjtcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGJvb3RzdHJhcFN0YWNrOiBDbG91ZEZvcm1hdGlvblN0YWNrO1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCByZWFkb25seSBzZGs6IElTREspIHtcbiAgfVxuICBwdWJsaWMgYWJzdHJhY3QgdmFsaWRhdGVWZXJzaW9uKGV4cGVjdGVkVmVyc2lvbjogbnVtYmVyLCBzc21QYXJhbWV0ZXJOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPHZvaWQ+O1xuICBwdWJsaWMgYWJzdHJhY3QgcHJlcGFyZUVjclJlcG9zaXRvcnkocmVwb3NpdG9yeU5hbWU6IHN0cmluZyk6IFByb21pc2U8RWNyUmVwb3NpdG9yeUluZm8+O1xufVxuXG4vKipcbiAqIFJldHVybmVkIHdoZW4gYSBib290c3RyYXAgc3RhY2sgaXMgZm91bmRcbiAqL1xuY2xhc3MgRXhpc3RpbmdUb29sa2l0SW5mbyBleHRlbmRzIFRvb2xraXRJbmZvIHtcbiAgcHVibGljIHJlYWRvbmx5IGZvdW5kID0gdHJ1ZTtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgYm9vdHN0cmFwU3RhY2s6IENsb3VkRm9ybWF0aW9uU3RhY2ssIHNkazogSVNESykge1xuICAgIHN1cGVyKHNkayk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJ1Y2tldFVybCgpIHtcbiAgICByZXR1cm4gYGh0dHBzOi8vJHt0aGlzLnJlcXVpcmVPdXRwdXQoQlVDS0VUX0RPTUFJTl9OQU1FX09VVFBVVCl9YDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYnVja2V0TmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5yZXF1aXJlT3V0cHV0KEJVQ0tFVF9OQU1FX09VVFBVVCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHZlcnNpb24oKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuYm9vdHN0cmFwU3RhY2sub3V0cHV0c1tCT09UU1RSQVBfVkVSU0lPTl9PVVRQVVRdID8/ICcwJywgMTApO1xuICB9XG5cbiAgcHVibGljIGdldCBwYXJhbWV0ZXJzKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLmJvb3RzdHJhcFN0YWNrLnBhcmFtZXRlcnMgPz8ge307XG4gIH1cblxuICBwdWJsaWMgZ2V0IHRlcm1pbmF0aW9uUHJvdGVjdGlvbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5ib290c3RyYXBTdGFjay50ZXJtaW5hdGlvblByb3RlY3Rpb24gPz8gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCB0aGUgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gbWF0Y2hlcyBvciBleGNlZWRzIHRoZSBleHBlY3RlZCB2ZXJzaW9uXG4gICAqXG4gICAqIFVzZSB0aGUgU1NNIHBhcmFtZXRlciBuYW1lIHRvIHJlYWQgdGhlIHZlcnNpb24gbnVtYmVyIGlmIGdpdmVuLCBvdGhlcndpc2UgdXNlIHRoZSB2ZXJzaW9uXG4gICAqIGRpc2NvdmVyZWQgb24gdGhlIGJvb3RzdHJhcCBzdGFjay5cbiAgICpcbiAgICogUGFzcyBpbiB0aGUgU1NNIHBhcmFtZXRlciBuYW1lIHNvIHdlIGNhbiBjYWNoZSB0aGUgbG9va3VwcyBhbiBkb24ndCBuZWVkIHRvIGRvIHRoZSBzYW1lXG4gICAqIGxvb2t1cCBhZ2FpbiBhbmQgYWdhaW4gZm9yIGV2ZXJ5IGFydGlmYWN0LlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHZhbGlkYXRlVmVyc2lvbihleHBlY3RlZFZlcnNpb246IG51bWJlciwgc3NtUGFyYW1ldGVyTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgbGV0IHZlcnNpb24gPSB0aGlzLnZlcnNpb247IC8vIERlZmF1bHQgdG8gdGhlIGN1cnJlbnQgdmVyc2lvbiwgYnV0IHdpbGwgYmUgb3ZlcndyaXR0ZW4gYnkgYSBsb29rdXAgaWYgcmVxdWlyZWQuXG5cbiAgICBpZiAoc3NtUGFyYW1ldGVyTmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2ZXJzaW9uID0gYXdhaXQgVG9vbGtpdEluZm8udmVyc2lvbkZyb21Tc21QYXJhbWV0ZXIodGhpcy5zZGssIHNzbVBhcmFtZXRlck5hbWUsIHRoaXMuc3NtQ2FjaGUpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZS5jb2RlICE9PSAnQWNjZXNzRGVuaWVkRXhjZXB0aW9uJykgeyB0aHJvdyBlOyB9XG5cbiAgICAgICAgLy8gVGhpcyBpcyBhIGZhbGxiYWNrISBUaGUgYm9vdHN0cmFwIHRlbXBsYXRlIHRoYXQgZ29lcyBhbG9uZyB3aXRoIHRoaXMgY2hhbmdlIGludHJvZHVjZXNcbiAgICAgICAgLy8gYSBuZXcgJ3NzbTpHZXRQYXJhbWV0ZXInIHBlcm1pc3Npb24sIGJ1dCB3aGVuIHJ1biB1c2luZyB0aGUgcHJldmlvdXMgYm9vdHN0cmFwIHRlbXBsYXRlIHdlXG4gICAgICAgIC8vIHdvbid0IGhhdmUgdGhlIHBlcm1pc3Npb25zIHlldCB0byByZWFkIHRoZSB2ZXJzaW9uLCBzbyB3ZSB3b24ndCBiZSBhYmxlIHRvIHNob3cgdGhlXG4gICAgICAgIC8vIG1lc3NhZ2UgdGVsbGluZyB0aGUgdXNlciB0aGV5IG5lZWQgdG8gdXBkYXRlISBXaGVuIHdlIHNlZSBhbiBBY2Nlc3NEZW5pZWRFeGNlcHRpb24sIGZhbGxcbiAgICAgICAgLy8gYmFjayB0byB0aGUgdmVyc2lvbiB3ZSByZWFkIGZyb20gU3RhY2sgT3V0cHV0czsgYnV0IE9OTFkgaWYgdGhlIHZlcnNpb24gd2UgZGlzY292ZXJlZCB2aWFcbiAgICAgICAgLy8gb3V0cHV0cyBpcyBsZWdpdGltYXRlbHkgYW4gb2xkIHZlcnNpb24uIElmIGl0J3MgbmV3ZXIgdGhhbiB0aGF0LCBzb21ldGhpbmcgZWxzZSBtdXN0IGJlIGJyb2tlbixcbiAgICAgICAgLy8gc28gbGV0IGl0IGZhaWwgYXMgaXQgd291bGQgaWYgd2UgZGlkbid0IGhhdmUgdGhpcyBmYWxsYmFjay5cbiAgICAgICAgaWYgKHRoaXMudmVyc2lvbiA+PSBCT09UU1RSQVBfVEVNUExBVEVfVkVSU0lPTl9JTlRST0RVQ0lOR19HRVRQQVJBTUVURVIpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG5cbiAgICAgICAgd2FybmluZyhgQ291bGQgbm90IHJlYWQgU1NNIHBhcmFtZXRlciAke3NzbVBhcmFtZXRlck5hbWV9OiAke2UubWVzc2FnZX1gKTtcbiAgICAgICAgLy8gRmFsbCB0aHJvdWdoIG9uIHB1cnBvc2VcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXhwZWN0ZWRWZXJzaW9uID4gdmVyc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGlzIENESyBkZXBsb3ltZW50IHJlcXVpcmVzIGJvb3RzdHJhcCBzdGFjayB2ZXJzaW9uICcke2V4cGVjdGVkVmVyc2lvbn0nLCBmb3VuZCAnJHt2ZXJzaW9ufScuIFBsZWFzZSBydW4gJ2NkayBib290c3RyYXAnLmApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwYXJlIGFuIEVDUiByZXBvc2l0b3J5IGZvciB1cGxvYWRpbmcgdG8gdXNpbmcgRG9ja2VyXG4gICAqXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcHJlcGFyZUVjclJlcG9zaXRvcnkocmVwb3NpdG9yeU5hbWU6IHN0cmluZyk6IFByb21pc2U8RWNyUmVwb3NpdG9yeUluZm8+IHtcbiAgICBpZiAoIXRoaXMuc2RrKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Rvb2xraXRJbmZvIG5lZWRzIHRvIGhhdmUgYmVlbiBpbml0aWFsaXplZCB3aXRoIGFuIHNkayB0byBjYWxsIHByZXBhcmVFY3JSZXBvc2l0b3J5Jyk7XG4gICAgfVxuICAgIGNvbnN0IGVjciA9IHRoaXMuc2RrLmVjcigpO1xuXG4gICAgLy8gY2hlY2sgaWYgcmVwbyBhbHJlYWR5IGV4aXN0c1xuICAgIHRyeSB7XG4gICAgICBkZWJ1ZyhgJHtyZXBvc2l0b3J5TmFtZX06IGNoZWNraW5nIGlmIEVDUiByZXBvc2l0b3J5IGFscmVhZHkgZXhpc3RzYCk7XG4gICAgICBjb25zdCBkZXNjcmliZVJlc3BvbnNlID0gYXdhaXQgZWNyLmRlc2NyaWJlUmVwb3NpdG9yaWVzKHsgcmVwb3NpdG9yeU5hbWVzOiBbcmVwb3NpdG9yeU5hbWVdIH0pLnByb21pc2UoKTtcbiAgICAgIGNvbnN0IGV4aXN0aW5nUmVwb3NpdG9yeVVyaSA9IGRlc2NyaWJlUmVzcG9uc2UucmVwb3NpdG9yaWVzIVswXT8ucmVwb3NpdG9yeVVyaTtcbiAgICAgIGlmIChleGlzdGluZ1JlcG9zaXRvcnlVcmkpIHtcbiAgICAgICAgcmV0dXJuIHsgcmVwb3NpdG9yeVVyaTogZXhpc3RpbmdSZXBvc2l0b3J5VXJpIH07XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSAhPT0gJ1JlcG9zaXRvcnlOb3RGb3VuZEV4Y2VwdGlvbicpIHsgdGhyb3cgZTsgfVxuICAgIH1cblxuICAgIC8vIGNyZWF0ZSB0aGUgcmVwbyAodGFnIGl0IHNvIGl0IHdpbGwgYmUgZWFzaWVyIHRvIGdhcmJhZ2UgY29sbGVjdCBpbiB0aGUgZnV0dXJlKVxuICAgIGRlYnVnKGAke3JlcG9zaXRvcnlOYW1lfTogY3JlYXRpbmcgRUNSIHJlcG9zaXRvcnlgKTtcbiAgICBjb25zdCBhc3NldFRhZyA9IHsgS2V5OiAnYXdzY2RrOmFzc2V0JywgVmFsdWU6ICd0cnVlJyB9O1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZWNyLmNyZWF0ZVJlcG9zaXRvcnkoeyByZXBvc2l0b3J5TmFtZSwgdGFnczogW2Fzc2V0VGFnXSB9KS5wcm9taXNlKCk7XG4gICAgY29uc3QgcmVwb3NpdG9yeVVyaSA9IHJlc3BvbnNlLnJlcG9zaXRvcnk/LnJlcG9zaXRvcnlVcmk7XG4gICAgaWYgKCFyZXBvc2l0b3J5VXJpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENyZWF0ZVJlcG9zaXRvcnkgZGlkIG5vdCByZXR1cm4gYSByZXBvc2l0b3J5IFVSSSBmb3IgJHtyZXBvc2l0b3J5VXJpfWApO1xuICAgIH1cblxuICAgIC8vIGNvbmZpZ3VyZSBpbWFnZSBzY2FubmluZyBvbiBwdXNoIChoZWxwcyBpbiBpZGVudGlmeWluZyBzb2Z0d2FyZSB2dWxuZXJhYmlsaXRpZXMsIG5vIGFkZGl0aW9uYWwgY2hhcmdlKVxuICAgIGRlYnVnKGAke3JlcG9zaXRvcnlOYW1lfTogZW5hYmxlIGltYWdlIHNjYW5uaW5nYCk7XG4gICAgYXdhaXQgZWNyLnB1dEltYWdlU2Nhbm5pbmdDb25maWd1cmF0aW9uKHsgcmVwb3NpdG9yeU5hbWUsIGltYWdlU2Nhbm5pbmdDb25maWd1cmF0aW9uOiB7IHNjYW5PblB1c2g6IHRydWUgfSB9KS5wcm9taXNlKCk7XG5cbiAgICByZXR1cm4geyByZXBvc2l0b3J5VXJpIH07XG4gIH1cblxuICBwcml2YXRlIHJlcXVpcmVPdXRwdXQob3V0cHV0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICghKG91dHB1dCBpbiB0aGlzLmJvb3RzdHJhcFN0YWNrLm91dHB1dHMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBDREsgdG9vbGtpdCBzdGFjayAoJHt0aGlzLmJvb3RzdHJhcFN0YWNrLnN0YWNrTmFtZX0pIGRvZXMgbm90IGhhdmUgYW4gb3V0cHV0IG5hbWVkICR7b3V0cHV0fS4gVXNlICdjZGsgYm9vdHN0cmFwJyB0byBjb3JyZWN0IHRoaXMuYCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmJvb3RzdHJhcFN0YWNrLm91dHB1dHNbb3V0cHV0XTtcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybmVkIHdoZW4gYSBib290c3RyYXAgc3RhY2sgY291bGQgbm90IGJlIGZvdW5kXG4gKlxuICogVGhpcyBpcyBub3QgYW4gZXJyb3IgaW4gcHJpbmNpcGxlLCBVTlRJTCBvbmUgb2YgdGhlIG1lbWJlcnMgaXMgY2FsbGVkIHRoYXQgcmVxdWlyZXNcbiAqIHRoZSBib290c3RyYXAgc3RhY2sgdG8gaGF2ZSBiZWVuIGZvdW5kLCBpbiB3aGljaCBjYXNlIHRoZSBsb29rdXAgZXJyb3IgaXMgc3RpbGwgdGhyb3duXG4gKiBiZWxhdGVkbHkuXG4gKlxuICogVGhlIGVycm9ycyBiZWxvdyBzZXJ2ZSBhcyBhIGxhc3Qgc3RvcC1nYXAgbWVzc2FnZS0tbm9ybWFsbHkgY2FsbGluZyBjb2RlIHNob3VsZCBoYXZlXG4gKiBjaGVja2VkIGB0b29sa2l0LmZvdW5kYCBhbmQgcHJvZHVjZWQgYW4gYXBwcm9wcmlhdGUgZXJyb3IgbWVzc2FnZS5cbiAqL1xuY2xhc3MgQm9vdHN0cmFwU3RhY2tOb3RGb3VuZEluZm8gZXh0ZW5kcyBUb29sa2l0SW5mbyB7XG4gIHB1YmxpYyByZWFkb25seSBmb3VuZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHNkazogSVNESywgcHJpdmF0ZSByZWFkb25seSBlcnJvck1lc3NhZ2U6IHN0cmluZykge1xuICAgIHN1cGVyKHNkayk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJvb3RzdHJhcFN0YWNrKCk6IENsb3VkRm9ybWF0aW9uU3RhY2sge1xuICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmVycm9yTWVzc2FnZSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJ1Y2tldFVybCgpOiBzdHJpbmcge1xuICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmVycm9yTWVzc2FnZSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJ1Y2tldE5hbWUoKTogc3RyaW5nIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5lcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgcHVibGljIGdldCB2ZXJzaW9uKCk6IG51bWJlciB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHRoaXMuZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyB2YWxpZGF0ZVZlcnNpb24oZXhwZWN0ZWRWZXJzaW9uOiBudW1iZXIsIHNzbVBhcmFtZXRlck5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChzc21QYXJhbWV0ZXJOYW1lID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLmVycm9yTWVzc2FnZSk7XG4gICAgfVxuXG4gICAgbGV0IHZlcnNpb246IG51bWJlcjtcbiAgICB0cnkge1xuICAgICAgdmVyc2lvbiA9IGF3YWl0IFRvb2xraXRJbmZvLnZlcnNpb25Gcm9tU3NtUGFyYW1ldGVyKHRoaXMuc2RrLCBzc21QYXJhbWV0ZXJOYW1lLCB0aGlzLnNzbUNhY2hlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnQWNjZXNzRGVuaWVkRXhjZXB0aW9uJykgeyB0aHJvdyBlOyB9XG5cbiAgICAgIC8vIFRoaXMgaXMgYSBmYWxsYmFjayEgVGhlIGJvb3RzdHJhcCB0ZW1wbGF0ZSB0aGF0IGdvZXMgYWxvbmcgd2l0aCB0aGlzIGNoYW5nZSBpbnRyb2R1Y2VzXG4gICAgICAvLyBhIG5ldyAnc3NtOkdldFBhcmFtZXRlcicgcGVybWlzc2lvbiwgYnV0IHdoZW4gcnVuIHVzaW5nIGEgcHJldmlvdXMgYm9vdHN0cmFwIHRlbXBsYXRlIHdlXG4gICAgICAvLyB3b24ndCBoYXZlIHRoZSBwZXJtaXNzaW9ucyB5ZXQgdG8gcmVhZCB0aGUgdmVyc2lvbiwgc28gd2Ugd29uJ3QgYmUgYWJsZSB0byBzaG93IHRoZVxuICAgICAgLy8gbWVzc2FnZSB0ZWxsaW5nIHRoZSB1c2VyIHRoZXkgbmVlZCB0byB1cGRhdGUhIFdoZW4gd2Ugc2VlIGFuIEFjY2Vzc0RlbmllZEV4Y2VwdGlvbiwgZmFsbFxuICAgICAgLy8gYmFjayB0byB0aGUgdmVyc2lvbiB3ZSByZWFkIGZyb20gU3RhY2sgT3V0cHV0cy5cbiAgICAgIHdhcm5pbmcoYENvdWxkIG5vdCByZWFkIFNTTSBwYXJhbWV0ZXIgJHtzc21QYXJhbWV0ZXJOYW1lfTogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgQ0RLIGRlcGxveW1lbnQgcmVxdWlyZXMgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gJyR7ZXhwZWN0ZWRWZXJzaW9ufScsIGZvdW5kIGFuIG9sZGVyIHZlcnNpb24uIFBsZWFzZSBydW4gJ2NkayBib290c3RyYXAnLmApO1xuICAgIH1cblxuICAgIGlmIChleHBlY3RlZFZlcnNpb24gPiB2ZXJzaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgQ0RLIGRlcGxveW1lbnQgcmVxdWlyZXMgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gJyR7ZXhwZWN0ZWRWZXJzaW9ufScsIGZvdW5kICcke3ZlcnNpb259Jy4gUGxlYXNlIHJ1biAnY2RrIGJvb3RzdHJhcCcuYCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHByZXBhcmVFY3JSZXBvc2l0b3J5KCk6IFByb21pc2U8RWNyUmVwb3NpdG9yeUluZm8+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5lcnJvck1lc3NhZ2UpO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWNyUmVwb3NpdG9yeUluZm8ge1xuICByZXBvc2l0b3J5VXJpOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWNyQ3JlZGVudGlhbHMge1xuICB1c2VybmFtZTogc3RyaW5nO1xuICBwYXNzd29yZDogc3RyaW5nO1xuICBlbmRwb2ludDogc3RyaW5nO1xufVxuIl19
|