@pagopa/dx-savemoney 0.2.6 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -27
- package/dist/__tests__/finding.test.d.ts +17 -0
- package/dist/__tests__/finding.test.d.ts.map +1 -0
- package/dist/__tests__/finding.test.js +124 -0
- package/dist/__tests__/finding.test.js.map +1 -0
- package/dist/azure/__tests__/analyzer-tags.test.d.ts +8 -0
- package/dist/azure/__tests__/analyzer-tags.test.d.ts.map +1 -0
- package/dist/azure/__tests__/analyzer-tags.test.js +43 -0
- package/dist/azure/__tests__/analyzer-tags.test.js.map +1 -0
- package/dist/azure/__tests__/config.test.d.ts +9 -0
- package/dist/azure/__tests__/config.test.d.ts.map +1 -0
- package/dist/azure/__tests__/config.test.js +70 -0
- package/dist/azure/__tests__/config.test.js.map +1 -0
- package/dist/azure/__tests__/report.test.d.ts +9 -0
- package/dist/azure/__tests__/report.test.d.ts.map +1 -0
- package/dist/azure/__tests__/report.test.js +120 -0
- package/dist/azure/__tests__/report.test.js.map +1 -0
- package/dist/azure/__tests__/utils.test.d.ts +15 -0
- package/dist/azure/__tests__/utils.test.d.ts.map +1 -0
- package/dist/azure/__tests__/utils.test.js +181 -0
- package/dist/azure/__tests__/utils.test.js.map +1 -0
- package/dist/azure/analyzer.d.ts +18 -5
- package/dist/azure/analyzer.d.ts.map +1 -1
- package/dist/azure/analyzer.js +295 -48
- package/dist/azure/analyzer.js.map +1 -1
- package/dist/azure/analyzers/__tests__/advisor.test.d.ts +9 -0
- package/dist/azure/analyzers/__tests__/advisor.test.d.ts.map +1 -0
- package/dist/azure/analyzers/__tests__/advisor.test.js +314 -0
- package/dist/azure/analyzers/__tests__/advisor.test.js.map +1 -0
- package/dist/azure/analyzers/advisor.d.ts +68 -0
- package/dist/azure/analyzers/advisor.d.ts.map +1 -0
- package/dist/azure/analyzers/advisor.js +234 -0
- package/dist/azure/analyzers/advisor.js.map +1 -0
- package/dist/azure/analyzers/index.d.ts +3 -1
- package/dist/azure/analyzers/index.d.ts.map +1 -1
- package/dist/azure/analyzers/index.js +2 -1
- package/dist/azure/analyzers/index.js.map +1 -1
- package/dist/azure/analyzers/registry.d.ts +8 -0
- package/dist/azure/analyzers/registry.d.ts.map +1 -1
- package/dist/azure/analyzers/registry.js +10 -0
- package/dist/azure/analyzers/registry.js.map +1 -1
- package/dist/azure/analyzers/subscription.d.ts +53 -0
- package/dist/azure/analyzers/subscription.d.ts.map +1 -0
- package/dist/azure/analyzers/subscription.js +18 -0
- package/dist/azure/analyzers/subscription.js.map +1 -0
- package/dist/azure/config.d.ts.map +1 -1
- package/dist/azure/config.js +1 -0
- package/dist/azure/config.js.map +1 -1
- package/dist/azure/index.d.ts +1 -0
- package/dist/azure/index.d.ts.map +1 -1
- package/dist/azure/index.js +1 -0
- package/dist/azure/index.js.map +1 -1
- package/dist/azure/report.d.ts.map +1 -1
- package/dist/azure/report.js +178 -29
- package/dist/azure/report.js.map +1 -1
- package/dist/azure/resources/__tests__/storage.test.d.ts +11 -0
- package/dist/azure/resources/__tests__/storage.test.d.ts.map +1 -0
- package/dist/azure/resources/__tests__/storage.test.js +99 -0
- package/dist/azure/resources/__tests__/storage.test.js.map +1 -0
- package/dist/azure/types.d.ts +28 -1
- package/dist/azure/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +78 -0
- package/dist/index.test.js.map +1 -0
- package/dist/schema.d.ts +4 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +9 -0
- package/dist/schema.js.map +1 -1
- package/package.json +5 -3
- package/src/azure/__tests__/analyzer-tags.test.ts +74 -0
- package/src/azure/__tests__/report.test.ts +35 -6
- package/src/azure/analyzer.ts +421 -65
- package/src/azure/analyzers/__tests__/advisor.test.ts +367 -0
- package/src/azure/analyzers/advisor.ts +324 -0
- package/src/azure/analyzers/index.ts +9 -1
- package/src/azure/analyzers/registry.ts +12 -0
- package/src/azure/analyzers/subscription.ts +56 -0
- package/src/azure/config.ts +1 -0
- package/src/azure/index.ts +1 -0
- package/src/azure/report.ts +206 -35
- package/src/azure/types.ts +29 -1
- package/src/index.ts +1 -1
- package/src/schema.ts +9 -0
package/dist/azure/report.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Azure report generation
|
|
3
3
|
*/
|
|
4
|
+
import Table from "cli-table3";
|
|
5
|
+
// Fixed column widths — keeps the Reason column within a readable width
|
|
6
|
+
// while allowing cli-table3 to word-wrap long content across multiple lines.
|
|
7
|
+
const COL_WIDTHS = [30, 35, 25, 8, 55];
|
|
4
8
|
// ANSI color codes — only applied when stdout is a TTY to avoid cluttering redirected output
|
|
5
9
|
const isTTY = process.stdout.isTTY ?? false;
|
|
6
10
|
const RED = isTTY ? "\x1b[31m" : "";
|
|
7
11
|
const YELLOW = isTTY ? "\x1b[33m" : "";
|
|
8
12
|
const BLUE = isTTY ? "\x1b[34m" : "";
|
|
13
|
+
const GREEN = isTTY ? "\x1b[32m" : "";
|
|
14
|
+
const CYAN = isTTY ? "\x1b[36m" : "";
|
|
9
15
|
const BOLD = isTTY ? "\x1b[1m" : "";
|
|
10
16
|
const RESET = isTTY ? "\x1b[0m" : "";
|
|
11
17
|
const DIM = isTTY ? "\x1b[2m" : "";
|
|
@@ -30,66 +36,209 @@ export async function generateReport(report, format) {
|
|
|
30
36
|
console.log(JSON.stringify(report, null, 2));
|
|
31
37
|
return;
|
|
32
38
|
}
|
|
33
|
-
// For other formats, we extract the summary data.
|
|
34
|
-
const summaryReport = report.map((r) => ({
|
|
35
|
-
costRisk: r.analysis.costRisk,
|
|
36
|
-
location: r.resource.location ?? "",
|
|
37
|
-
name: r.resource.name ?? "unknown",
|
|
38
|
-
reason: r.analysis.reason,
|
|
39
|
-
resourceGroup: r.resource.id?.split("/")[4],
|
|
40
|
-
subscriptionId: r.resource.id?.split("/")[2] ?? "unknown",
|
|
41
|
-
suspectedUnused: r.analysis.suspectedUnused,
|
|
42
|
-
type: r.resource.type ?? "unknown",
|
|
43
|
-
}));
|
|
44
39
|
if (format === "json") {
|
|
40
|
+
const summaryReport = report.map((r) => ({
|
|
41
|
+
costRisk: r.analysis.costRisk,
|
|
42
|
+
location: r.resource.location ?? "",
|
|
43
|
+
name: r.resource.name ?? "unknown",
|
|
44
|
+
reason: r.analysis.reason,
|
|
45
|
+
resourceGroup: r.resource.id?.split("/")[4],
|
|
46
|
+
subscriptionId: r.resource.id?.split("/")[2] ?? "unknown",
|
|
47
|
+
suspectedUnused: r.analysis.suspectedUnused,
|
|
48
|
+
type: r.resource.type ?? "unknown",
|
|
49
|
+
}));
|
|
45
50
|
console.log(JSON.stringify(summaryReport, null, 2));
|
|
46
51
|
}
|
|
47
52
|
else if (format === "lint") {
|
|
48
53
|
generateLintReport(report);
|
|
49
54
|
}
|
|
50
55
|
else {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const summaryReport = report.map((r) => ({
|
|
57
|
+
costRisk: r.analysis.costRisk,
|
|
58
|
+
location: r.resource.location ?? "",
|
|
59
|
+
name: r.resource.name ?? "unknown",
|
|
60
|
+
reason: r.analysis.reason,
|
|
61
|
+
resourceGroup: r.resource.id?.split("/")[4],
|
|
62
|
+
subscriptionId: r.resource.id?.split("/")[2] ?? "unknown",
|
|
63
|
+
suspectedUnused: r.analysis.suspectedUnused,
|
|
64
|
+
type: r.resource.type ?? "unknown",
|
|
65
|
+
}));
|
|
66
|
+
const table = new Table({
|
|
67
|
+
colWidths: [...COL_WIDTHS],
|
|
68
|
+
head: ["Name", "Type", "Resource Group", "Risk", "Reason"],
|
|
69
|
+
wordWrap: true,
|
|
70
|
+
});
|
|
71
|
+
for (const r of summaryReport) {
|
|
72
|
+
table.push([
|
|
73
|
+
r.name,
|
|
74
|
+
r.type,
|
|
75
|
+
r.resourceGroup || "N/A",
|
|
76
|
+
r.costRisk,
|
|
77
|
+
r.reason,
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
console.log(table.toString());
|
|
81
|
+
// Same summary block the lint format prints, so the table view also
|
|
82
|
+
// surfaces totals, source breakdown and estimated savings at a glance.
|
|
83
|
+
printSummary(computeSummary(report));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Walks the report once to compute totals, source breakdown and savings
|
|
88
|
+
* per currency without mutating it. Used by the table format, which has
|
|
89
|
+
* no per-line walk of its own.
|
|
90
|
+
*/
|
|
91
|
+
function computeSummary(report) {
|
|
92
|
+
const summary = {
|
|
93
|
+
counts: { high: 0, low: 0, medium: 0 },
|
|
94
|
+
savingsByCurrency: new Map(),
|
|
95
|
+
sourceCounts: {},
|
|
96
|
+
};
|
|
97
|
+
for (const entry of report) {
|
|
98
|
+
const lines = entry.findings?.length
|
|
99
|
+
? entry.findings.map((f) => ({
|
|
100
|
+
savings: f.estimatedMonthlySavings,
|
|
101
|
+
severity: f.severity,
|
|
102
|
+
source: f.source,
|
|
103
|
+
}))
|
|
104
|
+
: splitReasons(entry.analysis.reason).map(() => ({
|
|
105
|
+
savings: undefined,
|
|
106
|
+
severity: entry.analysis.costRisk,
|
|
107
|
+
source: "custom",
|
|
108
|
+
}));
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
summary.counts[line.severity]++;
|
|
111
|
+
summary.sourceCounts[line.source] =
|
|
112
|
+
(summary.sourceCounts[line.source] ?? 0) + 1;
|
|
113
|
+
if (line.savings) {
|
|
114
|
+
summary.savingsByCurrency.set(line.savings.currency, (summary.savingsByCurrency.get(line.savings.currency) ?? 0) +
|
|
115
|
+
line.savings.amount);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return summary;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Formats a monetary amount with an ISO 4217 currency code, falling back
|
|
123
|
+
* to the raw code prefix when the runtime locale data lacks the currency
|
|
124
|
+
* symbol.
|
|
125
|
+
*/
|
|
126
|
+
function formatAmount(amount, currency) {
|
|
127
|
+
try {
|
|
128
|
+
return new Intl.NumberFormat("en-US", {
|
|
129
|
+
currency,
|
|
130
|
+
maximumFractionDigits: 2,
|
|
131
|
+
minimumFractionDigits: 2,
|
|
132
|
+
style: "currency",
|
|
133
|
+
}).format(amount);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return `${currency} ${amount.toFixed(2)}`;
|
|
58
137
|
}
|
|
59
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Renders an estimated monthly savings value as the short "(€ 12.50/mo)"
|
|
141
|
+
* label that ships next to each lint line. Returns an empty string when
|
|
142
|
+
* the analyzer didn't provide an estimate.
|
|
143
|
+
*/
|
|
144
|
+
function formatSavings(savings) {
|
|
145
|
+
if (!savings)
|
|
146
|
+
return "";
|
|
147
|
+
return `(${formatAmount(savings.amount, savings.currency)}/mo)`;
|
|
148
|
+
}
|
|
60
149
|
/**
|
|
61
150
|
* Renders a linter-style report to stdout, grouping findings by resource.
|
|
62
151
|
*
|
|
152
|
+
* When `Finding[]` is attached to a report (Phase 1+), each finding is
|
|
153
|
+
* rendered with its `source` badge (e.g. `[advisor]`) and the estimated
|
|
154
|
+
* monthly savings, when known. For older payloads without `findings` we
|
|
155
|
+
* fall back to splitting `analysis.reason` like before so the format stays
|
|
156
|
+
* backward compatible.
|
|
157
|
+
*
|
|
63
158
|
* Example output:
|
|
64
159
|
*
|
|
65
160
|
* /subscriptions/.../virtualMachines/my-vm
|
|
66
|
-
* ✖ HIGH VM
|
|
67
|
-
* ✖ HIGH No tags found.
|
|
161
|
+
* ✖ HIGH [advisor] Right-size your VM. (€ 12.50/mo)
|
|
162
|
+
* ✖ HIGH [custom] No tags found.
|
|
68
163
|
*
|
|
69
164
|
* Summary: 3 issues found (2 high, 0 medium, 1 low)
|
|
165
|
+
* Estimated monthly savings: € 12.50
|
|
70
166
|
*/
|
|
71
167
|
function generateLintReport(report) {
|
|
72
|
-
const
|
|
168
|
+
const summary = {
|
|
169
|
+
counts: { high: 0, low: 0, medium: 0 },
|
|
170
|
+
savingsByCurrency: new Map(),
|
|
171
|
+
sourceCounts: {},
|
|
172
|
+
};
|
|
73
173
|
for (const entry of report) {
|
|
74
174
|
const resourceId = entry.resource.id ?? `unknown/${entry.resource.name ?? "unknown"}`;
|
|
75
|
-
const risk = entry.analysis.costRisk;
|
|
76
|
-
const findings = splitReasons(entry.analysis.reason);
|
|
77
175
|
console.log(`${BOLD}${resourceId}${RESET}`);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
176
|
+
const lines = entry.findings?.length
|
|
177
|
+
? entry.findings.map((f) => ({
|
|
178
|
+
extra: formatSavings(f.estimatedMonthlySavings),
|
|
179
|
+
severity: f.severity,
|
|
180
|
+
source: f.source,
|
|
181
|
+
text: f.reason,
|
|
182
|
+
}))
|
|
183
|
+
: splitReasons(entry.analysis.reason).map((text) => ({
|
|
184
|
+
extra: "",
|
|
185
|
+
severity: entry.analysis.costRisk,
|
|
186
|
+
source: "custom",
|
|
187
|
+
text,
|
|
188
|
+
}));
|
|
189
|
+
for (const line of lines) {
|
|
190
|
+
const icon = RISK_ICON[line.severity];
|
|
191
|
+
const color = RISK_COLOR[line.severity];
|
|
192
|
+
const label = `${color}${line.severity.toUpperCase().padEnd(6)}${RESET}`;
|
|
193
|
+
const sourceBadge = `${CYAN}[${line.source}]${RESET}`;
|
|
194
|
+
const extra = line.extra ? ` ${GREEN}${line.extra}${RESET}` : "";
|
|
195
|
+
console.log(` ${icon} ${label} ${sourceBadge} ${DIM}${line.text}${RESET}${extra}`);
|
|
196
|
+
summary.counts[line.severity]++;
|
|
197
|
+
summary.sourceCounts[line.source] =
|
|
198
|
+
(summary.sourceCounts[line.source] ?? 0) + 1;
|
|
199
|
+
}
|
|
200
|
+
if (entry.findings) {
|
|
201
|
+
for (const f of entry.findings) {
|
|
202
|
+
if (f.estimatedMonthlySavings) {
|
|
203
|
+
const { amount, currency } = f.estimatedMonthlySavings;
|
|
204
|
+
summary.savingsByCurrency.set(currency, (summary.savingsByCurrency.get(currency) ?? 0) + amount);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
84
207
|
}
|
|
85
208
|
console.log();
|
|
86
209
|
}
|
|
210
|
+
printSummary(summary);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Prints the shared trailer (issues, sources, estimated savings) used by
|
|
214
|
+
* both the lint and the table format.
|
|
215
|
+
*
|
|
216
|
+
* Savings are kept grouped by currency intentionally: Azure Advisor
|
|
217
|
+
* returns each recommendation in the subscription's native billing
|
|
218
|
+
* currency, so the same report can carry EUR and USD figures at the
|
|
219
|
+
* same time when subscriptions are billed in different regions. We do
|
|
220
|
+
* NOT convert across currencies — the rates would be both volatile and
|
|
221
|
+
* out of scope for this tool.
|
|
222
|
+
*/
|
|
223
|
+
function printSummary(summary) {
|
|
224
|
+
const { counts, savingsByCurrency, sourceCounts } = summary;
|
|
87
225
|
const total = counts.high + counts.medium + counts.low;
|
|
88
226
|
const summaryLine = `${BOLD}Summary:${RESET} ${total} issue${total !== 1 ? "s" : ""} found` +
|
|
89
227
|
` ${RED}(${counts.high} high${RESET}` +
|
|
90
228
|
`, ${YELLOW}${counts.medium} medium${RESET}` +
|
|
91
229
|
`, ${BLUE}${counts.low} low${RESET})`;
|
|
92
230
|
console.log(summaryLine);
|
|
231
|
+
const sourceBreakdown = Object.entries(sourceCounts)
|
|
232
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
233
|
+
.map(([source, n]) => `${n} ${source}`)
|
|
234
|
+
.join(", ");
|
|
235
|
+
if (sourceBreakdown) {
|
|
236
|
+
console.log(`${BOLD}Sources:${RESET} ${sourceBreakdown}`);
|
|
237
|
+
}
|
|
238
|
+
if (savingsByCurrency.size > 0) {
|
|
239
|
+
const parts = [...savingsByCurrency.entries()].map(([currency, amount]) => `${GREEN}${formatAmount(amount, currency)}${RESET}`);
|
|
240
|
+
console.log(`${BOLD}Estimated monthly savings:${RESET} ${parts.join(", ")}`);
|
|
241
|
+
}
|
|
93
242
|
}
|
|
94
243
|
/**
|
|
95
244
|
* Splits a concatenated reason string (sentences separated by ". ") into
|
package/dist/azure/report.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/azure/report.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/azure/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for analyzeStorageAccount() — verifies that custom thresholds
|
|
3
|
+
* actually change the analysis outcome.
|
|
4
|
+
*
|
|
5
|
+
* Key scenario:
|
|
6
|
+
* - Metric: 30 avg transactions/day
|
|
7
|
+
* - Default threshold: 10 → 30 >= 10 → NOT flagged
|
|
8
|
+
* - Custom threshold: 50 → 30 < 50 → IS flagged ✓ proves the feature works
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=storage.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.test.d.ts","sourceRoot":"","sources":["../../../../src/azure/resources/__tests__/storage.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for analyzeStorageAccount() — verifies that custom thresholds
|
|
3
|
+
* actually change the analysis outcome.
|
|
4
|
+
*
|
|
5
|
+
* Key scenario:
|
|
6
|
+
* - Metric: 30 avg transactions/day
|
|
7
|
+
* - Default threshold: 10 → 30 >= 10 → NOT flagged
|
|
8
|
+
* - Custom threshold: 50 → 30 < 50 → IS flagged ✓ proves the feature works
|
|
9
|
+
*/
|
|
10
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
11
|
+
import { DEFAULT_THRESHOLDS } from "../../../types.js";
|
|
12
|
+
// Mock the utils module so we control getMetric without real Azure calls
|
|
13
|
+
vi.mock("../../utils.js", () => ({
|
|
14
|
+
getMetric: vi.fn(),
|
|
15
|
+
verboseLog: vi.fn(),
|
|
16
|
+
verboseLogAnalysisResult: vi.fn(),
|
|
17
|
+
verboseLogResourceStart: vi.fn(),
|
|
18
|
+
}));
|
|
19
|
+
// Import after vi.mock so the module resolves the mock
|
|
20
|
+
import { getMetric } from "../../utils.js";
|
|
21
|
+
import { analyzeStorageAccount } from "../storage.js";
|
|
22
|
+
// ── helpers ────────────────────────────────────────────────────────────────
|
|
23
|
+
// Minimal stub: analyzeStorageAccount only needs monitorClient to be passed
|
|
24
|
+
// through to getMetric, which is fully mocked. We provide only the shape that
|
|
25
|
+
// TypeScript requires without unsafe type assertions.
|
|
26
|
+
const FAKE_CLIENT = {
|
|
27
|
+
metrics: { list: vi.fn() },
|
|
28
|
+
};
|
|
29
|
+
const FAKE_RESOURCE = {
|
|
30
|
+
id: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Storage/storageAccounts/st1",
|
|
31
|
+
name: "st1",
|
|
32
|
+
type: "Microsoft.Storage/storageAccounts",
|
|
33
|
+
};
|
|
34
|
+
const mockGetMetric = vi.mocked(getMetric);
|
|
35
|
+
// ── tests ──────────────────────────────────────────────────────────────────
|
|
36
|
+
describe("analyzeStorageAccount — threshold sensitivity", () => {
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
mockGetMetric.mockReset();
|
|
39
|
+
});
|
|
40
|
+
describe("with DEFAULT threshold (transactionsPerDay = 10)", () => {
|
|
41
|
+
it("does NOT flag a resource with 30 transactions/day (30 ≥ 10)", async () => {
|
|
42
|
+
mockGetMetric.mockResolvedValue(30);
|
|
43
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30, DEFAULT_THRESHOLDS);
|
|
44
|
+
expect(result.suspectedUnused).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
it("flags a resource with 5 transactions/day (5 < 10)", async () => {
|
|
47
|
+
mockGetMetric.mockResolvedValue(5);
|
|
48
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30, DEFAULT_THRESHOLDS);
|
|
49
|
+
expect(result.suspectedUnused).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
it("does not flag when metric is exactly at the threshold (10)", async () => {
|
|
52
|
+
mockGetMetric.mockResolvedValue(10);
|
|
53
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30, DEFAULT_THRESHOLDS);
|
|
54
|
+
// 10 < 10 is false → not flagged
|
|
55
|
+
expect(result.suspectedUnused).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("with CUSTOM threshold (transactionsPerDay = 50)", () => {
|
|
59
|
+
const customThresholds = {
|
|
60
|
+
...DEFAULT_THRESHOLDS,
|
|
61
|
+
storage: { transactionsPerDay: 50 },
|
|
62
|
+
};
|
|
63
|
+
it("DOES flag a resource with 30 transactions/day (30 < 50) — proves override works", async () => {
|
|
64
|
+
mockGetMetric.mockResolvedValue(30);
|
|
65
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30, customThresholds);
|
|
66
|
+
expect(result.suspectedUnused).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
it("does NOT flag a resource with 60 transactions/day (60 ≥ 50)", async () => {
|
|
69
|
+
mockGetMetric.mockResolvedValue(60);
|
|
70
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30, customThresholds);
|
|
71
|
+
expect(result.suspectedUnused).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
it("flags at threshold boundary (49 < 50)", async () => {
|
|
74
|
+
mockGetMetric.mockResolvedValue(49);
|
|
75
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30, customThresholds);
|
|
76
|
+
expect(result.suspectedUnused).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe("edge cases", () => {
|
|
80
|
+
it("returns suspectedUnused: false when metric is null (data unavailable)", async () => {
|
|
81
|
+
mockGetMetric.mockResolvedValue(null);
|
|
82
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30, DEFAULT_THRESHOLDS);
|
|
83
|
+
expect(result.suspectedUnused).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
it("returns suspectedUnused: false when resource id is missing", async () => {
|
|
86
|
+
const resourceWithoutId = { ...FAKE_RESOURCE, id: undefined };
|
|
87
|
+
const result = await analyzeStorageAccount(resourceWithoutId, FAKE_CLIENT, 30, DEFAULT_THRESHOLDS);
|
|
88
|
+
expect(result.suspectedUnused).toBe(false);
|
|
89
|
+
expect(mockGetMetric).not.toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it("applies default thresholds when the parameter is omitted", async () => {
|
|
92
|
+
// 5 < DEFAULT 10 → flagged even without explicit thresholds argument
|
|
93
|
+
mockGetMetric.mockResolvedValue(5);
|
|
94
|
+
const result = await analyzeStorageAccount(FAKE_RESOURCE, FAKE_CLIENT, 30);
|
|
95
|
+
expect(result.suspectedUnused).toBe(true);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=storage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../../../src/azure/resources/__tests__/storage.test.ts"],"names":[],"mappings":"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"}
|
package/dist/azure/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Azure-specific types
|
|
3
3
|
*/
|
|
4
4
|
import type * as armResources from "@azure/arm-resources";
|
|
5
|
+
import type { Finding } from "../finding.js";
|
|
5
6
|
import type { AnalysisResult, BaseConfig, CostRisk, Thresholds } from "../types.js";
|
|
6
7
|
/**
|
|
7
8
|
* Azure configuration extending base config
|
|
@@ -18,6 +19,14 @@ export type AzureConfig = BaseConfig & {
|
|
|
18
19
|
* If omitted, all resources are analyzed.
|
|
19
20
|
*/
|
|
20
21
|
filterTags?: Map<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Which finding sources to include in the run.
|
|
24
|
+
* - `"custom"` → enables the per-resource analyzer plugins
|
|
25
|
+
* - `"advisor"` → enables the Azure Advisor subscription-level analyzer
|
|
26
|
+
*
|
|
27
|
+
* Defaults to `["advisor", "custom"]` when omitted (i.e. all sources).
|
|
28
|
+
*/
|
|
29
|
+
sources?: AzureSource[];
|
|
21
30
|
subscriptionIds: string[];
|
|
22
31
|
/**
|
|
23
32
|
* Analysis thresholds. Defaults from DEFAULT_THRESHOLDS are used when not provided.
|
|
@@ -26,10 +35,22 @@ export type AzureConfig = BaseConfig & {
|
|
|
26
35
|
verbose?: boolean;
|
|
27
36
|
};
|
|
28
37
|
/**
|
|
29
|
-
* Detailed report for a single Azure resource with full resource object
|
|
38
|
+
* Detailed report for a single Azure resource with full resource object.
|
|
39
|
+
*
|
|
40
|
+
* Phase 1 introduces the optional `findings` field carrying the unified
|
|
41
|
+
* `Finding[]` model alongside the legacy `analysis` summary. The two are
|
|
42
|
+
* kept in sync by the orchestrator so existing report formats keep
|
|
43
|
+
* working untouched while new consumers (GUI, JSON exports, Phase 2
|
|
44
|
+
* pricing aggregation) can read structured findings directly.
|
|
30
45
|
*/
|
|
31
46
|
export type AzureDetailedResourceReport = {
|
|
32
47
|
analysis: AnalysisResult;
|
|
48
|
+
/**
|
|
49
|
+
* Structured findings attached to the resource. Always populated by the
|
|
50
|
+
* orchestrator (possibly empty). Optional only for backward compatibility
|
|
51
|
+
* with serialised payloads produced before Phase 1.
|
|
52
|
+
*/
|
|
53
|
+
findings?: Finding[];
|
|
33
54
|
resource: armResources.GenericResource;
|
|
34
55
|
};
|
|
35
56
|
/**
|
|
@@ -45,4 +66,10 @@ export type AzureResourceReport = {
|
|
|
45
66
|
suspectedUnused: boolean;
|
|
46
67
|
type: string;
|
|
47
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Finding sources that are valid for Azure analysis.
|
|
71
|
+
* Narrowed from `FindingSource` to exclude "aws", which is not a valid
|
|
72
|
+
* filter for Azure runs and would silently produce an empty report.
|
|
73
|
+
*/
|
|
74
|
+
export type AzureSource = "advisor" | "custom";
|
|
48
75
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/azure/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,QAAQ,EACR,UAAU,EACX,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/azure/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,QAAQ,EACR,UAAU,EACX,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,cAAc,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC,eAAe,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* This tool does NOT modify, tag, or delete any resources.
|
|
14
14
|
*/
|
|
15
15
|
export { type Analyzer, type AnalyzerContext, type AzureClients, createDefaultAnalyzers, } from "./azure/analyzers/index.js";
|
|
16
|
-
export type { AzureConfig } from "./azure/types.js";
|
|
16
|
+
export type { AzureConfig, AzureSource } from "./azure/types.js";
|
|
17
17
|
import * as azureModule from "./azure/index.js";
|
|
18
18
|
export declare const azure: typeof azureModule;
|
|
19
19
|
export { type MetricsCache, type MonitorClientLike } from "./azure/utils.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGjE,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,eAAO,MAAM,KAAK,oBAAc,CAAC;AAEjC,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG7E,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,0BAA0B,EAC1B,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC;AACtB,cAAc,YAAY,CAAC;AAE3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAE1E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { mergeResults } from "./index.js";
|
|
3
|
+
describe("mergeResults", () => {
|
|
4
|
+
it("should concatenate reasons from both results", () => {
|
|
5
|
+
const baseResult = {
|
|
6
|
+
costRisk: "low",
|
|
7
|
+
reason: "No tags found. ",
|
|
8
|
+
suspectedUnused: true,
|
|
9
|
+
};
|
|
10
|
+
const specificResult = {
|
|
11
|
+
costRisk: "medium",
|
|
12
|
+
reason: "Disk is unattached. ",
|
|
13
|
+
suspectedUnused: true,
|
|
14
|
+
};
|
|
15
|
+
const merged = mergeResults(baseResult, specificResult);
|
|
16
|
+
expect(merged.reason).toBe("No tags found. Disk is unattached. ");
|
|
17
|
+
expect(merged.costRisk).toBe("medium");
|
|
18
|
+
expect(merged.suspectedUnused).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it("should use specific result's cost risk", () => {
|
|
21
|
+
const baseResult = {
|
|
22
|
+
costRisk: "low",
|
|
23
|
+
reason: "Base reason. ",
|
|
24
|
+
suspectedUnused: false,
|
|
25
|
+
};
|
|
26
|
+
const specificResult = {
|
|
27
|
+
costRisk: "high",
|
|
28
|
+
reason: "High risk reason. ",
|
|
29
|
+
suspectedUnused: true,
|
|
30
|
+
};
|
|
31
|
+
const merged = mergeResults(baseResult, specificResult);
|
|
32
|
+
expect(merged.costRisk).toBe("high");
|
|
33
|
+
});
|
|
34
|
+
it("should OR suspectedUnused flags", () => {
|
|
35
|
+
const baseResult = {
|
|
36
|
+
costRisk: "low",
|
|
37
|
+
reason: "Base. ",
|
|
38
|
+
suspectedUnused: false,
|
|
39
|
+
};
|
|
40
|
+
const specificResult = {
|
|
41
|
+
costRisk: "medium",
|
|
42
|
+
reason: "Specific. ",
|
|
43
|
+
suspectedUnused: true,
|
|
44
|
+
};
|
|
45
|
+
const merged = mergeResults(baseResult, specificResult);
|
|
46
|
+
expect(merged.suspectedUnused).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it("should handle empty reasons", () => {
|
|
49
|
+
const baseResult = {
|
|
50
|
+
costRisk: "low",
|
|
51
|
+
reason: "",
|
|
52
|
+
suspectedUnused: false,
|
|
53
|
+
};
|
|
54
|
+
const specificResult = {
|
|
55
|
+
costRisk: "medium",
|
|
56
|
+
reason: "Only specific reason. ",
|
|
57
|
+
suspectedUnused: false,
|
|
58
|
+
};
|
|
59
|
+
const merged = mergeResults(baseResult, specificResult);
|
|
60
|
+
expect(merged.reason).toBe("Only specific reason. ");
|
|
61
|
+
});
|
|
62
|
+
it("should preserve both reasons when both are present", () => {
|
|
63
|
+
const baseResult = {
|
|
64
|
+
costRisk: "low",
|
|
65
|
+
reason: "First issue. ",
|
|
66
|
+
suspectedUnused: true,
|
|
67
|
+
};
|
|
68
|
+
const specificResult = {
|
|
69
|
+
costRisk: "high",
|
|
70
|
+
reason: "Second issue. ",
|
|
71
|
+
suspectedUnused: false,
|
|
72
|
+
};
|
|
73
|
+
const merged = mergeResults(baseResult, specificResult);
|
|
74
|
+
expect(merged.reason).toBe("First issue. Second issue. ");
|
|
75
|
+
expect(merged.suspectedUnused).toBe(true); // true OR false = true
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -88,6 +88,10 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
88
88
|
azure: z.ZodObject<{
|
|
89
89
|
concurrency: z.ZodOptional<z.ZodNumber>;
|
|
90
90
|
preferredLocation: z.ZodDefault<z.ZodString>;
|
|
91
|
+
sources: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
92
|
+
custom: "custom";
|
|
93
|
+
advisor: "advisor";
|
|
94
|
+
}>>>;
|
|
91
95
|
subscriptionIds: z.ZodArray<z.ZodString>;
|
|
92
96
|
thresholds: z.ZodPipe<z.ZodOptional<z.ZodObject<{
|
|
93
97
|
appService: z.ZodPipe<z.ZodOptional<z.ZodObject<{
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA4DxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqBlB,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA4DxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqBlB,CAAC;AAkCZ;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAmD,CAAC;AAI7E,2DAA2D;AAC3D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wDAAwD;AACxD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
package/dist/schema.js
CHANGED
|
@@ -87,6 +87,15 @@ const AzureSectionSchema = z
|
|
|
87
87
|
*/
|
|
88
88
|
concurrency: z.number().int().positive().optional(),
|
|
89
89
|
preferredLocation: z.string().default("italynorth"),
|
|
90
|
+
/**
|
|
91
|
+
* Which finding sources to include. Defaults to all known sources.
|
|
92
|
+
* Authors can narrow the run to e.g. `["advisor"]` to fetch only
|
|
93
|
+
* Azure Advisor recommendations, or `["custom"]` to skip Advisor.
|
|
94
|
+
*/
|
|
95
|
+
sources: z
|
|
96
|
+
.array(z.enum(["advisor", "custom"]))
|
|
97
|
+
.nonempty()
|
|
98
|
+
.default(["advisor", "custom"]),
|
|
90
99
|
subscriptionIds: z
|
|
91
100
|
.array(z.string())
|
|
92
101
|
.min(1, "Config file must contain at least one entry in 'azure.subscriptionIds'"),
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|