Google Cloud Platform Bindings — 11 Units für Cloud Storage (GCS), Compute Engine (GCE), Cloud Firestore, Pub/Sub, Cloud Functions, Cloud Run, Cloud Logging, Cloud Monitoring, Secret Manager und IAM. Vollständig in Lyx implementiert, kein GCP SDK. Alle HTTPS-Anfragen laufen über std.net.tls; Authentifizierung über JWT RS256 (Service Accounts), OAuth 2.0 Refresh Token oder GCE-Metadata-Server.
→ Standard Library · std.cloud · std.crypto
| Unit | Import | Beschreibung |
|---|---|---|
| std.cloud.gcp.credentials | import std.cloud.gcp.credentials; | Application Default Credentials: Credential Chain, Token-Cache, GCE-Erkennung (8 Fn) |
| std.cloud.gcp.jwt | import std.cloud.gcp.jwt; | JWT RS256 für Service Accounts: GCPServiceAccount, GCPBuildJWT, Base64url-Kodierung (5 Fn) |
| std.cloud.gcp.oauth | import std.cloud.gcp.oauth; | Access-Token-Verwaltung: GCPToken, auto-Refresh (Ablauf − 60 s), drei Token-Quellen (5 Fn) |
| std.cloud.gcp.transport | import std.cloud.gcp.transport; | HTTP-Transport: GCPClient, GCPResponse, GCPError, auto-Retry auf 429/5xx (10 Fn) |
| std.cloud.gcp.storage | import std.cloud.gcp.storage; | Cloud Storage (GCS): Buckets, Upload/Download, Metadaten, Listing (13 Fn) |
| std.cloud.gcp.compute | import std.cloud.gcp.compute; | Compute Engine (GCE): Instanzen, asynchrone Operationen, Standard-Zone europe-west1-b (10 Fn) |
| std.cloud.gcp.firestore | import std.cloud.gcp.firestore; | Cloud Firestore: FSDoc (max. 64 Felder), CRUD, Listing, JSON-Antwort (20 Fn) |
| std.cloud.gcp.pubsub | import std.cloud.gcp.pubsub; | Cloud Pub/Sub: Topics, Subscriptions, Publish, Pull, Acknowledge (10 Fn) |
| std.cloud.gcp.functions | import std.cloud.gcp.functions; | Cloud Functions v2 + Cloud Run v2: Deploy, Invoke, Service-Listing (12 Fn) |
| std.cloud.gcp.logging | import std.cloud.gcp.logging; | Cloud Logging + Cloud Monitoring: Text- und JSON-Logs, Custom Metrics, Alert Policies (10 Fn) |
| std.cloud.gcp.secrets | import std.cloud.gcp.secrets; | Secret Manager + IAM: Secret-CRUD, Versionierung, Service Accounts, IAM-Policies (15 Fn) |
┌───────────────────────────────────────────────────────────────────┐
│ Service-Units │
│ storage (GCS) · compute (GCE) · firestore · pubsub │
│ functions (GCF + GCR) · logging (+ Monitoring) · secrets (+ IAM)│
├───────────────────────────────────────────────────────────────────┤
│ Interne GCP-Schichten │
│ gcp/credentials (Credential Chain, Token-Cache) │
│ gcp/jwt (JWT RS256, GCPServiceAccount) │
│ gcp/oauth (GCPToken, auto-Refresh) │
│ gcp/transport (GCPClient, GCPResponse, Retry, Backoff) │
├───────────────────────────────────────────────────────────────────┤
│ Netzwerk-Grundschicht │
│ std.net.tls · std.net.http │
└───────────────────────────────────────────────────────────────────┘
GCPCredentialsDefault durchsucht drei Quellen in dieser Reihenfolge:
~/.config/gcloud/application_default_credentials.json (nach gcloud auth application-default login)metadata.google.internal)| Typ | Konstante | Authentifizierungsweg |
|---|---|---|
| Service Account | GCP_CREDS_SERVICE_ACCOUNT (1) | JSON-Datei → JWT RS256 → Bearer Token |
| Authorized User | GCP_CREDS_REFRESH_TOKEN (2) | JSON-Datei → OAuth 2.0 Refresh → Bearer Token |
| GCE-Metadata | GCP_CREDS_METADATA (3) | GCE-Metadata-Server → Bearer Token |
Der Token wird im GCPCredentials-Struct gecacht und automatisch erneuert, sobald er weniger als 60 Sekunden gültig ist.
import std.cloud.gcp.credentials;
import std.cloud.gcp.storage;
fn main(): int64 {
// Credential Chain: env → ADC → GCE-Metadata
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/cloud-platform"c);
var gcs: GCSConn := GCSConnect(addr creds, "mein-projekt"c);
var data: pchar := "Hello GCS"c;
GCSUpload(gcs, "mein-bucket"c, "hello.txt"c, data as int64, 9, "text/plain"c);
GCSDisconnect(gcs);
GCPCredentialsFree(creds);
return 0;
}
Alle Service-Funktionen geben GCPResponse zurück:
| Feld | Typ | Beschreibung |
|---|---|---|
statusCode | int64 | HTTP-Statuscode (200, 404, 429 …) |
body | int64 | Zeiger auf allokierten Antwort-Body (oder 0) |
bodyLen | int64 | Länge des Body in Bytes |
contentType | int64 | Content-Type-Header-Wert (pchar oder 0) |
GCPResponseFree® gibt body und contentType frei.
| Konstante | Wert | Bedeutung |
|---|---|---|
GCP_ERR_OK | 0 | Erfolg |
GCP_ERR_AUTH | 401 | Authentifizierung fehlgeschlagen |
GCP_ERR_FORBIDDEN | 403 | Zugriff verweigert |
GCP_ERR_NOT_FOUND | 404 | Ressource nicht gefunden |
GCP_ERR_CONFLICT | 409 | Ressource existiert bereits |
GCP_ERR_RATE_LIMIT | 429 | Zu viele Anfragen |
GCP_ERR_SERVER | 500 | Server-Fehler |
Der Transport-Layer wiederholt Anfragen bei 429, 500, 502, 503 und 504 automatisch — bis zu 3 Mal, mit exponentiellem Backoff (100 ms × 2ⁿ). User-Agent: lyxgcloud/1.0.
API: storage.googleapis.com · Pfad: /storage/v1/b/{bucket}/o/{object}
| Funktion | Signatur | Beschreibung |
|---|---|---|
GCSConnect | (credsPtr, project) → GCSConn | Verbindung zur Storage API |
GCSDisconnect | © | Ressourcen freigeben |
GCSBucketCreate | (c, bucket, location) → int64 | Bucket anlegen; location Standard: „US“ |
GCSBucketDelete | (c, bucket) → int64 | Bucket löschen |
GCSBucketExists | (c, bucket) → int64 | 1 = vorhanden |
GCSUpload | (c, bucket, object, data, dataLen, contentType) → int64 | Objekt hochladen |
GCSUploadJSON | (c, bucket, object, json, jsonLen) → int64 | JSON-Objekt hochladen |
GCSDownload | (c, bucket, object) → GCPResponse | Objekt herunterladen; Caller gibt r via GCPResponseFree frei |
GCSDownloadRange | (c, bucket, object, start, end) → GCPResponse | Teilbereich; TODO: Range-Header noch nicht implementiert |
GCSDelete | (c, bucket, object) → int64 | Objekt löschen |
GCSExists | (c, bucket, object) → int64 | 1 = vorhanden |
GCSGetMeta | (c, bucket, object) → GCPResponse | Objekt-Metadaten als JSON |
GCSList | (c, bucket, prefix, pageSize) → GCPResponse | Objekte auflisten (paginiert) |
import std.cloud.gcp.credentials;
import std.cloud.gcp.storage;
fn main(): int64 {
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/devstorage.read_write"c);
var gcs: GCSConn := GCSConnect(addr creds, "mein-projekt"c);
// Datei hochladen
var data: pchar := "Hallo Welt"c;
GCSUpload(gcs, "mein-bucket"c, "test.txt"c, data as int64, 10, "text/plain"c);
// Datei herunterladen
var r: GCPResponse := GCSDownload(gcs, "mein-bucket"c, "test.txt"c);
if (r.statusCode == 200) {
Print(r.body as pchar); PrintLn(""c);
}
GCPResponseFree(r);
GCSDisconnect(gcs);
GCPCredentialsFree(creds);
return 0;
}
API: compute.googleapis.com · Standard-Zone: europe-west1-b
Asynchrone Operationen (Erstellen, Löschen, Starten, Stoppen) geben GCEOperation zurück. GCEOperationWait pollt alle 2 Sekunden, maximal 30 Versuche (60 Sekunden gesamt).
| Funktion | Signatur | Beschreibung |
|---|---|---|
GCEConnect | (credsPtr, project, zone) → GCEConn | Verbindung; zone = 0 → europe-west1-b |
GCEDisconnect | © | Ressourcen freigeben |
GCEInstanceCreate | (c, name, machineType, image, diskSizeGB) → GCEOperation | VM anlegen (asynchron) |
GCEInstanceDelete | (c, name) → GCEOperation | VM löschen (asynchron) |
GCEInstanceStart | (c, name) → GCEOperation | VM starten (asynchron) |
GCEInstanceStop | (c, name) → GCEOperation | VM stoppen (asynchron) |
GCEInstanceGet | (c, name) → int64 | VM-Details als JSON-pchar (Caller frees) |
GCEInstanceList | © → GCPResponse | Alle VMs in der Zone auflisten |
GCEOperationWait | (c, op) → GCEOperation | Warten bis done = 1 (max. 60 s) |
GCEOperationFree | (op) | GCEOperation-Ressourcen freigeben |
import std.cloud.gcp.credentials;
import std.cloud.gcp.compute;
fn main(): int64 {
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/compute"c);
var gce: GCEConn := GCEConnect(addr creds, "mein-projekt"c, "europe-west1-b"c);
var op: GCEOperation := GCEInstanceCreate(gce, "web-01"c, "e2-micro"c,
"projects/debian-cloud/global/images/debian-12-bookworm-v20250101"c, 20);
op = GCEOperationWait(gce, op);
if (op.done == 1) {
PrintLn("VM bereit"c);
}
GCEOperationFree(op);
GCEDisconnect(gce);
GCPCredentialsFree(creds);
return 0;
}
API: firestore.googleapis.com · Standard-Datenbank: (default)
Dokumente werden über FSDoc verwaltet (max. 64 Felder). Unterstützte Feldtypen: String, Int64, Bool, Null.
| Typ | Beschreibung |
|---|---|
FirestoreConn | Verbindungskontext (client, project, database) |
FSDoc | Dokument-Handle; intern verwaltet Feldname + Wert + Typ |
| Feldtyp-Konstante | Wert |
|---|---|
FS_TYPE_STRING | 1 |
FS_TYPE_INT | 2 |
FS_TYPE_BOOL | 3 |
FS_TYPE_NULL | 4 |
| Funktion | Signatur | Beschreibung |
|---|---|---|
FSDocNew | () → int64 | Leeres Dokument anlegen |
FSDocFree | (doc) | Dokument freigeben |
FSDocSetString | (doc, key, value) | String-Feld setzen |
FSDocSetInt | (doc, key, value) | Int64-Feld setzen |
FSDocSetBool | (doc, key, value) | Bool-Feld setzen |
FSDocGetString | (doc, key) → pchar | String-Wert lesen (oder 0) |
FSDocGetInt | (doc, key) → int64 | Int-Wert lesen (oder 0) |
FSDocHasField | (doc, key) → int64 | 1 = Feld vorhanden |
FSDocFieldCount | (doc) → int64 | Anzahl der Felder |
FSDocToJSON | (doc) → int64 | Firestore-REST-JSON erzeugen (Caller frees via FSDocFreeJSON) |
FirestoreConnect | (credsPtr, project, database) → FirestoreConn | Verbindung aufbauen |
FirestoreDisconnect | © | Ressourcen freigeben |
FSCreate | (c, collection, docId, doc) → int64 | Dokument anlegen |
FSGet | (c, collection, docId) → int64 | Dokument lesen → FSDoc mit Roh-JSON im Feld „json“ |
FSUpdate | (c, collection, docId, doc) → int64 | Dokument aktualisieren (PATCH) |
FSSet | (c, collection, docId, doc) → int64 | Alias für FSCreate |
FSDelete | (c, collection, docId) → int64 | Dokument löschen |
FSExists | (c, collection, docId) → int64 | 1 = Dokument vorhanden |
FSList | (c, collection, pageSize) → GCPResponse | Alle Dokumente einer Collection |
Hinweis zu FSGet: Das zurückgegebene FSDoc enthält das Feld „json“ mit dem Roh-JSON-Body der Firestore REST-Antwort. Ein vollständiger Firestore-Value-Type-Parser (stringValue, integerValue …) ist nicht implementiert — bei Bedarf muss der JSON-Body selbst ausgewertet werden.
import std.cloud.gcp.credentials;
import std.cloud.gcp.firestore;
fn main(): int64 {
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/datastore"c);
var fs: FirestoreConn := FirestoreConnect(addr creds, "mein-projekt"c, "(default)"c);
var doc: int64 := FSDocNew();
FSDocSetString(doc, "name"c, "Andreas"c);
FSDocSetInt(doc, "version"c, 1);
FSDocSetBool(doc, "aktiv"c, 1);
FSCreate(fs, "users"c, "user-1"c, doc);
FSDocFree(doc);
FirestoreDisconnect(fs);
GCPCredentialsFree(creds);
return 0;
}
API: pubsub.googleapis.com · Ressourcen-Format: projects/{project}/topics/{topic}
Nachrichten-Payload wird beim Publishen automatisch als Base64url kodiert. PubSubAck erwartet ein int64*-Array von pchar-Zeigern (die ackId-Strings aus der Pull-Antwort).
| Funktion | Signatur | Beschreibung |
|---|---|---|
PubSubConnect | (credsPtr, project) → PubSubConn | Verbindung zur Pub/Sub API |
PubSubDisconnect | © | Ressourcen freigeben |
PubSubTopicCreate | (c, topic) → int64 | Topic anlegen |
PubSubTopicDelete | (c, topic) → int64 | Topic löschen |
PubSubTopicExists | (c, topic) → int64 | 1 = vorhanden |
PubSubSubscriptionCreate | (c, sub, topic, ackDeadline) → int64 | Subscription anlegen; ackDeadline ≤ 0 → 30 s |
PubSubSubscriptionDelete | (c, sub) → int64 | Subscription löschen |
PubSubPublish | (c, topic, data, dataLen) → GCPResponse | Nachricht publishen (base64url-kodiert) |
PubSubPull | (c, sub, maxMessages) → GCPResponse | Nachrichten abrufen; ≤ 0 → max. 10 |
PubSubAck | (c, sub, ackIds, ackIdCount) → int64 | Nachrichten bestätigen |
import std.cloud.gcp.credentials;
import std.cloud.gcp.pubsub;
fn main(): int64 {
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/pubsub"c);
var ps: PubSubConn := PubSubConnect(addr creds, "mein-projekt"c);
PubSubTopicCreate(ps, "events"c);
PubSubSubscriptionCreate(ps, "events-sub"c, "events"c, 60);
var msg: pchar := "Ereignis eingetreten"c;
var r: GCPResponse := PubSubPublish(ps, "events"c, msg as int64, 20);
GCPResponseFree(r);
PubSubDisconnect(ps);
GCPCredentialsFree(creds);
return 0;
}
Beide Dienste nutzen dieselbe Region-Konfiguration. Standard-Region: europe-west1.
Cloud Functions v2: API cloudfunctions.googleapis.com · Pfad /v2/projects/{proj}/locations/{region}/functions
Cloud Run v2: API run.googleapis.com · Pfad /v2/projects/{proj}/locations/{region}/services
Hinweis: GCRServiceInvoke ist ein Platzhalter (gibt HTTP 501 zurück). Cloud Run Services werden über ihre eigene Service-URL aufgerufen — dafür direkt std.net.https mit Bearer-Token aus GCPGetToken verwenden.
| Funktion | Typ | Beschreibung |
|---|---|---|
GCFConnect | GCFConn | Verbindung zu Cloud Functions v2 |
GCFDisconnect | — | Ressourcen freigeben |
GCFList | → GCPResponse | Alle Functions in der Region auflisten |
GCFGet | → GCPResponse | Eine Function abrufen |
GCFDelete | → int64 | Function löschen |
GCFDeploy | → GCPResponse | Function deployen (runtime, entryPoint, GCS-Source „bucket/path.zip“) |
GCFInvoke | → GCPResponse | Function aufrufen (POST …:call) |
GCRConnect | GCRConn | Verbindung zu Cloud Run v2 |
GCRDisconnect | — | Ressourcen freigeben |
GCRServiceList | → GCPResponse | Alle Cloud Run Services auflisten |
GCRServiceGet | → GCPResponse | Einen Cloud Run Service abrufen |
GCRServiceInvoke | → GCPResponse | Platzhalter — gibt HTTP 501 zurück |
import std.cloud.gcp.credentials;
import std.cloud.gcp.functions;
fn main(): int64 {
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/cloud-platform"c);
var gcf: GCFConn := GCFConnect(addr creds, "mein-projekt"c, "europe-west1"c);
// Cloud Function deployen (Quellcode als ZIP in GCS)
var r: GCPResponse := GCFDeploy(gcf, "helloWorld"c, "nodejs20"c,
"helloWorld"c, "mein-bucket/function.zip"c);
GCPResponseFree(r);
// Function aufrufen
var body: pchar := "{\"name\":\"Lyx\"}"c;
var res: GCPResponse := GCFInvoke(gcf, "helloWorld"c, body as int64, 14);
if (res.statusCode == 200) {
Print(res.body as pchar); PrintLn(""c);
}
GCPResponseFree(res);
GCFDisconnect(gcf);
GCPCredentialsFree(creds);
return 0;
}
Logging: API logging.googleapis.com · Endpunkt POST /v2/entries:write
Log-Einträge werden mit resource.type=„global“ erstellt. Der vollständige Log-Name wird automatisch aus projects/{project}/logs/{logName} zusammengebaut.
| Schweregrad-Konstante | Wert | Syslog-Äquivalent |
|---|---|---|
LOG_DEFAULT | 0 | — |
LOG_DEBUG | 100 | DEBUG |
LOG_INFO | 200 | INFO |
LOG_NOTICE | 300 | NOTICE |
LOG_WARNING | 400 | WARNING |
LOG_ERROR | 500 | ERROR |
LOG_CRITICAL | 600 | CRITICAL |
LOG_ALERT | 700 | ALERT |
LOG_EMERGENCY | 800 | EMERGENCY |
| Funktion | Signatur | Beschreibung |
|---|---|---|
LogConnect | (credsPtr, project) → LogConn | Verbindung zur Logging API |
LogDisconnect | © | Ressourcen freigeben |
LogWrite | (c, logName, severity, message) → int64 | Text-Log-Eintrag schreiben |
LogWriteJSON | (c, logName, severity, jsonPayload, jsonLen) → int64 | Strukturierten JSON-Log schreiben |
LogList | (c, logName, filter, pageSize) → GCPResponse | Log-Einträge lesen (pageSize ≤ 0 → 100) |
Monitoring: API monitoring.googleapis.com · Endpunkt POST /v3/projects/{project}/timeSeries
MonWriteMetric schreibt einen Integer-Gauge-Wert als Custom Metric Time Series. metricType muss mit custom.googleapis.com/ beginnen.
| Funktion | Signatur | Beschreibung |
|---|---|---|
MonConnect | (credsPtr, project) → MonConn | Verbindung zur Monitoring API |
MonDisconnect | © | Ressourcen freigeben |
MonWriteMetric | (c, metricType, value, labels) → int64 | Gauge-Wert schreiben; labels = JSON-Objekt oder 0 |
MonListMetrics | (c, filter) → GCPResponse | Time Series auflisten |
MonCreateAlertPolicy | (c, policy, policyLen) → int64 | Alert Policy anlegen (JSON-Body) |
import std.cloud.gcp.credentials;
import std.cloud.gcp.logging;
fn main(): int64 {
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/logging.write"c);
var log: LogConn := LogConnect(addr creds, "mein-projekt"c);
LogWrite(log, "app-log"c, LOG_INFO, "Anwendung gestartet"c);
var json: pchar := "{\"event\":\"startup\",\"version\":2}"c;
LogWriteJSON(log, "app-log"c, LOG_INFO, json as int64, 30);
var mon: MonConn := MonConnect(addr creds, "mein-projekt"c);
MonWriteMetric(mon, "custom.googleapis.com/anfragen_pro_sekunde"c, 42, 0);
MonDisconnect(mon);
LogDisconnect(log);
GCPCredentialsFree(creds);
return 0;
}
Secret Manager: API secretmanager.googleapis.com · Pfad /v1/projects/{project}/secrets
Secrets werden base64url-kodiert gespeichert. SecretCreate führt zwei API-Aufrufe durch: Zuerst wird das Secret angelegt (automatische Replikation), dann wird die erste Version mit dem Payload hinzugefügt.
SecretGetLatest und SecretGet dekodieren den Payload automatisch und geben einen allokierten pchar zurück (Caller frees mit free(val, StrLen(val) + 1)).
IAM: API iam.googleapis.com · Pfad /v1/projects/{project}/serviceAccounts
| Funktion | Signatur | Beschreibung |
|---|---|---|
SecretConnect | (credsPtr, project) → SecretConn | Verbindung zu Secret Manager |
SecretDisconnect | © | Ressourcen freigeben |
SecretCreate | (c, name, payload, payloadLen) → int64 | Secret anlegen + erste Version speichern (2 API-Aufrufe) |
SecretGet | (c, name) → int64 | Neueste Version abrufen und dekodieren (= SecretGetLatest) |
SecretGetLatest | (c, name) → int64 | Neueste Version abrufen und base64url-dekodieren (Caller frees) |
SecretAddVersion | (c, name, payload, payloadLen) → int64 | Neue Version zu bestehendem Secret hinzufügen |
SecretList | © → GCPResponse | Alle Secrets auflisten |
SecretDelete | (c, name) → int64 | Secret löschen |
IAMConnect | (credsPtr, project) → IAMConn | Verbindung zu IAM |
IAMDisconnect | © | Ressourcen freigeben |
IAMListServiceAccounts | © → GCPResponse | Alle Service Accounts auflisten |
IAMCreateServiceAccount | (c, accountId, displayName) → int64 | Service Account anlegen |
IAMDeleteServiceAccount | (c, email) → int64 | Service Account löschen (via E-Mail) |
IAMGetIAMPolicy | (c, resource) → GCPResponse | IAM-Policy einer Ressource abrufen |
IAMSetIAMPolicy | (c, resource, policy, policyLen) → int64 | IAM-Policy setzen |
import std.cloud.gcp.credentials;
import std.cloud.gcp.secrets;
import std.alloc;
fn main(): int64 {
var creds: GCPCredentials := GCPCredentialsDefault(
"https://www.googleapis.com/auth/cloud-platform"c);
var sc: SecretConn := SecretConnect(addr creds, "mein-projekt"c);
// Secret anlegen (Payload wird base64url-kodiert gespeichert)
var payload: pchar := "geheimes-passwort-123"c;
SecretCreate(sc, "db-password"c, payload as int64, 21);
// Secret auslesen (automatisch dekodiert)
var val: int64 := SecretGet(sc, "db-password"c);
if (val != 0) {
Print(val as pchar); PrintLn(""c);
free(val, StrLen(val as pchar) + 1);
}
SecretDisconnect(sc);
GCPCredentialsFree(creds);
return 0;
}
Letzte Aktualisierung: 2026-06-13