NimbusKart assignment project for detecting and cleaning cloud waste using LocalStack, Terraform, and a Python janitor CLI.
.
├── .github
│ └── workflows
│ └── cost-janitor.yml # CI: LocalStack + Terraform + dry-run report
├── .gitignore
├── DESIGN.md # Part C design note
├── README.md
├── nimbuskart-janitor # Part B: janitor CLI
│ ├── README.md
│ ├── janitor.py
│ ├── main.py
│ ├── pyproject.toml
│ ├── report.json
│ ├── requirements.txt
│ ├── summary.md
│ └── uv.lock
└── terraform # Part A: IaC for baseline AWS resources
├── Modules
│ └── Network
│ ├── main.tf
│ ├── output.tf
│ └── variables.tf
├── main.tf
├── outputs.tf
└── variables.tf
6 directories, 25 files
- VPC (
10.20.0.0/16) with two public subnets and internet routing. - Security group allowing 80/443 and configurable SSH CIDR.
- Two
t3.microEC2 instances (web tier tags). - S3 logs bucket with versioning.
- One unattached EBS volume for janitor detection testing.
LocalStack (4566)
^
| tflocal apply
|
Terraform root stack ---> Network module (VPC/Subnets/SG)
|
+--> EC2 instances
+--> S3 logs bucket
`--> Unattached EBS
janitor.py --dry-run/--delete ---> EC2 APIs (instances/volumes/addresses)
---> report.json + summary.md
- Docker
- Python
3.14+(source of truth:nimbuskart-janitor/pyproject.toml) - Terraform
1.5+ terraform-local(tflocal)
- Start LocalStack:
docker run --rm -it -p 4566:4566 localstack/localstack- Export LocalStack AWS environment variables:
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_DEFAULT_REGION=us-east-1
export AWS_ENDPOINT_URL=http://localhost:4566- Install tools:
pip install terraform-local
pip install -r nimbuskart-janitor/requirements.txt- Apply Terraform baseline (same pattern used by CI):
tflocal -chdir=terraform init
tflocal -chdir=terraform validate
tflocal -chdir=terraform apply -auto-approve -var="enable_s3_lifecycle=false"- Run janitor dry-run:
python nimbuskart-janitor/janitor.py --dry-run --summary- Optional delete mode:
python nimbuskart-janitor/janitor.py --delete- Detects:
- unattached EBS volumes (
available) - stopped EC2 instances older than
--days(default14) - unassociated Elastic IPs
- unattached EBS volumes (
- Deletion safety: resources tagged
Protected=trueare skipped. - Outputs are always written to repo root:
report.jsonsummary.md
Workflow: .github/workflows/cost-janitor.yml
Execution order:
- Start LocalStack service container.
tflocal fmt -check -difftflocal inittflocal validatetflocal apply -auto-approve -var="enable_s3_lifecycle=false"python nimbuskart-janitor/janitor.py --dry-run- Upload
report.jsonandsummary.mdartifacts. - Post
summary.mdas PR comment.
- LocalStack-first provider wiring: Terraform provider endpoints in
terraform/main.tfare hardcoded tohttp://localhost:4566with test credentials to guarantee local reproducibility. - S3 lifecycle disabled in CI apply: CI passes
-var="enable_s3_lifecycle=false"due to LocalStack lifecycle compatibility issues; Terraform still supports enabling it. - CLI flag behavior differs from assignment wording: assignment says dry-run default, but implementation currently requires explicit
--dry-runor--deleteand exits otherwise. - Python runtime bumped to 3.14:
pyproject.tomland CI use3.14, which is stricter than assignment's 3.10+ guidance. - Single-file janitor implementation:
nimbuskart-janitor/janitor.pyintentionally keeps scanning, filtering, reporting, and delete logic together for assignment speed;DESIGN.mddefines the modular multi-cloud path.
- Fast delivery vs modularity: single-file janitor is quicker to reason about for this assignment, but less extensible than an adapter-based design.
- Reproducibility vs production realism: hardcoded LocalStack endpoints simplify setup but make current Terraform unsafe for direct real-AWS use without edits.
- Safety vs aggressive cleanup:
Protected=truechecks and explicit delete mode reduce outage risk but may leave some waste uncleaned. - CI stability vs feature completeness: disabling S3 lifecycle in CI avoids flaky failures in emulation at the cost of not continuously validating lifecycle behavior.
tflocal -chdir=terraform fmt -check -diff
tflocal -chdir=terraform validate
python nimbuskart-janitor/janitor.py --dry-run --summary