@pagopa/dx-savemoney 0.3.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/__tests__/finding.test.js +22 -0
- package/dist/__tests__/finding.test.js.map +1 -1
- package/dist/azure/__tests__/analyzer-tags.test.js +28 -1
- package/dist/azure/__tests__/analyzer-tags.test.js.map +1 -1
- package/dist/azure/__tests__/config.test.js +31 -1
- package/dist/azure/__tests__/config.test.js.map +1 -1
- package/dist/azure/__tests__/report.test.js +71 -0
- package/dist/azure/__tests__/report.test.js.map +1 -1
- package/dist/azure/analyzer.d.ts +8 -1
- package/dist/azure/analyzer.d.ts.map +1 -1
- package/dist/azure/analyzer.js +57 -41
- package/dist/azure/analyzer.js.map +1 -1
- package/dist/azure/analyzers/registry.d.ts.map +1 -1
- package/dist/azure/analyzers/registry.js +4 -4
- package/dist/azure/analyzers/registry.js.map +1 -1
- package/dist/azure/analyzers/types.d.ts +6 -0
- package/dist/azure/analyzers/types.d.ts.map +1 -1
- package/dist/azure/config.d.ts.map +1 -1
- package/dist/azure/config.js +1 -5
- package/dist/azure/config.js.map +1 -1
- package/dist/azure/pricing/__tests__/cache.test.d.ts +8 -0
- package/dist/azure/pricing/__tests__/cache.test.d.ts.map +1 -0
- package/dist/azure/pricing/__tests__/cache.test.js +56 -0
- package/dist/azure/pricing/__tests__/cache.test.js.map +1 -0
- package/dist/azure/pricing/__tests__/client.test.d.ts +9 -0
- package/dist/azure/pricing/__tests__/client.test.d.ts.map +1 -0
- package/dist/azure/pricing/__tests__/client.test.js +181 -0
- package/dist/azure/pricing/__tests__/client.test.js.map +1 -0
- package/dist/azure/pricing/__tests__/pricing-service.test.d.ts +6 -0
- package/dist/azure/pricing/__tests__/pricing-service.test.d.ts.map +1 -0
- package/dist/azure/pricing/__tests__/pricing-service.test.js +283 -0
- package/dist/azure/pricing/__tests__/pricing-service.test.js.map +1 -0
- package/dist/azure/pricing/cache.d.ts +45 -0
- package/dist/azure/pricing/cache.d.ts.map +1 -0
- package/dist/azure/pricing/cache.js +79 -0
- package/dist/azure/pricing/cache.js.map +1 -0
- package/dist/azure/pricing/client.d.ts +67 -0
- package/dist/azure/pricing/client.d.ts.map +1 -0
- package/dist/azure/pricing/client.js +96 -0
- package/dist/azure/pricing/client.js.map +1 -0
- package/dist/azure/pricing/index.d.ts +6 -0
- package/dist/azure/pricing/index.d.ts.map +1 -0
- package/dist/azure/pricing/index.js +6 -0
- package/dist/azure/pricing/index.js.map +1 -0
- package/dist/azure/pricing/pricing-service.d.ts +46 -0
- package/dist/azure/pricing/pricing-service.d.ts.map +1 -0
- package/dist/azure/pricing/pricing-service.js +84 -0
- package/dist/azure/pricing/pricing-service.js.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.d.ts +5 -0
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.js +137 -0
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.js.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/disk.test.d.ts +5 -0
- package/dist/azure/pricing/resolvers/__tests__/disk.test.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/disk.test.js +160 -0
- package/dist/azure/pricing/resolvers/__tests__/disk.test.js.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.d.ts +5 -0
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.js +113 -0
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.js.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/vm.test.d.ts +9 -0
- package/dist/azure/pricing/resolvers/__tests__/vm.test.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/__tests__/vm.test.js +204 -0
- package/dist/azure/pricing/resolvers/__tests__/vm.test.js.map +1 -0
- package/dist/azure/pricing/resolvers/app-service.d.ts +27 -0
- package/dist/azure/pricing/resolvers/app-service.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/app-service.js +67 -0
- package/dist/azure/pricing/resolvers/app-service.js.map +1 -0
- package/dist/azure/pricing/resolvers/disk.d.ts +59 -0
- package/dist/azure/pricing/resolvers/disk.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/disk.js +140 -0
- package/dist/azure/pricing/resolvers/disk.js.map +1 -0
- package/dist/azure/pricing/resolvers/index.d.ts +12 -0
- package/dist/azure/pricing/resolvers/index.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/index.js +8 -0
- package/dist/azure/pricing/resolvers/index.js.map +1 -0
- package/dist/azure/pricing/resolvers/public-ip.d.ts +32 -0
- package/dist/azure/pricing/resolvers/public-ip.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/public-ip.js +56 -0
- package/dist/azure/pricing/resolvers/public-ip.js.map +1 -0
- package/dist/azure/pricing/resolvers/vm.d.ts +51 -0
- package/dist/azure/pricing/resolvers/vm.d.ts.map +1 -0
- package/dist/azure/pricing/resolvers/vm.js +89 -0
- package/dist/azure/pricing/resolvers/vm.js.map +1 -0
- package/dist/azure/pricing/schema.d.ts +88 -0
- package/dist/azure/pricing/schema.d.ts.map +1 -0
- package/dist/azure/pricing/schema.js +64 -0
- package/dist/azure/pricing/schema.js.map +1 -0
- package/dist/azure/pricing/test-cache-dir.d.ts +3 -0
- package/dist/azure/pricing/test-cache-dir.d.ts.map +1 -0
- package/dist/azure/pricing/test-cache-dir.js +17 -0
- package/dist/azure/pricing/test-cache-dir.js.map +1 -0
- package/dist/azure/report.d.ts.map +1 -1
- package/dist/azure/report.js +57 -18
- package/dist/azure/report.js.map +1 -1
- package/dist/azure/resources/__tests__/app-service.test.d.ts +5 -0
- package/dist/azure/resources/__tests__/app-service.test.d.ts.map +1 -0
- package/dist/azure/resources/__tests__/app-service.test.js +105 -0
- package/dist/azure/resources/__tests__/app-service.test.js.map +1 -0
- package/dist/azure/resources/app-service.d.ts +8 -3
- package/dist/azure/resources/app-service.d.ts.map +1 -1
- package/dist/azure/resources/app-service.js +35 -2
- package/dist/azure/resources/app-service.js.map +1 -1
- package/dist/azure/resources/disk.d.ts +3 -1
- package/dist/azure/resources/disk.d.ts.map +1 -1
- package/dist/azure/resources/disk.js +35 -3
- package/dist/azure/resources/disk.js.map +1 -1
- package/dist/azure/resources/public-ip.d.ts +3 -1
- package/dist/azure/resources/public-ip.d.ts.map +1 -1
- package/dist/azure/resources/public-ip.js +41 -3
- package/dist/azure/resources/public-ip.js.map +1 -1
- package/dist/azure/resources/vm.d.ts +4 -1
- package/dist/azure/resources/vm.d.ts.map +1 -1
- package/dist/azure/resources/vm.js +49 -6
- package/dist/azure/resources/vm.js.map +1 -1
- package/dist/azure/types.d.ts +18 -3
- package/dist/azure/types.d.ts.map +1 -1
- package/dist/finding.d.ts +3 -3
- package/dist/finding.d.ts.map +1 -1
- package/dist/finding.js +7 -0
- package/dist/finding.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +5 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +5 -3
- package/dist/schema.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/finding.test.ts +24 -0
- package/src/azure/__tests__/analyzer-tags.test.ts +36 -1
- package/src/azure/__tests__/config.test.ts +43 -1
- package/src/azure/__tests__/fixtures/full-override.yaml +2 -0
- package/src/azure/__tests__/report.test.ts +78 -0
- package/src/azure/analyzer.ts +70 -52
- package/src/azure/analyzers/registry.ts +8 -2
- package/src/azure/analyzers/types.ts +6 -0
- package/src/azure/config.ts +1 -5
- package/src/azure/pricing/__tests__/cache.test.ts +67 -0
- package/src/azure/pricing/__tests__/client.test.ts +212 -0
- package/src/azure/pricing/__tests__/fixtures/vm-b2s-westeurope.json +51 -0
- package/src/azure/pricing/__tests__/pricing-service.test.ts +315 -0
- package/src/azure/pricing/cache.ts +92 -0
- package/src/azure/pricing/client.ts +137 -0
- package/src/azure/pricing/index.ts +6 -0
- package/src/azure/pricing/pricing-service.ts +125 -0
- package/src/azure/pricing/resolvers/__tests__/app-service.test.ts +154 -0
- package/src/azure/pricing/resolvers/__tests__/disk.test.ts +189 -0
- package/src/azure/pricing/resolvers/__tests__/public-ip.test.ts +130 -0
- package/src/azure/pricing/resolvers/__tests__/vm.test.ts +232 -0
- package/src/azure/pricing/resolvers/app-service.ts +102 -0
- package/src/azure/pricing/resolvers/disk.ts +170 -0
- package/src/azure/pricing/resolvers/index.ts +31 -0
- package/src/azure/pricing/resolvers/public-ip.ts +87 -0
- package/src/azure/pricing/resolvers/vm.ts +125 -0
- package/src/azure/pricing/schema.ts +69 -0
- package/src/azure/pricing/test-cache-dir.ts +26 -0
- package/src/azure/report.ts +86 -21
- package/src/azure/resources/__tests__/app-service.test.ts +165 -0
- package/src/azure/resources/app-service.ts +65 -4
- package/src/azure/resources/disk.ts +46 -4
- package/src/azure/resources/public-ip.ts +61 -2
- package/src/azure/resources/vm.ts +89 -11
- package/src/azure/types.ts +19 -3
- package/src/finding.ts +10 -3
- package/src/index.ts +4 -3
- package/src/schema.ts +7 -3
- package/src/types.ts +12 -0
package/dist/finding.d.ts
CHANGED
|
@@ -30,9 +30,9 @@ export type Finding = {
|
|
|
30
30
|
*/
|
|
31
31
|
code: string;
|
|
32
32
|
/**
|
|
33
|
-
* Estimated monthly
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* Estimated monthly saving for this specific finding. Populated by Advisor
|
|
34
|
+
* recommendations; custom Retail Prices estimates stay at resource level
|
|
35
|
+
* because they represent cost at risk, not a per-finding saving.
|
|
36
36
|
*/
|
|
37
37
|
estimatedMonthlySavings?: Money;
|
|
38
38
|
/**
|
package/dist/finding.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB;;;OAGG;IACH,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,KAAK,CAAC;IAChC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,EAAE,QAAQ,CAAC;IACnB;;OAEG;IACH,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,uBAAuB,GACvB,aAAa,GACb,aAAa,GACb,UAAU,CAAC;AAEf;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzD;;;GAGG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,CAAC,SAAS,GAAG,OAAO,IAAI;IAChD,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,GAAG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB;;;OAGG;IACH,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,KAAK,CAAC;IAChC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,EAAE,QAAQ,CAAC;IACnB;;OAEG;IACH,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,uBAAuB,GACvB,aAAa,GACb,aAAa,GACb,UAAU,CAAC;AAEf;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzD;;;GAGG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,CAAC,SAAS,GAAG,OAAO,IAAI;IAChD,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,GAAG,OAAO,EAAE,CAqBZ"}
|
package/dist/finding.js
CHANGED
|
@@ -27,6 +27,13 @@ export function findingsFromAnalysisResult(args) {
|
|
|
27
27
|
if (sentences.length === 0) {
|
|
28
28
|
return [];
|
|
29
29
|
}
|
|
30
|
+
// We intentionally do NOT propagate any monetary estimate down to the
|
|
31
|
+
// individual findings: a per-resource cost (e.g. €29.94/mo for a VM)
|
|
32
|
+
// attached to a sentence like "No tags found" would falsely suggest
|
|
33
|
+
// "add the missing tags to save €29.94". The resource-level cost is
|
|
34
|
+
// carried instead by `AnalysisResult.estimatedMonthlySavings` and
|
|
35
|
+
// surfaced by the report layer as a per-resource header — see
|
|
36
|
+
// `azure/report.ts`.
|
|
30
37
|
return sentences.map((sentence) => ({
|
|
31
38
|
category: "cost",
|
|
32
39
|
code: code ?? "custom.unknown",
|
package/dist/finding.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finding.js","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgGH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAM1C;IACC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;IACvE,MAAM,SAAS,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAClC,QAAQ,EAAE,MAAe;QACzB,IAAI,EAAE,IAAI,IAAI,gBAAgB;QAC9B,MAAM,EAAE,QAAQ;QAChB,UAAU;QACV,QAAQ;QACR,MAAM;KACP,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,MAAc;IAC9C,OAAO,MAAM;SACV,KAAK,CAAC,WAAW,CAAC;SAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
|
1
|
+
{"version":3,"file":"finding.js","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgGH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAM1C;IACC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;IACvE,MAAM,SAAS,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,sEAAsE;IACtE,qEAAqE;IACrE,oEAAoE;IACpE,oEAAoE;IACpE,kEAAkE;IAClE,8DAA8D;IAC9D,qBAAqB;IACrB,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAClC,QAAQ,EAAE,MAAe;QACzB,IAAI,EAAE,IAAI,IAAI,gBAAgB;QAC9B,MAAM,EAAE,QAAQ;QAChB,UAAU;QACV,QAAQ;QACR,MAAM;KACP,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,MAAc;IAC9C,OAAO,MAAM;SACV,KAAK,CAAC,WAAW,CAAC;SAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,11 +13,12 @@
|
|
|
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, AzureSource } from "./azure/types.js";
|
|
16
|
+
export type { AzureConfig, AzureSource, PricingConfig } from "./azure/types.js";
|
|
17
|
+
export { type MetricsCache, type MonitorClientLike } from "./azure/utils.js";
|
|
17
18
|
import * as azureModule from "./azure/index.js";
|
|
18
19
|
export declare const azure: typeof azureModule;
|
|
19
|
-
export { type MetricsCache, type MonitorClientLike } from "./azure/utils.js";
|
|
20
20
|
export { type Finding, type FindingCategory, findingsFromAnalysisResult, type FindingSource, type Money, type ResourceReport, } from "./finding.js";
|
|
21
|
+
export { AZURE_SOURCE_VALUES } from "./schema.js";
|
|
21
22
|
export * from "./types.js";
|
|
22
23
|
import type { AzureConfig } from "./azure/types.js";
|
|
23
24
|
/**
|
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,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,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG7E,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,eAAO,MAAM,KAAK,oBAAc,CAAC;AAGjC,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,0BAA0B,EAC1B,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,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"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import * as azureModule from "./azure/index.js";
|
|
|
18
18
|
export const azure = azureModule;
|
|
19
19
|
// Phase 0: unified Finding model and analyzer plugin layer
|
|
20
20
|
export { findingsFromAnalysisResult, } from "./finding.js";
|
|
21
|
+
export { AZURE_SOURCE_VALUES } from "./schema.js";
|
|
21
22
|
export * from "./types.js";
|
|
22
23
|
import { loadAzureConfig } from "./azure/config.js";
|
|
23
24
|
/**
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAIL,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAIL,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AAMpC,sBAAsB;AACtB,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC;AAEjC,2DAA2D;AAC3D,OAAO,EAGL,0BAA0B,GAI3B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,cAAc,YAAY,CAAC;AAI3B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAmB;IAClD,OAAO,eAAe,CAAC,UAAU,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -80,6 +80,7 @@ export declare const ThresholdsSchema: z.ZodObject<{
|
|
|
80
80
|
networkInBytesPerDay: number;
|
|
81
81
|
} | undefined>>;
|
|
82
82
|
}, z.core.$strict>;
|
|
83
|
+
export declare const AZURE_SOURCE_VALUES: readonly ["advisor", "custom"];
|
|
83
84
|
/**
|
|
84
85
|
* Single Zod schema representing the entire YAML configuration file.
|
|
85
86
|
* Use `ConfigSchema.parse(rawYaml)` to validate and apply defaults.
|
|
@@ -88,9 +89,12 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
88
89
|
azure: z.ZodObject<{
|
|
89
90
|
concurrency: z.ZodOptional<z.ZodNumber>;
|
|
90
91
|
preferredLocation: z.ZodDefault<z.ZodString>;
|
|
91
|
-
sources: z.ZodDefault<z.
|
|
92
|
+
sources: z.ZodDefault<z.ZodTuple<[z.ZodEnum<{
|
|
93
|
+
advisor: "advisor";
|
|
92
94
|
custom: "custom";
|
|
95
|
+
}>], z.ZodEnum<{
|
|
93
96
|
advisor: "advisor";
|
|
97
|
+
custom: "custom";
|
|
94
98
|
}>>>;
|
|
95
99
|
subscriptionIds: z.ZodArray<z.ZodString>;
|
|
96
100
|
thresholds: 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;AAIZ,eAAO,MAAM,mBAAmB,gCAAiC,CAAC;AAkClE;;;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
|
@@ -79,6 +79,8 @@ export const ThresholdsSchema = z
|
|
|
79
79
|
})
|
|
80
80
|
.strict();
|
|
81
81
|
// ── top-level config schema ──────────────────────────────────────────────────
|
|
82
|
+
export const AZURE_SOURCE_VALUES = ["advisor", "custom"];
|
|
83
|
+
const AzureSourceSchema = z.enum(AZURE_SOURCE_VALUES);
|
|
82
84
|
const AzureSectionSchema = z
|
|
83
85
|
.object({
|
|
84
86
|
/**
|
|
@@ -93,9 +95,9 @@ const AzureSectionSchema = z
|
|
|
93
95
|
* Azure Advisor recommendations, or `["custom"]` to skip Advisor.
|
|
94
96
|
*/
|
|
95
97
|
sources: z
|
|
96
|
-
.
|
|
97
|
-
.
|
|
98
|
-
.default([
|
|
98
|
+
.tuple([AzureSourceSchema])
|
|
99
|
+
.rest(AzureSourceSchema)
|
|
100
|
+
.default([...AZURE_SOURCE_VALUES]),
|
|
99
101
|
subscriptionIds: z
|
|
100
102
|
.array(z.string())
|
|
101
103
|
.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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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Common types shared across all cloud providers
|
|
3
3
|
*/
|
|
4
|
+
import type { Money } from "./finding.js";
|
|
4
5
|
export type AnalysisResult = {
|
|
5
6
|
costRisk: CostRisk;
|
|
7
|
+
/**
|
|
8
|
+
* Estimated monthly resource cost at risk. Custom pricing-enriched
|
|
9
|
+
* analyzers populate it when a Retail Prices lookup succeeds; the report
|
|
10
|
+
* renders it once per resource instead of treating it as a per-finding
|
|
11
|
+
* saving.
|
|
12
|
+
*/
|
|
13
|
+
estimatedMonthlySavings?: Money;
|
|
6
14
|
reason: string;
|
|
7
15
|
suspectedUnused: boolean;
|
|
8
16
|
};
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAI1C,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,KAAK,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEjD;;;GAGG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;CAA6B,CAAC;AAE7D;;GAEG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,cAAc,GAC7B,cAAc,CAUhB"}
|
package/dist/types.js
CHANGED
|
@@ -13,6 +13,8 @@ export const DEFAULT_THRESHOLDS = ThresholdsSchema.parse({});
|
|
|
13
13
|
export function mergeResults(baseResult, specificResult) {
|
|
14
14
|
return {
|
|
15
15
|
costRisk: specificResult.costRisk,
|
|
16
|
+
estimatedMonthlySavings: specificResult.estimatedMonthlySavings ??
|
|
17
|
+
baseResult.estimatedMonthlySavings,
|
|
16
18
|
reason: baseResult.reason + specificResult.reason,
|
|
17
19
|
suspectedUnused: baseResult.suspectedUnused || specificResult.suspectedUnused,
|
|
18
20
|
};
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA+B/C;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAE7D;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,UAA0B,EAC1B,cAA8B;IAE9B,OAAO;QACL,QAAQ,EAAE,cAAc,CAAC,QAAQ;QACjC,uBAAuB,EACrB,cAAc,CAAC,uBAAuB;YACtC,UAAU,CAAC,uBAAuB;QACpC,MAAM,EAAE,UAAU,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM;QACjD,eAAe,EACb,UAAU,CAAC,eAAe,IAAI,cAAc,CAAC,eAAe;KAC/D,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -145,5 +145,29 @@ describe("findingsFromAnalysisResult", () => {
|
|
|
145
145
|
});
|
|
146
146
|
expect(result.every((f) => f.category === "cost")).toBe(true);
|
|
147
147
|
});
|
|
148
|
+
|
|
149
|
+
it("never attaches estimatedMonthlySavings to custom findings", () => {
|
|
150
|
+
// Custom analyzers carry the resource's monthly cost on
|
|
151
|
+
// `AnalysisResult.estimatedMonthlySavings` and the report layer
|
|
152
|
+
// renders it at the resource level. Propagating it down to a
|
|
153
|
+
// single finding sentence (e.g. "No tags found") would falsely
|
|
154
|
+
// suggest that fixing that sentence yields the full saving.
|
|
155
|
+
const result = findingsFromAnalysisResult({
|
|
156
|
+
...BASE_ARGS,
|
|
157
|
+
reason: "Low CPU. Low network. Idle.",
|
|
158
|
+
});
|
|
159
|
+
expect(result).toHaveLength(3);
|
|
160
|
+
for (const f of result) {
|
|
161
|
+
expect(f.estimatedMonthlySavings).toBeUndefined();
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("omits estimatedMonthlySavings entirely", () => {
|
|
166
|
+
const result = findingsFromAnalysisResult({
|
|
167
|
+
...BASE_ARGS,
|
|
168
|
+
reason: "Low CPU.",
|
|
169
|
+
});
|
|
170
|
+
expect(result[0].estimatedMonthlySavings).toBeUndefined();
|
|
171
|
+
});
|
|
148
172
|
});
|
|
149
173
|
});
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
import { describe, expect, it } from "vitest";
|
|
9
9
|
|
|
10
10
|
import type { Finding } from "../../finding.js";
|
|
11
|
+
import type { AzureDetailedResourceReport } from "../types.js";
|
|
11
12
|
|
|
12
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
mergeFinding,
|
|
15
|
+
shouldIncludeAdvisorFindingForTags,
|
|
16
|
+
} from "../analyzer.js";
|
|
13
17
|
|
|
14
18
|
function mkFinding(resourceId: string, source: Finding["source"]): Finding {
|
|
15
19
|
return {
|
|
@@ -72,3 +76,34 @@ describe("shouldIncludeAdvisorFindingForTags", () => {
|
|
|
72
76
|
).toBe(false);
|
|
73
77
|
});
|
|
74
78
|
});
|
|
79
|
+
|
|
80
|
+
describe("mergeFinding", () => {
|
|
81
|
+
it("preserves custom cost at risk when merging an Advisor finding", () => {
|
|
82
|
+
const resourceId =
|
|
83
|
+
"/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm1";
|
|
84
|
+
const existing: AzureDetailedResourceReport = {
|
|
85
|
+
analysis: {
|
|
86
|
+
costRisk: "high",
|
|
87
|
+
estimatedMonthlySavings: { amount: 29.94, currency: "EUR" },
|
|
88
|
+
reason: "VM is deallocated.",
|
|
89
|
+
suspectedUnused: true,
|
|
90
|
+
},
|
|
91
|
+
findings: [mkFinding(resourceId, "custom")],
|
|
92
|
+
resource: {
|
|
93
|
+
id: resourceId,
|
|
94
|
+
name: "vm1",
|
|
95
|
+
type: "Microsoft.Compute/virtualMachines",
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
const reports = [existing];
|
|
99
|
+
const reportsById = new Map([[resourceId.toLowerCase(), existing]]);
|
|
100
|
+
|
|
101
|
+
mergeFinding(mkFinding(resourceId, "advisor"), reports, reportsById);
|
|
102
|
+
|
|
103
|
+
expect(existing.analysis.estimatedMonthlySavings).toEqual({
|
|
104
|
+
amount: 29.94,
|
|
105
|
+
currency: "EUR",
|
|
106
|
+
});
|
|
107
|
+
expect(existing.findings).toHaveLength(2);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
|
-
import { describe, expect, it } from "vitest";
|
|
11
|
+
import { afterEach, describe, expect, expectTypeOf, it, vi } from "vitest";
|
|
12
|
+
|
|
13
|
+
import type { AzureConfig, AzureSource } from "../../index.js";
|
|
12
14
|
|
|
13
15
|
import { loadConfig } from "../../index.js";
|
|
16
|
+
import { ConfigSchema } from "../../schema.js";
|
|
14
17
|
import { DEFAULT_THRESHOLDS } from "../../types.js";
|
|
15
18
|
|
|
16
19
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -23,6 +26,10 @@ const FIXTURE_PARTIAL = path.resolve(
|
|
|
23
26
|
const FIXTURE_FULL = path.resolve(__dirname, "fixtures/full-override.yaml");
|
|
24
27
|
|
|
25
28
|
describe("loadConfig", () => {
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
vi.unstubAllEnvs();
|
|
31
|
+
});
|
|
32
|
+
|
|
26
33
|
it("throws when explicit path does not exist", async () => {
|
|
27
34
|
await expect(loadConfig("/nonexistent/config.yaml")).rejects.toThrow(
|
|
28
35
|
"Config file not found",
|
|
@@ -32,13 +39,25 @@ describe("loadConfig", () => {
|
|
|
32
39
|
it("loads subscriptionIds and defaults from a partial YAML file", async () => {
|
|
33
40
|
const result = await loadConfig(FIXTURE_PARTIAL);
|
|
34
41
|
|
|
42
|
+
expectTypeOf<AzureConfig["sources"]>().toEqualTypeOf<
|
|
43
|
+
[AzureSource, ...AzureSource[]]
|
|
44
|
+
>();
|
|
35
45
|
expect(result.subscriptionIds).toEqual([
|
|
36
46
|
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
|
37
47
|
]);
|
|
38
48
|
expect(result.preferredLocation).toBe("italynorth");
|
|
49
|
+
expect(result.sources).toEqual(["advisor", "custom"]);
|
|
39
50
|
expect(result.timespanDays).toBe(30);
|
|
40
51
|
});
|
|
41
52
|
|
|
53
|
+
it("applies sources defaults when loading from the environment", async () => {
|
|
54
|
+
vi.stubEnv("ARM_SUBSCRIPTION_ID", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
|
55
|
+
|
|
56
|
+
const result = await loadConfig();
|
|
57
|
+
|
|
58
|
+
expect(result.sources).toEqual(["advisor", "custom"]);
|
|
59
|
+
});
|
|
60
|
+
|
|
42
61
|
it("loads partial threshold overrides and keeps defaults for missing fields", async () => {
|
|
43
62
|
const result = await loadConfig(FIXTURE_PARTIAL);
|
|
44
63
|
|
|
@@ -69,6 +88,7 @@ describe("loadConfig", () => {
|
|
|
69
88
|
|
|
70
89
|
expect(result.subscriptionIds).toHaveLength(2);
|
|
71
90
|
expect(result.preferredLocation).toBe("westeurope");
|
|
91
|
+
expect(result.sources).toEqual(["custom"]);
|
|
72
92
|
expect(result.timespanDays).toBe(60);
|
|
73
93
|
|
|
74
94
|
expect(result.thresholds?.vm.cpuPercent).toBe(5);
|
|
@@ -94,4 +114,26 @@ describe("loadConfig", () => {
|
|
|
94
114
|
expect(result.thresholds).toHaveProperty("publicIp");
|
|
95
115
|
expect(result.thresholds).toHaveProperty("staticSite");
|
|
96
116
|
});
|
|
117
|
+
|
|
118
|
+
it("rejects an empty sources list", () => {
|
|
119
|
+
const result = ConfigSchema.safeParse({
|
|
120
|
+
azure: {
|
|
121
|
+
sources: [],
|
|
122
|
+
subscriptionIds: ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(result.success).toBe(false);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("does not expose pricing settings in YAML config", () => {
|
|
130
|
+
const result = ConfigSchema.safeParse({
|
|
131
|
+
azure: {
|
|
132
|
+
pricing: { enabled: false },
|
|
133
|
+
subscriptionIds: ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
expect(result.success).toBe(false);
|
|
138
|
+
});
|
|
97
139
|
});
|
|
@@ -133,6 +133,84 @@ describe("generateReport — lint format", () => {
|
|
|
133
133
|
expect(calls).toHaveLength(1);
|
|
134
134
|
expect(calls[0]).toContain("0 issues found");
|
|
135
135
|
});
|
|
136
|
+
|
|
137
|
+
describe("monetary annotations", () => {
|
|
138
|
+
const VM_WITH_COST: AzureDetailedResourceReport = {
|
|
139
|
+
analysis: {
|
|
140
|
+
costRisk: "high",
|
|
141
|
+
estimatedMonthlySavings: { amount: 29.94, currency: "EUR" },
|
|
142
|
+
reason: "No tags found. VM is deallocated.",
|
|
143
|
+
suspectedUnused: true,
|
|
144
|
+
},
|
|
145
|
+
resource: {
|
|
146
|
+
id: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm-x",
|
|
147
|
+
name: "vm-x",
|
|
148
|
+
type: "Microsoft.Compute/virtualMachines",
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
const ADVISOR_WITH_SAVINGS: AzureDetailedResourceReport = {
|
|
152
|
+
analysis: {
|
|
153
|
+
costRisk: "medium",
|
|
154
|
+
reason: "Advisor recommends a reservation.",
|
|
155
|
+
suspectedUnused: true,
|
|
156
|
+
},
|
|
157
|
+
findings: [
|
|
158
|
+
{
|
|
159
|
+
category: "cost",
|
|
160
|
+
code: "advisor.reservation",
|
|
161
|
+
estimatedMonthlySavings: { amount: 12.34, currency: "EUR" },
|
|
162
|
+
reason: "Advisor recommends a reservation.",
|
|
163
|
+
resourceId:
|
|
164
|
+
"/subscriptions/sub1/providers/Microsoft.Advisor/recommendations/rec-1",
|
|
165
|
+
severity: "medium",
|
|
166
|
+
source: "advisor",
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
resource: {
|
|
170
|
+
id: "/subscriptions/sub1/providers/Microsoft.Advisor/recommendations/rec-1",
|
|
171
|
+
name: "rec-1",
|
|
172
|
+
type: "Microsoft.Advisor/recommendations",
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
it("renders the resource monthly cost ONCE as a header annotation, not on each finding", async () => {
|
|
177
|
+
await generateReport([VM_WITH_COST], "lint");
|
|
178
|
+
const output = allLogs(logSpy);
|
|
179
|
+
// header line contains the cost-at-risk label
|
|
180
|
+
expect(output).toMatch(/cost at risk:.*29[.,]94/);
|
|
181
|
+
// exactly one occurrence — must NOT appear next to each finding
|
|
182
|
+
const matches = output.match(/29[.,]94/g) ?? [];
|
|
183
|
+
// 1× header + 1× summary trailer = 2 occurrences; the per-finding line must not carry it
|
|
184
|
+
expect(matches.length).toBe(2);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("does not attach the resource cost to the 'No tags found' finding line", async () => {
|
|
188
|
+
await generateReport([VM_WITH_COST], "lint");
|
|
189
|
+
const findingLines = logSpy.mock.calls
|
|
190
|
+
.map((c: unknown[]) => String(c[0]))
|
|
191
|
+
.filter((l: string) => l.includes("No tags found"));
|
|
192
|
+
expect(findingLines).toHaveLength(1);
|
|
193
|
+
expect(findingLines[0]).not.toMatch(/29[.,]94/);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("uses the 'Estimated monthly cost at risk' label in the summary trailer", async () => {
|
|
197
|
+
await generateReport([VM_WITH_COST], "lint");
|
|
198
|
+
const output = allLogs(logSpy);
|
|
199
|
+
expect(output).toContain("Estimated monthly cost at risk");
|
|
200
|
+
// The old, misleading "Estimated monthly savings (custom)" label is gone
|
|
201
|
+
expect(output).not.toMatch(/Estimated monthly savings:\s*€/);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("renders Advisor savings separately from custom cost at risk", async () => {
|
|
205
|
+
await generateReport([VM_WITH_COST, ADVISOR_WITH_SAVINGS], "lint");
|
|
206
|
+
const output = allLogs(logSpy);
|
|
207
|
+
|
|
208
|
+
expect(output).toMatch(/cost at risk:.*29[.,]94/);
|
|
209
|
+
expect(output).toMatch(/saving:.*12[.,]34/);
|
|
210
|
+
expect(output).toContain("Estimated monthly cost at risk (custom)");
|
|
211
|
+
expect(output).toContain("Estimated monthly savings (advisor)");
|
|
212
|
+
});
|
|
213
|
+
});
|
|
136
214
|
});
|
|
137
215
|
|
|
138
216
|
describe("generateReport — table format", () => {
|