Lightweight Python-based cost estimation for Terraform plans. This tool provides a CLI to estimate costs from Terraform plan JSON files or directories, using a mock pricing API for local development and CI..
- Features
- Quick Start
- Repository Layout
- CLI Usage
- Configuration
- Mock Pricing API
- Development
- GitHub Actions
- Troubleshooting
- Contributing
- License
- FAQ
- CLI Tool: Estimate costs from Terraform plan JSON or directories.
- Mock Pricing API: Run locally or in CI without external dependencies.
- GitHub Actions:
- Python CI: Linting, type checking, tests, and CLI smoke tests.
- PR Cost Diff: Comments cost differences on pull requests.
- Sample Terraform Projects: Examples under
examples/for testing.
Clone and set up the project:
git clone https://github.com/<your-username>/GCPy.git
cd GCPy
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" || pip install -r requirements.txtRun against a test plan with the mock API:
export PLANCOSTS_API_URL=http://127.0.0.1:4000
python -m plancosts.tests.mock_price & # Start mock API
python plancosts/main.py --tfjson plancosts/test_plan_ern.json -o table.
├── .github/workflows/ # GitHub Actions
│ ├── python.yml # Python CI: lint, typecheck, tests
│ └── plancosts-diff.yml # PR cost diff comment
├── examples/terraform_0_13/ # Sample Terraform project
│ ├── main.tf
│ ├── storage/main.tf
│ ├── web_app/main.tf
│ └── plan.json
├── plancosts/ # Python package
│ ├── main.py # CLI entry point
│ ├── config.py # API endpoint/env handling
│ ├── base/ output/ parsers/ providers/ # Core logic
│ └── tests/ # Tests and mock API
│ ├── mock_price.py # Mock pricing API (POST /graphql)
│ ├── test_*.py
│ └── test_plan.json
├── Makefile # Dev helpers: fmt, lint, test
├── pyproject.toml # Package metadata + extras
└── requirements.txt # Fallback dependencies
Run the CLI from the repo root after installing dependencies:
python plancosts/main.py --tfjson <plan.json> -o table
python plancosts/main.py --tfdir examples/terraform_0_13 -o table--tfjson PATH: Path to a Terraform plan JSON file.--tfdir DIR: Directory of Terraform files (auto-derives resources).-o table|json: Output format (table or JSON).
The CLI uses a GraphQL endpoint for pricing data, configured via environment variables (in precedence order):
PLAN_COSTS_PRICE_LIST_API_ENDPOINT: Legacy, accepts base URL or/graphql.PLANCOSTS_API_URL: Base URL (no/graphqlneeded).
Default: http://127.0.0.1:4000. The tool appends /graphql if needed.
Example:
export PLANCOSTS_API_URL=http://127.0.0.1:4000A minimal GraphQL server is included for local and CI use:
python -m plancosts.tests.mock_price & # Start in background
curl -X POST http://127.0.0.1:4000/graphql -d '{}' -H 'Content-Type: application/json'Note: Only POST /graphql is supported; GET / returns 501.
Install dev tools and run checks:
make deps # Install dev dependencies
make fmt # Format code (Black, isort)
make lint # Lint with Ruff
make typecheck # Type check with MyPy
make test # Run pytest
make check # Run all checks- Runs on Python 3.10, 3.11, 3.12.
- Installs dependencies (
pyproject.tomlorrequirements.txt). - Runs Black, isort, Ruff, MyPy (non-blocking), and pytest.
- Starts mock API and performs CLI smoke tests with
test_plan*.json. - Key env:
PLANCOSTS_API_URL=http://127.0.0.1:4000.
- Triggers on PRs modifying Terraform files, package, or workflow.
- Checks out base and PR branches to
base/andpr/. - Runs CLI on both branches (
--tfdir examples/terraform_0_13or fallback JSON). - Posts a PR comment with cost differences.
- Uses
POST /graphqlfor mock API readiness.
- ModuleNotFoundError: plancosts.*: Ensure
PYTHONPATHincludes repo root or usepip install -e .. - CI can't open
pr/main.py: Verify checkout paths; keepmain.pyat repo root. - Mock server readiness fails: Use
POST /graphqlfor health checks (GET /returns 501). - Totals are 0.00: Mock API uses placeholder prices. Use a real backend for accurate costs.
- Create a feature branch from
main. - Run
make checklocally. - Open a PR; workflows run automatically.
- Update
examples/ortests/if modifying parsers/providers.
MIT. See LICENSE file if present.
Why not use a custom GitHub Action?
Python-based workflows are simpler to maintain and debug without Docker.
Can I make MyPy block CI?
Edit python.yml to remove || true from the MyPy step.
Can I change the Terraform examples path?
Update TERRAFORM_DIR in plancosts-diff.yml and related docs/scripts.
