aws-inventory-manager 0.2.0__tar.gz → 0.3.0__tar.gz

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.

Potentially problematic release.


This version of aws-inventory-manager might be problematic. Click here for more details.

Files changed (79) hide show
  1. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/CLAUDE.md +3 -0
  2. {aws_inventory_manager-0.2.0/aws_inventory_manager.egg-info → aws_inventory_manager-0.3.0}/PKG-INFO +31 -5
  3. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/README.md +30 -4
  4. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0/aws_inventory_manager.egg-info}/PKG-INFO +31 -5
  5. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/aws_inventory_manager.egg-info/SOURCES.txt +4 -0
  6. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/pyproject.toml +1 -1
  7. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/cli/main.py +273 -0
  8. aws_inventory_manager-0.3.0/src/models/report.py +276 -0
  9. aws_inventory_manager-0.3.0/src/snapshot/report_formatter.py +250 -0
  10. aws_inventory_manager-0.3.0/src/snapshot/reporter.py +189 -0
  11. aws_inventory_manager-0.3.0/src/utils/export.py +305 -0
  12. aws_inventory_manager-0.3.0/src/utils/pagination.py +41 -0
  13. aws_inventory_manager-0.2.0/src/utils/export.py +0 -87
  14. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/LICENSE +0 -0
  15. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/MANIFEST.in +0 -0
  16. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/TESTING.md +0 -0
  17. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/aws_inventory_manager.egg-info/dependency_links.txt +0 -0
  18. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/aws_inventory_manager.egg-info/entry_points.txt +0 -0
  19. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/aws_inventory_manager.egg-info/requires.txt +0 -0
  20. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/aws_inventory_manager.egg-info/top_level.txt +0 -0
  21. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/requirements.txt +0 -0
  22. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/setup.cfg +0 -0
  23. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/__init__.py +0 -0
  24. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/aws/__init__.py +0 -0
  25. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/aws/client.py +0 -0
  26. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/aws/credentials.py +0 -0
  27. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/aws/rate_limiter.py +0 -0
  28. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/cli/__init__.py +0 -0
  29. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/cli/config.py +0 -0
  30. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/cost/__init__.py +0 -0
  31. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/cost/analyzer.py +0 -0
  32. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/cost/explorer.py +0 -0
  33. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/cost/reporter.py +0 -0
  34. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/delta/__init__.py +0 -0
  35. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/delta/calculator.py +0 -0
  36. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/delta/reporter.py +0 -0
  37. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/models/__init__.py +0 -0
  38. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/models/cost_report.py +0 -0
  39. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/models/delta_report.py +0 -0
  40. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/models/inventory.py +0 -0
  41. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/models/resource.py +0 -0
  42. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/models/snapshot.py +0 -0
  43. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/__init__.py +0 -0
  44. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/capturer.py +0 -0
  45. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/filter.py +0 -0
  46. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/inventory_storage.py +0 -0
  47. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/__init__.py +0 -0
  48. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/apigateway.py +0 -0
  49. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/backup.py +0 -0
  50. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/base.py +0 -0
  51. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/cloudformation.py +0 -0
  52. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/cloudwatch.py +0 -0
  53. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/codebuild.py +0 -0
  54. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/codepipeline.py +0 -0
  55. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/dynamodb.py +0 -0
  56. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/ec2.py +0 -0
  57. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/ecs.py +0 -0
  58. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/eks.py +0 -0
  59. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/elb.py +0 -0
  60. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/eventbridge.py +0 -0
  61. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/iam.py +0 -0
  62. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/kms.py +0 -0
  63. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/lambda_func.py +0 -0
  64. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/rds.py +0 -0
  65. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/route53.py +0 -0
  66. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/s3.py +0 -0
  67. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/secretsmanager.py +0 -0
  68. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/sns.py +0 -0
  69. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/sqs.py +0 -0
  70. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/ssm.py +0 -0
  71. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/stepfunctions.py +0 -0
  72. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/vpcendpoints.py +0 -0
  73. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/resource_collectors/waf.py +0 -0
  74. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/snapshot/storage.py +0 -0
  75. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/utils/__init__.py +0 -0
  76. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/utils/hash.py +0 -0
  77. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/utils/logging.py +0 -0
  78. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/utils/paths.py +0 -0
  79. {aws_inventory_manager-0.2.0 → aws_inventory_manager-0.3.0}/src/utils/progress.py +0 -0
@@ -5,6 +5,8 @@ Auto-generated from all feature plans. Last updated: 2025-10-26
5
5
  ## Active Technologies
6
6
  - Python 3.8+ (supports 3.8-3.13 per pyproject.toml) + boto3 (AWS SDK), typer (CLI), rich (terminal UI), pyyaml (storage), python-dateutil (timestamps) (002-inventory-management)
7
7
  - Local filesystem YAML files (.snapshots/inventories.yaml, .snapshots/snapshots/*.yaml) (002-inventory-management)
8
+ - Python 3.8+ (project requires >=3.8, testing on 3.8-3.13) + Typer 0.9+, Rich 13.0+, PyYAML 6.0+, boto3 1.28+ (003-snapshot-resource-report)
9
+ - YAML files in ~/.snapshots (configurable via AWS_INVENTORY_STORAGE_PATH) (003-snapshot-resource-report)
8
10
 
9
11
  - Python 3.8+ (supports 3.8-3.13 based on project standards) (001-aws-baseline-snapshot)
10
12
 
@@ -24,6 +26,7 @@ cd src [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES][ONLY COMMANDS FOR ACTIVE TECHNOLO
24
26
  Python 3.8+ (supports 3.8-3.13 based on project standards): Follow standard conventions
25
27
 
26
28
  ## Recent Changes
29
+ - 003-snapshot-resource-report: Added Python 3.8+ (project requires >=3.8, testing on 3.8-3.13) + Typer 0.9+, Rich 13.0+, PyYAML 6.0+, boto3 1.28+
27
30
  - 002-inventory-management: Added Python 3.8+ (supports 3.8-3.13 per pyproject.toml) + boto3 (AWS SDK), typer (CLI), rich (terminal UI), pyyaml (storage), python-dateutil (timestamps)
28
31
 
29
32
  - 001-aws-baseline-snapshot: Added Python 3.8+ (supports 3.8-3.13 based on project standards)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aws-inventory-manager
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: AWS Resource Inventory Management & Delta Tracking CLI tool
5
5
  Author-email: Troy Larson <troy@calvinware.com>
6
6
  License: MIT
@@ -63,6 +63,7 @@ A Python CLI tool that captures point-in-time snapshots of AWS resources organiz
63
63
 
64
64
  - **📦 Inventory Management**: Organize snapshots into named inventories with optional tag-based filters
65
65
  - **📸 Resource Snapshots**: Capture complete inventory of AWS resources across multiple regions
66
+ - **📋 Snapshot Reporting**: Generate comprehensive reports with filtering, detailed views, and export to JSON/CSV/TXT
66
67
  - **🔄 Delta Tracking**: Identify resources added, modified, or removed since a snapshot
67
68
  - **💰 Cost Analysis**: Analyze costs for resources within a specific inventory
68
69
  - **🔧 Resource Restoration**: Remove resources added since a snapshot to return to that state
@@ -109,13 +110,28 @@ This captures all resources in `us-east-1` and stores them in the `prod-baseline
109
110
  - Deploy new resources, update configurations, etc.
110
111
  - Then take another snapshot to track what changed
111
112
 
112
- **4. Compare snapshots** (see what changed)
113
+ **4. View snapshot report** (see what's in your snapshot)
114
+ ```bash
115
+ # Summary view with resource counts by service, region, and type
116
+ awsinv snapshot report --inventory prod-baseline
117
+
118
+ # Detailed view showing all resources with tags and metadata
119
+ awsinv snapshot report --inventory prod-baseline --detailed
120
+
121
+ # Filter by resource type
122
+ awsinv snapshot report --inventory prod-baseline --resource-type ec2
123
+
124
+ # Export to JSON, CSV, or TXT
125
+ awsinv snapshot report --inventory prod-baseline --export report.json
126
+ ```
127
+
128
+ **5. Compare snapshots** (see what changed)
113
129
  ```bash
114
130
  awsinv delta --snapshot initial --inventory prod-baseline
115
131
  ```
116
132
  This shows all resources added, removed, or modified since the `initial` snapshot.
117
133
 
118
- **5. Analyze costs**
134
+ **6. Analyze costs**
119
135
  ```bash
120
136
  # Costs since snapshot was created
121
137
  awsinv cost --snapshot initial --inventory prod-baseline
@@ -125,7 +141,7 @@ awsinv cost --snapshot initial --inventory prod-baseline \
125
141
  --start-date 2025-01-01 --end-date 2025-01-31
126
142
  ```
127
143
 
128
- **6. List your resources**
144
+ **7. List your resources**
129
145
  ```bash
130
146
  # List all inventories
131
147
  awsinv inventory list
@@ -456,6 +472,16 @@ awsinv snapshot create [name] \
456
472
  [--compress] \
457
473
  [--profile <aws-profile>]
458
474
 
475
+ # Generate snapshot report
476
+ awsinv snapshot report [snapshot-name] \
477
+ [--inventory <inventory-name>] \
478
+ [--resource-type <type>] \
479
+ [--region <region>] \
480
+ [--detailed] \
481
+ [--page-size <number>] \
482
+ [--export <file.json|file.csv|file.txt>] \
483
+ [--profile <aws-profile>]
484
+
459
485
  # List all snapshots
460
486
  awsinv snapshot list [--profile <aws-profile>]
461
487
 
@@ -503,6 +529,6 @@ MIT License - see LICENSE file for details
503
529
 
504
530
  ---
505
531
 
506
- **Version**: 0.2.0
532
+ **Version**: 0.3.0
507
533
  **Status**: Alpha
508
534
  **Python**: 3.8 - 3.13
@@ -20,6 +20,7 @@ A Python CLI tool that captures point-in-time snapshots of AWS resources organiz
20
20
 
21
21
  - **📦 Inventory Management**: Organize snapshots into named inventories with optional tag-based filters
22
22
  - **📸 Resource Snapshots**: Capture complete inventory of AWS resources across multiple regions
23
+ - **📋 Snapshot Reporting**: Generate comprehensive reports with filtering, detailed views, and export to JSON/CSV/TXT
23
24
  - **🔄 Delta Tracking**: Identify resources added, modified, or removed since a snapshot
24
25
  - **💰 Cost Analysis**: Analyze costs for resources within a specific inventory
25
26
  - **🔧 Resource Restoration**: Remove resources added since a snapshot to return to that state
@@ -66,13 +67,28 @@ This captures all resources in `us-east-1` and stores them in the `prod-baseline
66
67
  - Deploy new resources, update configurations, etc.
67
68
  - Then take another snapshot to track what changed
68
69
 
69
- **4. Compare snapshots** (see what changed)
70
+ **4. View snapshot report** (see what's in your snapshot)
71
+ ```bash
72
+ # Summary view with resource counts by service, region, and type
73
+ awsinv snapshot report --inventory prod-baseline
74
+
75
+ # Detailed view showing all resources with tags and metadata
76
+ awsinv snapshot report --inventory prod-baseline --detailed
77
+
78
+ # Filter by resource type
79
+ awsinv snapshot report --inventory prod-baseline --resource-type ec2
80
+
81
+ # Export to JSON, CSV, or TXT
82
+ awsinv snapshot report --inventory prod-baseline --export report.json
83
+ ```
84
+
85
+ **5. Compare snapshots** (see what changed)
70
86
  ```bash
71
87
  awsinv delta --snapshot initial --inventory prod-baseline
72
88
  ```
73
89
  This shows all resources added, removed, or modified since the `initial` snapshot.
74
90
 
75
- **5. Analyze costs**
91
+ **6. Analyze costs**
76
92
  ```bash
77
93
  # Costs since snapshot was created
78
94
  awsinv cost --snapshot initial --inventory prod-baseline
@@ -82,7 +98,7 @@ awsinv cost --snapshot initial --inventory prod-baseline \
82
98
  --start-date 2025-01-01 --end-date 2025-01-31
83
99
  ```
84
100
 
85
- **6. List your resources**
101
+ **7. List your resources**
86
102
  ```bash
87
103
  # List all inventories
88
104
  awsinv inventory list
@@ -413,6 +429,16 @@ awsinv snapshot create [name] \
413
429
  [--compress] \
414
430
  [--profile <aws-profile>]
415
431
 
432
+ # Generate snapshot report
433
+ awsinv snapshot report [snapshot-name] \
434
+ [--inventory <inventory-name>] \
435
+ [--resource-type <type>] \
436
+ [--region <region>] \
437
+ [--detailed] \
438
+ [--page-size <number>] \
439
+ [--export <file.json|file.csv|file.txt>] \
440
+ [--profile <aws-profile>]
441
+
416
442
  # List all snapshots
417
443
  awsinv snapshot list [--profile <aws-profile>]
418
444
 
@@ -460,6 +486,6 @@ MIT License - see LICENSE file for details
460
486
 
461
487
  ---
462
488
 
463
- **Version**: 0.2.0
489
+ **Version**: 0.3.0
464
490
  **Status**: Alpha
465
491
  **Python**: 3.8 - 3.13
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aws-inventory-manager
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: AWS Resource Inventory Management & Delta Tracking CLI tool
5
5
  Author-email: Troy Larson <troy@calvinware.com>
6
6
  License: MIT
@@ -63,6 +63,7 @@ A Python CLI tool that captures point-in-time snapshots of AWS resources organiz
63
63
 
64
64
  - **📦 Inventory Management**: Organize snapshots into named inventories with optional tag-based filters
65
65
  - **📸 Resource Snapshots**: Capture complete inventory of AWS resources across multiple regions
66
+ - **📋 Snapshot Reporting**: Generate comprehensive reports with filtering, detailed views, and export to JSON/CSV/TXT
66
67
  - **🔄 Delta Tracking**: Identify resources added, modified, or removed since a snapshot
67
68
  - **💰 Cost Analysis**: Analyze costs for resources within a specific inventory
68
69
  - **🔧 Resource Restoration**: Remove resources added since a snapshot to return to that state
@@ -109,13 +110,28 @@ This captures all resources in `us-east-1` and stores them in the `prod-baseline
109
110
  - Deploy new resources, update configurations, etc.
110
111
  - Then take another snapshot to track what changed
111
112
 
112
- **4. Compare snapshots** (see what changed)
113
+ **4. View snapshot report** (see what's in your snapshot)
114
+ ```bash
115
+ # Summary view with resource counts by service, region, and type
116
+ awsinv snapshot report --inventory prod-baseline
117
+
118
+ # Detailed view showing all resources with tags and metadata
119
+ awsinv snapshot report --inventory prod-baseline --detailed
120
+
121
+ # Filter by resource type
122
+ awsinv snapshot report --inventory prod-baseline --resource-type ec2
123
+
124
+ # Export to JSON, CSV, or TXT
125
+ awsinv snapshot report --inventory prod-baseline --export report.json
126
+ ```
127
+
128
+ **5. Compare snapshots** (see what changed)
113
129
  ```bash
114
130
  awsinv delta --snapshot initial --inventory prod-baseline
115
131
  ```
116
132
  This shows all resources added, removed, or modified since the `initial` snapshot.
117
133
 
118
- **5. Analyze costs**
134
+ **6. Analyze costs**
119
135
  ```bash
120
136
  # Costs since snapshot was created
121
137
  awsinv cost --snapshot initial --inventory prod-baseline
@@ -125,7 +141,7 @@ awsinv cost --snapshot initial --inventory prod-baseline \
125
141
  --start-date 2025-01-01 --end-date 2025-01-31
126
142
  ```
127
143
 
128
- **6. List your resources**
144
+ **7. List your resources**
129
145
  ```bash
130
146
  # List all inventories
131
147
  awsinv inventory list
@@ -456,6 +472,16 @@ awsinv snapshot create [name] \
456
472
  [--compress] \
457
473
  [--profile <aws-profile>]
458
474
 
475
+ # Generate snapshot report
476
+ awsinv snapshot report [snapshot-name] \
477
+ [--inventory <inventory-name>] \
478
+ [--resource-type <type>] \
479
+ [--region <region>] \
480
+ [--detailed] \
481
+ [--page-size <number>] \
482
+ [--export <file.json|file.csv|file.txt>] \
483
+ [--profile <aws-profile>]
484
+
459
485
  # List all snapshots
460
486
  awsinv snapshot list [--profile <aws-profile>]
461
487
 
@@ -503,6 +529,6 @@ MIT License - see LICENSE file for details
503
529
 
504
530
  ---
505
531
 
506
- **Version**: 0.2.0
532
+ **Version**: 0.3.0
507
533
  **Status**: Alpha
508
534
  **Python**: 3.8 - 3.13
@@ -30,12 +30,15 @@ src/models/__init__.py
30
30
  src/models/cost_report.py
31
31
  src/models/delta_report.py
32
32
  src/models/inventory.py
33
+ src/models/report.py
33
34
  src/models/resource.py
34
35
  src/models/snapshot.py
35
36
  src/snapshot/__init__.py
36
37
  src/snapshot/capturer.py
37
38
  src/snapshot/filter.py
38
39
  src/snapshot/inventory_storage.py
40
+ src/snapshot/report_formatter.py
41
+ src/snapshot/reporter.py
39
42
  src/snapshot/storage.py
40
43
  src/snapshot/resource_collectors/__init__.py
41
44
  src/snapshot/resource_collectors/apigateway.py
@@ -68,5 +71,6 @@ src/utils/__init__.py
68
71
  src/utils/export.py
69
72
  src/utils/hash.py
70
73
  src/utils/logging.py
74
+ src/utils/pagination.py
71
75
  src/utils/paths.py
72
76
  src/utils/progress.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aws-inventory-manager"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "AWS Resource Inventory Management & Delta Tracking CLI tool"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -1127,6 +1127,279 @@ def snapshot_delete(
1127
1127
  raise typer.Exit(code=1)
1128
1128
 
1129
1129
 
1130
+ @snapshot_app.command("report")
1131
+ def snapshot_report(
1132
+ snapshot_name: Optional[str] = typer.Argument(None, help="Snapshot name (default: active snapshot)"),
1133
+ inventory: Optional[str] = typer.Option(None, "--inventory", help="Inventory name (required if multiple exist)"),
1134
+ profile: Optional[str] = typer.Option(None, "--profile", help="AWS profile name"),
1135
+ storage_path: Optional[str] = typer.Option(None, "--storage-path", help="Override storage location"),
1136
+ resource_type: Optional[list[str]] = typer.Option(
1137
+ None, "--resource-type", help="Filter by resource type (can specify multiple)"
1138
+ ),
1139
+ region: Optional[list[str]] = typer.Option(None, "--region", help="Filter by region (can specify multiple)"),
1140
+ detailed: bool = typer.Option(
1141
+ False, "--detailed", help="Show detailed resource information (ARN, tags, creation date)"
1142
+ ),
1143
+ page_size: int = typer.Option(100, "--page-size", help="Resources per page in detailed view (default: 100)"),
1144
+ export: Optional[str] = typer.Option(
1145
+ None, "--export", help="Export report to file (format detected from extension: .json, .csv, .txt)"
1146
+ ),
1147
+ ):
1148
+ """Display resource summary report for a snapshot.
1149
+
1150
+ Shows aggregated resource counts by service, region, and type with
1151
+ visual progress bars and formatted output. Can export to JSON, CSV, or TXT formats.
1152
+
1153
+ Snapshot Selection (in order of precedence):
1154
+ 1. Explicit snapshot name argument
1155
+ 2. Most recent snapshot from specified --inventory
1156
+ 3. Active snapshot (set via 'awsinv snapshot set-active')
1157
+
1158
+ Examples:
1159
+ awsinv snapshot report # Report on active snapshot
1160
+ awsinv snapshot report baseline-2025-01 # Report on specific snapshot
1161
+ awsinv snapshot report --inventory prod # Most recent snapshot from 'prod' inventory
1162
+ awsinv snapshot report --resource-type ec2 # Filter by resource type
1163
+ awsinv snapshot report --region us-east-1 # Filter by region
1164
+ awsinv snapshot report --resource-type ec2 --resource-type lambda # Multiple filters
1165
+ awsinv snapshot report --export report.json # Export full report to JSON
1166
+ awsinv snapshot report --export resources.csv # Export resources to CSV
1167
+ awsinv snapshot report --export summary.txt # Export summary to TXT
1168
+ awsinv snapshot report --detailed --export details.json # Export detailed view
1169
+ """
1170
+ from ..models.report import FilterCriteria
1171
+ from ..snapshot.report_formatter import ReportFormatter
1172
+ from ..snapshot.reporter import SnapshotReporter
1173
+ from ..utils.export import detect_format, export_report_csv, export_report_json, export_report_txt
1174
+
1175
+ try:
1176
+ # Use provided storage path or default from config
1177
+ storage = SnapshotStorage(storage_path or config.storage_path)
1178
+
1179
+ # Determine which snapshot to load
1180
+ target_snapshot_name: str
1181
+ if snapshot_name:
1182
+ # Explicit snapshot name provided
1183
+ target_snapshot_name = snapshot_name
1184
+ elif inventory:
1185
+ # Inventory specified - find most recent snapshot from that inventory
1186
+ from datetime import datetime as dt
1187
+ from typing import TypedDict
1188
+
1189
+ class InventorySnapshot(TypedDict):
1190
+ name: str
1191
+ created_at: dt
1192
+
1193
+ all_snapshots = storage.list_snapshots()
1194
+ inventory_snapshots: list[InventorySnapshot] = []
1195
+
1196
+ for snap_meta in all_snapshots:
1197
+ try:
1198
+ snap = storage.load_snapshot(snap_meta["name"])
1199
+ if snap.inventory_name == inventory:
1200
+ inventory_snapshots.append(
1201
+ InventorySnapshot(
1202
+ name=snap.name,
1203
+ created_at=snap.created_at,
1204
+ )
1205
+ )
1206
+ except Exception:
1207
+ continue
1208
+
1209
+ if not inventory_snapshots:
1210
+ console.print(f"✗ No snapshots found for inventory '{inventory}'", style="bold red")
1211
+ console.print("\nCreate a snapshot first:")
1212
+ console.print(f" awsinv snapshot create --inventory {inventory}")
1213
+ raise typer.Exit(code=1)
1214
+
1215
+ # Sort by created_at and pick most recent
1216
+ inventory_snapshots.sort(key=lambda x: x["created_at"], reverse=True)
1217
+ target_snapshot_name = inventory_snapshots[0]["name"]
1218
+ console.print(
1219
+ f"ℹ Using most recent snapshot from inventory '{inventory}': {target_snapshot_name}", style="dim"
1220
+ )
1221
+ else:
1222
+ # Try to get active snapshot
1223
+ active_name = storage.get_active_snapshot_name()
1224
+ if not active_name:
1225
+ console.print("✗ No active snapshot found", style="bold red")
1226
+ console.print("\nSet an active snapshot with:")
1227
+ console.print(" awsinv snapshot set-active <name>")
1228
+ console.print("\nOr specify a snapshot explicitly:")
1229
+ console.print(" awsinv snapshot report <snapshot-name>")
1230
+ console.print("\nOr specify an inventory to use the most recent snapshot:")
1231
+ console.print(" awsinv snapshot report --inventory <inventory-name>")
1232
+ raise typer.Exit(code=1)
1233
+ target_snapshot_name = active_name
1234
+
1235
+ # Load the snapshot
1236
+ try:
1237
+ snapshot = storage.load_snapshot(target_snapshot_name)
1238
+ except FileNotFoundError:
1239
+ console.print(f"✗ Snapshot '{target_snapshot_name}' not found", style="bold red")
1240
+
1241
+ # Show available snapshots
1242
+ try:
1243
+ all_snapshots = storage.list_snapshots()
1244
+ if all_snapshots:
1245
+ console.print("\nAvailable snapshots:")
1246
+ for snap_name in all_snapshots[:5]:
1247
+ console.print(f" • {snap_name}")
1248
+ if len(all_snapshots) > 5:
1249
+ console.print(f" ... and {len(all_snapshots) - 5} more")
1250
+ console.print("\nRun 'awsinv snapshot list' to see all snapshots.")
1251
+ except Exception:
1252
+ pass
1253
+
1254
+ raise typer.Exit(code=1)
1255
+
1256
+ # Handle empty snapshot
1257
+ if snapshot.resource_count == 0:
1258
+ console.print(f"⚠️ Warning: Snapshot '{snapshot.name}' contains 0 resources", style="yellow")
1259
+ console.print("\nNo report to generate.")
1260
+ raise typer.Exit(code=0)
1261
+
1262
+ # Create filter criteria if filters provided
1263
+ has_filters = bool(resource_type or region)
1264
+ criteria = None
1265
+ if has_filters:
1266
+ criteria = FilterCriteria(
1267
+ resource_types=resource_type if resource_type else None,
1268
+ regions=region if region else None,
1269
+ )
1270
+
1271
+ # Generate report
1272
+ reporter = SnapshotReporter(snapshot)
1273
+ metadata = reporter._extract_metadata()
1274
+
1275
+ # Detailed view vs Summary view
1276
+ if detailed:
1277
+ # Get detailed resources (with optional filtering)
1278
+ detailed_resources = list(reporter.get_detailed_resources(criteria))
1279
+
1280
+ # Export mode
1281
+ if export:
1282
+ try:
1283
+ # Detect format from file extension
1284
+ export_format = detect_format(export)
1285
+
1286
+ # Export based on format
1287
+ if export_format == "json":
1288
+ # For JSON, export full report structure with detailed resources
1289
+ summary = (
1290
+ reporter.generate_filtered_summary(criteria) if criteria else reporter.generate_summary()
1291
+ )
1292
+ export_path = export_report_json(export, metadata, summary, detailed_resources)
1293
+ console.print(
1294
+ f"✓ Exported {len(detailed_resources):,} resources to JSON: {export_path}",
1295
+ style="bold green",
1296
+ )
1297
+ elif export_format == "csv":
1298
+ # For CSV, export detailed resources
1299
+ export_path = export_report_csv(export, detailed_resources)
1300
+ console.print(
1301
+ f"✓ Exported {len(detailed_resources):,} resources to CSV: {export_path}",
1302
+ style="bold green",
1303
+ )
1304
+ elif export_format == "txt":
1305
+ # For TXT, export summary (detailed view doesn't make sense for plain text)
1306
+ summary = (
1307
+ reporter.generate_filtered_summary(criteria) if criteria else reporter.generate_summary()
1308
+ )
1309
+ export_path = export_report_txt(export, metadata, summary)
1310
+ console.print(f"✓ Exported summary to TXT: {export_path}", style="bold green")
1311
+ except FileExistsError as e:
1312
+ console.print(f"✗ {e}", style="bold red")
1313
+ console.print("\nUse a different filename or delete the existing file.", style="yellow")
1314
+ raise typer.Exit(code=1)
1315
+ except FileNotFoundError as e:
1316
+ console.print(f"✗ {e}", style="bold red")
1317
+ raise typer.Exit(code=1)
1318
+ except ValueError as e:
1319
+ console.print(f"✗ {e}", style="bold red")
1320
+ raise typer.Exit(code=1)
1321
+ else:
1322
+ # Display mode - show filter information if applied
1323
+ if criteria:
1324
+ console.print("\n[bold cyan]Filters Applied:[/bold cyan]")
1325
+ if resource_type:
1326
+ console.print(f" • Resource Types: {', '.join(resource_type)}")
1327
+ if region:
1328
+ console.print(f" • Regions: {', '.join(region)}")
1329
+ console.print(
1330
+ f" • Matching Resources: {len(detailed_resources):,} (of {snapshot.resource_count:,} total)\n"
1331
+ )
1332
+
1333
+ # Format and display detailed view
1334
+ formatter = ReportFormatter(console)
1335
+ formatter.format_detailed(metadata, detailed_resources, page_size=page_size)
1336
+ else:
1337
+ # Generate summary (filtered or full)
1338
+ if criteria:
1339
+ summary = reporter.generate_filtered_summary(criteria)
1340
+ else:
1341
+ summary = reporter.generate_summary()
1342
+
1343
+ # Export mode
1344
+ if export:
1345
+ try:
1346
+ # Detect format from file extension
1347
+ export_format = detect_format(export)
1348
+
1349
+ # Export based on format
1350
+ if export_format == "json":
1351
+ # For JSON, export full report structure
1352
+ # Get all resources for complete export
1353
+ all_resources = list(reporter.get_detailed_resources(criteria))
1354
+ export_path = export_report_json(export, metadata, summary, all_resources)
1355
+ console.print(
1356
+ f"✓ Exported {summary.total_count:,} resources to JSON: {export_path}", style="bold green"
1357
+ )
1358
+ elif export_format == "csv":
1359
+ # For CSV, export resources
1360
+ all_resources = list(reporter.get_detailed_resources(criteria))
1361
+ export_path = export_report_csv(export, all_resources)
1362
+ console.print(
1363
+ f"✓ Exported {len(all_resources):,} resources to CSV: {export_path}", style="bold green"
1364
+ )
1365
+ elif export_format == "txt":
1366
+ # For TXT, export summary only
1367
+ export_path = export_report_txt(export, metadata, summary)
1368
+ console.print(f"✓ Exported summary to TXT: {export_path}", style="bold green")
1369
+ except FileExistsError as e:
1370
+ console.print(f"✗ {e}", style="bold red")
1371
+ console.print("\nUse a different filename or delete the existing file.", style="yellow")
1372
+ raise typer.Exit(code=1)
1373
+ except FileNotFoundError as e:
1374
+ console.print(f"✗ {e}", style="bold red")
1375
+ raise typer.Exit(code=1)
1376
+ except ValueError as e:
1377
+ console.print(f"✗ {e}", style="bold red")
1378
+ raise typer.Exit(code=1)
1379
+ else:
1380
+ # Display mode - show filter information
1381
+ if criteria:
1382
+ console.print("\n[bold cyan]Filters Applied:[/bold cyan]")
1383
+ if resource_type:
1384
+ console.print(f" • Resource Types: {', '.join(resource_type)}")
1385
+ if region:
1386
+ console.print(f" • Regions: {', '.join(region)}")
1387
+ console.print(
1388
+ f" • Matching Resources: {summary.total_count:,} (of {snapshot.resource_count:,} total)\n"
1389
+ )
1390
+
1391
+ # Format and display summary report
1392
+ formatter = ReportFormatter(console)
1393
+ formatter.format_summary(metadata, summary, has_filters=has_filters)
1394
+
1395
+ except typer.Exit:
1396
+ raise
1397
+ except Exception as e:
1398
+ console.print(f"✗ Error generating report: {e}", style="bold red")
1399
+ logger.exception("Error in snapshot report command")
1400
+ raise typer.Exit(code=2)
1401
+
1402
+
1130
1403
  @app.command()
1131
1404
  def delta(
1132
1405
  snapshot: Optional[str] = typer.Option(