@aws-cdk/toolkit-lib 1.29.0 → 1.30.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/diagnose/index.d.ts +28 -0
- package/lib/actions/diagnose/index.js +1 -1
- package/lib/actions/validate/index.d.ts +2 -0
- package/lib/actions/validate/index.js +1 -1
- package/lib/api/aws-auth/sdk.d.ts +5 -1
- package/lib/api/aws-auth/sdk.js +5 -1
- package/lib/api/cloud-assembly/environment.js +4 -1
- package/lib/api/cloud-assembly/stack-collection.d.ts +2 -0
- package/lib/api/cloud-assembly/stack-collection.js +3 -1
- package/lib/api/deployments/deploy-stack.js +4 -2
- package/lib/api/deployments/deployments.js +3 -1
- package/lib/api/diagnosing/diagnosis-formatting.js +54 -13
- package/lib/api/diagnosing/format-utils.d.ts +3 -0
- package/lib/api/diagnosing/format-utils.js +36 -0
- package/lib/api/diagnosing/resource-investigation.d.ts +41 -0
- package/lib/api/diagnosing/resource-investigation.js +302 -0
- package/lib/api/diagnosing/stack-diagnoser.d.ts +39 -3
- package/lib/api/diagnosing/stack-diagnoser.js +71 -30
- package/lib/api/hotswap/hotswap-deployments.js +3 -1
- package/lib/api/io/private/messages.js +2 -2
- package/lib/api/validate/validate-formatting.d.ts +9 -2
- package/lib/api/validate/validate-formatting.js +117 -69
- package/lib/payloads/hotswap.d.ts +8 -1
- package/lib/payloads/hotswap.js +1 -1
- package/lib/private/tools.js +26 -24
- package/lib/toolkit/private/collect-annotation-report.d.ts +12 -0
- package/lib/toolkit/private/collect-annotation-report.js +85 -0
- package/lib/toolkit/private/validation-report.d.ts +32 -0
- package/lib/toolkit/private/validation-report.js +119 -0
- package/lib/toolkit/toolkit.d.ts +4 -7
- package/lib/toolkit/toolkit.js +24 -67
- package/lib/toolkit/types.d.ts +1 -0
- package/lib/toolkit/types.js +1 -1
- package/lib/util/glob-matcher.d.ts +19 -7
- package/lib/util/glob-matcher.js +63 -14
- package/package.json +5 -5
- package/lib/api/diagnosing/tree-builder.d.ts +0 -13
- package/lib/api/diagnosing/tree-builder.js +0 -86
- package/lib/api/diagnosing/tree.d.ts +0 -19
- package/lib/api/diagnosing/tree.js +0 -72
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.investigateResource = investigateResource;
|
|
4
|
+
exports.parseEcsServiceIdentifier = parseEcsServiceIdentifier;
|
|
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;
|
|
12
|
+
/**
|
|
13
|
+
* Investigate a failed resource using AWS service APIs to gather additional root cause context.
|
|
14
|
+
*
|
|
15
|
+
* Returns additional diagnostic context (e.g. log lines) or an empty array if
|
|
16
|
+
* investigation is not possible or yields no results for this resource type.
|
|
17
|
+
*/
|
|
18
|
+
async function investigateResource(err, sdk, debug, options = {}) {
|
|
19
|
+
switch (err.resourceType) {
|
|
20
|
+
case 'AWS::ECS::Service':
|
|
21
|
+
return investigateEcsService(err, sdk, debug, options);
|
|
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;
|
|
83
|
+
}
|
|
84
|
+
// `logConfigs` has one entry per container in the task definition that uses the awslogs
|
|
85
|
+
// driver — a handful at most — so this fan-out is bounded by the task shape and needs no
|
|
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;
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
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}`;
|
|
301
|
+
}
|
|
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==
|
|
@@ -11,7 +11,21 @@ export interface CloudFormationStackDiagnoserProps {
|
|
|
11
11
|
readonly sourceTracer: ISourceTracer;
|
|
12
12
|
readonly ioHelper: IoHelper;
|
|
13
13
|
readonly topLevelStackHierarchicalId: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optionally: a function to return an SDK that can be used for additional
|
|
16
|
+
* (readonly) exploratory calls.
|
|
17
|
+
*
|
|
18
|
+
* Typically, this should be an SDK that is primed with the "lookup" role, or similar.
|
|
19
|
+
*
|
|
20
|
+
* This is necessary because the "deploy" role will not typically have permissions to
|
|
21
|
+
* do very much.
|
|
22
|
+
*
|
|
23
|
+
* Regardless, if lookups of additional information fail, they are emitted at debug
|
|
24
|
+
* level and their information is simply not added to the output.
|
|
25
|
+
*/
|
|
26
|
+
readonly additionalExplorationSdkProvider?: SdkProvider;
|
|
14
27
|
}
|
|
28
|
+
export type SdkProvider = () => Promise<SDK>;
|
|
15
29
|
/**
|
|
16
30
|
* Diagnose a stack's failed state
|
|
17
31
|
*
|
|
@@ -25,10 +39,27 @@ export interface CloudFormationStackDiagnoserProps {
|
|
|
25
39
|
* This class works at the CloudFormation level, and does not deal with tracing
|
|
26
40
|
* CloudFormation errors to construct code sources yet.
|
|
27
41
|
*/
|
|
42
|
+
/**
|
|
43
|
+
* Options that affect how a diagnosis is performed.
|
|
44
|
+
*/
|
|
45
|
+
export interface DiagnoseOptions {
|
|
46
|
+
/**
|
|
47
|
+
* Whether CloudFormation rollback is enabled for this deployment.
|
|
48
|
+
*
|
|
49
|
+
* When rollback is enabled, failed resources are torn down before we can
|
|
50
|
+
* inspect their runtime state (e.g. ECS tasks), so the investigation degrades
|
|
51
|
+
* to durable sources and may suggest re-running with `--no-rollback`.
|
|
52
|
+
*
|
|
53
|
+
* @default true
|
|
54
|
+
*/
|
|
55
|
+
readonly rollbackEnabled?: boolean;
|
|
56
|
+
}
|
|
28
57
|
export declare class CloudFormationStackDiagnoser {
|
|
29
58
|
private readonly props;
|
|
30
59
|
private readonly cfn;
|
|
31
60
|
private parentStackLogicalIds;
|
|
61
|
+
private _additionalExplorationSdkPromise?;
|
|
62
|
+
private rollbackEnabled;
|
|
32
63
|
constructor(props: CloudFormationStackDiagnoserProps);
|
|
33
64
|
/**
|
|
34
65
|
* Diagnose a stack's root cause given no pre-existing state
|
|
@@ -41,7 +72,7 @@ export declare class CloudFormationStackDiagnoser {
|
|
|
41
72
|
/**
|
|
42
73
|
* Diagnose potential problems with the change set
|
|
43
74
|
*/
|
|
44
|
-
diagnoseFromErrorCollection(errors: ResourceErrors, stack: Stack): Promise<StackDiagnosis>;
|
|
75
|
+
diagnoseFromErrorCollection(errors: ResourceErrors, stack: Stack, allowFallback?: boolean, options?: DiagnoseOptions): Promise<StackDiagnosis>;
|
|
45
76
|
/**
|
|
46
77
|
* Diagnose a deployment failure via stack events
|
|
47
78
|
*
|
|
@@ -65,8 +96,9 @@ export declare class CloudFormationStackDiagnoser {
|
|
|
65
96
|
* error.
|
|
66
97
|
*/
|
|
67
98
|
private _reportChangeSetFailureFromEvents;
|
|
68
|
-
private
|
|
69
|
-
private
|
|
99
|
+
private enhanceErrors;
|
|
100
|
+
private enhanceError;
|
|
101
|
+
private investigateResourceBestEffort;
|
|
70
102
|
/**
|
|
71
103
|
* Build a generic stack error from the given change set information
|
|
72
104
|
*
|
|
@@ -94,6 +126,10 @@ export declare class CloudFormationStackDiagnoser {
|
|
|
94
126
|
* ```
|
|
95
127
|
*/
|
|
96
128
|
private _tryDetectFailedAutoImport;
|
|
129
|
+
/**
|
|
130
|
+
* Return the additional exploration SDK, if available.
|
|
131
|
+
*/
|
|
132
|
+
private additionalExplorationSdk;
|
|
97
133
|
}
|
|
98
134
|
/**
|
|
99
135
|
* Return true if the given change set has no changes
|