Service Usage
floci-gcp emulates the Service Usage API (serviceusage.googleapis.com v1) over REST JSON —
the API that enables and lists a project's GCP services. It is the first thing most IaC
tooling touches: Terraform's google_project_service and Pulumi's gcp.projects.Service
call it before managing any other resource, and gcloud services is built on it.
The emulator is an accept-and-succeed control plane: enabling a service flips it to
ENABLED (persisted, project-namespaced), disabling reverses it, and get/list echo that
state. There is no real API gating or dependency resolution — services work whether or not
they were "enabled".
Configuration
| Variable | Default | Description |
|---|---|---|
FLOCI_GCP_SERVICES_SERVICEUSAGE_ENABLED |
true |
Enable/disable Service Usage |
FLOCI_GCP_SERVICES_RESOURCEMANAGER_ENABLED |
true |
Enable/disable the Cloud Resource Manager project lookup (see below) |
Endpoints
| Method | Path |
|---|---|
POST |
/v1/projects/{project}/services/{service}:enable |
POST |
/v1/projects/{project}/services/{service}:disable |
GET |
/v1/projects/{project}/services/{service} |
GET |
/v1/projects/{project}/services (?filter=state:ENABLED\|state:DISABLED) |
POST |
/v1/projects/{project}/services:batchEnable |
GET |
/v1/projects/{project}/services:batchGet?names=... |
GET |
/v1/operations/{operation}, /v1/operations |
enable, disable, and batchEnable return an already-completed
google.longrunning.Operation (done: true) whose response carries the proto response
type, so SDK operation futures resolve immediately. Disabling a service that is not
enabled returns FAILED_PRECONDITION, matching real GCP.
Cloud Resource Manager companion
The Terraform/Pulumi Google providers verify a project exists via
cloudresourcemanager.v1.Projects.GetProject before reading google_project_service.
floci-gcp therefore serves a minimal Cloud Resource Manager v1 surface:
| Method | Path |
|---|---|
GET |
/v1/projects/{projectId} |
Every project ID resolves to an ACTIVE project with a stable synthetic
projectNumber (the emulator's multi-tenancy is keyed by project ID; projects are never
created or deleted).
Quick Start
provider "google" {
project = "my-project"
service_usage_custom_endpoint = "http://localhost:4588/v1/"
resource_manager_custom_endpoint = "http://localhost:4588/v1/"
}
resource "google_project_service" "run" {
service = "run.googleapis.com"
disable_on_destroy = true
}
Export a fake token first: export GOOGLE_OAUTH_ACCESS_TOKEN=fake-token.
export CLOUDSDK_AUTH_DISABLE_CREDENTIALS=true
export CLOUDSDK_API_ENDPOINT_OVERRIDES_SERVICEUSAGE=http://localhost:4588/
gcloud services enable run.googleapis.com pubsub.googleapis.com --project=my-project
gcloud services list --enabled --project=my-project
gcloud services disable run.googleapis.com --project=my-project --force
ServiceUsageClient client = ServiceUsageClient.create(
ServiceUsageSettings.newHttpJsonBuilder()
.setEndpoint("http://localhost:4588")
.setCredentialsProvider(NoCredentialsProvider.create())
.build());
client.enableServiceAsync(EnableServiceRequest.newBuilder()
.setName("projects/my-project/services/run.googleapis.com")
.build())
.get();
Service service = client.getService(GetServiceRequest.newBuilder()
.setName("projects/my-project/services/run.googleapis.com")
.build());
// service.getState() == State.ENABLED
Scope and deviations
ListServicesreturns only services whose state has been tracked (enabled or later disabled) for the project. Real GCP also lists every public API in theDISABLEDstate; the emulator does not ship a catalog of Google APIs.Service.configcarries only the servicename; real GCP includes title, quota, auth, and endpoint configuration.disableDependentServicesandcheckIfServiceHasUsageare accepted and ignored — there is no dependency graph or usage tracking.- Batch limits match real GCP: 20 services per
batchEnable, 30 names perbatchGet, page size capped at 200.