Zum Hauptinhalt springen
Version: Weekly Build

Automatisierung von Aufgaben mit der API

Während sich die Codesphere CLI hervorragend für Terminal-Workflows und die Nutzung in CI/CD-Pipelines mit vorab festgelegten Anwendungsfällen eignet, ermöglicht die Public API das Schreiben eigener Skripte, um Pipelines zu automatisieren, Infrastruktur-Lebenszyklen zu verwalten und Codesphere in interne Tools zu integrieren.

Dieser Leitfaden behandelt die Grundlagen des Scriptings und liefert praxisnahe Automatisierungsbeispiele.

Erste Schritte​

Um programmatisch mit der Codesphere API zu interagieren, werden zwei Dinge benötigt: ein HTTP-Client und ein sicherer Weg, das Authentifizierungs-Token zu übergeben.

Authentifizierungs-Header​

Jede API-Anfrage benötigt einen Authorization-Header, der das API-Token im Bearer-Token-Format enthält.

Umgang mit Secrets

Das API-Token darf niemals fest im Skript hinterlegt werden. Lade es stattdessen immer aus einer Umgebungsvariable oder einem sicheren Secret-Manager (z. B. AWS Secrets Manager, GitHub Secrets), um versehentliche Lecks in der Versionskontrolle zu vermeiden.

Grundlegende Einrichtung des HTTP-Clients​

Hier ein Beispiel, wie eine grundlegende authentifizierte Anfrage zum Abrufen der Workspaces einer Resource Group in gängigen Sprachen eingerichtet wird. Idealerweise werden einzelne Requests vorab mit Tools wie Postman getestet, bevor diese Skripte geschrieben werden.

Mit der beliebten requests-Bibliothek:

import os
import requests

# Load credentials from environment variables
API_TOKEN = os.environ.get("CODESPHERE_TOKEN")
RESOURCE_GROUP_ID = os.environ.get("CODESPHERE_RESOURCE_GROUP_ID")
BASE_URL = "https://cloud.codesphere.com/api"

headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}

# Example: Fetch all workspaces
response = requests.get(f"{BASE_URL}/workspaces/resource-group/{RESOURCE_GROUP_ID}", headers=headers)

if response.status_code == 200:
print("Workspaces fetched successfully!")
print(response.json())
else:
print(f"Error: {response.status_code} - {response.text}")

Automatisierungsbeispiele​

Im Folgenden einige praxisnahe Beispiele, wie die API genutzt werden kann, um mühsame Aufgaben im Lebenszyklus-Management zu automatisieren.

Integration des Deployment-Status in interne Tools​

Falls das Unternehmen ein eigenes internes Developer-Portal (wie Backstage) oder einen eigenen Slack-Bot nutzt, kann es sinnvoll sein, die API regelmäßig abzufragen, um den Zustand und den Pipeline-Status eines bestimmten Deployments zu melden.

Dieses Skript zeigt, wie der Status der Pipeline eines bestimmten Workspace abgerufen wird.

import os
import requests

API_TOKEN = os.environ.get("CODESPHERE_TOKEN")
WORKSPACE_ID = "YOUR_WORKSPACE_ID"
BASE_URL = "https://cloud.codesphere.com/api"
HEADERS = {"Authorization": f"Bearer {API_TOKEN}"}

def check_deployment_status():
# Fetch the status of the run pipeline
url = f"{BASE_URL}/workspaces/{WORKSPACE_ID}/pipeline/run"
response = requests.get(url, headers=HEADERS)

if response.status_code == 200:
status_data = response.json()

# Extract relevant status information
state = status_data.get("status", "UNKNOWN")
is_running = state == "RUNNING"

print(f"Deployment Status: {state}")

# Example logic for internal tool integration
if not is_running:
print("Alert: The application is currently down or stopped!")
# trigger_slack_alert(f"Workspace {WORKSPACE_ID} is down!")
return state
else:
print(f"Failed to fetch status: {response.text}")
return None

if __name__ == "__main__":
check_deployment_status()
Umgang mit API-Limits

Beim Schreiben von Skripten, die Endpunkte abfragen (z. B. das wiederholte Prüfen des Deployment-Status in einer Schleife), sollte eine Verzögerung (z. B. time.sleep(5) oder setTimeout) zwischen den Anfragen eingebaut werden, um Rate-Limits zu vermeiden.

Deployment- & Release-Workflows​

Einzelne Endpunkte sind bereits für sich genommen wertvoll, doch die eigentliche Stärke entsteht durch die Kombination mehrerer API-Aufrufe zu einem vollständigen Release-Flow (z. B. das Auslösen eines Releases beim Merge in einer GitHub Action).

Einfacher Release-Fall​

Der einfache Fall eignet sich hervorragend für statische Websites und Anwendungen, die nahezu sofort neu starten können.

  1. Änderungen ziehen: POST /workspaces/{workspaceId}/git/pull/{remote}
  2. Anwendung neu bauen (optional): POST /workspaces/{workspaceId}/pipeline/prepare/start
  3. Auf Build warten: GET /workspaces/{workspaceId}/pipeline/prepare abfragen, bis 200 zurückgegeben wird.
  4. Anwendung stoppen: POST /workspaces/{workspaceId}/pipeline/run/stop
  5. Anwendung neu starten: POST /workspaces/{workspaceId}/pipeline/run/start

Automatisierung von Zero-Downtime-Releases​

Für geschäftskritische Anwendungen, bei denen Ausfallzeiten inakzeptabel sind, lässt sich ein Blue/Green-Zero-Downtime-Release vollständig über die API automatisieren:

  1. Neuen Workspace erstellen: POST /workspaces (den neuen Git-Commit, die Resource-Group-ID, die Plan-ID, den Branch und die Replica-Anzahl festlegen).
  2. Abhängigkeiten bauen: POST /workspaces/{workspaceId}/pipeline/prepare/start
  3. Auf Build warten: GET /workspaces/{workspaceId}/pipeline/prepare abfragen, bis erfolgreich.
  4. Tests ausführen (optional): POST /workspaces/{workspaceId}/pipeline/test/start und abfragen, bis erfolgreich. Den Ablauf stoppen, falls Tests fehlschlagen!
  5. Anwendung starten: POST /workspaces/{workspaceId}/pipeline/run/start
  6. Domain-Routing umschalten: Sobald die neue Anwendung fehlerfrei läuft, den Traffic sofort dorthin umleiten, indem die Workspace-Verbindung aktualisiert wird: PUT /domains/resource-group/{resourceGroupId}/domain/{domainName}/workspace-connections

Programmatisches Skalieren von Replicas​

Codesphere Workspaces können mehrere Services gleichzeitig als Teil einer Landscape ausführen (z. B. ein Frontend, ein Backend und eine Datenbank).

Die Anzahl der horizontalen Replicas für bestimmte Services innerhalb eines Workspace lässt sich dynamisch anpassen.

Über den Endpunkt PATCH /workspaces/{workspaceId}/landscape/scale kann ein JSON-Objekt übergeben werden, bei dem die Keys den exakten Namen der jeweiligen Services entsprechen und die Values die gewünschte Anzahl der Replicas angeben.

import os
import json
import urllib.request

API_TOKEN = os.environ.get("CODESPHERE_TOKEN")
WORKSPACE_ID = "YOUR_WORKSPACE_ID"
BASE_URL = "YOUR_CODESPHERE_INSTANCE_URL/api"

url = f"{BASE_URL}/workspaces/{WORKSPACE_ID}/landscape/scale"

payload = json.dumps({
"YOUR-SERVICE-NAME": 1 # <--- CHANGE THIS TO YOUR SERVICE NAME & desired number of replicas (i.e. "backend")
}).encode('utf-8')

headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
}

req = urllib.request.Request(url, data=payload, headers=headers, method='PATCH')

try:
with urllib.request.urlopen(req) as response:
if response.status in [200, 204]:
print(f"Success! Services in Workspace {WORKSPACE_ID} have been scaled.")
except urllib.error.HTTPError as e:
print(f"Failed to scale. Error code: {e.code}")
print(e.read().decode())
except Exception as e:
print(f"An error occurred: {e}")
400-Fehler: Plan-Limits & ungültige Werte

Falls beim Versuch, Replicas zu skalieren, ein 400 Bad Request-Fehler zurückgegeben wird, deutet dies typischerweise auf einen von zwei Gründen hin:

  • Überschreitung der Plan-Limits: Es wird versucht, über die maximale Anzahl an Replicas hinaus zu skalieren, die im aktuellen Plan des Service erlaubt ist. Beispielsweise schlägt eine Anfrage nach 5 Replicas bei einem auf 3 begrenzten Plan fehl.
  • Ungültiger Integer-Wert: Die API erfordert eine positive Ganzzahl. Wird die Replica-Anzahl auf 0 oder einen negativen Wert gesetzt, führt dies zu einem Typfehler.