The Philosophical Developer — Chapter 19: GCP on the Local Cloud
2026-07-10 · 4 min read

GCP on the Local Cloud
The AWS local cloud proved the concept. Seven modules, each with plan-mode tests, validated by a Dagger pipeline, running against a local Floci emulator. The pillars held. The pattern worked.
But one cloud is a proof. Two clouds are a pattern. Three clouds are a methodology.
This chapter takes everything we built for AWS and applies it to Google Cloud Platform using floci-gcp. The same discipline. The same structure. The same tests. Different provider, different services, different endpoints. The methodology does not change.
Why GCP First
GCP and AWS share the same paradigm. Regional resources, IAM policies, managed services with API-driven lifecycles. The OpenTofu Google provider mirrors the AWS provider in structure: resource blocks with familiar arguments, outputs for referencing, and a provider configuration that supports custom endpoints.
The difference is the endpoint mechanism. Where AWS uses a flat endpoints block, GCP uses per-service *_custom_endpoint attributes. The Google provider maps each GCP service to its own endpoint URL, which means you configure each one individually.
provider "google" {
project = "floci-local"
region = "us-central1"
pubsub_custom_endpoint = "http://localhost:4588/v1/"
storage_custom_endpoint = "http://localhost:4588/storage/v1/"
secret_manager_custom_endpoint = "http://localhost:4588/v1/"
firestore_custom_endpoint = "http://localhost:4588/v1/"
}
Every request hits localhost:4588. Floci-gcp handles all 17 GCP services on a single port.
The Modules
Five modules, matching the GCP services that floci-gcp supports and that mirror the AWS equivalents.
Cloud Storage (GCS)
The GCS module creates a storage bucket with versioning enabled. It mirrors the S3 module from Chapter 14 exactly: same variable structure, same outputs, same TDD pattern.
resource "google_storage_bucket" "this" {
name = var.bucket_name
location = var.location
force_destroy = true
versioning {
enabled = true
}
}
Pub/Sub
GCP’s managed messaging service, equivalent to AWS SNS/SQS. The module creates a topic with a single default subscription. The test asserts the topic name follows convention and the subscription is attached.
Cloud IAM
Service accounts with key generation. The GCP IAM module mirrors the AWS IAM module in purpose: proving you can define principals and credentials through code.
Secret Manager
GCP’s equivalent of AWS Secrets Manager. Stores sensitive values with versioning. The module tests validate naming, replication policy, and output shape.
Firestore
A NoSQL document database, analogous to DynamoDB. The module configures the Firestore database in native mode. The test checks the database name and location type.
The Pipeline
The Dagger pipeline follows the same four stages as the AWS version:
- fmt-check – validates OpenTofu formatting
- validate-modules – initialises and validates each module
- test-modules – runs plan-mode tests for every module
- integration-plan – generates a combined plan for the local environment
The pipeline code is identical in structure. Only the provider names and module paths differ. This is the point: the pipeline is not tied to AWS. It is tied to the discipline of validating infrastructure before applying it.
Plan Mode Tests
Every module test runs with command = plan. No resources are created. No Floci instance is needed. The tests validate:
- Naming conventions – the bucket name, topic name, and secret ID follow the
-local-cloudsuffix pattern - Output contracts – every module exposes the expected outputs with the right types
- Provider schemas – the resource blocks are valid against the Google provider schema
run "default_bucket" {
command = plan
module {
source = "./."
}
assert {
condition = output.bucket_name == "gcp-local-cloud-artifacts"
error_message = "Bucket name should use gcp prefix"
}
assert {
condition = output.versioning_enabled == true
error_message = "Versioning should be enabled"
}
}
The Result
Five modules, all passing. The integration plan shows the full environment structure without touching a live API. The Dagger pipeline runs in 60 seconds.
The pattern ported cleanly because it was never about AWS. It was about:
- Reproducible – the same code produces the same plan every time
- Traceable – every change is in git, validated by the pipeline
- Testable – plan-mode tests verify contracts before any API call
- Safe – nothing applies without human review
What This Means
A methodology that only works on one cloud is not a methodology. It is a configuration. The local cloud approach works on GCP because it was designed to work on infrastructure in general. The cloud provider is a parameter. The discipline is the constant.
Repos: github.com/dark5un/local-cloud-gcp
Also on LinkedIn.
Here I geek out with my young Padawan, OrsonRius.