cloudfit-provider-gcp
GCP Compute Engine provider plugin for cloudfit-core.
Fetches machine types, availability, and on-demand, spot, and 1-year committed-use pricing from the GCP Compute Engine and Cloud Billing Catalog APIs, and normalizes them into MachineType objects that cloudfit-core understands, including each family's perf_factor and each GPU's gpu_type.
Installation
pip install cloudfit-provider-gcp
Requires Python 3.10 or newer (CI tests 3.10 through 3.14) and cloudfit-core>=0.8.2.
Authentication
Uses Application Default Credentials. Set up once with:
gcloud auth application-default login
Or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to a service account key path. In production (Cloud Run, GKE), credentials are picked up automatically from the instance metadata server: no configuration needed.
Quick start
from cloudfit_provider_gcp import GCPProvider
from cloudfit import rank, WorkloadProfile
# initialize: no credentials needed if ADC is configured
provider = GCPProvider(project_id="your-gcp-project")
# fetch all machine types for a region
instances = provider.fetch_instances(region="us-central1")
print(f"fetched {len(instances)} machine types")
# plug directly into cloudfit-core
profile = WorkloadProfile(
vcpu=60,
ram_gb=224,
workload="io-intensive",
archetype="io",
optimize_for="balanced",
)
results = rank(profile, instances)
for r in results[:3]:
print(f"{r.instance.id:35s} score={r.score:.2f} ${r.instance.price_hr:.2f}/hr")
Fetching multiple regions
from cloudfit_provider_gcp import GCPProvider
provider = GCPProvider(project_id="your-gcp-project")
regions = ["us-central1", "us-east1", "europe-west1", "asia-east1"]
all_instances = []
for region in regions:
all_instances.extend(provider.fetch_instances(region=region))
print(f"total: {len(all_instances)} machine types across {len(regions)} regions")
Examples
Runnable scripts are in examples/:
| Script | Needs GCP credentials? | What it shows |
|---|---|---|
recommend.py |
yes (ADC) | live GCPProvider.fetch_instances() → cloudfit.rank() |
recommend_offline.py |
no | recorded fixture → normalize_machine_type() → cloudfit.rank() |
Try the offline one first: it runs anywhere, no GCP account required:
python examples/recommend_offline.py
Ranking for 32 vCPU / 120 GB (optimize_for=balanced):
ok n2-standard-32 score=1.00 $ 1.53/hr [active]
ok c3d-standard-60-lssd score=0.62 $ 2.87/hr [active]
ok c2-standard-60 score=0.59 $ 2.82/hr [active]
-- a2-highgpu-1g $ 0.73/hr [active] ✗ RAM 85 GB < required 120 GB
-- n1-standard-8 $ 0.37/hr [deprecated] ✗ RAM 30 GB < required 120 GB
-- f1-micro $ 0.03/hr [tombstoned] ✗ RAM 1 GB < required 120 GB
Pricing
Pricing is fetched from the GCP Cloud Billing Catalog API, using each SKU's structured category (usage type, resource group, service regions) rather than parsing descriptions. fetch_instances fills three prices per machine type, each reconstructed from the family's per-vCPU and per-GB rates for the region:
| Field | Source SKUs |
|---|---|
price_hr |
on-demand |
spot_price_hr |
spot (preemptible) |
cud_1yr_price_hr |
1-year committed use |
cloudfit-core scores whichever one the workload's pricing_mode selects. If a family's SKUs can't be matched, that price is left unset: price_hr falls back to 0.0 (the instance is still scored, with cost_score 0), and a missing spot or committed-use price falls back to on-demand at scoring time.
Limitation: the reconstruction covers CPU and RAM only. Accelerator cost is not added, so GPU machine types are under-priced by it; supply a known price_hr for GPU instances (the bundled snapshots do).
price_hr = provider.get_pricing("n2-standard-32", region="us-central1") # on-demand
# → about 1.55
Scheduled refresh
Bundled snapshots (weekly, automated)
cloudfit-api and cloudfit-ui ship a curated 875-instance GCP snapshot (alongside the AWS one from cloudfit-provider-aws). The refresh-snapshot workflow in this repo runs every Monday at 06:00 UTC: it refreshes on-demand, spot, and committed-use prices in both snapshots in place with examples/refresh_prices.py (row set, regions, and statuses are preserved; GPU prices are left as is) and opens a pull request in each repo. The run fails instead of opening a PR if any region's prices can't be fetched. It authenticates to GCP with Workload Identity Federation (no stored keys) and needs the SNAPSHOT_TOKEN, GCP_WORKLOAD_IDENTITY_PROVIDER, and GCP_SERVICE_ACCOUNT secrets; see the comments in the workflow file.
To refresh locally (needs gcloud auth application-default login):
make refresh-snapshot # refreshes ../cloudfit-api and ../cloudfit-ui snapshots in place
To build a brand-new snapshot from a live fetch instead, use examples/generate_snapshot.py.
Registry (PostgreSQL)
For a live registry, run the fetcher on a schedule and write results to the cloudfit registry store (PostgreSQL). The recommended pattern is a Cloud Scheduler trigger invoking a Cloud Run Job.
from cloudfit_provider_gcp import GCPProvider
from cloudfit_provider_gcp.registry import write_to_registry
provider = GCPProvider(project_id="your-gcp-project")
instances = provider.fetch_instances_all_regions()
write_to_registry(instances, database_url=os.environ["DATABASE_URL"])
Deprecation handling
When GCP marks a machine type as deprecated, the provider sets status="deprecated" on the MachineType. When a type is fully removed, it becomes status="tombstoned": it is never deleted from the registry, so existing configs can warn instead of silently breaking.
Repository structure
cloudfit-provider-gcp/
├── README.md
├── CHANGELOG.md # release notes; GitHub Releases are built from it
├── CONTRIBUTING.md
├── CITATION.cff
├── pyproject.toml
├── Makefile # version bump, tag, test, lint, build
├── LICENSE
├── .gitignore
├── .github/
│ ├── dependabot.yml # monthly GitHub Actions updates
│ └── workflows/
│ ├── ci.yml # lint, mypy --strict, tests; PyPI publish and release on tags
│ └── refresh-snapshot.yml # weekly price refresh PRs to cloudfit-api and cloudfit-ui
│
├── cloudfit_provider_gcp/
│ ├── __init__.py # exports GCPProvider
│ ├── provider.py # GCPProvider: implements Provider base class
│ ├── normalizer.py # raw GCP API response → MachineType
│ ├── pricing.py # Cloud Billing Catalog API → on-demand, spot, CUD prices
│ ├── regions.py # GCP region list + helpers
│ └── registry.py # write normalized instances to PostgreSQL
│
├── examples/
│ ├── recommend.py # live fetch → rank (needs GCP credentials)
│ ├── recommend_offline.py # fixture → rank (no credentials needed)
│ ├── generate_snapshot.py # build a fresh snapshot from a live fetch
│ └── refresh_prices.py # refresh prices in existing snapshots in place
│
└── tests/
├── test_normalizer.py # unit tests: no API calls needed
├── test_pricing.py # SKU parsing and price reconstruction
├── test_regions.py
├── test_registry.py
└── fixtures/
└── machine_type_response.json # recorded GCP API response
Related projects
cloudfit-core: scoring enginecloudfit-provider-aws: AWS EC2 provider (public price list, no credentials)cloudfit-api: REST API over the scoring engine (live demo)cloudfit-ui: Gradio UI over the scoring engine (live demo)samplesheet-parser: Illumina SampleSheet parser
License
Apache 2.0: see LICENSE.
Author: Chaitanya Krishna Kasaraneni · Google Scholar · ORCID 0000-0001-5792-1095
Metadata
Release files for cloudfit-provider-gcp 0.3.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| cloudfit_provider_gcp-0.3.4.tar.gz | 34.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cloudfit_provider_gcp-0.3.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.0 kB
Release files / cloudfit_provider_gcp-0.3.4.tar.gz
| Download URL | cloudfit_provider_gcp-0.3.4.tar.gz |
|---|---|
| Size | 34.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e13eb35a59fce2387f6118bc218f6ea34ff1bc54ffb07e112141302297f8e07c
|
|
BLAKE2b-256 checksum How to use checksums |
d8233d6b48211728273ee9315fa06a1b8b7121bdeff2f3b818df111f8efaa024
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logRelease files / cloudfit_provider_gcp-0.3.4-py3-none-any.whl
| Download URL | cloudfit_provider_gcp-0.3.4-py3-none-any.whl |
|---|---|
| Size | 20.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9b86db5bab10264347ec7632f621069f2563234e4a0e7536da86b3d78801a349
|
|
BLAKE2b-256 checksum How to use checksums |
c3d393b23c258a638fe58279357109e5fbc120a568abcd3b9e959deaca1faca6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logSecurity for cloudfit-provider-gcp 0.3.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for cloudfit_provider_gcp-0.3.4.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.