Google Cloud Platform (GCP) Services

DevCloud provides local emulation for Google Cloud Platform services on port 4747, covering object storage, secret management, and messaging APIs.

Supported Services

ServiceIdentifierLocal limits and backend
Cloud StoragegcsLocal filesystem-backed FileStore under data/gcs. Supports bucket CRUD, object CRUD, multipart uploads, media downloads, and CRC32c / MD5 checksums.
Secret ManagergcpsecretsIn-memory secret store. Supports secret creation, listing, deletion, payload versioning, access (:access), and payload destruction (:destroy).
Cloud Pub/SubgcppubsubIn-memory messaging engine. Supports topic CRUD, message publishing (:publish), subscription CRUD, message pull (:pull), and message acknowledgement (:acknowledge).

Operations

Cloud Storage (gcs)

AreaOperationMethod & URINotes
BucketsListBucketsGET /storage/v1/b?project={project}Returns JSON list of buckets in the project
BucketsInsertBucketPOST /storage/v1/bCreates a new bucket (201 Created or 409 Conflict)
BucketsGetBucketGET /storage/v1/b/{bucket}Returns bucket metadata and timestamps
BucketsDeleteBucketDELETE /storage/v1/b/{bucket}Deletes bucket (204 No Content or 404 Not Found)
ObjectsListObjectsGET /storage/v1/b/{bucket}/oLists objects within a bucket
ObjectsInsertObjectPOST /upload/storage/v1/b/{bucket}/o?uploadType=media&name={name}Uploads raw binary object payload
ObjectsGetObjectGET /storage/v1/b/{bucket}/o/{object}?alt=mediaDownloads object binary content with checksums
ObjectsGetObjectMetadataGET /storage/v1/b/{bucket}/o/{object}Returns object JSON metadata (size, contentType, md5Hash, crc32c)
ObjectsDeleteObjectDELETE /storage/v1/b/{bucket}/o/{object}Removes object (204 No Content or 404 Not Found)

Secret Manager (gcpsecrets)

AreaOperationMethod & URINotes
SecretsCreateSecretPOST /v1/projects/{project}/secrets?secretId={id}Creates secret metadata resource
SecretsGetSecretGET /v1/projects/{project}/secrets/{secret}Retrieves secret resource metadata
SecretsListSecretsGET /v1/projects/{project}/secretsLists secrets within a project
SecretsDeleteSecretDELETE /v1/projects/{project}/secrets/{secret}Deletes secret and all its payload versions
VersionsAddSecretVersionPOST /v1/projects/{project}/secrets/{secret}:addVersionAdds a new base64 payload version
VersionsAccessSecretVersionGET /v1/projects/{project}/secrets/{secret}/versions/{version}:accessAccesses secret payload (supports version number or latest)
VersionsDestroySecretVersionPOST /v1/projects/{project}/secrets/{secret}/versions/{version}:destroyDestroys version payload data

Cloud Pub/Sub (gcppubsub)

AreaOperationMethod & URINotes
TopicsCreateTopicPUT /v1/projects/{project}/topics/{topic}Creates a Pub/Sub topic
TopicsGetTopicGET /v1/projects/{project}/topics/{topic}Retrieves topic resource details
TopicsListTopicsGET /v1/projects/{project}/topicsLists all topics in the project
TopicsDeleteTopicDELETE /v1/projects/{project}/topics/{topic}Deletes topic and detached associations
TopicsPublishPOST /v1/projects/{project}/topics/{topic}:publishPublishes base64 message batch to subscribers
SubscriptionsCreateSubscriptionPUT /v1/projects/{project}/subscriptions/{sub}Creates subscription bound to a topic
SubscriptionsGetSubscriptionGET /v1/projects/{project}/subscriptions/{sub}Retrieves subscription settings
SubscriptionsListSubscriptionsGET /v1/projects/{project}/subscriptionsLists subscriptions in the project
SubscriptionsDeleteSubscriptionDELETE /v1/projects/{project}/subscriptions/{sub}Deletes subscription
SubscriptionsPullPOST /v1/projects/{project}/subscriptions/{sub}:pullPulls delivered messages with ack IDs
SubscriptionsAcknowledgePOST /v1/projects/{project}/subscriptions/{sub}:acknowledgeConfirms message processing by ack IDs

Configuration

In devcloud.yaml, GCP services are configured under providers.gcp:

server:
  port: 4747

providers:
  gcp:
    services:
      gcs:
        enabled: true
        data_dir: ./data/gcp/gcs
      gcpsecrets:
        enabled: true
      gcppubsub:
        enabled: true

Credentials & Endpoint Setup

DevCloud accepts Google OAuth2 Bearer tokens (Bearer ya29...) or placeholder credentials without rejecting calls on signature verification.

To direct the Google Cloud Python SDK to DevCloud:

export STORAGE_EMULATOR_HOST="http://127.0.0.1:4747"
export GOOGLE_APPLICATION_CREDENTIALS="/dev/null"

Python SDK Examples

Secret Manager (google-cloud-secret-manager)

import base64
import requests

endpoint = "http://localhost:4747"
project = "local-project"
headers = {"Authorization": "Bearer local-token"}

# 1. Create a secret
requests.post(
    f"{endpoint}/v1/projects/{project}/secrets?secretId=DatabasePassword",
    json={"replication": {"automatic": {}}},
    headers=headers,
)

# 2. Add a secret version
payload = base64.b64encode(b"ProductionDatabasePassword123").decode()
requests.post(
    f"{endpoint}/v1/projects/{project}/secrets/DatabasePassword:addVersion",
    json={"payload": {"data": payload}},
    headers=headers,
)

# 3. Access secret version (latest)
resp = requests.get(
    f"{endpoint}/v1/projects/{project}/secrets/DatabasePassword/versions/latest:access",
    headers=headers,
)
retrieved = base64.b64decode(resp.json()["payload"]["data"]).decode()
print("Retrieved secret:", retrieved)

Cloud Pub/Sub (google-cloud-pubsub)

import base64
import requests

endpoint = "http://localhost:4747"
project = "local-project"
headers = {"Authorization": "Bearer local-token"}

# 1. Create a topic
requests.put(
    f"{endpoint}/v1/projects/{project}/topics/order-events",
    headers=headers,
)

# 2. Create a subscription
requests.put(
    f"{endpoint}/v1/projects/{project}/subscriptions/order-worker",
    json={"topic": f"projects/{project}/topics/order-events"},
    headers=headers,
)

# 3. Publish a message
msg_data = base64.b64encode(b"order_id=456 status=paid").decode()
requests.post(
    f"{endpoint}/v1/projects/{project}/topics/order-events:publish",
    json={"messages": [{"data": msg_data}]},
    headers=headers,
)

# 4. Pull and acknowledge message
pull_resp = requests.post(
    f"{endpoint}/v1/projects/{project}/subscriptions/order-worker:pull",
    json={"maxMessages": 10},
    headers=headers,
)
messages = pull_resp.json().get("receivedMessages", [])
for m in messages:
    ack_id = m["ackId"]
    content = base64.b64decode(m["message"]["data"]).decode()
    print("Received:", content)
    requests.post(
        f"{endpoint}/v1/projects/{project}/subscriptions/order-worker:acknowledge",
        json={"ackIds": [ack_id]},
        headers=headers,
    )