@aws-cdk/toolkit-lib 1.30.0 → 1.32.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/build-info.json +2 -2
- package/lib/actions/bootstrap/index.d.ts +5 -0
- package/lib/actions/bootstrap/index.js +35 -2
- package/lib/actions/deploy/index.d.ts +6 -0
- package/lib/actions/deploy/index.js +1 -1
- package/lib/actions/destroy/index.d.ts +6 -0
- package/lib/actions/destroy/index.js +1 -1
- package/lib/actions/diff/private/helpers.js +36 -3
- package/lib/api/aws-auth/account-cache.js +36 -3
- package/lib/api/aws-auth/sdk-provider.js +36 -3
- package/lib/api/aws-auth/sdk.d.ts +2 -1
- package/lib/api/aws-auth/sdk.js +2 -1
- package/lib/api/aws-auth/user-agent.js +35 -2
- package/lib/api/aws-auth/util.js +35 -2
- package/lib/api/bootstrap/bootstrap-environment.js +35 -2
- package/lib/api/bootstrap/bootstrap-props.d.ts +6 -0
- package/lib/api/bootstrap/bootstrap-props.js +1 -1
- package/lib/api/bootstrap/deploy-bootstrap.js +39 -4
- package/lib/api/cloud-assembly/context-store.js +36 -3
- package/lib/api/cloud-assembly/environment.js +37 -4
- package/lib/api/cloud-assembly/private/context-aware-source.js +35 -2
- package/lib/api/cloud-assembly/private/exec.js +35 -2
- package/lib/api/cloud-assembly/private/prepare-source.js +39 -6
- package/lib/api/cloud-assembly/source-builder.js +37 -4
- package/lib/api/cloud-assembly/stack-assembly.js +8 -4
- package/lib/api/cloudformation/logical-id-map.js +35 -2
- package/lib/api/cloudformation/nested-stack-helpers.js +36 -3
- package/lib/api/cloudformation/template-body-parameter.js +42 -6
- package/lib/api/deployments/asset-manifest-builder.js +35 -2
- package/lib/api/deployments/assets.js +42 -6
- package/lib/api/deployments/cfn-api.d.ts +4 -2
- package/lib/api/deployments/cfn-api.js +47 -6
- package/lib/api/deployments/deploy-stack.d.ts +13 -0
- package/lib/api/deployments/deploy-stack.js +29 -9
- package/lib/api/deployments/deployment-result.d.ts +7 -1
- package/lib/api/deployments/deployment-result.js +1 -1
- package/lib/api/deployments/deployments.d.ts +5 -0
- package/lib/api/deployments/deployments.js +42 -4
- package/lib/api/diagnosing/format-utils.d.ts +29 -0
- package/lib/api/diagnosing/format-utils.js +141 -1
- package/lib/api/diagnosing/investigate-custom-resource.d.ts +17 -0
- package/lib/api/diagnosing/investigate-custom-resource.js +247 -0
- package/lib/api/diagnosing/investigate-ecs-service.d.ts +20 -0
- package/lib/api/diagnosing/investigate-ecs-service.js +242 -0
- package/lib/api/diagnosing/resource-identifiers.d.ts +39 -0
- package/lib/api/diagnosing/resource-identifiers.js +90 -0
- package/lib/api/diagnosing/resource-investigation.d.ts +2 -30
- package/lib/api/diagnosing/resource-investigation.js +9 -289
- package/lib/api/diff/diff-formatter.js +11 -8
- package/lib/api/drift/drift-formatter.js +20 -17
- package/lib/api/garbage-collection/garbage-collector.js +7 -4
- package/lib/api/garbage-collection/progress-printer.js +7 -4
- package/lib/api/hotswap/hotswap-deployments.js +47 -10
- package/lib/api/hotswap/hotswap-template-cache.js +36 -3
- package/lib/api/io/private/io-default-messages.js +35 -2
- package/lib/api/io/private/message-maker.d.ts +4 -0
- package/lib/api/io/private/message-maker.js +3 -1
- package/lib/api/io/private/messages.d.ts +5 -0
- package/lib/api/io/private/messages.js +55 -2
- package/lib/api/io/private/span.js +35 -2
- package/lib/api/logs-monitor/logs-monitor.js +40 -4
- package/lib/api/network-detector/network-detector.js +37 -4
- package/lib/api/notices/cached-data-source.js +35 -2
- package/lib/api/notices/filter.js +35 -2
- package/lib/api/notices/notices.js +35 -2
- package/lib/api/notices/web-data-source.js +35 -2
- package/lib/api/refactoring/digest.js +35 -2
- package/lib/api/refactoring/stack-definitions.js +40 -4
- package/lib/api/resource-import/importer.js +60 -17
- package/lib/api/resource-import/migrator.js +42 -6
- package/lib/api/rwlock.js +35 -2
- package/lib/api/settings.js +38 -5
- package/lib/api/source-tracing/private/stack-source-tracing.js +38 -5
- package/lib/api/stack-events/resource-errors.d.ts +12 -0
- package/lib/api/stack-events/resource-errors.js +2 -1
- package/lib/api/stack-events/stack-activity-monitor.d.ts +5 -0
- package/lib/api/stack-events/stack-activity-monitor.js +42 -2
- package/lib/api/stack-events/stack-event-poller.d.ts +8 -1
- package/lib/api/stack-events/stack-event-poller.js +19 -1
- package/lib/api/stack-events/stack-progress-monitor.js +35 -2
- package/lib/api/toolkit-info.js +7 -4
- package/lib/api/tree.js +36 -3
- package/lib/api/validate/validate-formatting.js +53 -17
- package/lib/api/work-graph/build-destroy-work-graph.js +35 -2
- package/lib/api/work-graph/work-graph-builder.js +35 -2
- package/lib/context-providers/index.js +35 -2
- package/lib/private/activity-printer/current.d.ts +19 -0
- package/lib/private/activity-printer/current.js +109 -17
- package/lib/private/activity-printer/history.js +50 -14
- package/lib/private/tools.js +38 -1
- package/lib/toolkit/non-interactive-io-host.js +11 -8
- package/lib/toolkit/private/collect-annotation-report.js +35 -2
- package/lib/toolkit/private/validation-report.js +36 -3
- package/lib/toolkit/toolkit-error.d.ts +20 -0
- package/lib/toolkit/toolkit-error.js +30 -2
- package/lib/toolkit/toolkit.d.ts +8 -0
- package/lib/toolkit/toolkit.js +107 -41
- package/lib/toolkit/types.d.ts +22 -0
- package/lib/toolkit/types.js +1 -1
- package/lib/util/cfn-express.d.ts +24 -0
- package/lib/util/cfn-express.js +55 -0
- package/lib/util/content-hash.js +35 -2
- package/lib/util/directories.js +38 -5
- package/lib/util/guess-language.js +36 -3
- package/lib/util/index.d.ts +1 -0
- package/lib/util/index.js +2 -1
- package/lib/util/package-info.js +35 -2
- package/lib/util/serialize.js +36 -3
- package/lib/util/version-range.js +35 -2
- package/lib/util/yaml-cfn.js +36 -3
- package/package.json +2 -2
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Pure parsers for resource identifiers used during failure diagnosis. */
|
|
2
|
+
/**
|
|
3
|
+
* Parse an ECS service physical resource ID into cluster and service identifiers.
|
|
4
|
+
*
|
|
5
|
+
* The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
|
|
6
|
+
* accept either form for their `cluster` parameter, so this is fine downstream.
|
|
7
|
+
*
|
|
8
|
+
* Recognized formats:
|
|
9
|
+
* - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
|
|
10
|
+
* - Path: `cluster-name/service-name`
|
|
11
|
+
* - Bare service name (uses the default cluster)
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseEcsServiceIdentifier(physicalId: string): {
|
|
14
|
+
cluster?: string;
|
|
15
|
+
serviceName?: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* If a ServiceToken is an `Fn::GetAtt` or `Ref` intrinsic, return the referenced logical ID.
|
|
19
|
+
*/
|
|
20
|
+
export declare function serviceTokenReferencedLogicalId(serviceToken: any): string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Extract a Lambda function name from a function ARN or a bare name.
|
|
23
|
+
*
|
|
24
|
+
* Returns `undefined` for non-Lambda ARNs (e.g. an SNS-topic ServiceToken).
|
|
25
|
+
*/
|
|
26
|
+
export declare function functionNameFromArnOrName(arnOrName: string): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Extract the log stream name out of a cfn-response failure reason
|
|
29
|
+
* ("See the details in CloudWatch Log Stream: <name>").
|
|
30
|
+
*/
|
|
31
|
+
export declare function extractLogStreamName(message: string | undefined): string | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* cfn-response defaults the physical ID to the log stream name. Use it only when it looks
|
|
34
|
+
* like a Lambda log stream (`YYYY/MM/DD/...`), so a user-provided physical ID isn't mistaken
|
|
35
|
+
* for one.
|
|
36
|
+
*/
|
|
37
|
+
export declare function logStreamNameFromPhysicalId(physicalId: string | undefined): string | undefined;
|
|
38
|
+
export declare function ecsStoppedTasksConsoleUrl(region: string, cluster: string, serviceName: string): string;
|
|
39
|
+
//# sourceMappingURL=resource-identifiers.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Pure parsers for resource identifiers used during failure diagnosis. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.parseEcsServiceIdentifier = parseEcsServiceIdentifier;
|
|
5
|
+
exports.serviceTokenReferencedLogicalId = serviceTokenReferencedLogicalId;
|
|
6
|
+
exports.functionNameFromArnOrName = functionNameFromArnOrName;
|
|
7
|
+
exports.extractLogStreamName = extractLogStreamName;
|
|
8
|
+
exports.logStreamNameFromPhysicalId = logStreamNameFromPhysicalId;
|
|
9
|
+
exports.ecsStoppedTasksConsoleUrl = ecsStoppedTasksConsoleUrl;
|
|
10
|
+
/**
|
|
11
|
+
* Parse an ECS service physical resource ID into cluster and service identifiers.
|
|
12
|
+
*
|
|
13
|
+
* The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
|
|
14
|
+
* accept either form for their `cluster` parameter, so this is fine downstream.
|
|
15
|
+
*
|
|
16
|
+
* Recognized formats:
|
|
17
|
+
* - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
|
|
18
|
+
* - Path: `cluster-name/service-name`
|
|
19
|
+
* - Bare service name (uses the default cluster)
|
|
20
|
+
*/
|
|
21
|
+
function parseEcsServiceIdentifier(physicalId) {
|
|
22
|
+
const arnMatch = physicalId.match(/^arn:[^:]+:ecs:[^:]*:[^:]*:service\/([^/]+)\/([^/]+)$/);
|
|
23
|
+
if (arnMatch) {
|
|
24
|
+
return { cluster: arnMatch[1], serviceName: arnMatch[2] };
|
|
25
|
+
}
|
|
26
|
+
const parts = physicalId.split('/');
|
|
27
|
+
if (parts.length === 2 && parts[0] && parts[1]) {
|
|
28
|
+
return { cluster: parts[0], serviceName: parts[1] };
|
|
29
|
+
}
|
|
30
|
+
if (parts.length === 1 && parts[0]) {
|
|
31
|
+
return { serviceName: parts[0] };
|
|
32
|
+
}
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* If a ServiceToken is an `Fn::GetAtt` or `Ref` intrinsic, return the referenced logical ID.
|
|
37
|
+
*/
|
|
38
|
+
function serviceTokenReferencedLogicalId(serviceToken) {
|
|
39
|
+
if (!serviceToken || typeof serviceToken !== 'object') {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const getAtt = serviceToken['Fn::GetAtt'];
|
|
43
|
+
// Array form (JSON / CDK output): ["LogicalId", "Arn"].
|
|
44
|
+
if (Array.isArray(getAtt) && typeof getAtt[0] === 'string') {
|
|
45
|
+
return getAtt[0];
|
|
46
|
+
}
|
|
47
|
+
// String short-form (how YAML `!GetAtt LogicalId.Arn` deserializes): "LogicalId.Attr".
|
|
48
|
+
if (typeof getAtt === 'string') {
|
|
49
|
+
return getAtt.split('.')[0] || undefined;
|
|
50
|
+
}
|
|
51
|
+
if (typeof serviceToken.Ref === 'string') {
|
|
52
|
+
return serviceToken.Ref;
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Extract a Lambda function name from a function ARN or a bare name.
|
|
58
|
+
*
|
|
59
|
+
* Returns `undefined` for non-Lambda ARNs (e.g. an SNS-topic ServiceToken).
|
|
60
|
+
*/
|
|
61
|
+
function functionNameFromArnOrName(arnOrName) {
|
|
62
|
+
const arnMatch = arnOrName.match(/^arn:[^:]+:lambda:[^:]*:[^:]*:function:([^:]+)/);
|
|
63
|
+
if (arnMatch) {
|
|
64
|
+
return arnMatch[1];
|
|
65
|
+
}
|
|
66
|
+
if (arnOrName.startsWith('arn:')) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return arnOrName || undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract the log stream name out of a cfn-response failure reason
|
|
73
|
+
* ("See the details in CloudWatch Log Stream: <name>").
|
|
74
|
+
*/
|
|
75
|
+
function extractLogStreamName(message) {
|
|
76
|
+
const match = message?.match(/CloudWatch Log Stream:\s*(\S+)/);
|
|
77
|
+
return match ? match[1] : undefined;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* cfn-response defaults the physical ID to the log stream name. Use it only when it looks
|
|
81
|
+
* like a Lambda log stream (`YYYY/MM/DD/...`), so a user-provided physical ID isn't mistaken
|
|
82
|
+
* for one.
|
|
83
|
+
*/
|
|
84
|
+
function logStreamNameFromPhysicalId(physicalId) {
|
|
85
|
+
return physicalId && /^\d{4}\/\d{2}\/\d{2}\/.+/.test(physicalId) ? physicalId : undefined;
|
|
86
|
+
}
|
|
87
|
+
function ecsStoppedTasksConsoleUrl(region, cluster, serviceName) {
|
|
88
|
+
return `https://${region}.console.aws.amazon.com/ecs/v2/clusters/${cluster}/services/${serviceName}/tasks?status=STOPPED®ion=${region}`;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtaWRlbnRpZmllcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJyZXNvdXJjZS1pZGVudGlmaWVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMkVBQTJFOztBQWEzRSw4REFlQztBQUtELDBFQWlCQztBQU9ELDhEQVNDO0FBTUQsb0RBR0M7QUFPRCxrRUFFQztBQUVELDhEQUVDO0FBdEZEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFnQix5QkFBeUIsQ0FBQyxVQUFrQjtJQUMxRCxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7SUFDM0YsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUNiLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM1RCxDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMvQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQUNELElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDbkMsT0FBTyxFQUFFLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQsT0FBTyxFQUFFLENBQUM7QUFDWixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQiwrQkFBK0IsQ0FBQyxZQUFpQjtJQUMvRCxJQUFJLENBQUMsWUFBWSxJQUFJLE9BQU8sWUFBWSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3RELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDMUMsd0RBQXdEO0lBQ3hELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUMzRCxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsdUZBQXVGO0lBQ3ZGLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDL0IsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQztJQUMzQyxDQUFDO0lBQ0QsSUFBSSxPQUFPLFlBQVksQ0FBQyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDekMsT0FBTyxZQUFZLENBQUMsR0FBRyxDQUFDO0lBQzFCLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQWdCLHlCQUF5QixDQUFDLFNBQWlCO0lBQ3pELE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztJQUNuRixJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQ2IsT0FBTyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUNELElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLFNBQVMsSUFBSSxTQUFTLENBQUM7QUFDaEMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLG9CQUFvQixDQUFDLE9BQTJCO0lBQzlELE1BQU0sS0FBSyxHQUFHLE9BQU8sRUFBRSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUMvRCxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDdEMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQiwyQkFBMkIsQ0FBQyxVQUE4QjtJQUN4RSxPQUFPLFVBQVUsSUFBSSwwQkFBMEIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzVGLENBQUM7QUFFRCxTQUFnQix5QkFBeUIsQ0FBQyxNQUFjLEVBQUUsT0FBZSxFQUFFLFdBQW1CO0lBQzVGLE9BQU8sV0FBVyxNQUFNLDJDQUEyQyxPQUFPLGFBQWEsV0FBVyxnQ0FBZ0MsTUFBTSxFQUFFLENBQUM7QUFDN0ksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBQdXJlIHBhcnNlcnMgZm9yIHJlc291cmNlIGlkZW50aWZpZXJzIHVzZWQgZHVyaW5nIGZhaWx1cmUgZGlhZ25vc2lzLiAqL1xuXG4vKipcbiAqIFBhcnNlIGFuIEVDUyBzZXJ2aWNlIHBoeXNpY2FsIHJlc291cmNlIElEIGludG8gY2x1c3RlciBhbmQgc2VydmljZSBpZGVudGlmaWVycy5cbiAqXG4gKiBUaGUgY2x1c3RlciBwb3J0aW9uIGlzIGEgbmFtZSAobm90IGFuIEFSTikg4oCUIGBkZXNjcmliZVNlcnZpY2VzYC9gZGVzY3JpYmVUYXNrc2BcbiAqIGFjY2VwdCBlaXRoZXIgZm9ybSBmb3IgdGhlaXIgYGNsdXN0ZXJgIHBhcmFtZXRlciwgc28gdGhpcyBpcyBmaW5lIGRvd25zdHJlYW0uXG4gKlxuICogUmVjb2duaXplZCBmb3JtYXRzOlxuICogLSBMb25nIEFSTjogYGFybjphd3M6ZWNzOnJlZ2lvbjphY2NvdW50OnNlcnZpY2UvY2x1c3Rlci1uYW1lL3NlcnZpY2UtbmFtZWAgKGN1cnJlbnQgZGVmYXVsdClcbiAqIC0gUGF0aDogYGNsdXN0ZXItbmFtZS9zZXJ2aWNlLW5hbWVgXG4gKiAtIEJhcmUgc2VydmljZSBuYW1lICh1c2VzIHRoZSBkZWZhdWx0IGNsdXN0ZXIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUVjc1NlcnZpY2VJZGVudGlmaWVyKHBoeXNpY2FsSWQ6IHN0cmluZyk6IHsgY2x1c3Rlcj86IHN0cmluZzsgc2VydmljZU5hbWU/OiBzdHJpbmcgfSB7XG4gIGNvbnN0IGFybk1hdGNoID0gcGh5c2ljYWxJZC5tYXRjaCgvXmFybjpbXjpdKzplY3M6W146XSo6W146XSo6c2VydmljZVxcLyhbXi9dKylcXC8oW14vXSspJC8pO1xuICBpZiAoYXJuTWF0Y2gpIHtcbiAgICByZXR1cm4geyBjbHVzdGVyOiBhcm5NYXRjaFsxXSwgc2VydmljZU5hbWU6IGFybk1hdGNoWzJdIH07XG4gIH1cblxuICBjb25zdCBwYXJ0cyA9IHBoeXNpY2FsSWQuc3BsaXQoJy8nKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMiAmJiBwYXJ0c1swXSAmJiBwYXJ0c1sxXSkge1xuICAgIHJldHVybiB7IGNsdXN0ZXI6IHBhcnRzWzBdLCBzZXJ2aWNlTmFtZTogcGFydHNbMV0gfTtcbiAgfVxuICBpZiAocGFydHMubGVuZ3RoID09PSAxICYmIHBhcnRzWzBdKSB7XG4gICAgcmV0dXJuIHsgc2VydmljZU5hbWU6IHBhcnRzWzBdIH07XG4gIH1cblxuICByZXR1cm4ge307XG59XG5cbi8qKlxuICogSWYgYSBTZXJ2aWNlVG9rZW4gaXMgYW4gYEZuOjpHZXRBdHRgIG9yIGBSZWZgIGludHJpbnNpYywgcmV0dXJuIHRoZSByZWZlcmVuY2VkIGxvZ2ljYWwgSUQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXJ2aWNlVG9rZW5SZWZlcmVuY2VkTG9naWNhbElkKHNlcnZpY2VUb2tlbjogYW55KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFzZXJ2aWNlVG9rZW4gfHwgdHlwZW9mIHNlcnZpY2VUb2tlbiAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGNvbnN0IGdldEF0dCA9IHNlcnZpY2VUb2tlblsnRm46OkdldEF0dCddO1xuICAvLyBBcnJheSBmb3JtIChKU09OIC8gQ0RLIG91dHB1dCk6IFtcIkxvZ2ljYWxJZFwiLCBcIkFyblwiXS5cbiAgaWYgKEFycmF5LmlzQXJyYXkoZ2V0QXR0KSAmJiB0eXBlb2YgZ2V0QXR0WzBdID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBnZXRBdHRbMF07XG4gIH1cbiAgLy8gU3RyaW5nIHNob3J0LWZvcm0gKGhvdyBZQU1MIGAhR2V0QXR0IExvZ2ljYWxJZC5Bcm5gIGRlc2VyaWFsaXplcyk6IFwiTG9naWNhbElkLkF0dHJcIi5cbiAgaWYgKHR5cGVvZiBnZXRBdHQgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGdldEF0dC5zcGxpdCgnLicpWzBdIHx8IHVuZGVmaW5lZDtcbiAgfVxuICBpZiAodHlwZW9mIHNlcnZpY2VUb2tlbi5SZWYgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHNlcnZpY2VUb2tlbi5SZWY7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGEgTGFtYmRhIGZ1bmN0aW9uIG5hbWUgZnJvbSBhIGZ1bmN0aW9uIEFSTiBvciBhIGJhcmUgbmFtZS5cbiAqXG4gKiBSZXR1cm5zIGB1bmRlZmluZWRgIGZvciBub24tTGFtYmRhIEFSTnMgKGUuZy4gYW4gU05TLXRvcGljIFNlcnZpY2VUb2tlbikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmdW5jdGlvbk5hbWVGcm9tQXJuT3JOYW1lKGFybk9yTmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgYXJuTWF0Y2ggPSBhcm5Pck5hbWUubWF0Y2goL15hcm46W146XSs6bGFtYmRhOlteOl0qOlteOl0qOmZ1bmN0aW9uOihbXjpdKykvKTtcbiAgaWYgKGFybk1hdGNoKSB7XG4gICAgcmV0dXJuIGFybk1hdGNoWzFdO1xuICB9XG4gIGlmIChhcm5Pck5hbWUuc3RhcnRzV2l0aCgnYXJuOicpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gYXJuT3JOYW1lIHx8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IHRoZSBsb2cgc3RyZWFtIG5hbWUgb3V0IG9mIGEgY2ZuLXJlc3BvbnNlIGZhaWx1cmUgcmVhc29uXG4gKiAoXCJTZWUgdGhlIGRldGFpbHMgaW4gQ2xvdWRXYXRjaCBMb2cgU3RyZWFtOiA8bmFtZT5cIikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0TG9nU3RyZWFtTmFtZShtZXNzYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBtYXRjaCA9IG1lc3NhZ2U/Lm1hdGNoKC9DbG91ZFdhdGNoIExvZyBTdHJlYW06XFxzKihcXFMrKS8pO1xuICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBjZm4tcmVzcG9uc2UgZGVmYXVsdHMgdGhlIHBoeXNpY2FsIElEIHRvIHRoZSBsb2cgc3RyZWFtIG5hbWUuIFVzZSBpdCBvbmx5IHdoZW4gaXQgbG9va3NcbiAqIGxpa2UgYSBMYW1iZGEgbG9nIHN0cmVhbSAoYFlZWVkvTU0vREQvLi4uYCksIHNvIGEgdXNlci1wcm92aWRlZCBwaHlzaWNhbCBJRCBpc24ndCBtaXN0YWtlblxuICogZm9yIG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvZ1N0cmVhbU5hbWVGcm9tUGh5c2ljYWxJZChwaHlzaWNhbElkOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gcGh5c2ljYWxJZCAmJiAvXlxcZHs0fVxcL1xcZHsyfVxcL1xcZHsyfVxcLy4rLy50ZXN0KHBoeXNpY2FsSWQpID8gcGh5c2ljYWxJZCA6IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVjc1N0b3BwZWRUYXNrc0NvbnNvbGVVcmwocmVnaW9uOiBzdHJpbmcsIGNsdXN0ZXI6IHN0cmluZywgc2VydmljZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgaHR0cHM6Ly8ke3JlZ2lvbn0uY29uc29sZS5hd3MuYW1hem9uLmNvbS9lY3MvdjIvY2x1c3RlcnMvJHtjbHVzdGVyfS9zZXJ2aWNlcy8ke3NlcnZpY2VOYW1lfS90YXNrcz9zdGF0dXM9U1RPUFBFRCZyZWdpb249JHtyZWdpb259YDtcbn1cbiJdfQ==
|
|
@@ -1,21 +1,8 @@
|
|
|
1
|
+
import { type InvestigateOptions } from './investigate-ecs-service';
|
|
1
2
|
import type { AdditionalDiagnosticContext } from '../../actions/diagnose';
|
|
2
3
|
import type { SDK } from '../aws-auth/sdk';
|
|
3
4
|
import type { ResourceError } from '../stack-events/resource-errors';
|
|
4
|
-
|
|
5
|
-
* Options that influence how a resource is investigated.
|
|
6
|
-
*/
|
|
7
|
-
export interface InvestigateOptions {
|
|
8
|
-
/**
|
|
9
|
-
* Whether CloudFormation rollback is enabled for this deployment.
|
|
10
|
-
*
|
|
11
|
-
* When rollback is enabled, a failed resource is torn down before we can
|
|
12
|
-
* inspect its runtime state, so we may suggest re-running with `--no-rollback`
|
|
13
|
-
* to retain that detail.
|
|
14
|
-
*
|
|
15
|
-
* @default true
|
|
16
|
-
*/
|
|
17
|
-
readonly rollbackEnabled?: boolean;
|
|
18
|
-
}
|
|
5
|
+
export type { InvestigateOptions };
|
|
19
6
|
/**
|
|
20
7
|
* Investigate a failed resource using AWS service APIs to gather additional root cause context.
|
|
21
8
|
*
|
|
@@ -23,19 +10,4 @@ export interface InvestigateOptions {
|
|
|
23
10
|
* investigation is not possible or yields no results for this resource type.
|
|
24
11
|
*/
|
|
25
12
|
export declare function investigateResource(err: ResourceError, sdk: SDK, debug: (msg: string) => Promise<void>, options?: InvestigateOptions): Promise<AdditionalDiagnosticContext[]>;
|
|
26
|
-
/**
|
|
27
|
-
* Parse an ECS service physical resource ID into cluster and service identifiers.
|
|
28
|
-
*
|
|
29
|
-
* The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
|
|
30
|
-
* accept either form for their `cluster` parameter, so this is fine downstream.
|
|
31
|
-
*
|
|
32
|
-
* Recognized formats:
|
|
33
|
-
* - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
|
|
34
|
-
* - Path: `cluster-name/service-name`
|
|
35
|
-
* - Bare service name (uses the default cluster)
|
|
36
|
-
*/
|
|
37
|
-
export declare function parseEcsServiceIdentifier(physicalId: string): {
|
|
38
|
-
cluster?: string;
|
|
39
|
-
serviceName?: string;
|
|
40
|
-
};
|
|
41
13
|
//# sourceMappingURL=resource-investigation.d.ts.map
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.investigateResource = investigateResource;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Maximum number of log lines included per CloudWatch Logs context block.
|
|
7
|
-
*
|
|
8
|
-
* The formatter renders the messages array verbatim, so this is the
|
|
9
|
-
* single user-visible cap.
|
|
10
|
-
*/
|
|
11
|
-
const MAX_LOG_LINES = 50;
|
|
4
|
+
const investigate_custom_resource_1 = require("./investigate-custom-resource");
|
|
5
|
+
const investigate_ecs_service_1 = require("./investigate-ecs-service");
|
|
12
6
|
/**
|
|
13
7
|
* Investigate a failed resource using AWS service APIs to gather additional root cause context.
|
|
14
8
|
*
|
|
@@ -16,287 +10,13 @@ const MAX_LOG_LINES = 50;
|
|
|
16
10
|
* investigation is not possible or yields no results for this resource type.
|
|
17
11
|
*/
|
|
18
12
|
async function investigateResource(err, sdk, debug, options = {}) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
default:
|
|
23
|
-
return [];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
async function investigateEcsService(err, sdk, debug, options) {
|
|
27
|
-
const physicalId = err.physicalId;
|
|
28
|
-
if (!physicalId) {
|
|
29
|
-
await debug('ECS investigation: no physical ID available');
|
|
30
|
-
return [];
|
|
31
|
-
}
|
|
32
|
-
const { cluster, serviceName } = parseEcsServiceIdentifier(physicalId);
|
|
33
|
-
if (!serviceName) {
|
|
34
|
-
await debug(`ECS investigation: could not parse service identifier from "${physicalId}"`);
|
|
35
|
-
return [];
|
|
36
|
-
}
|
|
37
|
-
const region = sdk.currentRegion;
|
|
38
|
-
const ecs = sdk.ecs();
|
|
39
|
-
const cwl = sdk.cloudWatchLogs();
|
|
40
|
-
const service = await describeService(ecs, cluster, serviceName, debug);
|
|
41
|
-
if (!service) {
|
|
42
|
-
// The service is gone. The most common reason is that CloudFormation rolled the
|
|
43
|
-
// deployment back and deleted it, taking the task/runtime detail with it. If rollback
|
|
44
|
-
// was enabled, point the user at the flag that would have retained that detail.
|
|
45
|
-
if (options.rollbackEnabled) {
|
|
46
|
-
return [{
|
|
47
|
-
source: 'ECS Service',
|
|
48
|
-
messages: [
|
|
49
|
-
'The service and its tasks were removed during rollback, so container-level failure detail is unavailable.',
|
|
50
|
-
'Re-run the deployment with `--no-rollback` to retain the failed tasks and see why they stopped.',
|
|
51
|
-
],
|
|
52
|
-
}];
|
|
53
|
-
}
|
|
54
|
-
return [];
|
|
55
|
-
}
|
|
56
|
-
const results = [];
|
|
57
|
-
const stoppedTaskResult = await getStoppedTaskReasons(ecs, cluster, serviceName, region, service, debug);
|
|
58
|
-
if (stoppedTaskResult.context) {
|
|
59
|
-
results.push(stoppedTaskResult.context);
|
|
60
|
-
}
|
|
61
|
-
const taskDefinitionArn = service.taskDefinition;
|
|
62
|
-
if (!taskDefinitionArn) {
|
|
63
|
-
return results;
|
|
64
|
-
}
|
|
65
|
-
const taskDefInfo = await getTaskDefinitionInfo(ecs, taskDefinitionArn, debug);
|
|
66
|
-
if (!taskDefInfo) {
|
|
67
|
-
return results;
|
|
68
|
-
}
|
|
69
|
-
const logConfigs = taskDefInfo.logConfigs;
|
|
70
|
-
if (logConfigs.length === 0) {
|
|
71
|
-
results.push({
|
|
72
|
-
source: 'CloudWatch Logs',
|
|
73
|
-
messages: [
|
|
74
|
-
'No CloudWatch Logs configuration found. Enable logging to see container output on failure.',
|
|
75
|
-
'Example:',
|
|
76
|
-
' taskDefinition.addContainer("app", {',
|
|
77
|
-
' // ...',
|
|
78
|
-
' logging: ecs.LogDrivers.awsLogs({ streamPrefix: "my-service" }),',
|
|
79
|
-
' });',
|
|
80
|
-
],
|
|
81
|
-
});
|
|
82
|
-
return results;
|
|
13
|
+
const resourceType = err.resourceType ?? '';
|
|
14
|
+
if (resourceType === 'AWS::ECS::Service') {
|
|
15
|
+
return (0, investigate_ecs_service_1.investigateEcsService)(err, sdk, debug, options);
|
|
83
16
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// explicit concurrency limit.
|
|
87
|
-
// eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
|
|
88
|
-
const logResults = await Promise.all(logConfigs.map(cfg => fetchRecentLogs(cwl, cfg, region, stoppedTaskResult.taskIds, debug)));
|
|
89
|
-
const logContexts = logResults.filter((c) => c !== undefined);
|
|
90
|
-
results.push(...logContexts);
|
|
91
|
-
if (logContexts.length === 0) {
|
|
92
|
-
results.push({
|
|
93
|
-
source: 'CloudWatch Logs',
|
|
94
|
-
messages: ['No CloudWatch Logs found.'],
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
return results;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Parse an ECS service physical resource ID into cluster and service identifiers.
|
|
101
|
-
*
|
|
102
|
-
* The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
|
|
103
|
-
* accept either form for their `cluster` parameter, so this is fine downstream.
|
|
104
|
-
*
|
|
105
|
-
* Recognized formats:
|
|
106
|
-
* - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
|
|
107
|
-
* - Path: `cluster-name/service-name`
|
|
108
|
-
* - Bare service name (uses the default cluster)
|
|
109
|
-
*/
|
|
110
|
-
function parseEcsServiceIdentifier(physicalId) {
|
|
111
|
-
const arnMatch = physicalId.match(/^arn:[^:]+:ecs:[^:]*:[^:]*:service\/([^/]+)\/([^/]+)$/);
|
|
112
|
-
if (arnMatch) {
|
|
113
|
-
return { cluster: arnMatch[1], serviceName: arnMatch[2] };
|
|
114
|
-
}
|
|
115
|
-
const parts = physicalId.split('/');
|
|
116
|
-
if (parts.length === 2 && parts[0] && parts[1]) {
|
|
117
|
-
return { cluster: parts[0], serviceName: parts[1] };
|
|
118
|
-
}
|
|
119
|
-
if (parts.length === 1 && parts[0]) {
|
|
120
|
-
return { serviceName: parts[0] };
|
|
121
|
-
}
|
|
122
|
-
return {};
|
|
123
|
-
}
|
|
124
|
-
async function describeService(ecs, cluster, serviceName, debug) {
|
|
125
|
-
try {
|
|
126
|
-
const resp = await ecs.describeServices({ cluster, services: [serviceName] });
|
|
127
|
-
const service = resp.services?.[0];
|
|
128
|
-
if (!service) {
|
|
129
|
-
await debug(`ECS investigation: service "${serviceName}" not found`);
|
|
130
|
-
}
|
|
131
|
-
return service;
|
|
17
|
+
if (resourceType === 'AWS::CloudFormation::CustomResource' || resourceType.startsWith('Custom::')) {
|
|
18
|
+
return (0, investigate_custom_resource_1.investigateCustomResource)(err, sdk, debug);
|
|
132
19
|
}
|
|
133
|
-
|
|
134
|
-
await debug(`ECS investigation: failed to describe service: ${e.message}`);
|
|
135
|
-
return undefined;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
async function getStoppedTaskReasons(ecs, cluster, serviceName, region, service, debug) {
|
|
139
|
-
try {
|
|
140
|
-
// Ask ECS for the service's stopped tasks. The IDs we need live in "has started 1 tasks: (task <id>)" events
|
|
141
|
-
const taskIds = await listStoppedTaskIds(ecs, cluster, serviceName, debug);
|
|
142
|
-
const messages = [];
|
|
143
|
-
if (taskIds.length > 0) {
|
|
144
|
-
// Show details from the most recently stopped task only.
|
|
145
|
-
const tasksResp = await ecs.describeTasks({ cluster, tasks: [taskIds[0]] });
|
|
146
|
-
const task = tasksResp.tasks?.[0];
|
|
147
|
-
if (task) {
|
|
148
|
-
if (task.stoppedReason) {
|
|
149
|
-
messages.push(`Task stopped: ${task.stoppedReason}`);
|
|
150
|
-
}
|
|
151
|
-
for (const container of task.containers ?? []) {
|
|
152
|
-
if (container.reason) {
|
|
153
|
-
messages.push(`Container "${container.name}": ${container.reason}`);
|
|
154
|
-
}
|
|
155
|
-
if (container.exitCode != null && container.exitCode !== 0) {
|
|
156
|
-
messages.push(`Container "${container.name}" exited with code ${container.exitCode}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
if (messages.length > 0 && taskIds.length > 1) {
|
|
161
|
-
messages.push(`(${taskIds.length - 1} other failed task(s) not shown)`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
// Fall back to the most relevant service event if we couldn't get a task-level reason
|
|
165
|
-
// (e.g. tasks already aged out, or no stopped tasks retained).
|
|
166
|
-
if (messages.length === 0) {
|
|
167
|
-
const failureEvent = (service.events ?? [])
|
|
168
|
-
.find(e => e.message?.includes('stopped') || e.message?.includes('failed') || e.message?.includes('unhealthy'));
|
|
169
|
-
if (failureEvent?.message) {
|
|
170
|
-
messages.push(failureEvent.message);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (messages.length === 0) {
|
|
174
|
-
return { taskIds };
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
context: {
|
|
178
|
-
source: 'ECS Stopped Tasks',
|
|
179
|
-
messages,
|
|
180
|
-
link: ecsStoppedTasksConsoleUrl(region, cluster ?? 'default', serviceName),
|
|
181
|
-
linkLabel: 'Tasks',
|
|
182
|
-
},
|
|
183
|
-
taskIds,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
catch (e) {
|
|
187
|
-
await debug(`ECS investigation: failed to get stopped task reasons: ${e.message}`);
|
|
188
|
-
return { taskIds: [] };
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Maximum number of stopped task IDs to consider. We only render detail for the most
|
|
193
|
-
* recent one, but keep a few so we can report how many others failed.
|
|
194
|
-
*/
|
|
195
|
-
const MAX_STOPPED_TASKS = 3;
|
|
196
|
-
/**
|
|
197
|
-
* List the bare task IDs of the service's stopped tasks, newest first.
|
|
198
|
-
*
|
|
199
|
-
* Prefers scoping by service name; if that yields nothing (some ECS API versions only
|
|
200
|
-
* apply the service filter to running tasks), falls back to listing the cluster's stopped
|
|
201
|
-
* tasks. Returns an empty array if none are retained (e.g. they aged out, or rollback
|
|
202
|
-
* already drained the cluster).
|
|
203
|
-
*/
|
|
204
|
-
async function listStoppedTaskIds(ecs, cluster, serviceName, debug) {
|
|
205
|
-
const toIds = (arns) => (arns ?? []).map(arn => arn.split('/').pop()).filter((id) => !!id);
|
|
206
|
-
let arns;
|
|
207
|
-
try {
|
|
208
|
-
const byService = await ecs.listTasks({ cluster, serviceName, desiredStatus: 'STOPPED' });
|
|
209
|
-
arns = byService.taskArns;
|
|
210
|
-
if (!arns || arns.length === 0) {
|
|
211
|
-
const byCluster = await ecs.listTasks({ cluster, desiredStatus: 'STOPPED' });
|
|
212
|
-
arns = byCluster.taskArns;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
catch (e) {
|
|
216
|
-
await debug(`ECS investigation: failed to list stopped tasks: ${e.message}`);
|
|
217
|
-
return [];
|
|
218
|
-
}
|
|
219
|
-
return toIds(arns).slice(0, MAX_STOPPED_TASKS);
|
|
220
|
-
}
|
|
221
|
-
async function getTaskDefinitionInfo(ecs, taskDefinitionArn, debug) {
|
|
222
|
-
try {
|
|
223
|
-
const resp = await ecs.describeTaskDefinition({ taskDefinition: taskDefinitionArn });
|
|
224
|
-
const containers = resp.taskDefinition?.containerDefinitions ?? [];
|
|
225
|
-
const logConfigs = [];
|
|
226
|
-
for (const container of containers) {
|
|
227
|
-
const logConfig = container.logConfiguration;
|
|
228
|
-
if (logConfig?.logDriver === 'awslogs') {
|
|
229
|
-
const logGroup = logConfig.options?.['awslogs-group'];
|
|
230
|
-
if (logGroup) {
|
|
231
|
-
logConfigs.push({
|
|
232
|
-
logGroup,
|
|
233
|
-
streamPrefix: logConfig.options?.['awslogs-stream-prefix'],
|
|
234
|
-
containerName: container.name,
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return { logConfigs };
|
|
240
|
-
}
|
|
241
|
-
catch (e) {
|
|
242
|
-
await debug(`ECS investigation: failed to describe task definition: ${e.message}`);
|
|
243
|
-
return undefined;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
async function fetchRecentLogs(cwl, logConfig, region, taskIds, debug) {
|
|
247
|
-
try {
|
|
248
|
-
// Target the most recently failed task's log stream for the most relevant output
|
|
249
|
-
const lastTaskId = taskIds[0];
|
|
250
|
-
const targetStream = (logConfig.streamPrefix && logConfig.containerName && lastTaskId)
|
|
251
|
-
? `${logConfig.streamPrefix}/${logConfig.containerName}/${lastTaskId}`
|
|
252
|
-
: undefined;
|
|
253
|
-
const resp = await cwl.filterLogEvents({
|
|
254
|
-
logGroupName: logConfig.logGroup,
|
|
255
|
-
startTime: Date.now() - 30 * 60 * 1000,
|
|
256
|
-
limit: 1000,
|
|
257
|
-
...(targetStream
|
|
258
|
-
? { logStreamNames: [targetStream] }
|
|
259
|
-
: logConfig.streamPrefix ? { logStreamNamePrefix: logConfig.streamPrefix } : {}),
|
|
260
|
-
});
|
|
261
|
-
const events = resp.events ?? [];
|
|
262
|
-
if (events.length === 0) {
|
|
263
|
-
await debug(`ECS investigation: no recent log events in ${logConfig.logGroup}${targetStream ? ` (targeted stream: ${targetStream})` : ''}`);
|
|
264
|
-
return undefined;
|
|
265
|
-
}
|
|
266
|
-
// Keep the most recent lines (newer output is more useful for diagnosis).
|
|
267
|
-
// This is the only truncation point — the formatter renders these verbatim.
|
|
268
|
-
const allMessages = events
|
|
269
|
-
.map(e => e.message?.trimEnd())
|
|
270
|
-
.filter((m) => m != null);
|
|
271
|
-
const messages = allMessages.slice(-MAX_LOG_LINES);
|
|
272
|
-
const omitted = allMessages.length - messages.length;
|
|
273
|
-
if (omitted > 0) {
|
|
274
|
-
messages.unshift(`... (${omitted} earlier lines omitted)`);
|
|
275
|
-
}
|
|
276
|
-
if (taskIds.length > 1) {
|
|
277
|
-
messages.push(`(showing logs from last failed task; ${taskIds.length - 1} other failed task(s) available in console)`);
|
|
278
|
-
}
|
|
279
|
-
const source = logConfig.containerName
|
|
280
|
-
? `CloudWatch Logs: ${logConfig.logGroup} (container: ${logConfig.containerName})`
|
|
281
|
-
: `CloudWatch Logs: ${logConfig.logGroup}`;
|
|
282
|
-
return {
|
|
283
|
-
source,
|
|
284
|
-
messages,
|
|
285
|
-
link: cloudWatchLogsConsoleUrl(region, logConfig.logGroup),
|
|
286
|
-
linkLabel: 'Logs',
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
catch (e) {
|
|
290
|
-
await debug(`ECS investigation: failed to fetch logs from ${logConfig.logGroup}: ${e.message}`);
|
|
291
|
-
return undefined;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
// CloudWatch console uses double-URI-encoding with '$' replacing '%' for the log group in the fragment.
|
|
295
|
-
function cloudWatchLogsConsoleUrl(region, logGroup) {
|
|
296
|
-
const encodedLogGroup = encodeURIComponent(encodeURIComponent(logGroup)).replace(/%/g, '$');
|
|
297
|
-
return `https://${region}.console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:log-groups/log-group/${encodedLogGroup}`;
|
|
298
|
-
}
|
|
299
|
-
function ecsStoppedTasksConsoleUrl(region, cluster, serviceName) {
|
|
300
|
-
return `https://${region}.console.aws.amazon.com/ecs/v2/clusters/${cluster}/services/${serviceName}/tasks?status=STOPPED®ion=${region}`;
|
|
20
|
+
return [];
|
|
301
21
|
}
|
|
302
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtaW52ZXN0aWdhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc291cmNlLWludmVzdGlnYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFrQ0Esa0RBWUM7QUF3R0QsOERBZUM7QUFqS0Q7Ozs7O0dBS0c7QUFDSCxNQUFNLGFBQWEsR0FBRyxFQUFFLENBQUM7QUFrQnpCOzs7OztHQUtHO0FBQ0ksS0FBSyxVQUFVLG1CQUFtQixDQUN2QyxHQUFrQixFQUNsQixHQUFRLEVBQ1IsS0FBcUMsRUFDckMsVUFBOEIsRUFBRTtJQUVoQyxRQUFRLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN6QixLQUFLLG1CQUFtQjtZQUN0QixPQUFPLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pEO1lBQ0UsT0FBTyxFQUFFLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FDbEMsR0FBa0IsRUFDbEIsR0FBUSxFQUNSLEtBQXFDLEVBQ3JDLE9BQTJCO0lBRTNCLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUM7SUFDbEMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7UUFDM0QsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsR0FBRyx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN2RSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakIsTUFBTSxLQUFLLENBQUMsK0RBQStELFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDMUYsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQztJQUNqQyxNQUFNLEdBQUcsR0FB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Q0FBQyxvQkFBb0IsU0FBUyxDQUFDLFFBQVEsZ0JBQWdCLFNBQVMsQ0FBQyxhQUFhLEdBQUc7WUFDbEYsQ0FBQyxDQUFDLG9CQUFvQixTQUFTLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFN0MsT0FBTztZQUNMLE1BQU07WUFDTixRQUFRO1lBQ1IsSUFBSSxFQUFFLHdCQUF3QixDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsUUFBUSxDQUFDO1lBQzFELFNBQVMsRUFBRSxNQUFNO1NBQ2xCLENBQUM7SUFDSixDQUFDO0lBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztRQUNoQixNQUFNLEtBQUssQ0FBQyxnREFBZ0QsU0FBUyxDQUFDLFFBQVEsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNoRyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQztBQUVELHdHQUF3RztBQUN4RyxTQUFTLHdCQUF3QixDQUFDLE1BQWMsRUFBRSxRQUFnQjtJQUNoRSxNQUFNLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDNUYsT0FBTyxXQUFXLE1BQU0sa0RBQWtELE1BQU0sZ0NBQWdDLGVBQWUsRUFBRSxDQUFDO0FBQ3BJLENBQUM7QUFFRCxTQUFTLHlCQUF5QixDQUFDLE1BQWMsRUFBRSxPQUFlLEVBQUUsV0FBbUI7SUFDckYsT0FBTyxXQUFXLE1BQU0sMkNBQTJDLE9BQU8sYUFBYSxXQUFXLGdDQUFnQyxNQUFNLEVBQUUsQ0FBQztBQUM3SSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHQgfSBmcm9tICcuLi8uLi9hY3Rpb25zL2RpYWdub3NlJztcbmltcG9ydCB0eXBlIHsgSUNsb3VkV2F0Y2hMb2dzQ2xpZW50LCBJRUNTQ2xpZW50LCBTREsgfSBmcm9tICcuLi9hd3MtYXV0aC9zZGsnO1xuaW1wb3J0IHR5cGUgeyBSZXNvdXJjZUVycm9yIH0gZnJvbSAnLi4vc3RhY2stZXZlbnRzL3Jlc291cmNlLWVycm9ycyc7XG5cbi8qKlxuICogTWF4aW11bSBudW1iZXIgb2YgbG9nIGxpbmVzIGluY2x1ZGVkIHBlciBDbG91ZFdhdGNoIExvZ3MgY29udGV4dCBibG9jay5cbiAqXG4gKiBUaGUgZm9ybWF0dGVyIHJlbmRlcnMgdGhlIG1lc3NhZ2VzIGFycmF5IHZlcmJhdGltLCBzbyB0aGlzIGlzIHRoZVxuICogc2luZ2xlIHVzZXItdmlzaWJsZSBjYXAuXG4gKi9cbmNvbnN0IE1BWF9MT0dfTElORVMgPSA1MDtcblxuLyoqXG4gKiBPcHRpb25zIHRoYXQgaW5mbHVlbmNlIGhvdyBhIHJlc291cmNlIGlzIGludmVzdGlnYXRlZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbnZlc3RpZ2F0ZU9wdGlvbnMge1xuICAvKipcbiAgICogV2hldGhlciBDbG91ZEZvcm1hdGlvbiByb2xsYmFjayBpcyBlbmFibGVkIGZvciB0aGlzIGRlcGxveW1lbnQuXG4gICAqXG4gICAqIFdoZW4gcm9sbGJhY2sgaXMgZW5hYmxlZCwgYSBmYWlsZWQgcmVzb3VyY2UgaXMgdG9ybiBkb3duIGJlZm9yZSB3ZSBjYW5cbiAgICogaW5zcGVjdCBpdHMgcnVudGltZSBzdGF0ZSwgc28gd2UgbWF5IHN1Z2dlc3QgcmUtcnVubmluZyB3aXRoIGAtLW5vLXJvbGxiYWNrYFxuICAgKiB0byByZXRhaW4gdGhhdCBkZXRhaWwuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHJvbGxiYWNrRW5hYmxlZD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogSW52ZXN0aWdhdGUgYSBmYWlsZWQgcmVzb3VyY2UgdXNpbmcgQVdTIHNlcnZpY2UgQVBJcyB0byBnYXRoZXIgYWRkaXRpb25hbCByb290IGNhdXNlIGNvbnRleHQuXG4gKlxuICogUmV0dXJucyBhZGRpdGlvbmFsIGRpYWdub3N0aWMgY29udGV4dCAoZS5nLiBsb2cgbGluZXMpIG9yIGFuIGVtcHR5IGFycmF5IGlmXG4gKiBpbnZlc3RpZ2F0aW9uIGlzIG5vdCBwb3NzaWJsZSBvciB5aWVsZHMgbm8gcmVzdWx0cyBmb3IgdGhpcyByZXNvdXJjZSB0eXBlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW52ZXN0aWdhdGVSZXNvdXJjZShcbiAgZXJyOiBSZXNvdXJjZUVycm9yLFxuICBzZGs6IFNESyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbiAgb3B0aW9uczogSW52ZXN0aWdhdGVPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPEFkZGl0aW9uYWxEaWFnbm9zdGljQ29udGV4dFtdPiB7XG4gIHN3aXRjaCAoZXJyLnJlc291cmNlVHlwZSkge1xuICAgIGNhc2UgJ0FXUzo6RUNTOjpTZXJ2aWNlJzpcbiAgICAgIHJldHVybiBpbnZlc3RpZ2F0ZUVjc1NlcnZpY2UoZXJyLCBzZGssIGRlYnVnLCBvcHRpb25zKTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIFtdO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGludmVzdGlnYXRlRWNzU2VydmljZShcbiAgZXJyOiBSZXNvdXJjZUVycm9yLFxuICBzZGs6IFNESyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbiAgb3B0aW9uczogSW52ZXN0aWdhdGVPcHRpb25zLFxuKTogUHJvbWlzZTxBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHRbXT4ge1xuICBjb25zdCBwaHlzaWNhbElkID0gZXJyLnBoeXNpY2FsSWQ7XG4gIGlmICghcGh5c2ljYWxJZCkge1xuICAgIGF3YWl0IGRlYnVnKCdFQ1MgaW52ZXN0aWdhdGlvbjogbm8gcGh5c2ljYWwgSUQgYXZhaWxhYmxlJyk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgeyBjbHVzdGVyLCBzZXJ2aWNlTmFtZSB9ID0gcGFyc2VFY3NTZXJ2aWNlSWRlbnRpZmllcihwaHlzaWNhbElkKTtcbiAgaWYgKCFzZXJ2aWNlTmFtZSkge1xuICAgIGF3YWl0IGRlYnVnKGBFQ1MgaW52ZXN0aWdhdGlvbjogY291bGQgbm90IHBhcnNlIHNlcnZpY2UgaWRlbnRpZmllciBmcm9tIFwiJHtwaHlzaWNhbElkfVwiYCk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgcmVnaW9uID0gc2RrLmN1cnJlbnRSZWdpb247XG4gIGNvbnN0IGVjcyA9IHNkay5lY3MoKTtcbiAgY29uc3QgY3dsID0gc2RrLmNsb3VkV2F0Y2hMb2dzKCk7XG5cbiAgY29uc3Qgc2VydmljZSA9IGF3YWl0IGRlc2NyaWJlU2VydmljZShlY3MsIGNsdXN0ZXIsIHNlcnZpY2VOYW1lLCBkZWJ1Zyk7XG4gIGlmICghc2VydmljZSkge1xuICAgIC8vIFRoZSBzZXJ2aWNlIGlzIGdvbmUuIFRoZSBtb3N0IGNvbW1vbiByZWFzb24gaXMgdGhhdCBDbG91ZEZvcm1hdGlvbiByb2xsZWQgdGhlXG4gICAgLy8gZGVwbG95bWVudCBiYWNrIGFuZCBkZWxldGVkIGl0LCB0YWtpbmcgdGhlIHRhc2svcnVudGltZSBkZXRhaWwgd2l0aCBpdC4gSWYgcm9sbGJhY2tcbiAgICAvLyB3YXMgZW5hYmxlZCwgcG9pbnQgdGhlIHVzZXIgYXQgdGhlIGZsYWcgdGhhdCB3b3VsZCBoYXZlIHJldGFpbmVkIHRoYXQgZGV0YWlsLlxuICAgIGlmIChvcHRpb25zLnJvbGxiYWNrRW5hYmxlZCkge1xuICAgICAgcmV0dXJuIFt7XG4gICAgICAgIHNvdXJjZTogJ0VDUyBTZXJ2aWNlJyxcbiAgICAgICAgbWVzc2FnZXM6IFtcbiAgICAgICAgICAnVGhlIHNlcnZpY2UgYW5kIGl0cyB0YXNrcyB3ZXJlIHJlbW92ZWQgZHVyaW5nIHJvbGxiYWNrLCBzbyBjb250YWluZXItbGV2ZWwgZmFpbHVyZSBkZXRhaWwgaXMgdW5hdmFpbGFibGUuJyxcbiAgICAgICAgICAnUmUtcnVuIHRoZSBkZXBsb3ltZW50IHdpdGggYC0tbm8tcm9sbGJhY2tgIHRvIHJldGFpbiB0aGUgZmFpbGVkIHRhc2tzIGFuZCBzZWUgd2h5IHRoZXkgc3RvcHBlZC4nLFxuICAgICAgICBdLFxuICAgICAgfV07XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdHM6IEFkZGl0aW9uYWxEaWFnbm9zdGljQ29udGV4dFtdID0gW107XG5cbiAgY29uc3Qgc3RvcHBlZFRhc2tSZXN1bHQgPSBhd2FpdCBnZXRTdG9wcGVkVGFza1JlYXNvbnMoZWNzLCBjbHVzdGVyLCBzZXJ2aWNlTmFtZSwgcmVnaW9uLCBzZXJ2aWNlLCBkZWJ1Zyk7XG4gIGlmIChzdG9wcGVkVGFza1Jlc3VsdC5jb250ZXh0KSB7XG4gICAgcmVzdWx0cy5wdXNoKHN0b3BwZWRUYXNrUmVzdWx0LmNvbnRleHQpO1xuICB9XG5cbiAgY29uc3QgdGFza0RlZmluaXRpb25Bcm4gPSBzZXJ2aWNlLnRhc2tEZWZpbml0aW9uO1xuICBpZiAoIXRhc2tEZWZpbml0aW9uQXJuKSB7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBjb25zdCB0YXNrRGVmSW5mbyA9IGF3YWl0IGdldFRhc2tEZWZpbml0aW9uSW5mbyhlY3MsIHRhc2tEZWZpbml0aW9uQXJuLCBkZWJ1Zyk7XG4gIGlmICghdGFza0RlZkluZm8pIHtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGNvbnN0IGxvZ0NvbmZpZ3MgPSB0YXNrRGVmSW5mby5sb2dDb25maWdzO1xuXG4gIGlmIChsb2dDb25maWdzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICBzb3VyY2U6ICdDbG91ZFdhdGNoIExvZ3MnLFxuICAgICAgbWVzc2FnZXM6IFtcbiAgICAgICAgJ05vIENsb3VkV2F0Y2ggTG9ncyBjb25maWd1cmF0aW9uIGZvdW5kLiBFbmFibGUgbG9nZ2luZyB0byBzZWUgY29udGFpbmVyIG91dHB1dCBvbiBmYWlsdXJlLicsXG4gICAgICAgICdFeGFtcGxlOicsXG4gICAgICAgICcgIHRhc2tEZWZpbml0aW9uLmFkZENvbnRhaW5lcihcImFwcFwiLCB7JyxcbiAgICAgICAgJyAgICAvLyAuLi4nLFxuICAgICAgICAnICAgIGxvZ2dpbmc6IGVjcy5Mb2dEcml2ZXJzLmF3c0xvZ3MoeyBzdHJlYW1QcmVmaXg6IFwibXktc2VydmljZVwiIH0pLCcsXG4gICAgICAgICcgIH0pOycsXG4gICAgICBdLFxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgLy8gYGxvZ0NvbmZpZ3NgIGhhcyBvbmUgZW50cnkgcGVyIGNvbnRhaW5lciBpbiB0aGUgdGFzayBkZWZpbml0aW9uIHRoYXQgdXNlcyB0aGUgYXdzbG9nc1xuICAvLyBkcml2ZXIg4oCUIGEgaGFuZGZ1bCBhdCBtb3N0IOKAlCBzbyB0aGlzIGZhbi1vdXQgaXMgYm91bmRlZCBieSB0aGUgdGFzayBzaGFwZSBhbmQgbmVlZHMgbm9cbiAgLy8gZXhwbGljaXQgY29uY3VycmVuY3kgbGltaXQuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAY2RrbGFicy9wcm9taXNlYWxsLW5vLXVuYm91bmRlZC1wYXJhbGxlbGlzbVxuICBjb25zdCBsb2dSZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwobG9nQ29uZmlncy5tYXAoY2ZnID0+IGZldGNoUmVjZW50TG9ncyhjd2wsIGNmZywgcmVnaW9uLCBzdG9wcGVkVGFza1Jlc3VsdC50YXNrSWRzLCBkZWJ1ZykpKTtcbiAgY29uc3QgbG9nQ29udGV4dHMgPSBsb2dSZXN1bHRzLmZpbHRlcigoYyk6IGMgaXMgQWRkaXRpb25hbERpYWdub3N0aWNDb250ZXh0ID0+IGMgIT09IHVuZGVmaW5lZCk7XG5cbiAgcmVzdWx0cy5wdXNoKC4uLmxvZ0NvbnRleHRzKTtcbiAgaWYgKGxvZ0NvbnRleHRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICBzb3VyY2U6ICdDbG91ZFdhdGNoIExvZ3MnLFxuICAgICAgbWVzc2FnZXM6IFsnTm8gQ2xvdWRXYXRjaCBMb2dzIGZvdW5kLiddLFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdHM7XG59XG5cbi8qKlxuICogUGFyc2UgYW4gRUNTIHNlcnZpY2UgcGh5c2ljYWwgcmVzb3VyY2UgSUQgaW50byBjbHVzdGVyIGFuZCBzZXJ2aWNlIGlkZW50aWZpZXJzLlxuICpcbiAqIFRoZSBjbHVzdGVyIHBvcnRpb24gaXMgYSBuYW1lIChub3QgYW4gQVJOKSDigJQgYGRlc2NyaWJlU2VydmljZXNgL2BkZXNjcmliZVRhc2tzYFxuICogYWNjZXB0IGVpdGhlciBmb3JtIGZvciB0aGVpciBgY2x1c3RlcmAgcGFyYW1ldGVyLCBzbyB0aGlzIGlzIGZpbmUgZG93bnN0cmVhbS5cbiAqXG4gKiBSZWNvZ25pemVkIGZvcm1hdHM6XG4gKiAtIExvbmcgQVJOOiBgYXJuOmF3czplY3M6cmVnaW9uOmFjY291bnQ6c2VydmljZS9jbHVzdGVyLW5hbWUvc2VydmljZS1uYW1lYCAoY3VycmVudCBkZWZhdWx0KVxuICogLSBQYXRoOiBgY2x1c3Rlci1uYW1lL3NlcnZpY2UtbmFtZWBcbiAqIC0gQmFyZSBzZXJ2aWNlIG5hbWUgKHVzZXMgdGhlIGRlZmF1bHQgY2x1c3RlcilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlRWNzU2VydmljZUlkZW50aWZpZXIocGh5c2ljYWxJZDogc3RyaW5nKTogeyBjbHVzdGVyPzogc3RyaW5nOyBzZXJ2aWNlTmFtZT86IHN0cmluZyB9IHtcbiAgY29uc3QgYXJuTWF0Y2ggPSBwaHlzaWNhbElkLm1hdGNoKC9eYXJuOlteOl0rOmVjczpbXjpdKjpbXjpdKjpzZXJ2aWNlXFwvKFteL10rKVxcLyhbXi9dKykkLyk7XG4gIGlmIChhcm5NYXRjaCkge1xuICAgIHJldHVybiB7IGNsdXN0ZXI6IGFybk1hdGNoWzFdLCBzZXJ2aWNlTmFtZTogYXJuTWF0Y2hbMl0gfTtcbiAgfVxuXG4gIGNvbnN0IHBhcnRzID0gcGh5c2ljYWxJZC5zcGxpdCgnLycpO1xuICBpZiAocGFydHMubGVuZ3RoID09PSAyICYmIHBhcnRzWzBdICYmIHBhcnRzWzFdKSB7XG4gICAgcmV0dXJuIHsgY2x1c3RlcjogcGFydHNbMF0sIHNlcnZpY2VOYW1lOiBwYXJ0c1sxXSB9O1xuICB9XG4gIGlmIChwYXJ0cy5sZW5ndGggPT09IDEgJiYgcGFydHNbMF0pIHtcbiAgICByZXR1cm4geyBzZXJ2aWNlTmFtZTogcGFydHNbMF0gfTtcbiAgfVxuXG4gIHJldHVybiB7fTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVzY3JpYmVTZXJ2aWNlKFxuICBlY3M6IElFQ1NDbGllbnQsXG4gIGNsdXN0ZXI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgc2VydmljZU5hbWU6IHN0cmluZyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbikge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBlY3MuZGVzY3JpYmVTZXJ2aWNlcyh7IGNsdXN0ZXIsIHNlcnZpY2VzOiBbc2VydmljZU5hbWVdIH0pO1xuICAgIGNvbnN0IHNlcnZpY2UgPSByZXNwLnNlcnZpY2VzPy5bMF07XG4gICAgaWYgKCFzZXJ2aWNlKSB7XG4gICAgICBhd2FpdCBkZWJ1ZyhgRUNTIGludmVzdGlnYXRpb246IHNlcnZpY2UgXCIke3NlcnZpY2VOYW1lfVwiIG5vdCBmb3VuZGApO1xuICAgIH1cbiAgICByZXR1cm4gc2VydmljZTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgYXdhaXQgZGVidWcoYEVDUyBpbnZlc3RpZ2F0aW9uOiBmYWlsZWQgdG8gZGVzY3JpYmUgc2VydmljZTogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgU3RvcHBlZFRhc2tSZXN1bHQge1xuICBjb250ZXh0PzogQWRkaXRpb25hbERpYWdub3N0aWNDb250ZXh0O1xuICB0YXNrSWRzOiBzdHJpbmdbXTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0U3RvcHBlZFRhc2tSZWFzb25zKFxuICBlY3M6IElFQ1NDbGllbnQsXG4gIGNsdXN0ZXI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgc2VydmljZU5hbWU6IHN0cmluZyxcbiAgcmVnaW9uOiBzdHJpbmcsXG4gIHNlcnZpY2U6IHsgZXZlbnRzPzogQXJyYXk8eyBtZXNzYWdlPzogc3RyaW5nIH0+OyBba2V5OiBzdHJpbmddOiBhbnkgfSxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8U3RvcHBlZFRhc2tSZXN1bHQ+IHtcbiAgdHJ5IHtcbiAgICAvLyBBc2sgRUNTIGZvciB0aGUgc2VydmljZSdzIHN0b3BwZWQgdGFza3MuIFRoZSBJRHMgd2UgbmVlZCBsaXZlIGluIFwiaGFzIHN0YXJ0ZWQgMSB0YXNrczogKHRhc2sgPGlkPilcIiBldmVudHNcbiAgICBjb25zdCB0YXNrSWRzID0gYXdhaXQgbGlzdFN0b3BwZWRUYXNrSWRzKGVjcywgY2x1c3Rlciwgc2VydmljZU5hbWUsIGRlYnVnKTtcblxuICAgIGNvbnN0IG1lc3NhZ2VzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKHRhc2tJZHMubGVuZ3RoID4gMCkge1xuICAgICAgLy8gU2hvdyBkZXRhaWxzIGZyb20gdGhlIG1vc3QgcmVjZW50bHkgc3RvcHBlZCB0YXNrIG9ubHkuXG4gICAgICBjb25zdCB0YXNrc1Jlc3AgPSBhd2FpdCBlY3MuZGVzY3JpYmVUYXNrcyh7IGNsdXN0ZXIsIHRhc2tzOiBbdGFza0lkc1swXV0gfSk7XG4gICAgICBjb25zdCB0YXNrID0gdGFza3NSZXNwLnRhc2tzPy5bMF07XG4gICAgICBpZiAodGFzaykge1xuICAgICAgICBpZiAodGFzay5zdG9wcGVkUmVhc29uKSB7XG4gICAgICAgICAgbWVzc2FnZXMucHVzaChgVGFzayBzdG9wcGVkOiAke3Rhc2suc3RvcHBlZFJlYXNvbn1gKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGNvbnRhaW5lciBvZiB0YXNrLmNvbnRhaW5lcnMgPz8gW10pIHtcbiAgICAgICAgICBpZiAoY29udGFpbmVyLnJlYXNvbikge1xuICAgICAgICAgICAgbWVzc2FnZXMucHVzaChgQ29udGFpbmVyIFwiJHtjb250YWluZXIubmFtZX1cIjogJHtjb250YWluZXIucmVhc29ufWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY29udGFpbmVyLmV4aXRDb2RlICE9IG51bGwgJiYgY29udGFpbmVyLmV4aXRDb2RlICE9PSAwKSB7XG4gICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGBDb250YWluZXIgXCIke2NvbnRhaW5lci5uYW1lfVwiIGV4aXRlZCB3aXRoIGNvZGUgJHtjb250YWluZXIuZXhpdENvZGV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobWVzc2FnZXMubGVuZ3RoID4gMCAmJiB0YXNrSWRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgbWVzc2FnZXMucHVzaChgKCR7dGFza0lkcy5sZW5ndGggLSAxfSBvdGhlciBmYWlsZWQgdGFzayhzKSBub3Qgc2hvd24pYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmFsbCBiYWNrIHRvIHRoZSBtb3N0IHJlbGV2YW50IHNlcnZpY2UgZXZlbnQgaWYgd2UgY291bGRuJ3QgZ2V0IGEgdGFzay1sZXZlbCByZWFzb25cbiAgICAvLyAoZS5nLiB0YXNrcyBhbHJlYWR5IGFnZWQgb3V0LCBvciBubyBzdG9wcGVkIHRhc2tzIHJldGFpbmVkKS5cbiAgICBpZiAobWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zdCBmYWlsdXJlRXZlbnQgPSAoc2VydmljZS5ldmVudHMgPz8gW10pXG4gICAgICAgIC5maW5kKGUgPT4gZS5tZXNzYWdlPy5pbmNsdWRlcygnc3RvcHBlZCcpIHx8IGUubWVzc2FnZT8uaW5jbHVkZXMoJ2ZhaWxlZCcpIHx8IGUubWVzc2FnZT8uaW5jbHVkZXMoJ3VuaGVhbHRoeScpKTtcbiAgICAgIGlmIChmYWlsdXJlRXZlbnQ/Lm1lc3NhZ2UpIHtcbiAgICAgICAgbWVzc2FnZXMucHVzaChmYWlsdXJlRXZlbnQubWVzc2FnZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHsgdGFza0lkcyB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZXh0OiB7XG4gICAgICAgIHNvdXJjZTogJ0VDUyBTdG9wcGVkIFRhc2tzJyxcbiAgICAgICAgbWVzc2FnZXMsXG4gICAgICAgIGxpbms6IGVjc1N0b3BwZWRUYXNrc0NvbnNvbGVVcmwocmVnaW9uLCBjbHVzdGVyID8/ICdkZWZhdWx0Jywgc2VydmljZU5hbWUpLFxuICAgICAgICBsaW5rTGFiZWw6ICdUYXNrcycsXG4gICAgICB9LFxuICAgICAgdGFza0lkcyxcbiAgICB9O1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICBhd2FpdCBkZWJ1ZyhgRUNTIGludmVzdGlnYXRpb246IGZhaWxlZCB0byBnZXQgc3RvcHBlZCB0YXNrIHJlYXNvbnM6ICR7ZS5tZXNzYWdlfWApO1xuICAgIHJldHVybiB7IHRhc2tJZHM6IFtdIH07XG4gIH1cbn1cblxuLyoqXG4gKiBNYXhpbXVtIG51bWJlciBvZiBzdG9wcGVkIHRhc2sgSURzIHRvIGNvbnNpZGVyLiBXZSBvbmx5IHJlbmRlciBkZXRhaWwgZm9yIHRoZSBtb3N0XG4gKiByZWNlbnQgb25lLCBidXQga2VlcCBhIGZldyBzbyB3ZSBjYW4gcmVwb3J0IGhvdyBtYW55IG90aGVycyBmYWlsZWQuXG4gKi9cbmNvbnN0IE1BWF9TVE9QUEVEX1RBU0tTID0gMztcblxuLyoqXG4gKiBMaXN0IHRoZSBiYXJlIHRhc2sgSURzIG9mIHRoZSBzZXJ2aWNlJ3Mgc3RvcHBlZCB0YXNrcywgbmV3ZXN0IGZpcnN0LlxuICpcbiAqIFByZWZlcnMgc2NvcGluZyBieSBzZXJ2aWNlIG5hbWU7IGlmIHRoYXQgeWllbGRzIG5vdGhpbmcgKHNvbWUgRUNTIEFQSSB2ZXJzaW9ucyBvbmx5XG4gKiBhcHBseSB0aGUgc2VydmljZSBmaWx0ZXIgdG8gcnVubmluZyB0YXNrcyksIGZhbGxzIGJhY2sgdG8gbGlzdGluZyB0aGUgY2x1c3RlcidzIHN0b3BwZWRcbiAqIHRhc2tzLiBSZXR1cm5zIGFuIGVtcHR5IGFycmF5IGlmIG5vbmUgYXJlIHJldGFpbmVkIChlLmcuIHRoZXkgYWdlZCBvdXQsIG9yIHJvbGxiYWNrXG4gKiBhbHJlYWR5IGRyYWluZWQgdGhlIGNsdXN0ZXIpLlxuICovXG5hc3luYyBmdW5jdGlvbiBsaXN0U3RvcHBlZFRhc2tJZHMoXG4gIGVjczogSUVDU0NsaWVudCxcbiAgY2x1c3Rlcjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBzZXJ2aWNlTmFtZTogc3RyaW5nLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCB0b0lkcyA9IChhcm5zOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPT4gKGFybnMgPz8gW10pLm1hcChhcm4gPT4gYXJuLnNwbGl0KCcvJykucG9wKCkpLmZpbHRlcigoaWQpOiBpZCBpcyBzdHJpbmcgPT4gISFpZCk7XG5cbiAgbGV0IGFybnM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICB0cnkge1xuICAgIGNvbnN0IGJ5U2VydmljZSA9IGF3YWl0IGVjcy5saXN0VGFza3MoeyBjbHVzdGVyLCBzZXJ2aWNlTmFtZSwgZGVzaXJlZFN0YXR1czogJ1NUT1BQRUQnIH0pO1xuICAgIGFybnMgPSBieVNlcnZpY2UudGFza0FybnM7XG4gICAgaWYgKCFhcm5zIHx8IGFybnMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zdCBieUNsdXN0ZXIgPSBhd2FpdCBlY3MubGlzdFRhc2tzKHsgY2x1c3RlciwgZGVzaXJlZFN0YXR1czogJ1NUT1BQRUQnIH0pO1xuICAgICAgYXJucyA9IGJ5Q2x1c3Rlci50YXNrQXJucztcbiAgICB9XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIGF3YWl0IGRlYnVnKGBFQ1MgaW52ZXN0aWdhdGlvbjogZmFpbGVkIHRvIGxpc3Qgc3RvcHBlZCB0YXNrczogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcmV0dXJuIHRvSWRzKGFybnMpLnNsaWNlKDAsIE1BWF9TVE9QUEVEX1RBU0tTKTtcbn1cblxuaW50ZXJmYWNlIEF3c0xvZ3NDb25maWcge1xuICBsb2dHcm91cDogc3RyaW5nO1xuICBzdHJlYW1QcmVmaXg/OiBzdHJpbmc7XG4gIGNvbnRhaW5lck5hbWU/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBUYXNrRGVmaW5pdGlvbkluZm8ge1xuICBsb2dDb25maWdzOiBBd3NMb2dzQ29uZmlnW107XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFRhc2tEZWZpbml0aW9uSW5mbyhcbiAgZWNzOiBJRUNTQ2xpZW50LFxuICB0YXNrRGVmaW5pdGlvbkFybjogc3RyaW5nLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxUYXNrRGVmaW5pdGlvbkluZm8gfCB1bmRlZmluZWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgZWNzLmRlc2NyaWJlVGFza0RlZmluaXRpb24oeyB0YXNrRGVmaW5pdGlvbjogdGFza0RlZmluaXRpb25Bcm4gfSk7XG4gICAgY29uc3QgY29udGFpbmVycyA9IHJlc3AudGFza0RlZmluaXRpb24/LmNvbnRhaW5lckRlZmluaXRpb25zID8/IFtdO1xuICAgIGNvbnN0IGxvZ0NvbmZpZ3M6IEF3c0xvZ3NDb25maWdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgY29udGFpbmVyIG9mIGNvbnRhaW5lcnMpIHtcbiAgICAgIGNvbnN0IGxvZ0NvbmZpZyA9IGNvbnRhaW5lci5sb2dDb25maWd1cmF0aW9uO1xuICAgICAgaWYgKGxvZ0NvbmZpZz8ubG9nRHJpdmVyID09PSAnYXdzbG9ncycpIHtcbiAgICAgICAgY29uc3QgbG9nR3JvdXAgPSBsb2dDb25maWcub3B0aW9ucz8uWydhd3Nsb2dzLWdyb3VwJ107XG4gICAgICAgIGlmIChsb2dHcm91cCkge1xuICAgICAgICAgIGxvZ0NvbmZpZ3MucHVzaCh7XG4gICAgICAgICAgICBsb2dHcm91cCxcbiAgICAgICAgICAgIHN0cmVhbVByZWZpeDogbG9nQ29uZmlnLm9wdGlvbnM/LlsnYXdzbG9ncy1zdHJlYW0tcHJlZml4J10sXG4gICAgICAgICAgICBjb250YWluZXJOYW1lOiBjb250YWluZXIubmFtZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBsb2dDb25maWdzIH07XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIGF3YWl0IGRlYnVnKGBFQ1MgaW52ZXN0aWdhdGlvbjogZmFpbGVkIHRvIGRlc2NyaWJlIHRhc2sgZGVmaW5pdGlvbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaFJlY2VudExvZ3MoXG4gIGN3bDogSUNsb3VkV2F0Y2hMb2dzQ2xpZW50LFxuICBsb2dDb25maWc6IEF3c0xvZ3NDb25maWcsXG4gIHJlZ2lvbjogc3RyaW5nLFxuICB0YXNrSWRzOiBzdHJpbmdbXSxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8QWRkaXRpb25hbERpYWdub3N0aWNDb250ZXh0IHwgdW5kZWZpbmVkPiB7XG4gIHRyeSB7XG4gICAgLy8gVGFyZ2V0IHRoZSBtb3N0IHJlY2VudGx5IGZhaWxlZCB0YXNrJ3MgbG9nIHN0cmVhbSBmb3IgdGhlIG1vc3QgcmVsZXZhbnQgb3V0cHV0XG4gICAgY29uc3QgbGFzdFRhc2tJZCA9IHRhc2tJZHNbMF07XG4gICAgY29uc3QgdGFyZ2V0U3RyZWFtID0gKGxvZ0NvbmZpZy5zdHJlYW1QcmVmaXggJiYgbG9nQ29uZmlnLmNvbnRhaW5lck5hbWUgJiYgbGFzdFRhc2tJZClcbiAgICAgID8gYCR7bG9nQ29uZmlnLnN0cmVhbVByZWZpeH0vJHtsb2dDb25maWcuY29udGFpbmVyTmFtZX0vJHtsYXN0VGFza0lkfWBcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IGN3bC5maWx0ZXJMb2dFdmVudHMoe1xuICAgICAgbG9nR3JvdXBOYW1lOiBsb2dDb25maWcubG9nR3JvdXAsXG4gICAgICBzdGFydFRpbWU6IERhdGUubm93KCkgLSAzMCAqIDYwICogMTAwMCxcbiAgICAgIGxpbWl0OiAxMDAwLFxuICAgICAgLi4uKHRhcmdldFN0cmVhbVxuICAgICAgICA/IHsgbG9nU3RyZWFtTmFtZXM6IFt0YXJnZXRTdHJlYW1dIH1cbiAgICAgICAgOiBsb2dDb25maWcuc3RyZWFtUHJlZml4ID8geyBsb2dTdHJlYW1OYW1lUHJlZml4OiBsb2dDb25maWcuc3RyZWFtUHJlZml4IH0gOiB7fSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBldmVudHMgPSByZXNwLmV2ZW50cyA/PyBbXTtcbiAgICBpZiAoZXZlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXdhaXQgZGVidWcoYEVDUyBpbnZlc3RpZ2F0aW9uOiBubyByZWNlbnQgbG9nIGV2ZW50cyBpbiAke2xvZ0NvbmZpZy5sb2dHcm91cH0ke3RhcmdldFN0cmVhbSA/IGAgKHRhcmdldGVkIHN0cmVhbTogJHt0YXJnZXRTdHJlYW19KWAgOiAnJ31gKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gS2VlcCB0aGUgbW9zdCByZWNlbnQgbGluZXMgKG5ld2VyIG91dHB1dCBpcyBtb3JlIHVzZWZ1bCBmb3IgZGlhZ25vc2lzKS5cbiAgICAvLyBUaGlzIGlzIHRoZSBvbmx5IHRydW5jYXRpb24gcG9pbnQg4oCUIHRoZSBmb3JtYXR0ZXIgcmVuZGVycyB0aGVzZSB2ZXJiYXRpbS5cbiAgICBjb25zdCBhbGxNZXNzYWdlcyA9IGV2ZW50c1xuICAgICAgLm1hcChlID0+IGUubWVzc2FnZT8udHJpbUVuZCgpKVxuICAgICAgLmZpbHRlcigobSk6IG0gaXMgc3RyaW5nID0+IG0gIT0gbnVsbCk7XG4gICAgY29uc3QgbWVzc2FnZXM6IHN0cmluZ1tdID0gYWxsTWVzc2FnZXMuc2xpY2UoLU1BWF9MT0dfTElORVMpO1xuICAgIGNvbnN0IG9taXR0ZWQgPSBhbGxNZXNzYWdlcy5sZW5ndGggLSBtZXNzYWdlcy5sZW5ndGg7XG4gICAgaWYgKG9taXR0ZWQgPiAwKSB7XG4gICAgICBtZXNzYWdlcy51bnNoaWZ0KGAuLi4gKCR7b21pdHRlZH0gZWFybGllciBsaW5lcyBvbWl0dGVkKWApO1xuICAgIH1cblxuICAgIGlmICh0YXNrSWRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIG1lc3NhZ2VzLnB1c2goYChzaG93aW5nIGxvZ3MgZnJvbSBsYXN0IGZhaWxlZCB0YXNrOyAke3Rhc2tJZHMubGVuZ3RoIC0gMX0gb3RoZXIgZmFpbGVkIHRhc2socykgYXZhaWxhYmxlIGluIGNvbnNvbGUpYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc291cmNlID0gbG9nQ29uZmlnLmNvbnRhaW5lck5hbWVcbiAgICAgID8gYENsb3VkV2F0Y2ggTG9nczogJHtsb2dDb25maWcubG9nR3JvdXB9IChjb250YWluZXI6ICR7bG9nQ29uZmlnLmNvbnRhaW5lck5hbWV9KWBcbiAgICAgIDogYENsb3VkV2F0Y2ggTG9nczogJHtsb2dDb25maWcubG9nR3JvdXB9YDtcblxuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2UsXG4gICAgICBtZXNzYWdlcyxcbiAgICAgIGxpbms6IGNsb3VkV2F0Y2hMb2dzQ29uc29sZVVybChyZWdpb24sIGxvZ0NvbmZpZy5sb2dHcm91cCksXG4gICAgICBsaW5rTGFiZWw6ICdMb2dzJyxcbiAgICB9O1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICBhd2FpdCBkZWJ1ZyhgRUNTIGludmVzdGlnYXRpb246IGZhaWxlZCB0byBmZXRjaCBsb2dzIGZyb20gJHtsb2dDb25maWcubG9nR3JvdXB9OiAke2UubWVzc2FnZX1gKTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8vIENsb3VkV2F0Y2ggY29uc29sZSB1c2VzIGRvdWJsZS1VUkktZW5jb2Rpbmcgd2l0aCAnJCcgcmVwbGFjaW5nICclJyBmb3IgdGhlIGxvZyBncm91cCBpbiB0aGUgZnJhZ21lbnQuXG5mdW5jdGlvbiBjbG91ZFdhdGNoTG9nc0NvbnNvbGVVcmwocmVnaW9uOiBzdHJpbmcsIGxvZ0dyb3VwOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBlbmNvZGVkTG9nR3JvdXAgPSBlbmNvZGVVUklDb21wb25lbnQoZW5jb2RlVVJJQ29tcG9uZW50KGxvZ0dyb3VwKSkucmVwbGFjZSgvJS9nLCAnJCcpO1xuICByZXR1cm4gYGh0dHBzOi8vJHtyZWdpb259LmNvbnNvbGUuYXdzLmFtYXpvbi5jb20vY2xvdWR3YXRjaC9ob21lP3JlZ2lvbj0ke3JlZ2lvbn0jbG9nc1YyOmxvZy1ncm91cHMvbG9nLWdyb3VwLyR7ZW5jb2RlZExvZ0dyb3VwfWA7XG59XG5cbmZ1bmN0aW9uIGVjc1N0b3BwZWRUYXNrc0NvbnNvbGVVcmwocmVnaW9uOiBzdHJpbmcsIGNsdXN0ZXI6IHN0cmluZywgc2VydmljZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgaHR0cHM6Ly8ke3JlZ2lvbn0uY29uc29sZS5hd3MuYW1hem9uLmNvbS9lY3MvdjIvY2x1c3RlcnMvJHtjbHVzdGVyfS9zZXJ2aWNlcy8ke3NlcnZpY2VOYW1lfS90YXNrcz9zdGF0dXM9U1RPUFBFRCZyZWdpb249JHtyZWdpb259YDtcbn1cbiJdfQ==
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtaW52ZXN0aWdhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc291cmNlLWludmVzdGlnYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFjQSxrREFjQztBQTVCRCwrRUFBMEU7QUFDMUUsdUVBQTJGO0FBTzNGOzs7OztHQUtHO0FBQ0ksS0FBSyxVQUFVLG1CQUFtQixDQUN2QyxHQUFrQixFQUNsQixHQUFRLEVBQ1IsS0FBcUMsRUFDckMsVUFBOEIsRUFBRTtJQUVoQyxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQztJQUM1QyxJQUFJLFlBQVksS0FBSyxtQkFBbUIsRUFBRSxDQUFDO1FBQ3pDLE9BQU8sSUFBQSwrQ0FBcUIsRUFBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsSUFBSSxZQUFZLEtBQUsscUNBQXFDLElBQUksWUFBWSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ2xHLE9BQU8sSUFBQSx1REFBeUIsRUFBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbnZlc3RpZ2F0ZUN1c3RvbVJlc291cmNlIH0gZnJvbSAnLi9pbnZlc3RpZ2F0ZS1jdXN0b20tcmVzb3VyY2UnO1xuaW1wb3J0IHsgaW52ZXN0aWdhdGVFY3NTZXJ2aWNlLCB0eXBlIEludmVzdGlnYXRlT3B0aW9ucyB9IGZyb20gJy4vaW52ZXN0aWdhdGUtZWNzLXNlcnZpY2UnO1xuaW1wb3J0IHR5cGUgeyBBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHQgfSBmcm9tICcuLi8uLi9hY3Rpb25zL2RpYWdub3NlJztcbmltcG9ydCB0eXBlIHsgU0RLIH0gZnJvbSAnLi4vYXdzLWF1dGgvc2RrJztcbmltcG9ydCB0eXBlIHsgUmVzb3VyY2VFcnJvciB9IGZyb20gJy4uL3N0YWNrLWV2ZW50cy9yZXNvdXJjZS1lcnJvcnMnO1xuXG5leHBvcnQgdHlwZSB7IEludmVzdGlnYXRlT3B0aW9ucyB9O1xuXG4vKipcbiAqIEludmVzdGlnYXRlIGEgZmFpbGVkIHJlc291cmNlIHVzaW5nIEFXUyBzZXJ2aWNlIEFQSXMgdG8gZ2F0aGVyIGFkZGl0aW9uYWwgcm9vdCBjYXVzZSBjb250ZXh0LlxuICpcbiAqIFJldHVybnMgYWRkaXRpb25hbCBkaWFnbm9zdGljIGNvbnRleHQgKGUuZy4gbG9nIGxpbmVzKSBvciBhbiBlbXB0eSBhcnJheSBpZlxuICogaW52ZXN0aWdhdGlvbiBpcyBub3QgcG9zc2libGUgb3IgeWllbGRzIG5vIHJlc3VsdHMgZm9yIHRoaXMgcmVzb3VyY2UgdHlwZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGludmVzdGlnYXRlUmVzb3VyY2UoXG4gIGVycjogUmVzb3VyY2VFcnJvcixcbiAgc2RrOiBTREssXG4gIGRlYnVnOiAobXNnOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4sXG4gIG9wdGlvbnM6IEludmVzdGlnYXRlT3B0aW9ucyA9IHt9LFxuKTogUHJvbWlzZTxBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHRbXT4ge1xuICBjb25zdCByZXNvdXJjZVR5cGUgPSBlcnIucmVzb3VyY2VUeXBlID8/ICcnO1xuICBpZiAocmVzb3VyY2VUeXBlID09PSAnQVdTOjpFQ1M6OlNlcnZpY2UnKSB7XG4gICAgcmV0dXJuIGludmVzdGlnYXRlRWNzU2VydmljZShlcnIsIHNkaywgZGVidWcsIG9wdGlvbnMpO1xuICB9XG4gIGlmIChyZXNvdXJjZVR5cGUgPT09ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpDdXN0b21SZXNvdXJjZScgfHwgcmVzb3VyY2VUeXBlLnN0YXJ0c1dpdGgoJ0N1c3RvbTo6JykpIHtcbiAgICByZXR1cm4gaW52ZXN0aWdhdGVDdXN0b21SZXNvdXJjZShlcnIsIHNkaywgZGVidWcpO1xuICB9XG4gIHJldHVybiBbXTtcbn1cbiJdfQ==
|