@pagopa/dx-savemoney 0.3.2 → 0.4.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 (163) hide show
  1. package/README.md +12 -0
  2. package/dist/__tests__/finding.test.js +22 -0
  3. package/dist/__tests__/finding.test.js.map +1 -1
  4. package/dist/azure/__tests__/analyzer-tags.test.js +28 -1
  5. package/dist/azure/__tests__/analyzer-tags.test.js.map +1 -1
  6. package/dist/azure/__tests__/config.test.js +10 -0
  7. package/dist/azure/__tests__/config.test.js.map +1 -1
  8. package/dist/azure/__tests__/report.test.js +71 -0
  9. package/dist/azure/__tests__/report.test.js.map +1 -1
  10. package/dist/azure/analyzer.d.ts +8 -1
  11. package/dist/azure/analyzer.d.ts.map +1 -1
  12. package/dist/azure/analyzer.js +55 -37
  13. package/dist/azure/analyzer.js.map +1 -1
  14. package/dist/azure/analyzers/registry.d.ts.map +1 -1
  15. package/dist/azure/analyzers/registry.js +4 -4
  16. package/dist/azure/analyzers/registry.js.map +1 -1
  17. package/dist/azure/analyzers/types.d.ts +6 -0
  18. package/dist/azure/analyzers/types.d.ts.map +1 -1
  19. package/dist/azure/pricing/__tests__/cache.test.d.ts +8 -0
  20. package/dist/azure/pricing/__tests__/cache.test.d.ts.map +1 -0
  21. package/dist/azure/pricing/__tests__/cache.test.js +56 -0
  22. package/dist/azure/pricing/__tests__/cache.test.js.map +1 -0
  23. package/dist/azure/pricing/__tests__/client.test.d.ts +9 -0
  24. package/dist/azure/pricing/__tests__/client.test.d.ts.map +1 -0
  25. package/dist/azure/pricing/__tests__/client.test.js +181 -0
  26. package/dist/azure/pricing/__tests__/client.test.js.map +1 -0
  27. package/dist/azure/pricing/__tests__/pricing-service.test.d.ts +6 -0
  28. package/dist/azure/pricing/__tests__/pricing-service.test.d.ts.map +1 -0
  29. package/dist/azure/pricing/__tests__/pricing-service.test.js +283 -0
  30. package/dist/azure/pricing/__tests__/pricing-service.test.js.map +1 -0
  31. package/dist/azure/pricing/cache.d.ts +45 -0
  32. package/dist/azure/pricing/cache.d.ts.map +1 -0
  33. package/dist/azure/pricing/cache.js +79 -0
  34. package/dist/azure/pricing/cache.js.map +1 -0
  35. package/dist/azure/pricing/client.d.ts +67 -0
  36. package/dist/azure/pricing/client.d.ts.map +1 -0
  37. package/dist/azure/pricing/client.js +96 -0
  38. package/dist/azure/pricing/client.js.map +1 -0
  39. package/dist/azure/pricing/index.d.ts +6 -0
  40. package/dist/azure/pricing/index.d.ts.map +1 -0
  41. package/dist/azure/pricing/index.js +6 -0
  42. package/dist/azure/pricing/index.js.map +1 -0
  43. package/dist/azure/pricing/pricing-service.d.ts +46 -0
  44. package/dist/azure/pricing/pricing-service.d.ts.map +1 -0
  45. package/dist/azure/pricing/pricing-service.js +84 -0
  46. package/dist/azure/pricing/pricing-service.js.map +1 -0
  47. package/dist/azure/pricing/resolvers/__tests__/app-service.test.d.ts +5 -0
  48. package/dist/azure/pricing/resolvers/__tests__/app-service.test.d.ts.map +1 -0
  49. package/dist/azure/pricing/resolvers/__tests__/app-service.test.js +137 -0
  50. package/dist/azure/pricing/resolvers/__tests__/app-service.test.js.map +1 -0
  51. package/dist/azure/pricing/resolvers/__tests__/disk.test.d.ts +5 -0
  52. package/dist/azure/pricing/resolvers/__tests__/disk.test.d.ts.map +1 -0
  53. package/dist/azure/pricing/resolvers/__tests__/disk.test.js +160 -0
  54. package/dist/azure/pricing/resolvers/__tests__/disk.test.js.map +1 -0
  55. package/dist/azure/pricing/resolvers/__tests__/public-ip.test.d.ts +5 -0
  56. package/dist/azure/pricing/resolvers/__tests__/public-ip.test.d.ts.map +1 -0
  57. package/dist/azure/pricing/resolvers/__tests__/public-ip.test.js +113 -0
  58. package/dist/azure/pricing/resolvers/__tests__/public-ip.test.js.map +1 -0
  59. package/dist/azure/pricing/resolvers/__tests__/vm.test.d.ts +9 -0
  60. package/dist/azure/pricing/resolvers/__tests__/vm.test.d.ts.map +1 -0
  61. package/dist/azure/pricing/resolvers/__tests__/vm.test.js +204 -0
  62. package/dist/azure/pricing/resolvers/__tests__/vm.test.js.map +1 -0
  63. package/dist/azure/pricing/resolvers/app-service.d.ts +27 -0
  64. package/dist/azure/pricing/resolvers/app-service.d.ts.map +1 -0
  65. package/dist/azure/pricing/resolvers/app-service.js +67 -0
  66. package/dist/azure/pricing/resolvers/app-service.js.map +1 -0
  67. package/dist/azure/pricing/resolvers/disk.d.ts +59 -0
  68. package/dist/azure/pricing/resolvers/disk.d.ts.map +1 -0
  69. package/dist/azure/pricing/resolvers/disk.js +140 -0
  70. package/dist/azure/pricing/resolvers/disk.js.map +1 -0
  71. package/dist/azure/pricing/resolvers/index.d.ts +12 -0
  72. package/dist/azure/pricing/resolvers/index.d.ts.map +1 -0
  73. package/dist/azure/pricing/resolvers/index.js +8 -0
  74. package/dist/azure/pricing/resolvers/index.js.map +1 -0
  75. package/dist/azure/pricing/resolvers/public-ip.d.ts +32 -0
  76. package/dist/azure/pricing/resolvers/public-ip.d.ts.map +1 -0
  77. package/dist/azure/pricing/resolvers/public-ip.js +56 -0
  78. package/dist/azure/pricing/resolvers/public-ip.js.map +1 -0
  79. package/dist/azure/pricing/resolvers/vm.d.ts +51 -0
  80. package/dist/azure/pricing/resolvers/vm.d.ts.map +1 -0
  81. package/dist/azure/pricing/resolvers/vm.js +89 -0
  82. package/dist/azure/pricing/resolvers/vm.js.map +1 -0
  83. package/dist/azure/pricing/schema.d.ts +88 -0
  84. package/dist/azure/pricing/schema.d.ts.map +1 -0
  85. package/dist/azure/pricing/schema.js +64 -0
  86. package/dist/azure/pricing/schema.js.map +1 -0
  87. package/dist/azure/pricing/test-cache-dir.d.ts +3 -0
  88. package/dist/azure/pricing/test-cache-dir.d.ts.map +1 -0
  89. package/dist/azure/pricing/test-cache-dir.js +17 -0
  90. package/dist/azure/pricing/test-cache-dir.js.map +1 -0
  91. package/dist/azure/report.d.ts.map +1 -1
  92. package/dist/azure/report.js +57 -18
  93. package/dist/azure/report.js.map +1 -1
  94. package/dist/azure/resources/__tests__/app-service.test.d.ts +5 -0
  95. package/dist/azure/resources/__tests__/app-service.test.d.ts.map +1 -0
  96. package/dist/azure/resources/__tests__/app-service.test.js +105 -0
  97. package/dist/azure/resources/__tests__/app-service.test.js.map +1 -0
  98. package/dist/azure/resources/app-service.d.ts +8 -3
  99. package/dist/azure/resources/app-service.d.ts.map +1 -1
  100. package/dist/azure/resources/app-service.js +35 -2
  101. package/dist/azure/resources/app-service.js.map +1 -1
  102. package/dist/azure/resources/disk.d.ts +3 -1
  103. package/dist/azure/resources/disk.d.ts.map +1 -1
  104. package/dist/azure/resources/disk.js +35 -3
  105. package/dist/azure/resources/disk.js.map +1 -1
  106. package/dist/azure/resources/public-ip.d.ts +3 -1
  107. package/dist/azure/resources/public-ip.d.ts.map +1 -1
  108. package/dist/azure/resources/public-ip.js +41 -3
  109. package/dist/azure/resources/public-ip.js.map +1 -1
  110. package/dist/azure/resources/vm.d.ts +4 -1
  111. package/dist/azure/resources/vm.d.ts.map +1 -1
  112. package/dist/azure/resources/vm.js +49 -6
  113. package/dist/azure/resources/vm.js.map +1 -1
  114. package/dist/azure/types.d.ts +13 -0
  115. package/dist/azure/types.d.ts.map +1 -1
  116. package/dist/finding.d.ts +3 -3
  117. package/dist/finding.d.ts.map +1 -1
  118. package/dist/finding.js +7 -0
  119. package/dist/finding.js.map +1 -1
  120. package/dist/index.d.ts +2 -2
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js.map +1 -1
  123. package/dist/types.d.ts +8 -0
  124. package/dist/types.d.ts.map +1 -1
  125. package/dist/types.js +2 -0
  126. package/dist/types.js.map +1 -1
  127. package/package.json +9 -9
  128. package/src/__tests__/finding.test.ts +24 -0
  129. package/src/azure/__tests__/analyzer-tags.test.ts +36 -1
  130. package/src/azure/__tests__/config.test.ts +12 -0
  131. package/src/azure/__tests__/report.test.ts +78 -0
  132. package/src/azure/analyzer.ts +67 -43
  133. package/src/azure/analyzers/registry.ts +8 -2
  134. package/src/azure/analyzers/types.ts +6 -0
  135. package/src/azure/pricing/__tests__/cache.test.ts +67 -0
  136. package/src/azure/pricing/__tests__/client.test.ts +212 -0
  137. package/src/azure/pricing/__tests__/fixtures/vm-b2s-westeurope.json +51 -0
  138. package/src/azure/pricing/__tests__/pricing-service.test.ts +315 -0
  139. package/src/azure/pricing/cache.ts +92 -0
  140. package/src/azure/pricing/client.ts +137 -0
  141. package/src/azure/pricing/index.ts +6 -0
  142. package/src/azure/pricing/pricing-service.ts +125 -0
  143. package/src/azure/pricing/resolvers/__tests__/app-service.test.ts +154 -0
  144. package/src/azure/pricing/resolvers/__tests__/disk.test.ts +189 -0
  145. package/src/azure/pricing/resolvers/__tests__/public-ip.test.ts +130 -0
  146. package/src/azure/pricing/resolvers/__tests__/vm.test.ts +232 -0
  147. package/src/azure/pricing/resolvers/app-service.ts +102 -0
  148. package/src/azure/pricing/resolvers/disk.ts +170 -0
  149. package/src/azure/pricing/resolvers/index.ts +31 -0
  150. package/src/azure/pricing/resolvers/public-ip.ts +87 -0
  151. package/src/azure/pricing/resolvers/vm.ts +125 -0
  152. package/src/azure/pricing/schema.ts +69 -0
  153. package/src/azure/pricing/test-cache-dir.ts +26 -0
  154. package/src/azure/report.ts +86 -21
  155. package/src/azure/resources/__tests__/app-service.test.ts +165 -0
  156. package/src/azure/resources/app-service.ts +65 -4
  157. package/src/azure/resources/disk.ts +46 -4
  158. package/src/azure/resources/public-ip.ts +61 -2
  159. package/src/azure/resources/vm.ts +89 -11
  160. package/src/azure/types.ts +14 -0
  161. package/src/finding.ts +10 -3
  162. package/src/index.ts +3 -3
  163. package/src/types.ts +12 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/azure/pricing/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC/C,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC;IAC7B,aAAa;IACb,oBAAoB;IACpB,aAAa;CACd,CAAC,CAAC;AACH,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC;AAE3D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,aAAa,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC9C,UAAU,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC3C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,kBAAkB,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACnD,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC5C,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACzC,OAAO,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACxC,SAAS,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC1C,WAAW,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC5C,eAAe,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAChD,WAAW,EAAE,gBAAgB;IAC7B,aAAa,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC9C,SAAS,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC1C,WAAW,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC5C,KAAK,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACtC,OAAO,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACxC,gBAAgB,EAAE,gBAAgB,CAAC,QAAQ,EAAE;IAC7C,4DAA4D;IAC5D,IAAI,EAAE,eAAe;IACrB,aAAa,EAAE,oBAAoB;IACnC,SAAS,EAAE,gBAAgB;CAC5B,CAAC,CAAC;AAGH;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IAChD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;IAC/B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACrD,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function makeTestCacheDir(prefix: string): Promise<string>;
2
+ export declare function removeTestCacheDir(dir: string): Promise<void>;
3
+ //# sourceMappingURL=test-cache-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-cache-dir.d.ts","sourceRoot":"","sources":["../../../src/azure/pricing/test-cache-dir.ts"],"names":[],"mappings":"AAUA,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGtE;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnE"}
@@ -0,0 +1,17 @@
1
+ import { mkdir, mkdtemp, rm } from "node:fs/promises";
2
+ import { isAbsolute, join, relative } from "node:path";
3
+ const TEST_CACHE_PARENT = join(process.cwd(), "node_modules", ".cache", "dx-savemoney-tests");
4
+ export async function makeTestCacheDir(prefix) {
5
+ await mkdir(TEST_CACHE_PARENT, { recursive: true });
6
+ return mkdtemp(join(TEST_CACHE_PARENT, `${prefix}-`));
7
+ }
8
+ export async function removeTestCacheDir(dir) {
9
+ const relativePath = relative(TEST_CACHE_PARENT, dir);
10
+ if (relativePath === "" ||
11
+ relativePath.startsWith("..") ||
12
+ isAbsolute(relativePath)) {
13
+ throw new Error(`Refusing to remove non-test cache directory: ${dir}`);
14
+ }
15
+ await rm(dir, { force: true, recursive: true });
16
+ }
17
+ //# sourceMappingURL=test-cache-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-cache-dir.js","sourceRoot":"","sources":["../../../src/azure/pricing/test-cache-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEvD,MAAM,iBAAiB,GAAG,IAAI,CAC5B,OAAO,CAAC,GAAG,EAAE,EACb,cAAc,EACd,QAAQ,EACR,oBAAoB,CACrB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,MAAM,KAAK,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAW;IAClD,MAAM,YAAY,GAAG,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACtD,IACE,YAAY,KAAK,EAAE;QACnB,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;QAC7B,UAAU,CAAC,YAAY,CAAC,EACxB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,gDAAgD,GAAG,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/azure/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,YAAY,CAAC;AAmCpB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,2BAA2B,EAAE,EACrC,MAAM,EAAE,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,iBAmDpD"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/azure/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,YAAY,CAAC;AA+CpB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,2BAA2B,EAAE,EACrC,MAAM,EAAE,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,iBAmDpD"}
@@ -90,6 +90,7 @@ export async function generateReport(report, format) {
90
90
  */
91
91
  function computeSummary(report) {
92
92
  const summary = {
93
+ costAtRiskByCurrency: new Map(),
93
94
  counts: { high: 0, low: 0, medium: 0 },
94
95
  savingsByCurrency: new Map(),
95
96
  sourceCounts: {},
@@ -110,11 +111,18 @@ function computeSummary(report) {
110
111
  summary.counts[line.severity]++;
111
112
  summary.sourceCounts[line.source] =
112
113
  (summary.sourceCounts[line.source] ?? 0) + 1;
113
- if (line.savings) {
114
+ if (line.source === "advisor" && line.savings) {
114
115
  summary.savingsByCurrency.set(line.savings.currency, (summary.savingsByCurrency.get(line.savings.currency) ?? 0) +
115
116
  line.savings.amount);
116
117
  }
117
118
  }
119
+ // Per-resource cost: counted ONCE per resource (not per finding) so
120
+ // that a resource with N findings doesn't inflate the total by Nx.
121
+ const costAtRisk = entry.analysis.estimatedMonthlySavings;
122
+ if (costAtRisk) {
123
+ summary.costAtRiskByCurrency.set(costAtRisk.currency, (summary.costAtRiskByCurrency.get(costAtRisk.currency) ?? 0) +
124
+ costAtRisk.amount);
125
+ }
118
126
  }
119
127
  return summary;
120
128
  }
@@ -137,45 +145,72 @@ function formatAmount(amount, currency) {
137
145
  }
138
146
  }
139
147
  /**
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.
148
+ * Renders an Advisor per-finding monthly saving as the short
149
+ * "(saving: € 12.50/mo)" label that ships next to each lint line.
150
+ * Returns an empty string when the finding doesn't carry an estimate.
151
+ *
152
+ * Only Advisor populates this today: Microsoft attaches an authoritative
153
+ * per-recommendation saving to each recommendation, so it aggregates
154
+ * cleanly. Custom analyzers do NOT propagate the resource's monthly
155
+ * bill down to each finding — see the per-resource "cost at risk"
156
+ * header rendered by `generateLintReport` instead.
143
157
  */
144
- function formatSavings(savings) {
158
+ function formatPerFindingSavings(savings) {
145
159
  if (!savings)
146
160
  return "";
147
- return `(${formatAmount(savings.amount, savings.currency)}/mo)`;
161
+ return `(saving: ${formatAmount(savings.amount, savings.currency)}/mo)`;
148
162
  }
149
163
  /**
150
164
  * Renders a linter-style report to stdout, grouping findings by resource.
151
165
  *
152
166
  * 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.
167
+ * rendered with its `source` badge (e.g. `[advisor]`) and its own
168
+ * estimated monthly saving (when populated by Advisor). For older
169
+ * payloads without `findings` we fall back to splitting `analysis.reason`
170
+ * like before so the format stays backward compatible.
171
+ *
172
+ * When a custom analyzer populated `analysis.estimatedMonthlySavings`,
173
+ * the value is printed ONCE per resource as a header annotation labelled
174
+ * "cost at risk" — it represents the monthly bill of the resource (an
175
+ * upper bound on what could be recovered by removing it), NOT the saving
176
+ * of any individual finding sentence.
157
177
  *
158
178
  * Example output:
159
179
  *
160
- * /subscriptions/.../virtualMachines/my-vm
161
- * ✖ HIGH [advisor] Right-size your VM. (€ 12.50/mo)
180
+ * /subscriptions/.../virtualMachines/my-vm (cost at risk: € 29.94/mo)
162
181
  * ✖ HIGH [custom] No tags found.
182
+ * ✖ HIGH [custom] VM is deallocated.
183
+ *
184
+ * /subscriptions/.../virtualMachines/other-vm
185
+ * ✖ HIGH [advisor] Right-size your VM. (saving: € 12.50/mo)
163
186
  *
164
187
  * Summary: 3 issues found (2 high, 0 medium, 1 low)
165
- * Estimated monthly savings: € 12.50
188
+ * Estimated monthly cost at risk (custom): € 29.94
189
+ * Estimated monthly savings (advisor): € 12.50
166
190
  */
167
191
  function generateLintReport(report) {
168
192
  const summary = {
193
+ costAtRiskByCurrency: new Map(),
169
194
  counts: { high: 0, low: 0, medium: 0 },
170
195
  savingsByCurrency: new Map(),
171
196
  sourceCounts: {},
172
197
  };
173
198
  for (const entry of report) {
174
199
  const resourceId = entry.resource.id ?? `unknown/${entry.resource.name ?? "unknown"}`;
175
- console.log(`${BOLD}${resourceId}${RESET}`);
200
+ const costAtRisk = entry.analysis.estimatedMonthlySavings;
201
+ const header = costAtRisk
202
+ ? `${BOLD}${resourceId}${RESET} ${GREEN}(cost at risk: ${formatAmount(costAtRisk.amount, costAtRisk.currency)}/mo)${RESET}`
203
+ : `${BOLD}${resourceId}${RESET}`;
204
+ console.log(header);
205
+ if (costAtRisk) {
206
+ summary.costAtRiskByCurrency.set(costAtRisk.currency, (summary.costAtRiskByCurrency.get(costAtRisk.currency) ?? 0) +
207
+ costAtRisk.amount);
208
+ }
176
209
  const lines = entry.findings?.length
177
210
  ? entry.findings.map((f) => ({
178
- extra: formatSavings(f.estimatedMonthlySavings),
211
+ extra: f.source === "advisor"
212
+ ? formatPerFindingSavings(f.estimatedMonthlySavings)
213
+ : "",
179
214
  severity: f.severity,
180
215
  source: f.source,
181
216
  text: f.reason,
@@ -199,7 +234,7 @@ function generateLintReport(report) {
199
234
  }
200
235
  if (entry.findings) {
201
236
  for (const f of entry.findings) {
202
- if (f.estimatedMonthlySavings) {
237
+ if (f.source === "advisor" && f.estimatedMonthlySavings) {
203
238
  const { amount, currency } = f.estimatedMonthlySavings;
204
239
  summary.savingsByCurrency.set(currency, (summary.savingsByCurrency.get(currency) ?? 0) + amount);
205
240
  }
@@ -221,7 +256,7 @@ function generateLintReport(report) {
221
256
  * out of scope for this tool.
222
257
  */
223
258
  function printSummary(summary) {
224
- const { counts, savingsByCurrency, sourceCounts } = summary;
259
+ const { costAtRiskByCurrency, counts, savingsByCurrency, sourceCounts } = summary;
225
260
  const total = counts.high + counts.medium + counts.low;
226
261
  const summaryLine = `${BOLD}Summary:${RESET} ${total} issue${total !== 1 ? "s" : ""} found` +
227
262
  ` ${RED}(${counts.high} high${RESET}` +
@@ -235,9 +270,13 @@ function printSummary(summary) {
235
270
  if (sourceBreakdown) {
236
271
  console.log(`${BOLD}Sources:${RESET} ${sourceBreakdown}`);
237
272
  }
273
+ if (costAtRiskByCurrency.size > 0) {
274
+ const parts = [...costAtRiskByCurrency.entries()].map(([currency, amount]) => `${GREEN}${formatAmount(amount, currency)}${RESET}`);
275
+ console.log(`${BOLD}Estimated monthly cost at risk (custom):${RESET} ${parts.join(", ")}`);
276
+ }
238
277
  if (savingsByCurrency.size > 0) {
239
278
  const parts = [...savingsByCurrency.entries()].map(([currency, amount]) => `${GREEN}${formatAmount(amount, currency)}${RESET}`);
240
- console.log(`${BOLD}Estimated monthly savings:${RESET} ${parts.join(", ")}`);
279
+ console.log(`${BOLD}Estimated monthly savings (advisor):${RESET} ${parts.join(", ")}`);
241
280
  }
242
281
  }
243
282
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/azure/report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/azure/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for analyzeAppServicePlan() pricing enrichment.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=app-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-service.test.d.ts","sourceRoot":"","sources":["../../../../src/azure/resources/__tests__/app-service.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Tests for analyzeAppServicePlan() pricing enrichment.
3
+ */
4
+ import { beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { DEFAULT_THRESHOLDS } from "../../../types.js";
6
+ vi.mock("../../utils.js", () => ({
7
+ getMetric: vi.fn(),
8
+ verboseLog: vi.fn(),
9
+ verboseLogAnalysisResult: vi.fn(),
10
+ verboseLogResourceStart: vi.fn(),
11
+ }));
12
+ import { getMetric } from "../../utils.js";
13
+ import { analyzeAppServicePlan } from "../app-service.js";
14
+ const RESOURCE = {
15
+ id: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Web/serverfarms/plan1",
16
+ location: "westeurope",
17
+ name: "plan1",
18
+ type: "Microsoft.Web/serverfarms",
19
+ };
20
+ const mockGetMetric = vi.mocked(getMetric);
21
+ function makeMonitorClient() {
22
+ return {
23
+ metrics: { list: vi.fn() },
24
+ };
25
+ }
26
+ function makePricingService() {
27
+ return {
28
+ resolveAppServicePlan: vi.fn().mockResolvedValue({
29
+ amount: 121.72,
30
+ currency: "EUR",
31
+ }),
32
+ };
33
+ }
34
+ function makeWebSiteClient(planDetails) {
35
+ const client = {
36
+ appServicePlans: {
37
+ get: vi.fn().mockResolvedValue({
38
+ location: "westeurope",
39
+ ...planDetails,
40
+ }),
41
+ },
42
+ };
43
+ return client;
44
+ }
45
+ describe("analyzeAppServicePlan", () => {
46
+ beforeEach(() => {
47
+ mockGetMetric.mockReset();
48
+ mockGetMetric.mockResolvedValue(50);
49
+ });
50
+ it("enriches suspected unused plans with App Service Plan pricing", async () => {
51
+ const pricing = makePricingService();
52
+ const result = await analyzeAppServicePlan(RESOURCE, makeWebSiteClient({
53
+ numberOfSites: 0,
54
+ reserved: true,
55
+ sku: {
56
+ capacity: 2,
57
+ name: "S1",
58
+ tier: "Standard",
59
+ },
60
+ }), makeMonitorClient(), 30, DEFAULT_THRESHOLDS, false, undefined, pricing);
61
+ expect(result.estimatedMonthlySavings).toEqual({
62
+ amount: 121.72,
63
+ currency: "EUR",
64
+ });
65
+ expect(pricing.resolveAppServicePlan).toHaveBeenCalledWith({
66
+ armRegionName: "westeurope",
67
+ os: "linux",
68
+ skuName: "S1",
69
+ workerCount: 2,
70
+ });
71
+ });
72
+ it("does not price Premium underutilization as full removable cost", async () => {
73
+ mockGetMetric.mockResolvedValue(1);
74
+ const pricing = makePricingService();
75
+ const result = await analyzeAppServicePlan(RESOURCE, makeWebSiteClient({
76
+ numberOfSites: 2,
77
+ reserved: false,
78
+ sku: {
79
+ capacity: 3,
80
+ name: "P1v3",
81
+ tier: "PremiumV3",
82
+ },
83
+ }), makeMonitorClient(), 30, DEFAULT_THRESHOLDS, false, undefined, pricing);
84
+ expect(result.suspectedUnused).toBe(true);
85
+ expect(result.reason).toContain("Premium tier with low resource utilization");
86
+ expect(result.estimatedMonthlySavings).toBeUndefined();
87
+ expect(pricing.resolveAppServicePlan).not.toHaveBeenCalled();
88
+ });
89
+ it("does not treat missing site count as an empty plan", async () => {
90
+ mockGetMetric.mockResolvedValue(50);
91
+ const pricing = makePricingService();
92
+ const result = await analyzeAppServicePlan(RESOURCE, makeWebSiteClient({
93
+ reserved: true,
94
+ sku: {
95
+ capacity: 2,
96
+ name: "S1",
97
+ tier: "Standard",
98
+ },
99
+ }), makeMonitorClient(), 30, DEFAULT_THRESHOLDS, false, undefined, pricing);
100
+ expect(result.suspectedUnused).toBe(false);
101
+ expect(result.estimatedMonthlySavings).toBeUndefined();
102
+ expect(pricing.resolveAppServicePlan).not.toHaveBeenCalled();
103
+ });
104
+ });
105
+ //# sourceMappingURL=app-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-service.test.js","sourceRoot":"","sources":["../../../../src/azure/resources/__tests__/app-service.test.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,14 @@
2
2
  * Azure App Service Plan analysis
3
3
  */
4
4
  import type { WebSiteManagementClient } from "@azure/arm-appservice";
5
- import type { MonitorClient } from "@azure/arm-monitor";
6
5
  import * as armResources from "@azure/arm-resources";
7
6
  import type { AnalysisResult, Thresholds } from "../../types.js";
8
- import { type MetricsCache } from "../utils.js";
7
+ import type { PricingService } from "../pricing/pricing-service.js";
8
+ import { type MetricsCache, type MonitorClientLike } from "../utils.js";
9
+ export type AppServicePlanClientLike = {
10
+ appServicePlans: Pick<WebSiteManagementClient["appServicePlans"], "get">;
11
+ };
12
+ type AppServicePlanPricing = Pick<PricingService, "resolveAppServicePlan">;
9
13
  /**
10
14
  * Analyzes an Azure App Service Plan for potential cost optimization.
11
15
  *
@@ -15,5 +19,6 @@ import { type MetricsCache } from "../utils.js";
15
19
  * @param timespanDays - Number of days to analyze metrics
16
20
  * @returns Analysis result with cost risk and reason
17
21
  */
18
- export declare function analyzeAppServicePlan(resource: armResources.GenericResource, webSiteClient: WebSiteManagementClient, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache): Promise<AnalysisResult>;
22
+ export declare function analyzeAppServicePlan(resource: armResources.GenericResource, webSiteClient: AppServicePlanClientLike, monitorClient: MonitorClientLike, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache, pricing?: AppServicePlanPricing): Promise<AnalysisResult>;
23
+ export {};
19
24
  //# sourceMappingURL=app-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-service.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/app-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,cAAc,CAAC,CA2FzB"}
1
+ {"version":3,"file":"app-service.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/app-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EAIvB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,wBAAwB,GAAG;IACrC,eAAe,EAAE,IAAI,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,CAAC;CAC1E,CAAC;AAEF,KAAK,qBAAqB,GAAG,IAAI,CAAC,cAAc,EAAE,uBAAuB,CAAC,CAAC;AAE3E;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,wBAAwB,EACvC,aAAa,EAAE,iBAAiB,EAChC,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,cAAc,CAAC,CAwGzB"}
@@ -13,7 +13,7 @@ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStar
13
13
  * @param timespanDays - Number of days to analyze metrics
14
14
  * @returns Analysis result with cost risk and reason
15
15
  */
16
- export async function analyzeAppServicePlan(resource, webSiteClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache) {
16
+ export async function analyzeAppServicePlan(resource, webSiteClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache, pricing) {
17
17
  verboseLogResourceStart(verbose, resource.name || "unknown", "App Service Plan (microsoft.web/serverfarms)");
18
18
  verboseLog(verbose, "Resource details:", resource);
19
19
  const costRisk = "high";
@@ -33,8 +33,9 @@ export async function analyzeAppServicePlan(resource, webSiteClient, monitorClie
33
33
  // Get detailed App Service Plan information
34
34
  const planDetails = await webSiteClient.appServicePlans.get(resourceGroupName, planName);
35
35
  verboseLog(verbose, "App Service Plan API details:", planDetails);
36
+ const hasNoApps = planDetails.numberOfSites === 0;
36
37
  // Check if the plan has no apps
37
- if (!planDetails.numberOfSites || planDetails.numberOfSites === 0) {
38
+ if (hasNoApps) {
38
39
  reason += "App Service Plan has no apps deployed. ";
39
40
  }
40
41
  // Check CPU and Memory metrics
@@ -54,6 +55,10 @@ export async function analyzeAppServicePlan(resource, webSiteClient, monitorClie
54
55
  cpuPercentage < thresholds.appService.premiumCpuPercent) {
55
56
  reason += "Premium tier with low resource utilization. ";
56
57
  }
58
+ const suspectedUnused = reason.length > 0;
59
+ const result = await enrichWithPricing({ costRisk, reason: reason.trim(), suspectedUnused }, planDetails, resource, hasNoApps, pricing);
60
+ verboseLogAnalysisResult(verbose, result);
61
+ return result;
57
62
  }
58
63
  catch (error) {
59
64
  const logger = getLogger(["savemoney", "azure"]);
@@ -65,4 +70,32 @@ export async function analyzeAppServicePlan(resource, webSiteClient, monitorClie
65
70
  verboseLogAnalysisResult(verbose, result);
66
71
  return result;
67
72
  }
73
+ async function enrichWithPricing(result, planDetails, resource, hasNoApps, pricing) {
74
+ // Underutilized plans need right-sizing analysis, not a full removable
75
+ // cost-at-risk.
76
+ if (!pricing || !result.suspectedUnused || !hasNoApps) {
77
+ return result;
78
+ }
79
+ try {
80
+ const skuName = planDetails.sku?.name;
81
+ const armRegionName = planDetails.location ?? resource.location;
82
+ if (!skuName || !armRegionName) {
83
+ return result;
84
+ }
85
+ const estimatedMonthlySavings = await pricing.resolveAppServicePlan({
86
+ armRegionName,
87
+ os: planDetails.reserved === true ? "linux" : "windows",
88
+ skuName,
89
+ workerCount: planDetails.sku?.capacity ?? planDetails.numberOfWorkers,
90
+ });
91
+ return estimatedMonthlySavings
92
+ ? { ...result, estimatedMonthlySavings }
93
+ : result;
94
+ }
95
+ catch (error) {
96
+ const logger = getLogger(["savemoney", "azure"]);
97
+ logger.warn(`Failed to enrich App Service Plan ${resource.name ?? "unknown"} with pricing: ${error instanceof Error ? error.message : error}`);
98
+ return result;
99
+ }
100
+ }
68
101
  //# sourceMappingURL=app-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-service.js","sourceRoot":"","sources":["../../../src/azure/resources/app-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app-service.js","sourceRoot":"","sources":["../../../src/azure/resources/app-service.ts"],"names":[],"mappings":"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"}
@@ -4,13 +4,15 @@
4
4
  import type { ComputeManagementClient } from "@azure/arm-compute";
5
5
  import * as armResources from "@azure/arm-resources";
6
6
  import type { AnalysisResult } from "../../types.js";
7
+ import type { PricingService } from "../pricing/pricing-service.js";
7
8
  /**
8
9
  * Analyzes an Azure Managed Disk for potential cost optimization.
9
10
  *
10
11
  * @param resource - The Azure resource object
11
12
  * @param computeClient - Azure Compute client for disk details
12
13
  * @param verbose - Whether verbose logging is enabled
14
+ * @param pricing - Optional pricing service for monetary enrichment
13
15
  * @returns Analysis result with cost risk and reason
14
16
  */
15
- export declare function analyzeDisk(resource: armResources.GenericResource, computeClient: ComputeManagementClient, verbose?: boolean): Promise<AnalysisResult>;
17
+ export declare function analyzeDisk(resource: armResources.GenericResource, computeClient: ComputeManagementClient, verbose?: boolean, pricing?: PricingService): Promise<AnalysisResult>;
16
18
  //# sourceMappingURL=disk.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/disk.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAQrD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,uBAAuB,EACtC,OAAO,UAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CA0DzB"}
1
+ {"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/disk.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAQ,MAAM,oBAAoB,CAAC;AAExE,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAIrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAUpE;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,uBAAuB,EACtC,OAAO,UAAQ,EACf,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC,CA2DzB"}
@@ -2,6 +2,7 @@
2
2
  * Azure Managed Disk analysis
3
3
  */
4
4
  import { getLogger } from "@logtape/logtape";
5
+ import { DiskSkuSchema } from "../pricing/resolvers/index.js";
5
6
  import { verboseLog, verboseLogAnalysisResult, verboseLogResourceStart, } from "../utils.js";
6
7
  /**
7
8
  * Analyzes an Azure Managed Disk for potential cost optimization.
@@ -9,9 +10,10 @@ import { verboseLog, verboseLogAnalysisResult, verboseLogResourceStart, } from "
9
10
  * @param resource - The Azure resource object
10
11
  * @param computeClient - Azure Compute client for disk details
11
12
  * @param verbose - Whether verbose logging is enabled
13
+ * @param pricing - Optional pricing service for monetary enrichment
12
14
  * @returns Analysis result with cost risk and reason
13
15
  */
14
- export async function analyzeDisk(resource, computeClient, verbose = false) {
16
+ export async function analyzeDisk(resource, computeClient, verbose = false, pricing) {
15
17
  verboseLogResourceStart(verbose, resource.name || "unknown", "Managed Disk (microsoft.compute/disks)");
16
18
  verboseLog(verbose, "Resource details:", resource);
17
19
  const costRisk = "medium";
@@ -38,8 +40,9 @@ export async function analyzeDisk(resource, computeClient, verbose = false) {
38
40
  reason: "Disk is unattached. ",
39
41
  suspectedUnused: true,
40
42
  };
41
- verboseLogAnalysisResult(verbose, result);
42
- return result;
43
+ const enriched = await enrichWithPricing(result, diskDetails, pricing);
44
+ verboseLogAnalysisResult(verbose, enriched);
45
+ return enriched;
43
46
  }
44
47
  }
45
48
  catch (error) {
@@ -53,4 +56,33 @@ export async function analyzeDisk(resource, computeClient, verbose = false) {
53
56
  verboseLogAnalysisResult(verbose, result);
54
57
  return result;
55
58
  }
59
+ /**
60
+ * Best-effort: looks up the monthly price for the disk's `(sku, size,
61
+ * region)` triple and attaches it as `estimatedMonthlySavings`. Any
62
+ * failure (unsupported SKU, missing fields, resolver error) leaves the
63
+ * original result unchanged.
64
+ */
65
+ async function enrichWithPricing(result, diskDetails, pricing) {
66
+ if (!pricing)
67
+ return result;
68
+ const sku = toSupportedSku(diskDetails.sku?.name);
69
+ const diskSizeGiB = diskDetails.diskSizeGB;
70
+ const armRegionName = diskDetails.location;
71
+ if (!sku || !diskSizeGiB || !armRegionName)
72
+ return result;
73
+ const money = await pricing.resolveDisk({
74
+ armRegionName,
75
+ diskSizeGiB,
76
+ sku,
77
+ });
78
+ return money ? { ...result, estimatedMonthlySavings: money } : result;
79
+ }
80
+ /**
81
+ * Narrows the SDK's `sku.name` string to the resolver-supported subset
82
+ * (excludes `UltraSSD_LRS` and any future tiers we don't price yet).
83
+ */
84
+ function toSupportedSku(name) {
85
+ const parsed = DiskSkuSchema.safeParse(name);
86
+ return parsed.success ? parsed.data : undefined;
87
+ }
56
88
  //# sourceMappingURL=disk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"disk.js","sourceRoot":"","sources":["../../../src/azure/resources/disk.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EACL,UAAU,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAsC,EACtC,aAAsC,EACtC,OAAO,GAAG,KAAK;IAEf,uBAAuB,CACrB,OAAO,EACP,QAAQ,CAAC,IAAI,IAAI,SAAS,EAC1B,wCAAwC,CACzC,CAAC;IACF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAA8B,QAAQ,CAAC;IAErD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,yBAAyB;YACjC,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IAED,wDAAwD;IACxD,MAAM,aAAa,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,iBAAiB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAElC,IAAI,CAAC;QACH,wDAAwD;QACxD,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,GAAG,CAC/C,iBAAiB,EACjB,QAAQ,CACT,CAAC;QAEF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,WAAW,CAAC,CAAC;QAEtD,8BAA8B;QAC9B,IACE,WAAW,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,YAAY;YACrD,CAAC,WAAW,CAAC,SAAS,EACtB,CAAC;YACD,MAAM,MAAM,GAAG;gBACb,QAAQ;gBACR,MAAM,EAAE,sBAAsB;gBAC9B,eAAe,EAAE,IAAI;aACtB,CAAC;YACF,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1C,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CACT,kCAAkC,QAAQ,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAChG,CAAC;QACF,oDAAoD;QACpD,wDAAwD;QACxD,+DAA+D;IACjE,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;IAChE,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"disk.js","sourceRoot":"","sources":["../../../src/azure/resources/disk.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import type { MonitorClient } from "@azure/arm-monitor";
5
5
  import type { NetworkManagementClient } from "@azure/arm-network";
6
6
  import * as armResources from "@azure/arm-resources";
7
7
  import type { AnalysisResult, Thresholds } from "../../types.js";
8
+ import type { PricingService } from "../pricing/pricing-service.js";
8
9
  import { type MetricsCache } from "../utils.js";
9
10
  /**
10
11
  * Analyzes an Azure Public IP for potential cost optimization.
@@ -13,7 +14,8 @@ import { type MetricsCache } from "../utils.js";
13
14
  * @param networkClient - Azure Network client for Public IP details
14
15
  * @param monitorClient - Azure Monitor client for metrics
15
16
  * @param timespanDays - Number of days to analyze metrics
17
+ * @param pricing - Optional pricing facade for estimated monthly cost
16
18
  * @returns Analysis result with cost risk and reason
17
19
  */
18
- export declare function analyzePublicIp(resource: armResources.GenericResource, networkClient: NetworkManagementClient, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache): Promise<AnalysisResult>;
20
+ export declare function analyzePublicIp(resource: armResources.GenericResource, networkClient: NetworkManagementClient, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache, pricing?: PricingService): Promise<AnalysisResult>;
19
21
  //# sourceMappingURL=public-ip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public-ip.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/public-ip.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,cAAc,CAAC,CAuEzB"}
1
+ {"version":3,"file":"public-ip.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/public-ip.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC,CAmFzB"}