@pagopa/dx-cli 0.8.2 → 0.10.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 +58 -0
- package/bin/index.js +35 -17
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -71,6 +71,64 @@ Checking monorepo scripts...
|
|
|
71
71
|
✅ Monorepo scripts are correctly set up
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
#### `savemoney`
|
|
75
|
+
|
|
76
|
+
Analyze Azure subscriptions to identify unused or underutilized resources that could be costing you money.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
dx savemoney [options]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Options:**
|
|
83
|
+
|
|
84
|
+
| Option | Alias | Description | Default |
|
|
85
|
+
| :----------- | :---- | :-------------------------------------------------------------------- | :----------- |
|
|
86
|
+
| `--config` | `-c` | Path to a JSON configuration file. | N/A |
|
|
87
|
+
| `--format` | `-f` | Report format (`table`, `json`, `detailed-json`). | `table` |
|
|
88
|
+
| `--days` | `-d` | Metric analysis period in days. | `30` |
|
|
89
|
+
| `--location` | `-l` | Preferred Azure location for resources. | `italynorth` |
|
|
90
|
+
| `--verbose` | `-v` | Enable verbose mode with detailed logging for each resource analyzed. | `false` |
|
|
91
|
+
|
|
92
|
+
**Example usage:**
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Analyze with default settings (interactive prompts)
|
|
96
|
+
dx savemoney
|
|
97
|
+
|
|
98
|
+
# Use a configuration file
|
|
99
|
+
dx savemoney --config config.json
|
|
100
|
+
|
|
101
|
+
# Output as JSON with verbose logging
|
|
102
|
+
dx savemoney --format json --verbose
|
|
103
|
+
|
|
104
|
+
# Analyze with specific timespan
|
|
105
|
+
dx savemoney --days 60 --location italynorth
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Configuration file example (`config.json`):**
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"tenantId": "your-tenant-id",
|
|
113
|
+
"subscriptionIds": ["subscription-1", "subscription-2"],
|
|
114
|
+
"preferredLocation": "italynorth",
|
|
115
|
+
"timespanDays": 30
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Analyzed Azure resources:**
|
|
120
|
+
|
|
121
|
+
- **Virtual Machines**: Deallocated or stopped VMs, low CPU usage
|
|
122
|
+
- **Managed Disks**: Unattached disks
|
|
123
|
+
- **Network Interfaces**: Unattached NICs
|
|
124
|
+
- **Public IP Addresses**: Unassociated static IPs
|
|
125
|
+
- **Storage Accounts**: Low transaction counts
|
|
126
|
+
- **App Service Plans**: Empty plans or oversized tiers
|
|
127
|
+
- **Private Endpoints**: Unused or misconfigured endpoints
|
|
128
|
+
|
|
129
|
+
> [!NOTE]
|
|
130
|
+
> Currently only Azure is supported. Support for additional cloud providers (AWS) is planned for future releases.
|
|
131
|
+
|
|
74
132
|
### Global Options
|
|
75
133
|
|
|
76
134
|
- `--version, -V`: Display version number
|
package/bin/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import "core-js/actual/set/index.js";
|
|
5
|
-
import { configure, getConsoleSink, getLogger as
|
|
5
|
+
import { configure, getConsoleSink, getLogger as getLogger8 } from "@logtape/logtape";
|
|
6
6
|
|
|
7
7
|
// src/adapters/codemods/registry.ts
|
|
8
8
|
import { okAsync } from "neverthrow";
|
|
@@ -756,37 +756,54 @@ var makeInitCommand = () => new Command4().name("init").description(
|
|
|
756
756
|
})
|
|
757
757
|
);
|
|
758
758
|
|
|
759
|
-
// src/adapters/commander/commands/
|
|
759
|
+
// src/adapters/commander/commands/savemoney.ts
|
|
760
|
+
import { azure, loadConfig } from "@pagopa/dx-savemoney";
|
|
760
761
|
import { Command as Command5 } from "commander";
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
762
|
+
var makeSavemoneyCommand = () => new Command5("savemoney").description(
|
|
763
|
+
"Analyze Azure subscriptions and report unused or inefficient resources"
|
|
764
|
+
).option("-c, --config <path>", "Path to configuration file (JSON)").option(
|
|
765
|
+
"-f, --format <format>",
|
|
766
|
+
"Report format: json, table, or detailed-json (default: table)",
|
|
767
|
+
"table"
|
|
768
|
+
).option(
|
|
769
|
+
"-l, --location <string>",
|
|
770
|
+
"Preferred Azure location for resources",
|
|
771
|
+
"italynorth"
|
|
772
|
+
).option("-d, --days <number>", "Number of days for metrics analysis", "30").option("-v, --verbose", "Enable verbose logging").action(async function(options) {
|
|
773
|
+
try {
|
|
774
|
+
const config2 = await loadConfig(options.config);
|
|
775
|
+
const finalConfig = {
|
|
776
|
+
...config2,
|
|
777
|
+
preferredLocation: options.location || config2.preferredLocation,
|
|
778
|
+
timespanDays: Number.parseInt(options.days, 10) || config2.timespanDays,
|
|
779
|
+
verbose: options.verbose || false
|
|
780
|
+
};
|
|
781
|
+
await azure.analyzeAzureResources(finalConfig, options.format);
|
|
782
|
+
} catch (error) {
|
|
783
|
+
this.error(
|
|
784
|
+
`Analysis failed: ${error instanceof Error ? error.message : error}`
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
});
|
|
771
788
|
|
|
772
789
|
// src/adapters/commander/index.ts
|
|
773
790
|
var makeCli = (deps2, config2, cliDeps) => {
|
|
774
791
|
const program2 = new Command6();
|
|
775
|
-
program2.name("dx").description("The CLI for DX-Platform").version("0.
|
|
792
|
+
program2.name("dx").description("The CLI for DX-Platform").version("0.10.0");
|
|
776
793
|
program2.addCommand(makeDoctorCommand(deps2, config2));
|
|
777
794
|
program2.addCommand(makeCodemodCommand(cliDeps));
|
|
795
|
+
program2.addCommand(makeSavemoneyCommand());
|
|
778
796
|
if (process.env.ENABLE_INIT_COMMAND) {
|
|
779
797
|
program2.addCommand(makeInitCommand());
|
|
780
798
|
}
|
|
781
|
-
program2.addCommand(makeVersionCommand());
|
|
782
799
|
program2.addCommand(makeInfoCommand(deps2, config2));
|
|
783
800
|
return program2;
|
|
784
801
|
};
|
|
785
802
|
|
|
786
803
|
// src/adapters/logtape/validation-reporter.ts
|
|
787
|
-
import { getLogger as
|
|
804
|
+
import { getLogger as getLogger7 } from "@logtape/logtape";
|
|
788
805
|
var makeValidationReporter = () => {
|
|
789
|
-
const logger2 =
|
|
806
|
+
const logger2 = getLogger7(["dx-cli", "validation"]);
|
|
790
807
|
return {
|
|
791
808
|
reportCheckResult(result) {
|
|
792
809
|
if (result.isValid) {
|
|
@@ -962,6 +979,7 @@ var listCodemods = (registry2) => () => registry2.getAll();
|
|
|
962
979
|
await configure({
|
|
963
980
|
loggers: [
|
|
964
981
|
{ category: ["dx-cli"], lowestLevel: "info", sinks: ["console"] },
|
|
982
|
+
{ category: ["savemoney"], lowestLevel: "debug", sinks: ["console"] },
|
|
965
983
|
{ category: ["json"], lowestLevel: "info", sinks: ["rawJson"] },
|
|
966
984
|
{
|
|
967
985
|
category: ["logtape", "meta"],
|
|
@@ -976,7 +994,7 @@ await configure({
|
|
|
976
994
|
}
|
|
977
995
|
}
|
|
978
996
|
});
|
|
979
|
-
var logger =
|
|
997
|
+
var logger = getLogger8(["dx-cli"]);
|
|
980
998
|
var repositoryReader = makeRepositoryReader();
|
|
981
999
|
var packageJsonReader = makePackageJsonReader();
|
|
982
1000
|
var validationReporter = makeValidationReporter();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/dx-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A CLI useful to manage DX tools.",
|
|
6
6
|
"repository": {
|
|
@@ -31,21 +31,22 @@
|
|
|
31
31
|
"semver": "^7.7.2",
|
|
32
32
|
"yaml": "^2.8.0",
|
|
33
33
|
"zod": "^3.25.28",
|
|
34
|
-
"@pagopa/monorepo-generator": "^0.8.
|
|
34
|
+
"@pagopa/monorepo-generator": "^0.8.3",
|
|
35
|
+
"@pagopa/dx-savemoney": "^0.1.1"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@tsconfig/node22": "22.0.2",
|
|
38
|
-
"@types/node": "^22.
|
|
39
|
+
"@types/node": "^22.19.1",
|
|
39
40
|
"@types/semver": "^7.7.1",
|
|
40
41
|
"@vitest/coverage-v8": "^3.2.4",
|
|
41
|
-
"eslint": "^9.
|
|
42
|
+
"eslint": "^9.39.1",
|
|
42
43
|
"memfs": "^4.23.0",
|
|
43
44
|
"prettier": "3.6.2",
|
|
44
45
|
"tsup": "^8.5.0",
|
|
45
46
|
"typescript": "~5.8.3",
|
|
46
47
|
"vitest": "^3.2.4",
|
|
47
48
|
"vitest-mock-extended": "^3.1.0",
|
|
48
|
-
"@pagopa/eslint-config": "^5.1.
|
|
49
|
+
"@pagopa/eslint-config": "^5.1.1"
|
|
49
50
|
},
|
|
50
51
|
"engines": {
|
|
51
52
|
"node": ">=22.0.0"
|