@pagopa/dx-savemoney 0.1.6 → 0.2.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 +104 -27
- package/dist/azure/analyzer.d.ts +4 -4
- package/dist/azure/analyzer.d.ts.map +1 -1
- package/dist/azure/analyzer.js +16 -10
- package/dist/azure/analyzer.js.map +1 -1
- package/dist/azure/config.d.ts +15 -3
- package/dist/azure/config.d.ts.map +1 -1
- package/dist/azure/config.js +32 -16
- package/dist/azure/config.js.map +1 -1
- package/dist/azure/report.d.ts +2 -2
- package/dist/azure/report.d.ts.map +1 -1
- package/dist/azure/report.js +68 -3
- package/dist/azure/report.js.map +1 -1
- package/dist/azure/resources/app-service.d.ts +2 -2
- package/dist/azure/resources/app-service.d.ts.map +1 -1
- package/dist/azure/resources/app-service.js +8 -5
- package/dist/azure/resources/app-service.js.map +1 -1
- package/dist/azure/resources/container-app.d.ts +2 -2
- package/dist/azure/resources/container-app.d.ts.map +1 -1
- package/dist/azure/resources/container-app.js +10 -8
- package/dist/azure/resources/container-app.js.map +1 -1
- package/dist/azure/resources/public-ip.d.ts +2 -2
- package/dist/azure/resources/public-ip.d.ts.map +1 -1
- package/dist/azure/resources/public-ip.js +3 -3
- package/dist/azure/resources/public-ip.js.map +1 -1
- package/dist/azure/resources/static-web-app.d.ts +2 -2
- package/dist/azure/resources/static-web-app.d.ts.map +1 -1
- package/dist/azure/resources/static-web-app.js +4 -5
- package/dist/azure/resources/static-web-app.js.map +1 -1
- package/dist/azure/resources/storage.d.ts +2 -2
- package/dist/azure/resources/storage.d.ts.map +1 -1
- package/dist/azure/resources/storage.js +4 -3
- package/dist/azure/resources/storage.js.map +1 -1
- package/dist/azure/resources/vm.d.ts +2 -2
- package/dist/azure/resources/vm.d.ts.map +1 -1
- package/dist/azure/resources/vm.js +4 -5
- package/dist/azure/resources/vm.js.map +1 -1
- package/dist/azure/types.d.ts +10 -2
- package/dist/azure/types.d.ts.map +1 -1
- package/dist/azure/utils.d.ts +9 -0
- package/dist/azure/utils.d.ts.map +1 -1
- package/dist/azure/utils.js +14 -0
- package/dist/azure/utils.js.map +1 -1
- package/dist/index.d.ts +16 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -54
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +210 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +97 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +8 -2
- package/src/azure/__tests__/config.test.ts +97 -0
- package/src/azure/__tests__/fixtures/full-override.yaml +25 -0
- package/src/azure/__tests__/fixtures/partial-override.yaml +10 -0
- package/src/azure/__tests__/report.test.ts +138 -0
- package/src/azure/__tests__/utils.test.ts +124 -0
- package/src/azure/analyzer.ts +24 -3
- package/src/azure/config.ts +33 -21
- package/src/azure/report.ts +81 -4
- package/src/azure/resources/__tests__/storage.test.ts +185 -0
- package/src/azure/resources/app-service.ts +13 -5
- package/src/azure/resources/container-app.ts +13 -4
- package/src/azure/resources/public-ip.ts +4 -3
- package/src/azure/resources/static-web-app.ts +5 -5
- package/src/azure/resources/storage.ts +7 -3
- package/src/azure/resources/vm.ts +5 -5
- package/src/azure/types.ts +15 -2
- package/src/azure/utils.ts +21 -0
- package/src/index.ts +19 -69
- package/src/schema.ts +134 -0
- package/src/types.ts +14 -0
package/src/schema.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for the SaveMoney YAML configuration file.
|
|
3
|
+
*
|
|
4
|
+
* The entire config is represented by a single `ConfigSchema` composed of
|
|
5
|
+
* sub-schemas. All types used at runtime are derived from these schemas via
|
|
6
|
+
* `z.infer<>` so the source of truth is always the schema.
|
|
7
|
+
*
|
|
8
|
+
* YAML structure:
|
|
9
|
+
* ```yaml
|
|
10
|
+
* azure:
|
|
11
|
+
* subscriptionIds:
|
|
12
|
+
* - xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
13
|
+
* preferredLocation: italynorth # optional
|
|
14
|
+
* timespanDays: 30 # optional
|
|
15
|
+
* thresholds: # optional – omit to keep built-in defaults
|
|
16
|
+
* vm:
|
|
17
|
+
* cpuPercent: 5
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
|
|
23
|
+
// ── per-resource threshold sub-schemas ──────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
const VmThresholdsSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
/** CPU threshold (%) below which usage is flagged as low. Default: 1 */
|
|
28
|
+
cpuPercent: z.number().default(1),
|
|
29
|
+
/** Network inbound threshold (bytes/day) below which traffic is flagged as low. Default: 3 MB */
|
|
30
|
+
networkInBytesPerDay: z.number().default(1024 * 1024 * 3),
|
|
31
|
+
})
|
|
32
|
+
.strict();
|
|
33
|
+
|
|
34
|
+
const AppServiceThresholdsSchema = z
|
|
35
|
+
.object({
|
|
36
|
+
/** CPU threshold (%) below which usage is flagged as very low. Default: 5 */
|
|
37
|
+
cpuPercent: z.number().default(5),
|
|
38
|
+
/** Memory threshold (%) below which usage is flagged as very low. Default: 10 */
|
|
39
|
+
memoryPercent: z.number().default(10),
|
|
40
|
+
/** CPU threshold (%) for Premium-tier plans below which over-provisioning is flagged. Default: 10 */
|
|
41
|
+
premiumCpuPercent: z.number().default(10),
|
|
42
|
+
})
|
|
43
|
+
.strict();
|
|
44
|
+
|
|
45
|
+
const ContainerAppThresholdsSchema = z
|
|
46
|
+
.object({
|
|
47
|
+
/** CPU threshold (nanoCores) below which usage is flagged as very low. Default: 1 000 000 (0.001 cores) */
|
|
48
|
+
cpuNanoCores: z.number().default(1_000_000),
|
|
49
|
+
/** Memory threshold (bytes) below which usage is flagged as very low. Default: 10 MB */
|
|
50
|
+
memoryBytes: z.number().default(10_485_760),
|
|
51
|
+
/** Combined Rx+Tx network threshold (bytes/day) below which traffic is flagged as very low. Default: ~33 KB */
|
|
52
|
+
networkBytes: z.number().default(34_000),
|
|
53
|
+
})
|
|
54
|
+
.strict();
|
|
55
|
+
|
|
56
|
+
const StorageThresholdsSchema = z
|
|
57
|
+
.object({
|
|
58
|
+
/** Average daily transaction count below which the account is flagged. Default: 10 */
|
|
59
|
+
transactionsPerDay: z.number().default(10),
|
|
60
|
+
})
|
|
61
|
+
.strict();
|
|
62
|
+
|
|
63
|
+
const PublicIpThresholdsSchema = z
|
|
64
|
+
.object({
|
|
65
|
+
/** DDoS inbound bytes/day threshold below which traffic is flagged as very low. Default: ~332 KB */
|
|
66
|
+
bytesInDDoS: z.number().default(340_000),
|
|
67
|
+
})
|
|
68
|
+
.strict();
|
|
69
|
+
|
|
70
|
+
const StaticSiteThresholdsSchema = z
|
|
71
|
+
.object({
|
|
72
|
+
/** Total bytes sent below which data transfer is flagged as very low. Default: 1 MB */
|
|
73
|
+
bytesSent: z.number().default(1_048_576),
|
|
74
|
+
/** Total site hits below which traffic is flagged as very low. Default: 100 */
|
|
75
|
+
siteHits: z.number().default(100),
|
|
76
|
+
})
|
|
77
|
+
.strict();
|
|
78
|
+
|
|
79
|
+
// ── composed thresholds schema ───────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
export const ThresholdsSchema = z
|
|
82
|
+
.object({
|
|
83
|
+
appService: AppServiceThresholdsSchema.optional().transform((v) =>
|
|
84
|
+
AppServiceThresholdsSchema.parse(v ?? {}),
|
|
85
|
+
),
|
|
86
|
+
containerApp: ContainerAppThresholdsSchema.optional().transform((v) =>
|
|
87
|
+
ContainerAppThresholdsSchema.parse(v ?? {}),
|
|
88
|
+
),
|
|
89
|
+
publicIp: PublicIpThresholdsSchema.optional().transform((v) =>
|
|
90
|
+
PublicIpThresholdsSchema.parse(v ?? {}),
|
|
91
|
+
),
|
|
92
|
+
staticSite: StaticSiteThresholdsSchema.optional().transform((v) =>
|
|
93
|
+
StaticSiteThresholdsSchema.parse(v ?? {}),
|
|
94
|
+
),
|
|
95
|
+
storage: StorageThresholdsSchema.optional().transform((v) =>
|
|
96
|
+
StorageThresholdsSchema.parse(v ?? {}),
|
|
97
|
+
),
|
|
98
|
+
vm: VmThresholdsSchema.optional().transform((v) =>
|
|
99
|
+
VmThresholdsSchema.parse(v ?? {}),
|
|
100
|
+
),
|
|
101
|
+
})
|
|
102
|
+
.strict();
|
|
103
|
+
|
|
104
|
+
// ── top-level config schema ──────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
const AzureSectionSchema = z
|
|
107
|
+
.object({
|
|
108
|
+
preferredLocation: z.string().default("italynorth"),
|
|
109
|
+
subscriptionIds: z
|
|
110
|
+
.array(z.string())
|
|
111
|
+
.min(
|
|
112
|
+
1,
|
|
113
|
+
"Config file must contain at least one entry in 'azure.subscriptionIds'",
|
|
114
|
+
),
|
|
115
|
+
thresholds: ThresholdsSchema.optional().transform((v) =>
|
|
116
|
+
ThresholdsSchema.parse(v ?? {}),
|
|
117
|
+
),
|
|
118
|
+
timespanDays: z.number().int().positive().default(30),
|
|
119
|
+
})
|
|
120
|
+
.strict();
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Single Zod schema representing the entire YAML configuration file.
|
|
124
|
+
* Use `ConfigSchema.parse(rawYaml)` to validate and apply defaults.
|
|
125
|
+
*/
|
|
126
|
+
export const ConfigSchema = z.object({ azure: AzureSectionSchema }).strict();
|
|
127
|
+
|
|
128
|
+
// ── inferred types ───────────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
/** Fully-resolved configuration (all defaults applied). */
|
|
131
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
132
|
+
|
|
133
|
+
/** Fully-resolved thresholds (all defaults applied). */
|
|
134
|
+
export type Thresholds = z.infer<typeof ThresholdsSchema>;
|
package/src/types.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Common types shared across all cloud providers
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { ThresholdsSchema } from "./schema.js";
|
|
6
|
+
|
|
5
7
|
export type AnalysisResult = {
|
|
6
8
|
costRisk: CostRisk;
|
|
7
9
|
reason: string;
|
|
@@ -18,6 +20,18 @@ export type BaseConfig = {
|
|
|
18
20
|
|
|
19
21
|
export type CostRisk = "high" | "low" | "medium";
|
|
20
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Configurable thresholds used during resource analysis.
|
|
25
|
+
* Derived from `ThresholdsSchema` — the schema is the single source of truth.
|
|
26
|
+
*/
|
|
27
|
+
export type { Thresholds } from "./schema.js";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Default threshold values — produced by parsing an empty object through
|
|
31
|
+
* `ThresholdsSchema`, which applies all schema-defined defaults.
|
|
32
|
+
*/
|
|
33
|
+
export const DEFAULT_THRESHOLDS = ThresholdsSchema.parse({});
|
|
34
|
+
|
|
21
35
|
/**
|
|
22
36
|
* Merges analysis results, preserving existing reasons and combining suspectedUnused flags.
|
|
23
37
|
*/
|