@aws-cdk/toolkit-lib 1.29.1 → 1.31.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.
Files changed (110) hide show
  1. package/build-info.json +2 -2
  2. package/lib/actions/bootstrap/index.js +35 -2
  3. package/lib/actions/diagnose/index.d.ts +28 -0
  4. package/lib/actions/diagnose/index.js +1 -1
  5. package/lib/actions/diff/private/helpers.js +36 -3
  6. package/lib/actions/validate/index.d.ts +2 -0
  7. package/lib/actions/validate/index.js +1 -1
  8. package/lib/api/aws-auth/account-cache.js +36 -3
  9. package/lib/api/aws-auth/sdk-provider.js +36 -3
  10. package/lib/api/aws-auth/sdk.d.ts +7 -2
  11. package/lib/api/aws-auth/sdk.js +6 -1
  12. package/lib/api/aws-auth/user-agent.js +35 -2
  13. package/lib/api/aws-auth/util.js +35 -2
  14. package/lib/api/bootstrap/bootstrap-environment.js +35 -2
  15. package/lib/api/bootstrap/deploy-bootstrap.js +37 -4
  16. package/lib/api/cloud-assembly/context-store.js +36 -3
  17. package/lib/api/cloud-assembly/environment.js +40 -4
  18. package/lib/api/cloud-assembly/private/context-aware-source.js +35 -2
  19. package/lib/api/cloud-assembly/private/exec.js +35 -2
  20. package/lib/api/cloud-assembly/private/prepare-source.js +39 -6
  21. package/lib/api/cloud-assembly/source-builder.js +37 -4
  22. package/lib/api/cloud-assembly/stack-assembly.js +8 -4
  23. package/lib/api/cloud-assembly/stack-collection.d.ts +2 -0
  24. package/lib/api/cloud-assembly/stack-collection.js +3 -1
  25. package/lib/api/cloudformation/logical-id-map.js +35 -2
  26. package/lib/api/cloudformation/nested-stack-helpers.js +36 -3
  27. package/lib/api/cloudformation/template-body-parameter.js +42 -6
  28. package/lib/api/deployments/asset-manifest-builder.js +35 -2
  29. package/lib/api/deployments/assets.js +42 -6
  30. package/lib/api/deployments/cfn-api.d.ts +4 -2
  31. package/lib/api/deployments/cfn-api.js +47 -6
  32. package/lib/api/deployments/deploy-stack.js +11 -6
  33. package/lib/api/deployments/deployments.js +42 -4
  34. package/lib/api/diagnosing/diagnosis-formatting.js +54 -13
  35. package/lib/api/diagnosing/format-utils.d.ts +32 -0
  36. package/lib/api/diagnosing/format-utils.js +176 -0
  37. package/lib/api/diagnosing/investigate-custom-resource.d.ts +17 -0
  38. package/lib/api/diagnosing/investigate-custom-resource.js +247 -0
  39. package/lib/api/diagnosing/investigate-ecs-service.d.ts +20 -0
  40. package/lib/api/diagnosing/investigate-ecs-service.js +242 -0
  41. package/lib/api/diagnosing/resource-identifiers.d.ts +39 -0
  42. package/lib/api/diagnosing/resource-identifiers.js +90 -0
  43. package/lib/api/diagnosing/resource-investigation.d.ts +13 -0
  44. package/lib/api/diagnosing/resource-investigation.js +22 -0
  45. package/lib/api/diagnosing/stack-diagnoser.d.ts +39 -3
  46. package/lib/api/diagnosing/stack-diagnoser.js +71 -30
  47. package/lib/api/diff/diff-formatter.js +11 -8
  48. package/lib/api/drift/drift-formatter.js +20 -17
  49. package/lib/api/garbage-collection/garbage-collector.js +7 -4
  50. package/lib/api/garbage-collection/progress-printer.js +7 -4
  51. package/lib/api/hotswap/hotswap-deployments.js +46 -10
  52. package/lib/api/hotswap/hotswap-template-cache.js +36 -3
  53. package/lib/api/io/private/io-default-messages.js +35 -2
  54. package/lib/api/io/private/message-maker.d.ts +4 -0
  55. package/lib/api/io/private/message-maker.js +3 -1
  56. package/lib/api/io/private/messages.d.ts +2 -0
  57. package/lib/api/io/private/messages.js +44 -3
  58. package/lib/api/io/private/span.js +35 -2
  59. package/lib/api/logs-monitor/logs-monitor.js +40 -4
  60. package/lib/api/network-detector/network-detector.js +37 -4
  61. package/lib/api/notices/cached-data-source.js +35 -2
  62. package/lib/api/notices/filter.js +35 -2
  63. package/lib/api/notices/notices.js +35 -2
  64. package/lib/api/notices/web-data-source.js +35 -2
  65. package/lib/api/refactoring/digest.js +35 -2
  66. package/lib/api/refactoring/stack-definitions.js +40 -4
  67. package/lib/api/resource-import/importer.js +58 -15
  68. package/lib/api/resource-import/migrator.js +42 -6
  69. package/lib/api/rwlock.js +35 -2
  70. package/lib/api/settings.js +38 -5
  71. package/lib/api/source-tracing/private/stack-source-tracing.js +38 -5
  72. package/lib/api/stack-events/resource-errors.d.ts +12 -0
  73. package/lib/api/stack-events/resource-errors.js +2 -1
  74. package/lib/api/stack-events/stack-activity-monitor.js +35 -2
  75. package/lib/api/stack-events/stack-progress-monitor.js +35 -2
  76. package/lib/api/toolkit-info.js +7 -4
  77. package/lib/api/tree.js +36 -3
  78. package/lib/api/validate/validate-formatting.d.ts +9 -2
  79. package/lib/api/validate/validate-formatting.js +161 -77
  80. package/lib/api/work-graph/build-destroy-work-graph.js +35 -2
  81. package/lib/api/work-graph/work-graph-builder.js +35 -2
  82. package/lib/context-providers/index.js +35 -2
  83. package/lib/private/activity-printer/current.js +52 -16
  84. package/lib/private/activity-printer/history.js +50 -14
  85. package/lib/private/tools.js +64 -25
  86. package/lib/toolkit/non-interactive-io-host.js +11 -8
  87. package/lib/toolkit/private/collect-annotation-report.d.ts +12 -0
  88. package/lib/toolkit/private/collect-annotation-report.js +118 -0
  89. package/lib/toolkit/private/validation-report.d.ts +32 -0
  90. package/lib/toolkit/private/validation-report.js +152 -0
  91. package/lib/toolkit/toolkit-error.d.ts +20 -0
  92. package/lib/toolkit/toolkit-error.js +30 -2
  93. package/lib/toolkit/toolkit.d.ts +12 -7
  94. package/lib/toolkit/toolkit.js +104 -101
  95. package/lib/toolkit/types.d.ts +1 -0
  96. package/lib/toolkit/types.js +1 -1
  97. package/lib/util/content-hash.js +35 -2
  98. package/lib/util/directories.js +38 -5
  99. package/lib/util/glob-matcher.d.ts +19 -7
  100. package/lib/util/glob-matcher.js +63 -14
  101. package/lib/util/guess-language.js +36 -3
  102. package/lib/util/package-info.js +35 -2
  103. package/lib/util/serialize.js +36 -3
  104. package/lib/util/version-range.js +35 -2
  105. package/lib/util/yaml-cfn.js +36 -3
  106. package/package.json +5 -5
  107. package/lib/api/diagnosing/tree-builder.d.ts +0 -13
  108. package/lib/api/diagnosing/tree-builder.js +0 -86
  109. package/lib/api/diagnosing/tree.d.ts +0 -19
  110. package/lib/api/diagnosing/tree.js +0 -72
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sideBySide = sideBySide;
4
+ exports.wrapText = wrapText;
5
+ exports.trimToRecentLines = trimToRecentLines;
6
+ exports.parseLambdaLogEvents = parseLambdaLogEvents;
7
+ exports.cloudWatchLogsConsoleUrl = cloudWatchLogsConsoleUrl;
8
+ function sideBySide(left, sep, right) {
9
+ const width = left.map(x => x.length).reduce((acc, n) => Math.max(acc, n), 0);
10
+ const ret = [];
11
+ for (let i = 0; i < left.length || i < right.length; i++) {
12
+ const l = i < left.length ? left[i] : ' '.repeat(width);
13
+ const r = i < right.length ? right[i] : '';
14
+ ret.push(`${l}${sep}${r}`);
15
+ }
16
+ return ret;
17
+ }
18
+ function wrapText(n, text) {
19
+ const breakers = [' ', '\n'];
20
+ const ret = [];
21
+ let lineStart = 0;
22
+ while (lineStart < text.length) {
23
+ let lineEnd = lineStart + n;
24
+ while (lineEnd > lineStart && lineEnd < text.length && !breakers.includes(text[lineEnd])) {
25
+ lineEnd -= 1;
26
+ }
27
+ if (lineEnd === lineStart) {
28
+ // Could not find a space in this line. Seek forward to the first space to get the smallest line overflow
29
+ lineEnd = lineStart + n;
30
+ while (lineEnd < text.length && !breakers.includes(text[lineEnd])) {
31
+ lineEnd += 1;
32
+ }
33
+ }
34
+ ret.push(text.slice(lineStart, lineEnd));
35
+ lineStart = lineEnd + 1;
36
+ }
37
+ return ret;
38
+ }
39
+ // --- CloudWatch log formatting ---
40
+ /**
41
+ * Maximum number of log lines included per CloudWatch Logs context block.
42
+ *
43
+ * The formatter renders the messages array verbatim, so this is the
44
+ * single user-visible cap.
45
+ */
46
+ const MAX_LOG_LINES = 50;
47
+ /**
48
+ * Trim already-extracted log lines to the set we render.
49
+ *
50
+ * Keeps only the most recent {@link MAX_LOG_LINES} (newer output is more useful for
51
+ * diagnosis) and prepends an "N earlier lines omitted" marker when truncation happened.
52
+ * This is the single truncation point shared by all CloudWatch contexts — the formatter
53
+ * renders the result verbatim.
54
+ */
55
+ function trimToRecentLines(lines) {
56
+ const messages = lines.slice(-MAX_LOG_LINES);
57
+ const omitted = lines.length - messages.length;
58
+ if (omitted > 0) {
59
+ messages.unshift(`... (${omitted} earlier lines omitted)`);
60
+ }
61
+ return messages;
62
+ }
63
+ /**
64
+ * Lambda platform log lines (text format) that carry no application signal.
65
+ */
66
+ const LAMBDA_PLATFORM_LINE = /^(INIT_START|START RequestId:|END RequestId:|REPORT RequestId:)/;
67
+ /**
68
+ * Normalize Lambda CloudWatch log events into readable lines.
69
+ *
70
+ * Lambda emits logs in one of two formats (per the function's `LoggingConfig.LogFormat`):
71
+ * - **Text**: `<timestamp>\t<requestId>\t<LEVEL>\t<message>`, plus platform lines.
72
+ * - **JSON**: one JSON object per event (`{ timestamp, level, message, ... }`).
73
+ *
74
+ * For both we surface `LEVEL message` (or just the message when there's no level), strip the
75
+ * redundant per-line timestamp/requestId (it's all one invocation), and drop pure platform
76
+ * boilerplate. The level and message are combined into a single rendered line. We never drop
77
+ * application output — failure detail is often logged at INFO (e.g. the cfn-response "Response
78
+ * body" line). Anything we don't recognize passes through verbatim, and the full logs remain
79
+ * available via the console link.
80
+ *
81
+ * This is Lambda-specific; it is not applied to ECS logs, which are arbitrary container output.
82
+ */
83
+ function parseLambdaLogEvents(events) {
84
+ const out = [];
85
+ for (const e of events) {
86
+ const raw = e.message;
87
+ if (raw == null) {
88
+ continue;
89
+ }
90
+ const normalized = normalizeLambdaLine(raw);
91
+ if (normalized !== undefined) {
92
+ out.push(normalized);
93
+ }
94
+ }
95
+ return out;
96
+ }
97
+ /**
98
+ * Normalize a single Lambda log line. Returns `undefined` to drop the line (platform noise),
99
+ * or the cleaned-up text to keep.
100
+ */
101
+ function normalizeLambdaLine(raw) {
102
+ const trimmed = raw.trimEnd();
103
+ // JSON-format event: { timestamp, level, message, ... } (one object per line).
104
+ const jsonResult = normalizeJsonLogLine(trimmed);
105
+ if (jsonResult !== undefined) {
106
+ return jsonResult || undefined;
107
+ }
108
+ // Text-format platform boilerplate: drop.
109
+ if (LAMBDA_PLATFORM_LINE.test(trimmed)) {
110
+ return undefined;
111
+ }
112
+ // Text-format app line: `<ISO timestamp>\t<requestId>\t<LEVEL>\t<message>`.
113
+ // Strip the timestamp + requestId prefix; keep `LEVEL message` (or the rest verbatim).
114
+ const parts = trimmed.split('\t');
115
+ if (parts.length >= 4 && /^\d{4}-\d{2}-\d{2}T/.test(parts[0])) {
116
+ const level = parts[2];
117
+ const message = parts.slice(3).join('\t');
118
+ return formatLeveledLine(level, message);
119
+ }
120
+ // Unrecognized (continuation line, plain stdout, etc.) — keep verbatim.
121
+ return trimmed;
122
+ }
123
+ /**
124
+ * If `line` is a JSON-format Lambda log object, render it as `LEVEL message` (the level
125
+ * space-padded to a fixed width; or just the message when there's no level). Returns
126
+ * `undefined` when it isn't JSON.
127
+ *
128
+ * Drops JSON platform events (`type`/`record` envelopes for `platform.*`), which carry no
129
+ * application signal.
130
+ */
131
+ function normalizeJsonLogLine(line) {
132
+ if (!line.startsWith('{')) {
133
+ return undefined;
134
+ }
135
+ let obj;
136
+ try {
137
+ obj = JSON.parse(line);
138
+ }
139
+ catch {
140
+ return undefined;
141
+ }
142
+ if (!obj || typeof obj !== 'object') {
143
+ return undefined;
144
+ }
145
+ // Platform events (e.g. { type: 'platform.report', record: {...} }) — drop.
146
+ if (typeof obj.type === 'string' && obj.type.startsWith('platform.')) {
147
+ return '';
148
+ }
149
+ const level = typeof obj.level === 'string' ? obj.level : undefined;
150
+ // Lambda uses `message`; a thrown error envelope uses `errorMessage` (+ optional stackTrace).
151
+ let message;
152
+ if (typeof obj.message === 'string') {
153
+ message = obj.message;
154
+ }
155
+ else if (typeof obj.errorMessage === 'string') {
156
+ message = Array.isArray(obj.stackTrace) ? [obj.errorMessage, ...obj.stackTrace].join('\n') : obj.errorMessage;
157
+ }
158
+ else {
159
+ // JSON, but not a shape we recognize — render compactly rather than dropping signal.
160
+ message = line;
161
+ }
162
+ return level ? formatLeveledLine(level, message) : message;
163
+ }
164
+ /**
165
+ * Render a log level and message as `LEVEL message`, padding the level to a fixed width so
166
+ * lines align in the terminal. Multi-line messages keep their internal newlines.
167
+ */
168
+ function formatLeveledLine(level, message) {
169
+ return `${level.padEnd(5)} ${message}`;
170
+ }
171
+ // CloudWatch console uses double-URI-encoding with '$' replacing '%' for the log group in the fragment.
172
+ function cloudWatchLogsConsoleUrl(region, logGroup) {
173
+ const encodedLogGroup = encodeURIComponent(encodeURIComponent(logGroup)).replace(/%/g, '$');
174
+ return `https://${region}.console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:log-groups/log-group/${encodedLogGroup}`;
175
+ }
176
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZm9ybWF0LXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsZ0NBVUM7QUFFRCw0QkFzQkM7QUFvQkQsOENBT0M7QUF1QkQsb0RBYUM7QUFtRkQsNERBR0M7QUF2TEQsU0FBZ0IsVUFBVSxDQUFDLElBQWMsRUFBRSxHQUFXLEVBQUUsS0FBZTtJQUNyRSxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRTlFLE1BQU0sR0FBRyxHQUFhLEVBQUUsQ0FBQztJQUN6QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzNDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FB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Q0FBQyxNQUFjLEVBQUUsUUFBZ0I7SUFDdkUsTUFBTSxlQUFlLEdBQUcsa0JBQWtCLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzVGLE9BQU8sV0FBVyxNQUFNLGtEQUFrRCxNQUFNLGdDQUFnQyxlQUFlLEVBQUUsQ0FBQztBQUNwSSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIHNpZGVCeVNpZGUobGVmdDogc3RyaW5nW10sIHNlcDogc3RyaW5nLCByaWdodDogc3RyaW5nW10pIHtcbiAgY29uc3Qgd2lkdGggPSBsZWZ0Lm1hcCh4ID0+IHgubGVuZ3RoKS5yZWR1Y2UoKGFjYywgbikgPT4gTWF0aC5tYXgoYWNjLCBuKSwgMCk7XG5cbiAgY29uc3QgcmV0OiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlZnQubGVuZ3RoIHx8IGkgPCByaWdodC5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGwgPSBpIDwgbGVmdC5sZW5ndGggPyBsZWZ0W2ldIDogJyAnLnJlcGVhdCh3aWR0aCk7XG4gICAgY29uc3QgciA9IGkgPCByaWdodC5sZW5ndGggPyByaWdodFtpXSA6ICcnO1xuICAgIHJldC5wdXNoKGAke2x9JHtzZXB9JHtyfWApO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3cmFwVGV4dChuOiBudW1iZXIsIHRleHQ6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgYnJlYWtlcnMgPSBbJyAnLCAnXFxuJ107XG5cbiAgY29uc3QgcmV0OiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgbGluZVN0YXJ0ID0gMDtcbiAgd2hpbGUgKGxpbmVTdGFydCA8IHRleHQubGVuZ3RoKSB7XG4gICAgbGV0IGxpbmVFbmQgPSBsaW5lU3RhcnQgKyBuO1xuICAgIHdoaWxlIChsaW5lRW5kID4gbGluZVN0YXJ0ICYmIGxpbmVFbmQgPCB0ZXh0Lmxlbmd0aCAmJiAhYnJlYWtlcnMuaW5jbHVkZXModGV4dFtsaW5lRW5kXSkpIHtcbiAgICAgIGxpbmVFbmQgLT0gMTtcbiAgICB9XG4gICAgaWYgKGxpbmVFbmQgPT09IGxpbmVTdGFydCkge1xuICAgICAgLy8gQ291bGQgbm90IGZpbmQgYSBzcGFjZSBpbiB0aGlzIGxpbmUuIFNlZWsgZm9yd2FyZCB0byB0aGUgZmlyc3Qgc3BhY2UgdG8gZ2V0IHRoZSBzbWFsbGVzdCBsaW5lIG92ZXJmbG93XG4gICAgICBsaW5lRW5kID0gbGluZVN0YXJ0ICsgbjtcbiAgICAgIHdoaWxlIChsaW5lRW5kIDwgdGV4dC5sZW5ndGggJiYgIWJyZWFrZXJzLmluY2x1ZGVzKHRleHRbbGluZUVuZF0pKSB7XG4gICAgICAgIGxpbmVFbmQgKz0gMTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXQucHVzaCh0ZXh0LnNsaWNlKGxpbmVTdGFydCwgbGluZUVuZCkpO1xuICAgIGxpbmVTdGFydCA9IGxpbmVFbmQgKyAxO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbi8vIC0tLSBDbG91ZFdhdGNoIGxvZyBmb3JtYXR0aW5nIC0tLVxuXG4vKipcbiAqIE1heGltdW0gbnVtYmVyIG9mIGxvZyBsaW5lcyBpbmNsdWRlZCBwZXIgQ2xvdWRXYXRjaCBMb2dzIGNvbnRleHQgYmxvY2suXG4gKlxuICogVGhlIGZvcm1hdHRlciByZW5kZXJzIHRoZSBtZXNzYWdlcyBhcnJheSB2ZXJiYXRpbSwgc28gdGhpcyBpcyB0aGVcbiAqIHNpbmdsZSB1c2VyLXZpc2libGUgY2FwLlxuICovXG5jb25zdCBNQVhfTE9HX0xJTkVTID0gNTA7XG5cbi8qKlxuICogVHJpbSBhbHJlYWR5LWV4dHJhY3RlZCBsb2cgbGluZXMgdG8gdGhlIHNldCB3ZSByZW5kZXIuXG4gKlxuICogS2VlcHMgb25seSB0aGUgbW9zdCByZWNlbnQge0BsaW5rIE1BWF9MT0dfTElORVN9IChuZXdlciBvdXRwdXQgaXMgbW9yZSB1c2VmdWwgZm9yXG4gKiBkaWFnbm9zaXMpIGFuZCBwcmVwZW5kcyBhbiBcIk4gZWFybGllciBsaW5lcyBvbWl0dGVkXCIgbWFya2VyIHdoZW4gdHJ1bmNhdGlvbiBoYXBwZW5lZC5cbiAqIFRoaXMgaXMgdGhlIHNpbmdsZSB0cnVuY2F0aW9uIHBvaW50IHNoYXJlZCBieSBhbGwgQ2xvdWRXYXRjaCBjb250ZXh0cyDigJQgdGhlIGZvcm1hdHRlclxuICogcmVuZGVycyB0aGUgcmVzdWx0IHZlcmJhdGltLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJpbVRvUmVjZW50TGluZXMobGluZXM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICBjb25zdCBtZXNzYWdlcyA9IGxpbmVzLnNsaWNlKC1NQVhfTE9HX0xJTkVTKTtcbiAgY29uc3Qgb21pdHRlZCA9IGxpbmVzLmxlbmd0aCAtIG1lc3NhZ2VzLmxlbmd0aDtcbiAgaWYgKG9taXR0ZWQgPiAwKSB7XG4gICAgbWVzc2FnZXMudW5zaGlmdChgLi4uICgke29taXR0ZWR9IGVhcmxpZXIgbGluZXMgb21pdHRlZClgKTtcbiAgfVxuICByZXR1cm4gbWVzc2FnZXM7XG59XG5cbi8qKlxuICogTGFtYmRhIHBsYXRmb3JtIGxvZyBsaW5lcyAodGV4dCBmb3JtYXQpIHRoYXQgY2Fycnkgbm8gYXBwbGljYXRpb24gc2lnbmFsLlxuICovXG5jb25zdCBMQU1CREFfUExBVEZPUk1fTElORSA9IC9eKElOSVRfU1RBUlR8U1RBUlQgUmVxdWVzdElkOnxFTkQgUmVxdWVzdElkOnxSRVBPUlQgUmVxdWVzdElkOikvO1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBMYW1iZGEgQ2xvdWRXYXRjaCBsb2cgZXZlbnRzIGludG8gcmVhZGFibGUgbGluZXMuXG4gKlxuICogTGFtYmRhIGVtaXRzIGxvZ3MgaW4gb25lIG9mIHR3byBmb3JtYXRzIChwZXIgdGhlIGZ1bmN0aW9uJ3MgYExvZ2dpbmdDb25maWcuTG9nRm9ybWF0YCk6XG4gKiAtICoqVGV4dCoqOiBgPHRpbWVzdGFtcD5cXHQ8cmVxdWVzdElkPlxcdDxMRVZFTD5cXHQ8bWVzc2FnZT5gLCBwbHVzIHBsYXRmb3JtIGxpbmVzLlxuICogLSAqKkpTT04qKjogb25lIEpTT04gb2JqZWN0IHBlciBldmVudCAoYHsgdGltZXN0YW1wLCBsZXZlbCwgbWVzc2FnZSwgLi4uIH1gKS5cbiAqXG4gKiBGb3IgYm90aCB3ZSBzdXJmYWNlIGBMRVZFTCAgbWVzc2FnZWAgKG9yIGp1c3QgdGhlIG1lc3NhZ2Ugd2hlbiB0aGVyZSdzIG5vIGxldmVsKSwgc3RyaXAgdGhlXG4gKiByZWR1bmRhbnQgcGVyLWxpbmUgdGltZXN0YW1wL3JlcXVlc3RJZCAoaXQncyBhbGwgb25lIGludm9jYXRpb24pLCBhbmQgZHJvcCBwdXJlIHBsYXRmb3JtXG4gKiBib2lsZXJwbGF0ZS4gVGhlIGxldmVsIGFuZCBtZXNzYWdlIGFyZSBjb21iaW5lZCBpbnRvIGEgc2luZ2xlIHJlbmRlcmVkIGxpbmUuIFdlIG5ldmVyIGRyb3BcbiAqIGFwcGxpY2F0aW9uIG91dHB1dCDigJQgZmFpbHVyZSBkZXRhaWwgaXMgb2Z0ZW4gbG9nZ2VkIGF0IElORk8gKGUuZy4gdGhlIGNmbi1yZXNwb25zZSBcIlJlc3BvbnNlXG4gKiBib2R5XCIgbGluZSkuIEFueXRoaW5nIHdlIGRvbid0IHJlY29nbml6ZSBwYXNzZXMgdGhyb3VnaCB2ZXJiYXRpbSwgYW5kIHRoZSBmdWxsIGxvZ3MgcmVtYWluXG4gKiBhdmFpbGFibGUgdmlhIHRoZSBjb25zb2xlIGxpbmsuXG4gKlxuICogVGhpcyBpcyBMYW1iZGEtc3BlY2lmaWM7IGl0IGlzIG5vdCBhcHBsaWVkIHRvIEVDUyBsb2dzLCB3aGljaCBhcmUgYXJiaXRyYXJ5IGNvbnRhaW5lciBvdXRwdXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUxhbWJkYUxvZ0V2ZW50cyhldmVudHM6IEFycmF5PHsgbWVzc2FnZT86IHN0cmluZyB9Pik6IHN0cmluZ1tdIHtcbiAgY29uc3Qgb3V0OiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGUgb2YgZXZlbnRzKSB7XG4gICAgY29uc3QgcmF3ID0gZS5tZXNzYWdlO1xuICAgIGlmIChyYXcgPT0gbnVsbCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVMYW1iZGFMaW5lKHJhdyk7XG4gICAgaWYgKG5vcm1hbGl6ZWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgb3V0LnB1c2gobm9ybWFsaXplZCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogTm9ybWFsaXplIGEgc2luZ2xlIExhbWJkYSBsb2cgbGluZS4gUmV0dXJucyBgdW5kZWZpbmVkYCB0byBkcm9wIHRoZSBsaW5lIChwbGF0Zm9ybSBub2lzZSksXG4gKiBvciB0aGUgY2xlYW5lZC11cCB0ZXh0IHRvIGtlZXAuXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZUxhbWJkYUxpbmUocmF3OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCB0cmltbWVkID0gcmF3LnRyaW1FbmQoKTtcblxuICAvLyBKU09OLWZvcm1hdCBldmVudDogeyB0aW1lc3RhbXAsIGxldmVsLCBtZXNzYWdlLCAuLi4gfSAob25lIG9iamVjdCBwZXIgbGluZSkuXG4gIGNvbnN0IGpzb25SZXN1bHQgPSBub3JtYWxpemVKc29uTG9nTGluZSh0cmltbWVkKTtcbiAgaWYgKGpzb25SZXN1bHQgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBqc29uUmVzdWx0IHx8IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIFRleHQtZm9ybWF0IHBsYXRmb3JtIGJvaWxlcnBsYXRlOiBkcm9wLlxuICBpZiAoTEFNQkRBX1BMQVRGT1JNX0xJTkUudGVzdCh0cmltbWVkKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBUZXh0LWZvcm1hdCBhcHAgbGluZTogYDxJU08gdGltZXN0YW1wPlxcdDxyZXF1ZXN0SWQ+XFx0PExFVkVMPlxcdDxtZXNzYWdlPmAuXG4gIC8vIFN0cmlwIHRoZSB0aW1lc3RhbXAgKyByZXF1ZXN0SWQgcHJlZml4OyBrZWVwIGBMRVZFTCBtZXNzYWdlYCAob3IgdGhlIHJlc3QgdmVyYmF0aW0pLlxuICBjb25zdCBwYXJ0cyA9IHRyaW1tZWQuc3BsaXQoJ1xcdCcpO1xuICBpZiAocGFydHMubGVuZ3RoID49IDQgJiYgL15cXGR7NH0tXFxkezJ9LVxcZHsyfVQvLnRlc3QocGFydHNbMF0pKSB7XG4gICAgY29uc3QgbGV2ZWwgPSBwYXJ0c1syXTtcbiAgICBjb25zdCBtZXNzYWdlID0gcGFydHMuc2xpY2UoMykuam9pbignXFx0Jyk7XG4gICAgcmV0dXJuIGZvcm1hdExldmVsZWRMaW5lKGxldmVsLCBtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIFVucmVjb2duaXplZCAoY29udGludWF0aW9uIGxpbmUsIHBsYWluIHN0ZG91dCwgZXRjLikg4oCUIGtlZXAgdmVyYmF0aW0uXG4gIHJldHVybiB0cmltbWVkO1xufVxuXG4vKipcbiAqIElmIGBsaW5lYCBpcyBhIEpTT04tZm9ybWF0IExhbWJkYSBsb2cgb2JqZWN0LCByZW5kZXIgaXQgYXMgYExFVkVMICBtZXNzYWdlYCAodGhlIGxldmVsXG4gKiBzcGFjZS1wYWRkZWQgdG8gYSBmaXhlZCB3aWR0aDsgb3IganVzdCB0aGUgbWVzc2FnZSB3aGVuIHRoZXJlJ3Mgbm8gbGV2ZWwpLiBSZXR1cm5zXG4gKiBgdW5kZWZpbmVkYCB3aGVuIGl0IGlzbid0IEpTT04uXG4gKlxuICogRHJvcHMgSlNPTiBwbGF0Zm9ybSBldmVudHMgKGB0eXBlYC9gcmVjb3JkYCBlbnZlbG9wZXMgZm9yIGBwbGF0Zm9ybS4qYCksIHdoaWNoIGNhcnJ5IG5vXG4gKiBhcHBsaWNhdGlvbiBzaWduYWwuXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZUpzb25Mb2dMaW5lKGxpbmU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghbGluZS5zdGFydHNXaXRoKCd7JykpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGxldCBvYmo6IGFueTtcbiAgdHJ5IHtcbiAgICBvYmogPSBKU09OLnBhcnNlKGxpbmUpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGlmICghb2JqIHx8IHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIFBsYXRmb3JtIGV2ZW50cyAoZS5nLiB7IHR5cGU6ICdwbGF0Zm9ybS5yZXBvcnQnLCByZWNvcmQ6IHsuLi59IH0pIOKAlCBkcm9wLlxuICBpZiAodHlwZW9mIG9iai50eXBlID09PSAnc3RyaW5nJyAmJiBvYmoudHlwZS5zdGFydHNXaXRoKCdwbGF0Zm9ybS4nKSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIGNvbnN0IGxldmVsID0gdHlwZW9mIG9iai5sZXZlbCA9PT0gJ3N0cmluZycgPyBvYmoubGV2ZWwgOiB1bmRlZmluZWQ7XG4gIC8vIExhbWJkYSB1c2VzIGBtZXNzYWdlYDsgYSB0aHJvd24gZXJyb3IgZW52ZWxvcGUgdXNlcyBgZXJyb3JNZXNzYWdlYCAoKyBvcHRpb25hbCBzdGFja1RyYWNlKS5cbiAgbGV0IG1lc3NhZ2U6IHN0cmluZztcbiAgaWYgKHR5cGVvZiBvYmoubWVzc2FnZSA9PT0gJ3N0cmluZycpIHtcbiAgICBtZXNzYWdlID0gb2JqLm1lc3NhZ2U7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG9iai5lcnJvck1lc3NhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgbWVzc2FnZSA9IEFycmF5LmlzQXJyYXkob2JqLnN0YWNrVHJhY2UpID8gW29iai5lcnJvck1lc3NhZ2UsIC4uLm9iai5zdGFja1RyYWNlXS5qb2luKCdcXG4nKSA6IG9iai5lcnJvck1lc3NhZ2U7XG4gIH0gZWxzZSB7XG4gICAgLy8gSlNPTiwgYnV0IG5vdCBhIHNoYXBlIHdlIHJlY29nbml6ZSDigJQgcmVuZGVyIGNvbXBhY3RseSByYXRoZXIgdGhhbiBkcm9wcGluZyBzaWduYWwuXG4gICAgbWVzc2FnZSA9IGxpbmU7XG4gIH1cbiAgcmV0dXJuIGxldmVsID8gZm9ybWF0TGV2ZWxlZExpbmUobGV2ZWwsIG1lc3NhZ2UpIDogbWVzc2FnZTtcbn1cblxuLyoqXG4gKiBSZW5kZXIgYSBsb2cgbGV2ZWwgYW5kIG1lc3NhZ2UgYXMgYExFVkVMICBtZXNzYWdlYCwgcGFkZGluZyB0aGUgbGV2ZWwgdG8gYSBmaXhlZCB3aWR0aCBzb1xuICogbGluZXMgYWxpZ24gaW4gdGhlIHRlcm1pbmFsLiBNdWx0aS1saW5lIG1lc3NhZ2VzIGtlZXAgdGhlaXIgaW50ZXJuYWwgbmV3bGluZXMuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdExldmVsZWRMaW5lKGxldmVsOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtsZXZlbC5wYWRFbmQoNSl9ICR7bWVzc2FnZX1gO1xufVxuXG4vLyBDbG91ZFdhdGNoIGNvbnNvbGUgdXNlcyBkb3VibGUtVVJJLWVuY29kaW5nIHdpdGggJyQnIHJlcGxhY2luZyAnJScgZm9yIHRoZSBsb2cgZ3JvdXAgaW4gdGhlIGZyYWdtZW50LlxuZXhwb3J0IGZ1bmN0aW9uIGNsb3VkV2F0Y2hMb2dzQ29uc29sZVVybChyZWdpb246IHN0cmluZywgbG9nR3JvdXA6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGVuY29kZWRMb2dHcm91cCA9IGVuY29kZVVSSUNvbXBvbmVudChlbmNvZGVVUklDb21wb25lbnQobG9nR3JvdXApKS5yZXBsYWNlKC8lL2csICckJyk7XG4gIHJldHVybiBgaHR0cHM6Ly8ke3JlZ2lvbn0uY29uc29sZS5hd3MuYW1hem9uLmNvbS9jbG91ZHdhdGNoL2hvbWU/cmVnaW9uPSR7cmVnaW9ufSNsb2dzVjI6bG9nLWdyb3Vwcy9sb2ctZ3JvdXAvJHtlbmNvZGVkTG9nR3JvdXB9YDtcbn1cbiJdfQ==
@@ -0,0 +1,17 @@
1
+ import type { AdditionalDiagnosticContext } from '../../actions/diagnose';
2
+ import type { SDK } from '../aws-auth/sdk';
3
+ import type { ResourceError } from '../stack-events/resource-errors';
4
+ /**
5
+ * Investigate a failed custom resource by surfacing its backing Lambda's CloudWatch logs.
6
+ *
7
+ * The CloudFormation event does not name the backing function — only the resource's
8
+ * `ServiceToken` (in the template) does. We resolve that to a function name, derive the
9
+ * log group (the `/aws/lambda/<fn>` convention, confirmed via the function's LoggingConfig
10
+ * only if the convention turns up empty), and fetch the relevant log lines.
11
+ *
12
+ * When the handler uses the cfn-response library, the failing log stream name is embedded
13
+ * in the status reason ("See the details in CloudWatch Log Stream: <name>"), so we can
14
+ * target that exact invocation.
15
+ */
16
+ export declare function investigateCustomResource(err: ResourceError, sdk: SDK, debug: (msg: string) => Promise<void>): Promise<AdditionalDiagnosticContext[]>;
17
+ //# sourceMappingURL=investigate-custom-resource.d.ts.map
@@ -0,0 +1,247 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.investigateCustomResource = investigateCustomResource;
4
+ const format_utils_1 = require("./format-utils");
5
+ const resource_identifiers_1 = require("./resource-identifiers");
6
+ const util_1 = require("../../util");
7
+ /** Fallback look-back when no failure timestamp is available. */
8
+ const FALLBACK_LOG_WINDOW_MS = 30 * 60 * 1000;
9
+ /**
10
+ * How far before/after the failure event to search CloudWatch Logs when we have a timestamp.
11
+ *
12
+ * The pre-window absorbs minor clock skew; the post-window covers output the function
13
+ * emits while it runs after the CloudFormation event was recorded.
14
+ */
15
+ const LOG_WINDOW_BEFORE_MS = 2 * 60 * 1000;
16
+ const LOG_WINDOW_AFTER_MS = 15 * 60 * 1000;
17
+ /**
18
+ * Investigate a failed custom resource by surfacing its backing Lambda's CloudWatch logs.
19
+ *
20
+ * The CloudFormation event does not name the backing function — only the resource's
21
+ * `ServiceToken` (in the template) does. We resolve that to a function name, derive the
22
+ * log group (the `/aws/lambda/<fn>` convention, confirmed via the function's LoggingConfig
23
+ * only if the convention turns up empty), and fetch the relevant log lines.
24
+ *
25
+ * When the handler uses the cfn-response library, the failing log stream name is embedded
26
+ * in the status reason ("See the details in CloudWatch Log Stream: <name>"), so we can
27
+ * target that exact invocation.
28
+ */
29
+ async function investigateCustomResource(err, sdk, debug) {
30
+ if (!err.logicalId) {
31
+ await debug('Custom resource investigation: no logical ID available');
32
+ return [];
33
+ }
34
+ const stackName = err.stackArn;
35
+ if (!stackName) {
36
+ await debug('Custom resource investigation: no stack ARN available');
37
+ return [];
38
+ }
39
+ const cfn = sdk.cloudFormation();
40
+ const lambda = sdk.lambda();
41
+ const cwl = sdk.cloudWatchLogs();
42
+ const region = sdk.currentRegion;
43
+ // Fetch the template once: it carries both the ServiceToken and (for functions defined in
44
+ // this stack) the backing function's LoggingConfig. The template survives rollback even
45
+ // when the function itself is deleted, so it's the most reliable source for the log group.
46
+ const template = await getStackTemplate(cfn, stackName, debug);
47
+ if (!template) {
48
+ return [];
49
+ }
50
+ const serviceToken = template.Resources?.[err.logicalId]?.Properties?.ServiceToken;
51
+ if (serviceToken === undefined) {
52
+ await debug(`Custom resource investigation: no ServiceToken on resource "${err.logicalId}"`);
53
+ return [];
54
+ }
55
+ const referencedLogicalId = (0, resource_identifiers_1.serviceTokenReferencedLogicalId)(serviceToken);
56
+ const functionName = await resolveServiceTokenToFunctionName(cfn, stackName, serviceToken, referencedLogicalId, debug);
57
+ if (!functionName) {
58
+ await debug('Custom resource investigation: could not resolve ServiceToken to a Lambda function');
59
+ return [];
60
+ }
61
+ // Prefer the function's configured log group as derived from the template (rollback-proof).
62
+ // Only resolvable when the function is defined in this stack (ServiceToken is a Ref/GetAtt).
63
+ const templateLogGroup = referencedLogicalId
64
+ ? await resolveConfiguredLogGroup(cfn, stackName, template, referencedLogicalId, debug)
65
+ : undefined;
66
+ // The cfn-response library writes the failing log stream name into the status reason
67
+ // (and uses it as the default physical ID). Targeting it gives the exact invocation.
68
+ const streamName = (0, resource_identifiers_1.extractLogStreamName)(err.message) ?? (0, resource_identifiers_1.logStreamNameFromPhysicalId)(err.physicalId);
69
+ return fetchCustomResourceLogs(cwl, lambda, functionName, templateLogGroup, streamName, err.timestamp, region, debug);
70
+ }
71
+ /**
72
+ * Fetch and parse the stack's (original) template. Returns `undefined` if it can't be read.
73
+ */
74
+ async function getStackTemplate(cfn, stackName, debug) {
75
+ try {
76
+ const resp = await cfn.getTemplate({ StackName: stackName, TemplateStage: 'Original' });
77
+ if (!resp.TemplateBody) {
78
+ await debug('Custom resource investigation: empty template body');
79
+ return undefined;
80
+ }
81
+ return (0, util_1.deserializeStructure)(resp.TemplateBody);
82
+ }
83
+ catch (e) {
84
+ await debug(`Custom resource investigation: failed to read template: ${e.message}`);
85
+ return undefined;
86
+ }
87
+ }
88
+ /**
89
+ * Resolve the backing Lambda's configured log group from the template.
90
+ *
91
+ * The template survives rollback (when the live function may not), so it is the preferred
92
+ * source. Handles the function's `LoggingConfig.LogGroup` as:
93
+ * - a literal string (returned directly);
94
+ * - a `Ref` to an `AWS::Logs::LogGroup` with a literal `LogGroupName` (returned directly);
95
+ * - a `Ref` to an `AWS::Logs::LogGroup` whose name CloudFormation generates (the common CDK
96
+ * case) — resolved to its physical name via `describeStackResources`, which still returns
97
+ * RETAINed/orphaned resources after a rollback.
98
+ *
99
+ * Returns `undefined` when there is no configured log group or it can't be resolved
100
+ * (caller then falls back to the live function configuration).
101
+ */
102
+ async function resolveConfiguredLogGroup(cfn, stackName, template, functionLogicalId, debug) {
103
+ const logGroup = template.Resources?.[functionLogicalId]?.Properties?.LoggingConfig?.LogGroup;
104
+ if (typeof logGroup === 'string') {
105
+ return logGroup;
106
+ }
107
+ if (logGroup && typeof logGroup === 'object' && typeof logGroup.Ref === 'string') {
108
+ const referenced = template.Resources?.[logGroup.Ref];
109
+ const name = referenced?.Properties?.LogGroupName;
110
+ if (typeof name === 'string') {
111
+ return name;
112
+ }
113
+ // No explicit name (CloudFormation generates it) — resolve the log-group resource's
114
+ // physical name, which is the log group name.
115
+ return (await resolveStackResource(cfn, stackName, logGroup.Ref, debug))?.physicalId;
116
+ }
117
+ return undefined;
118
+ }
119
+ /**
120
+ * Resolve a resource's physical ID and type by logical ID. Returns `undefined` on failure.
121
+ */
122
+ async function resolveStackResource(cfn, stackName, logicalId, debug) {
123
+ try {
124
+ const resp = await cfn.describeStackResources({ StackName: stackName, LogicalResourceId: logicalId });
125
+ const resource = resp.StackResources?.[0];
126
+ return resource ? { physicalId: resource.PhysicalResourceId, resourceType: resource.ResourceType } : undefined;
127
+ }
128
+ catch (e) {
129
+ await debug(`Custom resource investigation: failed to resolve resource "${logicalId}": ${e.message}`);
130
+ return undefined;
131
+ }
132
+ }
133
+ /**
134
+ * Resolve a `ServiceToken` value (a literal ARN, an `Fn::GetAtt`, or a `Ref`) to a Lambda
135
+ * function name. Intrinsics are resolved via `describeStackResources`.
136
+ */
137
+ async function resolveServiceTokenToFunctionName(cfn, stackName, serviceToken, referencedLogicalId, debug) {
138
+ if (referencedLogicalId) {
139
+ const resource = await resolveStackResource(cfn, stackName, referencedLogicalId, debug);
140
+ // Only treat the reference as a Lambda function. Without this, a ServiceToken pointing at
141
+ // a non-Lambda resource (e.g. an SNS topic) whose physical ID is a bare name would be
142
+ // mistaken for a function name, producing a misleading /aws/lambda/<name> log lookup.
143
+ if (resource?.resourceType && resource.resourceType !== 'AWS::Lambda::Function') {
144
+ await debug(`Custom resource investigation: ServiceToken references a ${resource.resourceType}, not a Lambda function`);
145
+ return undefined;
146
+ }
147
+ return resource?.physicalId ? (0, resource_identifiers_1.functionNameFromArnOrName)(resource.physicalId) : undefined;
148
+ }
149
+ if (typeof serviceToken === 'string') {
150
+ return (0, resource_identifiers_1.functionNameFromArnOrName)(serviceToken);
151
+ }
152
+ await debug('Custom resource investigation: unsupported ServiceToken shape');
153
+ return undefined;
154
+ }
155
+ async function fetchCustomResourceLogs(cwl, lambda, functionName, templateLogGroup, streamName, timestamp, region, debug) {
156
+ const failureTime = timestamp?.valueOf();
157
+ const startTime = failureTime !== undefined ? failureTime - LOG_WINDOW_BEFORE_MS : Date.now() - FALLBACK_LOG_WINDOW_MS;
158
+ const endTime = failureTime !== undefined ? failureTime + LOG_WINDOW_AFTER_MS : undefined;
159
+ // Convention first; only pay for the configured group if the convention group doesn't yield usable lines (empty group or fetch error).
160
+ const conventionGroup = `/aws/lambda/${functionName}`;
161
+ let result = await fetchLogLines(cwl, conventionGroup, streamName, startTime, endTime, debug);
162
+ // The group we point the user at. Once we learn the function's configured log group, prefer
163
+ // it for the link even if it too is empty — it's where the function actually logs, whereas
164
+ // the convention group may not exist for advanced-logging functions.
165
+ let logGroup = conventionGroup;
166
+ if (result.kind !== 'lines') {
167
+ // Prefer the template-derived group (rollback-proof); fall back to the live function
168
+ // configuration only when the template couldn't tell us (e.g. unresolvable intrinsic, or
169
+ // the function is defined outside this stack).
170
+ const configuredGroup = templateLogGroup ?? await configuredLogGroup(lambda, functionName, debug);
171
+ if (configuredGroup && configuredGroup !== conventionGroup) {
172
+ logGroup = configuredGroup;
173
+ const configuredResult = await fetchLogLines(cwl, configuredGroup, streamName, startTime, endTime, debug);
174
+ // Keep the configured-group result unless it errored while the convention attempt was a
175
+ // clean empty (an "empty" answer is more informative to surface than a fetch error).
176
+ if (configuredResult.kind === 'lines' || result.kind !== 'empty') {
177
+ result = configuredResult;
178
+ }
179
+ }
180
+ }
181
+ // Lead with the log group so the user can tell which function these logs belong to
182
+ // (the formatter renders messages but not `source`, and the link is URL-encoded).
183
+ const header = `Logs from ${logGroup}:`;
184
+ const body = result.kind === 'lines'
185
+ ? result.lines
186
+ : result.kind === 'error'
187
+ ? ['Could not fetch logs (the log group may not exist, or the credentials lack logs:FilterLogEvents). See the console link below.']
188
+ : ['No log events found around the time of failure. The function may not have produced output, or logging may not be configured.'];
189
+ return [{
190
+ source: 'Custom Resource Lambda Logs',
191
+ messages: [header, ...body],
192
+ link: (0, format_utils_1.cloudWatchLogsConsoleUrl)(region, logGroup),
193
+ linkLabel: 'Logs',
194
+ }];
195
+ }
196
+ /**
197
+ * Fetch and trim recent log lines from a group.
198
+ *
199
+ * Tries the targeted stream first (most relevant), but the cfn-response stream name can be
200
+ * stale on update/rollback failures (it's pinned to the original create invocation). If the
201
+ * targeted query finds nothing, falls back to a group-wide scan over the time window so a
202
+ * stale stream can't hide the actual failing invocation's logs.
203
+ */
204
+ async function fetchLogLines(cwl, logGroup, streamName, startTime, endTime, debug) {
205
+ if (streamName) {
206
+ const targeted = await filterLogLines(cwl, logGroup, streamName, startTime, endTime, debug);
207
+ if (targeted.kind === 'lines') {
208
+ return targeted;
209
+ }
210
+ }
211
+ return filterLogLines(cwl, logGroup, undefined, startTime, endTime, debug);
212
+ }
213
+ async function filterLogLines(cwl, logGroup, streamName, startTime, endTime, debug) {
214
+ try {
215
+ const resp = await cwl.filterLogEvents({
216
+ logGroupName: logGroup,
217
+ startTime,
218
+ ...(endTime !== undefined ? { endTime } : {}),
219
+ limit: 1000,
220
+ ...(streamName ? { logStreamNames: [streamName] } : {}),
221
+ });
222
+ const events = resp.events ?? [];
223
+ if (events.length === 0) {
224
+ await debug(`Custom resource investigation: no log events in ${logGroup}${streamName ? ` (stream: ${streamName})` : ''}`);
225
+ return { kind: 'empty' };
226
+ }
227
+ // Lambda log events have a known structure (text- or JSON-format), unlike raw ECS
228
+ // container output, so we normalize them into readable lines before trimming.
229
+ return { kind: 'lines', lines: (0, format_utils_1.trimToRecentLines)((0, format_utils_1.parseLambdaLogEvents)(events)) };
230
+ }
231
+ catch (e) {
232
+ await debug(`Custom resource investigation: failed to fetch logs from ${logGroup}: ${e.message}`);
233
+ return { kind: 'error' };
234
+ }
235
+ }
236
+ /** Read the function's configured (advanced-logging) log group, if any. */
237
+ async function configuredLogGroup(lambda, functionName, debug) {
238
+ try {
239
+ const resp = await lambda.getFunctionConfiguration({ FunctionName: functionName });
240
+ return resp.LoggingConfig?.LogGroup;
241
+ }
242
+ catch (e) {
243
+ await debug(`Custom resource investigation: failed to read function configuration: ${e.message}`);
244
+ return undefined;
245
+ }
246
+ }
247
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52ZXN0aWdhdGUtY3VzdG9tLXJlc291cmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaW52ZXN0aWdhdGUtY3VzdG9tLXJlc291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBb0NBLDhEQW9EQztBQXhGRCxpREFBbUc7QUFDbkcsaUVBS2dDO0FBRWhDLHFDQUFrRDtBQUlsRCxpRUFBaUU7QUFDakUsTUFBTSxzQkFBc0IsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUU5Qzs7Ozs7R0FLRztBQUNILE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDM0MsTUFBTSxtQkFBbUIsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUUzQzs7Ozs7Ozs7Ozs7R0FXRztBQUNJLEtBQUssVUFBVSx5QkFBeUIsQ0FDN0MsR0FBa0IsRUFDbEIsR0FBUSxFQUNSLEtBQXFDO0lBRXJDLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDbkIsTUFBTSxLQUFLLENBQUMsd0RBQXdELENBQUMsQ0FBQztRQUN0RSxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFDRCxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDO0lBQy9CLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNmLE1BQU0sS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7UUFDckUsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ2pDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUM1QixNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDakMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQztJQUVqQywwRkFBMEY7SUFDMUYs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QUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ2xHLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDM0IsQ0FBQztBQUNILENBQUM7QUFFRCwyRUFBMkU7QUFDM0UsS0FBSyxVQUFVLGtCQUFrQixDQUMvQixNQUFxQixFQUNyQixZQUFvQixFQUNwQixLQUFxQztJQUVyQyxJQUFJLENBQUM7UUFDSCxNQUFNLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQ25GLE9BQU8sSUFBSSxDQUFDLGFBQWEsRUFBRSxRQUFRLENBQUM7SUFDdEMsQ0FBQztJQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7UUFDaEIsTUFBTSxLQUFLLENBQUMseUVBQXlFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ2xHLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdHJpbVRvUmVjZW50TGluZXMsIHBhcnNlTGFtYmRhTG9nRXZlbnRzLCBjbG91ZFdhdGNoTG9nc0NvbnNvbGVVcmwgfSBmcm9tICcuL2Zvcm1hdC11dGlscyc7XG5pbXBvcnQge1xuICBzZXJ2aWNlVG9rZW5SZWZlcmVuY2VkTG9naWNhbElkLFxuICBmdW5jdGlvbk5hbWVGcm9tQXJuT3JOYW1lLFxuICBleHRyYWN0TG9nU3RyZWFtTmFtZSxcbiAgbG9nU3RyZWFtTmFtZUZyb21QaHlzaWNhbElkLFxufSBmcm9tICcuL3Jlc291cmNlLWlkZW50aWZpZXJzJztcbmltcG9ydCB0eXBlIHsgQWRkaXRpb25hbERpYWdub3N0aWNDb250ZXh0IH0gZnJvbSAnLi4vLi4vYWN0aW9ucy9kaWFnbm9zZSc7XG5pbXBvcnQgeyBkZXNlcmlhbGl6ZVN0cnVjdHVyZSB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHR5cGUgeyBJQ2xvdWRGb3JtYXRpb25DbGllbnQsIElDbG91ZFdhdGNoTG9nc0NsaWVudCwgSUxhbWJkYUNsaWVudCwgU0RLIH0gZnJvbSAnLi4vYXdzLWF1dGgvc2RrJztcbmltcG9ydCB0eXBlIHsgUmVzb3VyY2VFcnJvciB9IGZyb20gJy4uL3N0YWNrLWV2ZW50cy9yZXNvdXJjZS1lcnJvcnMnO1xuXG4vKiogRmFsbGJhY2sgbG9vay1iYWNrIHdoZW4gbm8gZmFpbHVyZSB0aW1lc3RhbXAgaXMgYXZhaWxhYmxlLiAqL1xuY29uc3QgRkFMTEJBQ0tfTE9HX1dJTkRPV19NUyA9IDMwICogNjAgKiAxMDAwO1xuXG4vKipcbiAqIEhvdyBmYXIgYmVmb3JlL2FmdGVyIHRoZSBmYWlsdXJlIGV2ZW50IHRvIHNlYXJjaCBDbG91ZFdhdGNoIExvZ3Mgd2hlbiB3ZSBoYXZlIGEgdGltZXN0YW1wLlxuICpcbiAqIFRoZSBwcmUtd2luZG93IGFic29yYnMgbWlub3IgY2xvY2sgc2tldzsgdGhlIHBvc3Qtd2luZG93IGNvdmVycyBvdXRwdXQgdGhlIGZ1bmN0aW9uXG4gKiBlbWl0cyB3aGlsZSBpdCBydW5zIGFmdGVyIHRoZSBDbG91ZEZvcm1hdGlvbiBldmVudCB3YXMgcmVjb3JkZWQuXG4gKi9cbmNvbnN0IExPR19XSU5ET1dfQkVGT1JFX01TID0gMiAqIDYwICogMTAwMDtcbmNvbnN0IExPR19XSU5ET1dfQUZURVJfTVMgPSAxNSAqIDYwICogMTAwMDtcblxuLyoqXG4gKiBJbnZlc3RpZ2F0ZSBhIGZhaWxlZCBjdXN0b20gcmVzb3VyY2UgYnkgc3VyZmFjaW5nIGl0cyBiYWNraW5nIExhbWJkYSdzIENsb3VkV2F0Y2ggbG9ncy5cbiAqXG4gKiBUaGUgQ2xvdWRGb3JtYXRpb24gZXZlbnQgZG9lcyBub3QgbmFtZSB0aGUgYmFja2luZyBmdW5jdGlvbiDigJQgb25seSB0aGUgcmVzb3VyY2Unc1xuICogYFNlcnZpY2VUb2tlbmAgKGluIHRoZSB0ZW1wbGF0ZSkgZG9lcy4gV2UgcmVzb2x2ZSB0aGF0IHRvIGEgZnVuY3Rpb24gbmFtZSwgZGVyaXZlIHRoZVxuICogbG9nIGdyb3VwICh0aGUgYC9hd3MvbGFtYmRhLzxmbj5gIGNvbnZlbnRpb24sIGNvbmZpcm1lZCB2aWEgdGhlIGZ1bmN0aW9uJ3MgTG9nZ2luZ0NvbmZpZ1xuICogb25seSBpZiB0aGUgY29udmVudGlvbiB0dXJucyB1cCBlbXB0eSksIGFuZCBmZXRjaCB0aGUgcmVsZXZhbnQgbG9nIGxpbmVzLlxuICpcbiAqIFdoZW4gdGhlIGhhbmRsZXIgdXNlcyB0aGUgY2ZuLXJlc3BvbnNlIGxpYnJhcnksIHRoZSBmYWlsaW5nIGxvZyBzdHJlYW0gbmFtZSBpcyBlbWJlZGRlZFxuICogaW4gdGhlIHN0YXR1cyByZWFzb24gKFwiU2VlIHRoZSBkZXRhaWxzIGluIENsb3VkV2F0Y2ggTG9nIFN0cmVhbTogPG5hbWU+XCIpLCBzbyB3ZSBjYW5cbiAqIHRhcmdldCB0aGF0IGV4YWN0IGludm9jYXRpb24uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnZlc3RpZ2F0ZUN1c3RvbVJlc291cmNlKFxuICBlcnI6IFJlc291cmNlRXJyb3IsXG4gIHNkazogU0RLLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHRbXT4ge1xuICBpZiAoIWVyci5sb2dpY2FsSWQpIHtcbiAgICBhd2FpdCBkZWJ1ZygnQ3VzdG9tIHJlc291cmNlIGludmVzdGlnYXRpb246IG5vIGxvZ2ljYWwgSUQgYXZhaWxhYmxlJyk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGNvbnN0IHN0YWNrTmFtZSA9IGVyci5zdGFja0FybjtcbiAgaWYgKCFzdGFja05hbWUpIHtcbiAgICBhd2FpdCBkZWJ1ZygnQ3VzdG9tIHJlc291cmNlIGludmVzdGlnYXRpb246IG5vIHN0YWNrIEFSTiBhdmFpbGFibGUnKTtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBjZm4gPSBzZGsuY2xvdWRGb3JtYXRpb24oKTtcbiAgY29uc3QgbGFtYmRhID0gc2RrLmxhbWJkYSgpO1xuICBjb25zdCBjd2wgPSBzZGsuY2xvdWRXYXRjaExvZ3MoKTtcbiAgY29uc3QgcmVnaW9uID0gc2RrLmN1cnJlbnRSZWdpb247XG5cbiAgLy8gRmV0Y2ggdGhlIHRlbXBsYXRlIG9uY2U6IGl0IGNhcnJpZXMgYm90aCB0aGUgU2VydmljZVRva2VuIGFuZCAoZm9yIGZ1bmN0aW9ucyBkZWZpbmVkIGluXG4gIC8vIHRoaXMgc3RhY2spIHRoZSBiYWNraW5nIGZ1bmN0aW9uJ3MgTG9nZ2luZ0NvbmZpZy4gVGhlIHRlbXBsYXRlIHN1cnZpdmVzIHJvbGxiYWNrIGV2ZW5cbiAgLy8gd2hlbiB0aGUgZnVuY3Rpb24gaXRzZWxmIGlzIGRlbGV0ZWQsIHNvIGl0J3MgdGhlIG1vc3QgcmVsaWFibGUgc291cmNlIGZvciB0aGUgbG9nIGdyb3VwLlxuICBjb25zdCB0ZW1wbGF0ZSA9IGF3YWl0IGdldFN0YWNrVGVtcGxhdGUoY2ZuLCBzdGFja05hbWUsIGRlYnVnKTtcbiAgaWYgKCF0ZW1wbGF0ZSkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHNlcnZpY2VUb2tlbiA9IHRlbXBsYXRlLlJlc291cmNlcz8uW2Vyci5sb2dpY2FsSWRdPy5Qcm9wZXJ0aWVzPy5TZXJ2aWNlVG9rZW47XG4gIGlmIChzZXJ2aWNlVG9rZW4gPT09IHVuZGVmaW5lZCkge1xuICAgIGF3YWl0IGRlYnVnKGBDdXN0b20gcmVzb3VyY2UgaW52ZXN0aWdhdGlvbjogbm8gU2VydmljZVRva2VuIG9uIHJlc291cmNlIFwiJHtlcnIubG9naWNhbElkfVwiYCk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgcmVmZXJlbmNlZExvZ2ljYWxJZCA9IHNlcnZpY2VUb2tlblJlZmVyZW5jZWRMb2dpY2FsSWQoc2VydmljZVRva2VuKTtcbiAgY29uc3QgZnVuY3Rpb25OYW1lID0gYXdhaXQgcmVzb2x2ZVNlcnZpY2VUb2tlblRvRnVuY3Rpb25OYW1lKGNmbiwgc3RhY2tOYW1lLCBzZXJ2aWNlVG9rZW4sIHJlZmVyZW5jZWRMb2dpY2FsSWQsIGRlYnVnKTtcbiAgaWYgKCFmdW5jdGlvbk5hbWUpIHtcbiAgICBhd2FpdCBkZWJ1ZygnQ3VzdG9tIHJlc291cmNlIGludmVzdGlnYXRpb246IGNvdWxkIG5vdCByZXNvbHZlIFNlcnZpY2VUb2tlbiB0byBhIExhbWJkYSBmdW5jdGlvbicpO1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8vIFByZWZlciB0aGUgZnVuY3Rpb24ncyBjb25maWd1cmVkIGxvZyBncm91cCBhcyBkZXJpdmVkIGZyb20gdGhlIHRlbXBsYXRlIChyb2xsYmFjay1wcm9vZikuXG4gIC8vIE9ubHkgcmVzb2x2YWJsZSB3aGVuIHRoZSBmdW5jdGlvbiBpcyBkZWZpbmVkIGluIHRoaXMgc3RhY2sgKFNlcnZpY2VUb2tlbiBpcyBhIFJlZi9HZXRBdHQpLlxuICBjb25zdCB0ZW1wbGF0ZUxvZ0dyb3VwID0gcmVmZXJlbmNlZExvZ2ljYWxJZFxuICAgID8gYXdhaXQgcmVzb2x2ZUNvbmZpZ3VyZWRMb2dHcm91cChjZm4sIHN0YWNrTmFtZSwgdGVtcGxhdGUsIHJlZmVyZW5jZWRMb2dpY2FsSWQsIGRlYnVnKVxuICAgIDogdW5kZWZpbmVkO1xuXG4gIC8vIFRoZSBjZm4tcmVzcG9uc2UgbGlicmFyeSB3cml0ZXMgdGhlIGZhaWxpbmcgbG9nIHN0cmVhbSBuYW1lIGludG8gdGhlIHN0YXR1cyByZWFzb25cbiAgLy8gKGFuZCB1c2VzIGl0IGFzIHRoZSBkZWZhdWx0IHBoeXNpY2FsIElEKS4gVGFyZ2V0aW5nIGl0IGdpdmVzIHRoZSBleGFjdCBpbnZvY2F0aW9uLlxuICBjb25zdCBzdHJlYW1OYW1lID0gZXh0cmFjdExvZ1N0cmVhbU5hbWUoZXJyLm1lc3NhZ2UpID8/IGxvZ1N0cmVhbU5hbWVGcm9tUGh5c2ljYWxJZChlcnIucGh5c2ljYWxJZCk7XG5cbiAgcmV0dXJuIGZldGNoQ3VzdG9tUmVzb3VyY2VMb2dzKGN3bCwgbGFtYmRhLCBmdW5jdGlvbk5hbWUsIHRlbXBsYXRlTG9nR3JvdXAsIHN0cmVhbU5hbWUsIGVyci50aW1lc3RhbXAsIHJlZ2lvbiwgZGVidWcpO1xufVxuXG4vKipcbiAqIEZldGNoIGFuZCBwYXJzZSB0aGUgc3RhY2sncyAob3JpZ2luYWwpIHRlbXBsYXRlLiBSZXR1cm5zIGB1bmRlZmluZWRgIGlmIGl0IGNhbid0IGJlIHJlYWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldFN0YWNrVGVtcGxhdGUoXG4gIGNmbjogSUNsb3VkRm9ybWF0aW9uQ2xpZW50LFxuICBzdGFja05hbWU6IHN0cmluZyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8YW55IHwgdW5kZWZpbmVkPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IGNmbi5nZXRUZW1wbGF0ZSh7IFN0YWNrTmFtZTogc3RhY2tOYW1lLCBUZW1wbGF0ZVN0YWdlOiAnT3JpZ2luYWwnIH0pO1xuICAgIGlmICghcmVzcC5UZW1wbGF0ZUJvZHkpIHtcbiAgICAgIGF3YWl0IGRlYnVnKCdDdXN0b20gcmVzb3VyY2UgaW52ZXN0aWdhdGlvbjogZW1wdHkgdGVtcGxhdGUgYm9keScpO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIGRlc2VyaWFsaXplU3RydWN0dXJlKHJlc3AuVGVtcGxhdGVCb2R5KTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgYXdhaXQgZGVidWcoYEN1c3RvbSByZXNvdXJjZSBpbnZlc3RpZ2F0aW9uOiBmYWlsZWQgdG8gcmVhZCB0ZW1wbGF0ZTogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIGJhY2tpbmcgTGFtYmRhJ3MgY29uZmlndXJlZCBsb2cgZ3JvdXAgZnJvbSB0aGUgdGVtcGxhdGUuXG4gKlxuICogVGhlIHRlbXBsYXRlIHN1cnZpdmVzIHJvbGxiYWNrICh3aGVuIHRoZSBsaXZlIGZ1bmN0aW9uIG1heSBub3QpLCBzbyBpdCBpcyB0aGUgcHJlZmVycmVkXG4gKiBzb3VyY2UuIEhhbmRsZXMgdGhlIGZ1bmN0aW9uJ3MgYExvZ2dpbmdDb25maWcuTG9nR3JvdXBgIGFzOlxuICogLSBhIGxpdGVyYWwgc3RyaW5nIChyZXR1cm5lZCBkaXJlY3RseSk7XG4gKiAtIGEgYFJlZmAgdG8gYW4gYEFXUzo6TG9nczo6TG9nR3JvdXBgIHdpdGggYSBsaXRlcmFsIGBMb2dHcm91cE5hbWVgIChyZXR1cm5lZCBkaXJlY3RseSk7XG4gKiAtIGEgYFJlZmAgdG8gYW4gYEFXUzo6TG9nczo6TG9nR3JvdXBgIHdob3NlIG5hbWUgQ2xvdWRGb3JtYXRpb24gZ2VuZXJhdGVzICh0aGUgY29tbW9uIENES1xuICogICBjYXNlKSDigJQgcmVzb2x2ZWQgdG8gaXRzIHBoeXNpY2FsIG5hbWUgdmlhIGBkZXNjcmliZVN0YWNrUmVzb3VyY2VzYCwgd2hpY2ggc3RpbGwgcmV0dXJuc1xuICogICBSRVRBSU5lZC9vcnBoYW5lZCByZXNvdXJjZXMgYWZ0ZXIgYSByb2xsYmFjay5cbiAqXG4gKiBSZXR1cm5zIGB1bmRlZmluZWRgIHdoZW4gdGhlcmUgaXMgbm8gY29uZmlndXJlZCBsb2cgZ3JvdXAgb3IgaXQgY2FuJ3QgYmUgcmVzb2x2ZWRcbiAqIChjYWxsZXIgdGhlbiBmYWxscyBiYWNrIHRvIHRoZSBsaXZlIGZ1bmN0aW9uIGNvbmZpZ3VyYXRpb24pLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlQ29uZmlndXJlZExvZ0dyb3VwKFxuICBjZm46IElDbG91ZEZvcm1hdGlvbkNsaWVudCxcbiAgc3RhY2tOYW1lOiBzdHJpbmcsXG4gIHRlbXBsYXRlOiBhbnksXG4gIGZ1bmN0aW9uTG9naWNhbElkOiBzdHJpbmcsXG4gIGRlYnVnOiAobXNnOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4sXG4pOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBsb2dHcm91cCA9IHRlbXBsYXRlLlJlc291cmNlcz8uW2Z1bmN0aW9uTG9naWNhbElkXT8uUHJvcGVydGllcz8uTG9nZ2luZ0NvbmZpZz8uTG9nR3JvdXA7XG4gIGlmICh0eXBlb2YgbG9nR3JvdXAgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGxvZ0dyb3VwO1xuICB9XG4gIGlmIChsb2dHcm91cCAmJiB0eXBlb2YgbG9nR3JvdXAgPT09ICdvYmplY3QnICYmIHR5cGVvZiBsb2dHcm91cC5SZWYgPT09ICdzdHJpbmcnKSB7XG4gICAgY29uc3QgcmVmZXJlbmNlZCA9IHRlbXBsYXRlLlJlc291cmNlcz8uW2xvZ0dyb3VwLlJlZl07XG4gICAgY29uc3QgbmFtZSA9IHJlZmVyZW5jZWQ/LlByb3BlcnRpZXM/LkxvZ0dyb3VwTmFtZTtcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9XG4gICAgLy8gTm8gZXhwbGljaXQgbmFtZSAoQ2xvdWRGb3JtYXRpb24gZ2VuZXJhdGVzIGl0KSDigJQgcmVzb2x2ZSB0aGUgbG9nLWdyb3VwIHJlc291cmNlJ3NcbiAgICAvLyBwaHlzaWNhbCBuYW1lLCB3aGljaCBpcyB0aGUgbG9nIGdyb3VwIG5hbWUuXG4gICAgcmV0dXJuIChhd2FpdCByZXNvbHZlU3RhY2tSZXNvdXJjZShjZm4sIHN0YWNrTmFtZSwgbG9nR3JvdXAuUmVmLCBkZWJ1ZykpPy5waHlzaWNhbElkO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIHJlc291cmNlJ3MgcGh5c2ljYWwgSUQgYW5kIHR5cGUgYnkgbG9naWNhbCBJRC4gUmV0dXJucyBgdW5kZWZpbmVkYCBvbiBmYWlsdXJlLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlU3RhY2tSZXNvdXJjZShcbiAgY2ZuOiBJQ2xvdWRGb3JtYXRpb25DbGllbnQsXG4gIHN0YWNrTmFtZTogc3RyaW5nLFxuICBsb2dpY2FsSWQ6IHN0cmluZyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8eyBwaHlzaWNhbElkPzogc3RyaW5nOyByZXNvdXJjZVR5cGU/OiBzdHJpbmcgfSB8IHVuZGVmaW5lZD4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBjZm4uZGVzY3JpYmVTdGFja1Jlc291cmNlcyh7IFN0YWNrTmFtZTogc3RhY2tOYW1lLCBMb2dpY2FsUmVzb3VyY2VJZDogbG9naWNhbElkIH0pO1xuICAgIGNvbnN0IHJlc291cmNlID0gcmVzcC5TdGFja1Jlc291cmNlcz8uWzBdO1xuICAgIHJldHVybiByZXNvdXJjZSA/IHsgcGh5c2ljYWxJZDogcmVzb3VyY2UuUGh5c2ljYWxSZXNvdXJjZUlkLCByZXNvdXJjZVR5cGU6IHJlc291cmNlLlJlc291cmNlVHlwZSB9IDogdW5kZWZpbmVkO1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICBhd2FpdCBkZWJ1ZyhgQ3VzdG9tIHJlc291cmNlIGludmVzdGlnYXRpb246IGZhaWxlZCB0byByZXNvbHZlIHJlc291cmNlIFwiJHtsb2dpY2FsSWR9XCI6ICR7ZS5tZXNzYWdlfWApO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXNvbHZlIGEgYFNlcnZpY2VUb2tlbmAgdmFsdWUgKGEgbGl0ZXJhbCBBUk4sIGFuIGBGbjo6R2V0QXR0YCwgb3IgYSBgUmVmYCkgdG8gYSBMYW1iZGFcbiAqIGZ1bmN0aW9uIG5hbWUuIEludHJpbnNpY3MgYXJlIHJlc29sdmVkIHZpYSBgZGVzY3JpYmVTdGFja1Jlc291cmNlc2AuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVTZXJ2aWNlVG9rZW5Ub0Z1bmN0aW9uTmFtZShcbiAgY2ZuOiBJQ2xvdWRGb3JtYXRpb25DbGllbnQsXG4gIHN0YWNrTmFtZTogc3RyaW5nLFxuICBzZXJ2aWNlVG9rZW46IGFueSxcbiAgcmVmZXJlbmNlZExvZ2ljYWxJZDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgaWYgKHJlZmVyZW5jZWRMb2dpY2FsSWQpIHtcbiAgICBjb25zdCByZXNvdXJjZSA9IGF3YWl0IHJlc29sdmVTdGFja1Jlc291cmNlKGNmbiwgc3RhY2tOYW1lLCByZWZlcmVuY2VkTG9naWNhbElkLCBkZWJ1Zyk7XG4gICAgLy8gT25seSB0cmVhdCB0aGUgcmVmZXJlbmNlIGFzIGEgTGFtYmRhIGZ1bmN0aW9uLiBXaXRob3V0IHRoaXMsIGEgU2VydmljZVRva2VuIHBvaW50aW5nIGF0XG4gICAgLy8gYSBub24tTGFtYmRhIHJlc291cmNlIChlLmcuIGFuIFNOUyB0b3BpYykgd2hvc2UgcGh5c2ljYWwgSUQgaXMgYSBiYXJlIG5hbWUgd291bGQgYmVcbiAgICAvLyBtaXN0YWtlbiBmb3IgYSBmdW5jdGlvbiBuYW1lLCBwcm9kdWNpbmcgYSBtaXNsZWFkaW5nIC9hd3MvbGFtYmRhLzxuYW1lPiBsb2cgbG9va3VwLlxuICAgIGlmIChyZXNvdXJjZT8ucmVzb3VyY2VUeXBlICYmIHJlc291cmNlLnJlc291cmNlVHlwZSAhPT0gJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpIHtcbiAgICAgIGF3YWl0IGRlYnVnKGBDdXN0b20gcmVzb3VyY2UgaW52ZXN0aWdhdGlvbjogU2VydmljZVRva2VuIHJlZmVyZW5jZXMgYSAke3Jlc291cmNlLnJlc291cmNlVHlwZX0sIG5vdCBhIExhbWJkYSBmdW5jdGlvbmApO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHJlc291cmNlPy5waHlzaWNhbElkID8gZnVuY3Rpb25OYW1lRnJvbUFybk9yTmFtZShyZXNvdXJjZS5waHlzaWNhbElkKSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygc2VydmljZVRva2VuID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmdW5jdGlvbk5hbWVGcm9tQXJuT3JOYW1lKHNlcnZpY2VUb2tlbik7XG4gIH1cblxuICBhd2FpdCBkZWJ1ZygnQ3VzdG9tIHJlc291cmNlIGludmVzdGlnYXRpb246IHVuc3VwcG9ydGVkIFNlcnZpY2VUb2tlbiBzaGFwZScpO1xuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaEN1c3RvbVJlc291cmNlTG9ncyhcbiAgY3dsOiBJQ2xvdWRXYXRjaExvZ3NDbGllbnQsXG4gIGxhbWJkYTogSUxhbWJkYUNsaWVudCxcbiAgZnVuY3Rpb25OYW1lOiBzdHJpbmcsXG4gIHRlbXBsYXRlTG9nR3JvdXA6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgc3RyZWFtTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICB0aW1lc3RhbXA6IERhdGUgfCB1bmRlZmluZWQsXG4gIHJlZ2lvbjogc3RyaW5nLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHRbXT4ge1xuICBjb25zdCBmYWlsdXJlVGltZSA9IHRpbWVzdGFtcD8udmFsdWVPZigpO1xuICBjb25zdCBzdGFydFRpbWUgPSBmYWlsdXJlVGltZSAhPT0gdW5kZWZpbmVkID8gZmFpbHVyZVRpbWUgLSBMT0dfV0lORE9XX0JFRk9SRV9NUyA6IERhdGUubm93KCkgLSBGQUxMQkFDS19MT0dfV0lORE9XX01TO1xuICBjb25zdCBlbmRUaW1lID0gZmFpbHVyZVRpbWUgIT09IHVuZGVmaW5lZCA/IGZhaWx1cmVUaW1lICsgTE9HX1dJTkRPV19BRlRFUl9NUyA6IHVuZGVmaW5lZDtcblxuICAvLyBDb252ZW50aW9uIGZpcnN0OyBvbmx5IHBheSBmb3IgdGhlIGNvbmZpZ3VyZWQgZ3JvdXAgaWYgdGhlIGNvbnZlbnRpb24gZ3JvdXAgZG9lc24ndCB5aWVsZCB1c2FibGUgbGluZXMgKGVtcHR5IGdyb3VwIG9yIGZldGNoIGVycm9yKS5cbiAgY29uc3QgY29udmVudGlvbkdyb3VwID0gYC9hd3MvbGFtYmRhLyR7ZnVuY3Rpb25OYW1lfWA7XG4gIGxldCByZXN1bHQgPSBhd2FpdCBmZXRjaExvZ0xpbmVzKGN3bCwgY29udmVudGlvbkdyb3VwLCBzdHJlYW1OYW1lLCBzdGFydFRpbWUsIGVuZFRpbWUsIGRlYnVnKTtcbiAgLy8gVGhlIGdyb3VwIHdlIHBvaW50IHRoZSB1c2VyIGF0LiBPbmNlIHdlIGxlYXJuIHRoZSBmdW5jdGlvbidzIGNvbmZpZ3VyZWQgbG9nIGdyb3VwLCBwcmVmZXJcbiAgLy8gaXQgZm9yIHRoZSBsaW5rIGV2ZW4gaWYgaXQgdG9vIGlzIGVtcHR5IOKAlCBpdCdzIHdoZXJlIHRoZSBmdW5jdGlvbiBhY3R1YWxseSBsb2dzLCB3aGVyZWFzXG4gIC8vIHRoZSBjb252ZW50aW9uIGdyb3VwIG1heSBub3QgZXhpc3QgZm9yIGFkdmFuY2VkLWxvZ2dpbmcgZnVuY3Rpb25zLlxuICBsZXQgbG9nR3JvdXAgPSBjb252ZW50aW9uR3JvdXA7XG5cbiAgaWYgKHJlc3VsdC5raW5kICE9PSAnbGluZXMnKSB7XG4gICAgLy8gUHJlZmVyIHRoZSB0ZW1wbGF0ZS1kZXJpdmVkIGdyb3VwIChyb2xsYmFjay1wcm9vZik7IGZhbGwgYmFjayB0byB0aGUgbGl2ZSBmdW5jdGlvblxuICAgIC8vIGNvbmZpZ3VyYXRpb24gb25seSB3aGVuIHRoZSB0ZW1wbGF0ZSBjb3VsZG4ndCB0ZWxsIHVzIChlLmcuIHVucmVzb2x2YWJsZSBpbnRyaW5zaWMsIG9yXG4gICAgLy8gdGhlIGZ1bmN0aW9uIGlzIGRlZmluZWQgb3V0c2lkZSB0aGlzIHN0YWNrKS5cbiAgICBjb25zdCBjb25maWd1cmVkR3JvdXAgPSB0ZW1wbGF0ZUxvZ0dyb3VwID8/IGF3YWl0IGNvbmZpZ3VyZWRMb2dHcm91cChsYW1iZGEsIGZ1bmN0aW9uTmFtZSwgZGVidWcpO1xuICAgIGlmIChjb25maWd1cmVkR3JvdXAgJiYgY29uZmlndXJlZEdyb3VwICE9PSBjb252ZW50aW9uR3JvdXApIHtcbiAgICAgIGxvZ0dyb3VwID0gY29uZmlndXJlZEdyb3VwO1xuICAgICAgY29uc3QgY29uZmlndXJlZFJlc3VsdCA9IGF3YWl0IGZldGNoTG9nTGluZXMoY3dsLCBjb25maWd1cmVkR3JvdXAsIHN0cmVhbU5hbWUsIHN0YXJ0VGltZSwgZW5kVGltZSwgZGVidWcpO1xuICAgICAgLy8gS2VlcCB0aGUgY29uZmlndXJlZC1ncm91cCByZXN1bHQgdW5sZXNzIGl0IGVycm9yZWQgd2hpbGUgdGhlIGNvbnZlbnRpb24gYXR0ZW1wdCB3YXMgYVxuICAgICAgLy8gY2xlYW4gZW1wdHkgKGFuIFwiZW1wdHlcIiBhbnN3ZXIgaXMgbW9yZSBpbmZvcm1hdGl2ZSB0byBzdXJmYWNlIHRoYW4gYSBmZXRjaCBlcnJvcikuXG4gICAgICBpZiAoY29uZmlndXJlZFJlc3VsdC5raW5kID09PSAnbGluZXMnIHx8IHJlc3VsdC5raW5kICE9PSAnZW1wdHknKSB7XG4gICAgICAgIHJlc3VsdCA9IGNvbmZpZ3VyZWRSZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gTGVhZCB3aXRoIHRoZSBsb2cgZ3JvdXAgc28gdGhlIHVzZXIgY2FuIHRlbGwgd2hpY2ggZnVuY3Rpb24gdGhlc2UgbG9ncyBiZWxvbmcgdG9cbiAgLy8gKHRoZSBmb3JtYXR0ZXIgcmVuZGVycyBtZXNzYWdlcyBidXQgbm90IGBzb3VyY2VgLCBhbmQgdGhlIGxpbmsgaXMgVVJMLWVuY29kZWQpLlxuICBjb25zdCBoZWFkZXIgPSBgTG9ncyBmcm9tICR7bG9nR3JvdXB9OmA7XG4gIGNvbnN0IGJvZHkgPSByZXN1bHQua2luZCA9PT0gJ2xpbmVzJ1xuICAgID8gcmVzdWx0LmxpbmVzXG4gICAgOiByZXN1bHQua2luZCA9PT0gJ2Vycm9yJ1xuICAgICAgPyBbJ0NvdWxkIG5vdCBmZXRjaCBsb2dzICh0aGUgbG9nIGdyb3VwIG1heSBub3QgZXhpc3QsIG9yIHRoZSBjcmVkZW50aWFscyBsYWNrIGxvZ3M6RmlsdGVyTG9nRXZlbnRzKS4gU2VlIHRoZSBjb25zb2xlIGxpbmsgYmVsb3cuJ11cbiAgICAgIDogWydObyBsb2cgZXZlbnRzIGZvdW5kIGFyb3VuZCB0aGUgdGltZSBvZiBmYWlsdXJlLiBUaGUgZnVuY3Rpb24gbWF5IG5vdCBoYXZlIHByb2R1Y2VkIG91dHB1dCwgb3IgbG9nZ2luZyBtYXkgbm90IGJlIGNvbmZpZ3VyZWQuJ107XG5cbiAgcmV0dXJuIFt7XG4gICAgc291cmNlOiAnQ3VzdG9tIFJlc291cmNlIExhbWJkYSBMb2dzJyxcbiAgICBtZXNzYWdlczogW2hlYWRlciwgLi4uYm9keV0sXG4gICAgbGluazogY2xvdWRXYXRjaExvZ3NDb25zb2xlVXJsKHJlZ2lvbiwgbG9nR3JvdXApLFxuICAgIGxpbmtMYWJlbDogJ0xvZ3MnLFxuICB9XTtcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgYXR0ZW1wdGluZyB0byBmZXRjaCBsb2dzIGZyb20gYSBncm91cDogdGhlIGxpbmVzIG9uIHN1Y2Nlc3MsIG9yIGEgcmVhc29uIHdlXG4gKiBoYXZlIG5vbmUg4oCUIGRpc3Rpbmd1aXNoaW5nIGFuIGVtcHR5IGdyb3VwIGZyb20gYSBmYWlsZWQgZmV0Y2ggKGUuZy4gbWlzc2luZyBwZXJtaXNzaW9ucyksXG4gKiBzbyB0aGUgdXNlci1mYWNpbmcgbWVzc2FnZSBjYW4gcmVmbGVjdCB0aGUgcmVhbCBjYXVzZS5cbiAqL1xudHlwZSBMb2dGZXRjaFJlc3VsdCA9XG4gIHwgeyBraW5kOiAnbGluZXMnOyBsaW5lczogc3RyaW5nW10gfVxuICB8IHsga2luZDogJ2VtcHR5JyB9XG4gIHwgeyBraW5kOiAnZXJyb3InIH07XG5cbi8qKlxuICogRmV0Y2ggYW5kIHRyaW0gcmVjZW50IGxvZyBsaW5lcyBmcm9tIGEgZ3JvdXAuXG4gKlxuICogVHJpZXMgdGhlIHRhcmdldGVkIHN0cmVhbSBmaXJzdCAobW9zdCByZWxldmFudCksIGJ1dCB0aGUgY2ZuLXJlc3BvbnNlIHN0cmVhbSBuYW1lIGNhbiBiZVxuICogc3RhbGUgb24gdXBkYXRlL3JvbGxiYWNrIGZhaWx1cmVzIChpdCdzIHBpbm5lZCB0byB0aGUgb3JpZ2luYWwgY3JlYXRlIGludm9jYXRpb24pLiBJZiB0aGVcbiAqIHRhcmdldGVkIHF1ZXJ5IGZpbmRzIG5vdGhpbmcsIGZhbGxzIGJhY2sgdG8gYSBncm91cC13aWRlIHNjYW4gb3ZlciB0aGUgdGltZSB3aW5kb3cgc28gYVxuICogc3RhbGUgc3RyZWFtIGNhbid0IGhpZGUgdGhlIGFjdHVhbCBmYWlsaW5nIGludm9jYXRpb24ncyBsb2dzLlxuICovXG5hc3luYyBmdW5jdGlvbiBmZXRjaExvZ0xpbmVzKFxuICBjd2w6IElDbG91ZFdhdGNoTG9nc0NsaWVudCxcbiAgbG9nR3JvdXA6IHN0cmluZyxcbiAgc3RyZWFtTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBzdGFydFRpbWU6IG51bWJlcixcbiAgZW5kVGltZTogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxMb2dGZXRjaFJlc3VsdD4ge1xuICBpZiAoc3RyZWFtTmFtZSkge1xuICAgIGNvbnN0IHRhcmdldGVkID0gYXdhaXQgZmlsdGVyTG9nTGluZXMoY3dsLCBsb2dHcm91cCwgc3RyZWFtTmFtZSwgc3RhcnRUaW1lLCBlbmRUaW1lLCBkZWJ1Zyk7XG4gICAgaWYgKHRhcmdldGVkLmtpbmQgPT09ICdsaW5lcycpIHtcbiAgICAgIHJldHVybiB0YXJnZXRlZDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZpbHRlckxvZ0xpbmVzKGN3bCwgbG9nR3JvdXAsIHVuZGVmaW5lZCwgc3RhcnRUaW1lLCBlbmRUaW1lLCBkZWJ1Zyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbHRlckxvZ0xpbmVzKFxuICBjd2w6IElDbG91ZFdhdGNoTG9nc0NsaWVudCxcbiAgbG9nR3JvdXA6IHN0cmluZyxcbiAgc3RyZWFtTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBzdGFydFRpbWU6IG51bWJlcixcbiAgZW5kVGltZTogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxMb2dGZXRjaFJlc3VsdD4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBjd2wuZmlsdGVyTG9nRXZlbnRzKHtcbiAgICAgIGxvZ0dyb3VwTmFtZTogbG9nR3JvdXAsXG4gICAgICBzdGFydFRpbWUsXG4gICAgICAuLi4oZW5kVGltZSAhPT0gdW5kZWZpbmVkID8geyBlbmRUaW1lIH0gOiB7fSksXG4gICAgICBsaW1pdDogMTAwMCxcbiAgICAgIC4uLihzdHJlYW1OYW1lID8geyBsb2dTdHJlYW1OYW1lczogW3N0cmVhbU5hbWVdIH0gOiB7fSksXG4gICAgfSk7XG4gICAgY29uc3QgZXZlbnRzID0gcmVzcC5ldmVudHMgPz8gW107XG4gICAgaWYgKGV2ZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IGRlYnVnKGBDdXN0b20gcmVzb3VyY2UgaW52ZXN0aWdhdGlvbjogbm8gbG9nIGV2ZW50cyBpbiAke2xvZ0dyb3VwfSR7c3RyZWFtTmFtZSA/IGAgKHN0cmVhbTogJHtzdHJlYW1OYW1lfSlgIDogJyd9YCk7XG4gICAgICByZXR1cm4geyBraW5kOiAnZW1wdHknIH07XG4gICAgfVxuICAgIC8vIExhbWJkYSBsb2cgZXZlbnRzIGhhdmUgYSBrbm93biBzdHJ1Y3R1cmUgKHRleHQtIG9yIEpTT04tZm9ybWF0KSwgdW5saWtlIHJhdyBFQ1NcbiAgICAvLyBjb250YWluZXIgb3V0cHV0LCBzbyB3ZSBub3JtYWxpemUgdGhlbSBpbnRvIHJlYWRhYmxlIGxpbmVzIGJlZm9yZSB0cmltbWluZy5cbiAgICByZXR1cm4geyBraW5kOiAnbGluZXMnLCBsaW5lczogdHJpbVRvUmVjZW50TGluZXMocGFyc2VMYW1iZGFMb2dFdmVudHMoZXZlbnRzKSkgfTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgYXdhaXQgZGVidWcoYEN1c3RvbSByZXNvdXJjZSBpbnZlc3RpZ2F0aW9uOiBmYWlsZWQgdG8gZmV0Y2ggbG9ncyBmcm9tICR7bG9nR3JvdXB9OiAke2UubWVzc2FnZX1gKTtcbiAgICByZXR1cm4geyBraW5kOiAnZXJyb3InIH07XG4gIH1cbn1cblxuLyoqIFJlYWQgdGhlIGZ1bmN0aW9uJ3MgY29uZmlndXJlZCAoYWR2YW5jZWQtbG9nZ2luZykgbG9nIGdyb3VwLCBpZiBhbnkuICovXG5hc3luYyBmdW5jdGlvbiBjb25maWd1cmVkTG9nR3JvdXAoXG4gIGxhbWJkYTogSUxhbWJkYUNsaWVudCxcbiAgZnVuY3Rpb25OYW1lOiBzdHJpbmcsXG4gIGRlYnVnOiAobXNnOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4sXG4pOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBsYW1iZGEuZ2V0RnVuY3Rpb25Db25maWd1cmF0aW9uKHsgRnVuY3Rpb25OYW1lOiBmdW5jdGlvbk5hbWUgfSk7XG4gICAgcmV0dXJuIHJlc3AuTG9nZ2luZ0NvbmZpZz8uTG9nR3JvdXA7XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIGF3YWl0IGRlYnVnKGBDdXN0b20gcmVzb3VyY2UgaW52ZXN0aWdhdGlvbjogZmFpbGVkIHRvIHJlYWQgZnVuY3Rpb24gY29uZmlndXJhdGlvbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIl19
@@ -0,0 +1,20 @@
1
+ import type { AdditionalDiagnosticContext } from '../../actions/diagnose';
2
+ import type { SDK } from '../aws-auth/sdk';
3
+ 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
+ }
19
+ export declare function investigateEcsService(err: ResourceError, sdk: SDK, debug: (msg: string) => Promise<void>, options: InvestigateOptions): Promise<AdditionalDiagnosticContext[]>;
20
+ //# sourceMappingURL=investigate-ecs-service.d.ts.map