Includes all pending changes needed for nixos-anywhere: - fiberlb: L7 policy, rule, certificate types - deployer: New service for cluster management - nix-nos: Generic network modules - Various service updates and fixes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1197 lines
24 KiB
Markdown
1197 lines
24 KiB
Markdown
# PhotonCloud REST API Guide
|
|
|
|
**Version:** 1.0
|
|
**Last Updated:** 2025-12-12
|
|
**Target:** MVP-Alpha Phase
|
|
|
|
## Overview
|
|
|
|
PhotonCloud provides REST/HTTP APIs for all core services, enabling easy access via `curl` for:
|
|
- 組み込み環境 (Embedded environments)
|
|
- Shell scripts and automation
|
|
- Debugging and troubleshooting
|
|
- Environments without gRPC tooling
|
|
|
|
All REST APIs follow consistent patterns and run alongside gRPC services on dedicated HTTP ports.
|
|
|
|
## Service Port Map
|
|
|
|
| Service | HTTP Port | gRPC Port | Purpose |
|
|
|---------|-----------|-----------|---------|
|
|
| **ChainFire** | 8081 | 50051 | Distributed KV store with Raft consensus |
|
|
| **FlareDB** | 8082 | 50052 | SQL database (KV backend) |
|
|
| **IAM** | 8083 | 50051 | Identity & Access Management |
|
|
| **PlasmaVMC** | 8084 | 50051 | Virtual Machine Controller |
|
|
| **k8shost** | 8085 | 6443 | Kubernetes Host (kubelet replacement) |
|
|
| **CreditService** | 8086 | 50057 | Credit/Quota Management |
|
|
| **PrismNET** | 8087 | 9090 | Network Management (VPC/Subnet) |
|
|
| **NightLight** | 9090 | — | Prometheus TSDB (HTTP-only) |
|
|
| **LightningSTOR** | 9000 | — | S3-compatible Object Storage |
|
|
|
|
## Common Patterns
|
|
|
|
### Request Format
|
|
```bash
|
|
# Standard POST request with JSON body
|
|
curl -X POST http://localhost:8081/api/v1/kv/mykey/put \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"value": "myvalue"}'
|
|
```
|
|
|
|
### Response Format
|
|
|
|
**Success Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"id": "resource-id",
|
|
"name": "resource-name",
|
|
...
|
|
},
|
|
"meta": {
|
|
"request_id": "uuid-v4",
|
|
"timestamp": "2025-12-12T08:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Response:**
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "NOT_FOUND",
|
|
"message": "Resource not found",
|
|
"details": null
|
|
},
|
|
"meta": {
|
|
"request_id": "uuid-v4",
|
|
"timestamp": "2025-12-12T08:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Authentication
|
|
|
|
Most services support multi-tenancy via `org_id` and `project_id`:
|
|
|
|
```bash
|
|
# Query parameters for filtering
|
|
curl "http://localhost:8087/api/v1/vpcs?org_id=org-123&project_id=proj-456"
|
|
|
|
# Request body for creation
|
|
curl -X POST http://localhost:8087/api/v1/vpcs \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "production-vpc",
|
|
"org_id": "org-123",
|
|
"project_id": "proj-456",
|
|
"cidr_block": "10.0.0.0/16"
|
|
}'
|
|
```
|
|
|
|
For IAM token-based auth:
|
|
```bash
|
|
# Issue token
|
|
TOKEN=$(curl -X POST http://localhost:8083/api/v1/auth/token \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"principal_id": "user-123",
|
|
"scope_id": "project-456",
|
|
"ttl_seconds": 3600
|
|
}' | jq -r '.data.token')
|
|
|
|
# Use token in Authorization header
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
http://localhost:8084/api/v1/vms
|
|
```
|
|
|
|
---
|
|
|
|
## 1. ChainFire (Distributed KV Store)
|
|
|
|
**Port:** 8081
|
|
**Purpose:** Raft-based distributed key-value store with strong consistency
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:8081/health
|
|
```
|
|
|
|
### Cluster Status
|
|
```bash
|
|
# Get cluster status (node_id, term, role, is_leader)
|
|
curl http://localhost:8081/api/v1/cluster/status
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"node_id": 1,
|
|
"cluster_id": "cluster-123",
|
|
"term": 42,
|
|
"role": "leader",
|
|
"is_leader": true
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
### KV Operations
|
|
|
|
**Put Key-Value:**
|
|
```bash
|
|
curl -X POST http://localhost:8081/api/v1/kv/user:123/put \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"value": "{\"name\":\"alice\",\"email\":\"alice@example.com\"}"}'
|
|
```
|
|
|
|
**Get Value:**
|
|
```bash
|
|
curl http://localhost:8081/api/v1/kv/user:123
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"key": "user:123",
|
|
"value": "{\"name\":\"alice\",\"email\":\"alice@example.com\"}"
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Delete Key:**
|
|
```bash
|
|
curl -X POST http://localhost:8081/api/v1/kv/user:123/delete
|
|
```
|
|
|
|
**Range Scan (Prefix Query):**
|
|
```bash
|
|
# List all keys starting with "user:"
|
|
curl "http://localhost:8081/api/v1/kv?prefix=user:"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"items": [
|
|
{"key": "user:123", "value": "{...}"},
|
|
{"key": "user:456", "value": "{...}"}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
### Cluster Management
|
|
|
|
**Add Cluster Member:**
|
|
```bash
|
|
curl -X POST http://localhost:8081/api/v1/cluster/members \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"node_id": 2,
|
|
"address": "192.168.1.102:50051"
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## 2. FlareDB (SQL Database)
|
|
|
|
**Port:** 8082
|
|
**Purpose:** Distributed SQL database with KV backend
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:8082/health
|
|
```
|
|
|
|
### KV Operations
|
|
|
|
**Put Key-Value:**
|
|
```bash
|
|
curl -X PUT http://localhost:8082/api/v1/kv/config:db_version \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"value": "1.0.0",
|
|
"namespace": "system"
|
|
}'
|
|
```
|
|
|
|
**Get Value:**
|
|
```bash
|
|
curl "http://localhost:8082/api/v1/kv/config:db_version?namespace=system"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"key": "config:db_version",
|
|
"value": "1.0.0",
|
|
"namespace": "system"
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Range Scan:**
|
|
```bash
|
|
curl "http://localhost:8082/api/v1/scan?start=config:&end=config;&&namespace=system"
|
|
```
|
|
|
|
### SQL Operations (Placeholder)
|
|
|
|
**Execute SQL:**
|
|
```bash
|
|
# Note: SQL endpoint is placeholder - use gRPC for full SQL functionality
|
|
curl -X POST http://localhost:8082/api/v1/sql \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"query": "SELECT * FROM users WHERE id = 123"
|
|
}'
|
|
```
|
|
|
|
**List Tables:**
|
|
```bash
|
|
# Note: Placeholder endpoint - use gRPC for full functionality
|
|
curl http://localhost:8082/api/v1/tables
|
|
```
|
|
|
|
---
|
|
|
|
## 3. IAM (Identity & Access Management)
|
|
|
|
**Port:** 8083
|
|
**Purpose:** Authentication, authorization, user and policy management
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:8083/health
|
|
```
|
|
|
|
### Token Operations
|
|
|
|
**Issue Token:**
|
|
```bash
|
|
curl -X POST http://localhost:8083/api/v1/auth/token \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"principal_id": "user-alice",
|
|
"principal_type": "user",
|
|
"scope_id": "project-prod",
|
|
"ttl_seconds": 3600
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"token": "eyJhbGciOiJIUzI1NiIs...",
|
|
"expires_at": "2025-12-12T10:30:00Z"
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Verify Token:**
|
|
```bash
|
|
curl -X POST http://localhost:8083/api/v1/auth/verify \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"token": "eyJhbGciOiJIUzI1NiIs..."
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"valid": true,
|
|
"principal_id": "user-alice",
|
|
"scope_id": "project-prod",
|
|
"expires_at": "2025-12-12T10:30:00Z"
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
### User Management
|
|
|
|
**Create User:**
|
|
```bash
|
|
curl -X POST http://localhost:8083/api/v1/users \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"id": "user-bob",
|
|
"name": "Bob Smith",
|
|
"email": "bob@example.com",
|
|
"type": "user"
|
|
}'
|
|
```
|
|
|
|
**List Users:**
|
|
```bash
|
|
curl "http://localhost:8083/api/v1/users?scope_id=project-prod"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"users": [
|
|
{
|
|
"id": "user-alice",
|
|
"name": "Alice Johnson",
|
|
"email": "alice@example.com",
|
|
"type": "user"
|
|
},
|
|
{
|
|
"id": "user-bob",
|
|
"name": "Bob Smith",
|
|
"email": "bob@example.com",
|
|
"type": "user"
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
### Project Management (Placeholder)
|
|
|
|
```bash
|
|
# Note: Project management uses Scope/PolicyBinding in gRPC
|
|
# These REST endpoints are placeholders
|
|
curl http://localhost:8083/api/v1/projects
|
|
curl -X POST http://localhost:8083/api/v1/projects \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name": "production", "org_id": "org-123"}'
|
|
```
|
|
|
|
---
|
|
|
|
## 4. PlasmaVMC (Virtual Machine Controller)
|
|
|
|
**Port:** 8084
|
|
**Purpose:** VM lifecycle management (create, start, stop, delete)
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:8084/health
|
|
```
|
|
|
|
### VM Operations
|
|
|
|
**List VMs:**
|
|
```bash
|
|
curl "http://localhost:8084/api/v1/vms?org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"vms": [
|
|
{
|
|
"id": "vm-001",
|
|
"name": "web-server-01",
|
|
"state": "Running",
|
|
"cpus": 4,
|
|
"memory_mb": 8192
|
|
},
|
|
{
|
|
"id": "vm-002",
|
|
"name": "db-server-01",
|
|
"state": "Stopped",
|
|
"cpus": 8,
|
|
"memory_mb": 16384
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Create VM:**
|
|
```bash
|
|
curl -X POST http://localhost:8084/api/v1/vms \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "app-server-03",
|
|
"org_id": "org-123",
|
|
"project_id": "proj-456",
|
|
"vcpus": 2,
|
|
"memory_mib": 4096,
|
|
"hypervisor": "kvm",
|
|
"image_id": "ubuntu-22.04",
|
|
"disk_size_gb": 50
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"id": "vm-003",
|
|
"name": "app-server-03",
|
|
"state": "Creating",
|
|
"cpus": 2,
|
|
"memory_mb": 4096
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Get VM Details:**
|
|
```bash
|
|
curl "http://localhost:8084/api/v1/vms/vm-003?org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
**Start VM:**
|
|
```bash
|
|
curl -X POST "http://localhost:8084/api/v1/vms/vm-003/start?org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
**Stop VM:**
|
|
```bash
|
|
curl -X POST "http://localhost:8084/api/v1/vms/vm-003/stop?org_id=org-123&project_id=proj-456" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"force": false}'
|
|
```
|
|
|
|
**Delete VM:**
|
|
```bash
|
|
curl -X DELETE "http://localhost:8084/api/v1/vms/vm-003?org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
---
|
|
|
|
## 5. k8shost (Kubernetes Host)
|
|
|
|
**Port:** 8085
|
|
**Purpose:** Kubernetes pod/service/node management (kubelet replacement)
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:8085/health
|
|
```
|
|
|
|
### Pod Operations
|
|
|
|
**List Pods:**
|
|
```bash
|
|
# All namespaces
|
|
curl http://localhost:8085/api/v1/pods
|
|
|
|
# Specific namespace
|
|
curl "http://localhost:8085/api/v1/pods?namespace=production"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"pods": [
|
|
{
|
|
"name": "nginx-deployment-7d8f9c5b6d-xk2p9",
|
|
"namespace": "production",
|
|
"phase": "Running",
|
|
"pod_ip": "10.244.1.5",
|
|
"node_name": "worker-01"
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Create Pod:**
|
|
```bash
|
|
curl -X POST http://localhost:8085/api/v1/pods \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "nginx-pod",
|
|
"namespace": "production",
|
|
"image": "nginx:1.21",
|
|
"command": ["/bin/sh"],
|
|
"args": ["-c", "nginx -g \"daemon off;\""]
|
|
}'
|
|
```
|
|
|
|
**Delete Pod:**
|
|
```bash
|
|
curl -X DELETE http://localhost:8085/api/v1/pods/production/nginx-pod
|
|
```
|
|
|
|
### Service Operations
|
|
|
|
**List Services:**
|
|
```bash
|
|
curl "http://localhost:8085/api/v1/services?namespace=production"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"services": [
|
|
{
|
|
"name": "nginx-service",
|
|
"namespace": "production",
|
|
"type": "ClusterIP",
|
|
"cluster_ip": "10.96.0.100",
|
|
"ports": [
|
|
{"port": 80, "target_port": 8080, "protocol": "TCP"}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Create Service:**
|
|
```bash
|
|
curl -X POST http://localhost:8085/api/v1/services \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "app-service",
|
|
"namespace": "production",
|
|
"service_type": "ClusterIP",
|
|
"port": 80,
|
|
"target_port": 8080,
|
|
"selector": {"app": "nginx"}
|
|
}'
|
|
```
|
|
|
|
**Delete Service:**
|
|
```bash
|
|
curl -X DELETE http://localhost:8085/api/v1/services/production/app-service
|
|
```
|
|
|
|
### Node Operations
|
|
|
|
**List Nodes:**
|
|
```bash
|
|
curl http://localhost:8085/api/v1/nodes
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"nodes": [
|
|
{
|
|
"name": "worker-01",
|
|
"status": "Ready",
|
|
"capacity_cpu": "8",
|
|
"capacity_memory": "16Gi",
|
|
"allocatable_cpu": "7.5",
|
|
"allocatable_memory": "14Gi"
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. CreditService (Credit/Quota Management)
|
|
|
|
**Port:** 8086
|
|
**Purpose:** Multi-tenant credit tracking, reservations, and billing
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:8086/health
|
|
```
|
|
|
|
### Wallet Operations
|
|
|
|
**Create Wallet:**
|
|
```bash
|
|
curl -X POST http://localhost:8086/api/v1/wallets \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"project_id": "proj-456",
|
|
"org_id": "org-123",
|
|
"initial_balance": 10000
|
|
}'
|
|
```
|
|
|
|
**Get Wallet Balance:**
|
|
```bash
|
|
curl http://localhost:8086/api/v1/wallets/proj-456
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"project_id": "proj-456",
|
|
"org_id": "org-123",
|
|
"balance": 10000,
|
|
"reserved": 2500,
|
|
"available": 7500,
|
|
"currency": "JPY",
|
|
"status": "active"
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Top Up Credits:**
|
|
```bash
|
|
curl -X POST http://localhost:8086/api/v1/wallets/proj-456/topup \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"amount": 5000,
|
|
"description": "Monthly credit purchase"
|
|
}'
|
|
```
|
|
|
|
**Get Transactions:**
|
|
```bash
|
|
curl "http://localhost:8086/api/v1/wallets/proj-456/transactions?limit=10"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"transactions": [
|
|
{
|
|
"id": "txn-001",
|
|
"project_id": "proj-456",
|
|
"amount": 5000,
|
|
"type": "deposit",
|
|
"description": "Monthly credit purchase",
|
|
"timestamp": "2025-12-12T08:00:00Z"
|
|
},
|
|
{
|
|
"id": "txn-002",
|
|
"project_id": "proj-456",
|
|
"amount": -1500,
|
|
"type": "charge",
|
|
"description": "VM usage charge",
|
|
"resource_id": "vm-003",
|
|
"timestamp": "2025-12-12T09:00:00Z"
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
### Reservation Operations
|
|
|
|
**Reserve Credits:**
|
|
```bash
|
|
curl -X POST http://localhost:8086/api/v1/reservations \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"project_id": "proj-456",
|
|
"amount": 2000,
|
|
"description": "VM creation reservation",
|
|
"resource_type": "vm",
|
|
"resource_id": "vm-004",
|
|
"ttl_seconds": 3600
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"id": "rsv-001",
|
|
"project_id": "proj-456",
|
|
"amount": 2000,
|
|
"status": "active",
|
|
"expires_at": "2025-12-12T10:00:00Z"
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Commit Reservation:**
|
|
```bash
|
|
curl -X POST http://localhost:8086/api/v1/reservations/rsv-001/commit \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"actual_amount": 1800,
|
|
"resource_id": "vm-004"
|
|
}'
|
|
```
|
|
|
|
**Release Reservation:**
|
|
```bash
|
|
curl -X POST http://localhost:8086/api/v1/reservations/rsv-001/release \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"reason": "VM creation failed"
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## 7. PrismNET (Network Management)
|
|
|
|
**Port:** 8087
|
|
**Purpose:** Multi-tenant VPC, subnet, and port management
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:8087/health
|
|
```
|
|
|
|
### VPC Operations
|
|
|
|
**List VPCs:**
|
|
```bash
|
|
curl "http://localhost:8087/api/v1/vpcs?org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"vpcs": [
|
|
{
|
|
"id": "vpc-001",
|
|
"name": "production-vpc",
|
|
"org_id": "org-123",
|
|
"project_id": "proj-456",
|
|
"cidr_block": "10.0.0.0/16",
|
|
"description": "Production environment VPC",
|
|
"status": "active"
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Create VPC:**
|
|
```bash
|
|
curl -X POST http://localhost:8087/api/v1/vpcs \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "staging-vpc",
|
|
"org_id": "org-123",
|
|
"project_id": "proj-456",
|
|
"cidr_block": "172.16.0.0/16",
|
|
"description": "Staging environment VPC"
|
|
}'
|
|
```
|
|
|
|
**Get VPC:**
|
|
```bash
|
|
curl "http://localhost:8087/api/v1/vpcs/vpc-001?org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
**Delete VPC:**
|
|
```bash
|
|
curl -X DELETE "http://localhost:8087/api/v1/vpcs/vpc-001?org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
### Subnet Operations
|
|
|
|
**List Subnets:**
|
|
```bash
|
|
curl "http://localhost:8087/api/v1/subnets?vpc_id=vpc-001&org_id=org-123&project_id=proj-456"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": {
|
|
"subnets": [
|
|
{
|
|
"id": "subnet-001",
|
|
"name": "web-subnet",
|
|
"vpc_id": "vpc-001",
|
|
"cidr_block": "10.0.1.0/24",
|
|
"gateway_ip": "10.0.1.1",
|
|
"description": "Web tier subnet",
|
|
"status": "active"
|
|
},
|
|
{
|
|
"id": "subnet-002",
|
|
"name": "db-subnet",
|
|
"vpc_id": "vpc-001",
|
|
"cidr_block": "10.0.2.0/24",
|
|
"gateway_ip": "10.0.2.1",
|
|
"description": "Database tier subnet",
|
|
"status": "active"
|
|
}
|
|
]
|
|
},
|
|
"meta": { ... }
|
|
}
|
|
```
|
|
|
|
**Create Subnet:**
|
|
```bash
|
|
curl -X POST http://localhost:8087/api/v1/subnets \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "app-subnet",
|
|
"vpc_id": "vpc-001",
|
|
"cidr_block": "10.0.3.0/24",
|
|
"gateway_ip": "10.0.3.1",
|
|
"description": "Application tier subnet"
|
|
}'
|
|
```
|
|
|
|
**Delete Subnet:**
|
|
```bash
|
|
curl -X DELETE "http://localhost:8087/api/v1/subnets/subnet-003?org_id=org-123&project_id=proj-456&vpc_id=vpc-001"
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Workflow Examples
|
|
|
|
### Example 1: Deploy VM with Networking
|
|
|
|
```bash
|
|
# 1. Create VPC
|
|
VPC_ID=$(curl -s -X POST http://localhost:8087/api/v1/vpcs \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "app-vpc",
|
|
"org_id": "org-123",
|
|
"project_id": "proj-456",
|
|
"cidr_block": "10.100.0.0/16"
|
|
}' | jq -r '.data.id')
|
|
|
|
# 2. Create Subnet
|
|
SUBNET_ID=$(curl -s -X POST http://localhost:8087/api/v1/subnets \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"name\": \"app-subnet\",
|
|
\"vpc_id\": \"$VPC_ID\",
|
|
\"cidr_block\": \"10.100.1.0/24\",
|
|
\"gateway_ip\": \"10.100.1.1\"
|
|
}" | jq -r '.data.id')
|
|
|
|
# 3. Reserve Credits
|
|
RSV_ID=$(curl -s -X POST http://localhost:8086/api/v1/reservations \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"project_id": "proj-456",
|
|
"amount": 5000,
|
|
"resource_type": "vm",
|
|
"ttl_seconds": 3600
|
|
}' | jq -r '.data.id')
|
|
|
|
# 4. Create VM
|
|
VM_ID=$(curl -s -X POST http://localhost:8084/api/v1/vms \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "app-server",
|
|
"org_id": "org-123",
|
|
"project_id": "proj-456",
|
|
"vcpus": 4,
|
|
"memory_mib": 8192,
|
|
"hypervisor": "kvm"
|
|
}' | jq -r '.data.id')
|
|
|
|
# 5. Start VM
|
|
curl -X POST "http://localhost:8084/api/v1/vms/$VM_ID/start?org_id=org-123&project_id=proj-456"
|
|
|
|
# 6. Commit Reservation
|
|
curl -X POST "http://localhost:8086/api/v1/reservations/$RSV_ID/commit" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"actual_amount\": 4500,
|
|
\"resource_id\": \"$VM_ID\"
|
|
}"
|
|
|
|
echo "VM deployed: $VM_ID in VPC: $VPC_ID, Subnet: $SUBNET_ID"
|
|
```
|
|
|
|
### Example 2: Deploy Kubernetes Pod with Service
|
|
|
|
```bash
|
|
# 1. Create Pod
|
|
curl -X POST http://localhost:8085/api/v1/pods \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "nginx-app",
|
|
"namespace": "production",
|
|
"image": "nginx:1.21"
|
|
}'
|
|
|
|
# 2. Create Service
|
|
curl -X POST http://localhost:8085/api/v1/services \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "nginx-service",
|
|
"namespace": "production",
|
|
"service_type": "ClusterIP",
|
|
"port": 80,
|
|
"target_port": 80,
|
|
"selector": {"app": "nginx"}
|
|
}'
|
|
|
|
# 3. Verify Pod Status
|
|
curl "http://localhost:8085/api/v1/pods?namespace=production" | jq '.data.pods[] | select(.name=="nginx-app")'
|
|
```
|
|
|
|
### Example 3: User Authentication Flow
|
|
|
|
```bash
|
|
# 1. Create User
|
|
curl -X POST http://localhost:8083/api/v1/users \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"id": "user-charlie",
|
|
"name": "Charlie Brown",
|
|
"email": "charlie@example.com",
|
|
"type": "user"
|
|
}'
|
|
|
|
# 2. Issue Token
|
|
TOKEN=$(curl -s -X POST http://localhost:8083/api/v1/auth/token \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"principal_id": "user-charlie",
|
|
"scope_id": "project-prod",
|
|
"ttl_seconds": 7200
|
|
}' | jq -r '.data.token')
|
|
|
|
# 3. Verify Token
|
|
curl -X POST http://localhost:8083/api/v1/auth/verify \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"token\": \"$TOKEN\"}"
|
|
|
|
# 4. Use Token for API Call
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
"http://localhost:8084/api/v1/vms?org_id=org-123&project_id=project-prod"
|
|
```
|
|
|
|
---
|
|
|
|
## Debugging Tips
|
|
|
|
### Check All Services Health
|
|
```bash
|
|
#!/bin/bash
|
|
services=(
|
|
"ChainFire:8081"
|
|
"FlareDB:8082"
|
|
"IAM:8083"
|
|
"PlasmaVMC:8084"
|
|
"k8shost:8085"
|
|
"CreditService:8086"
|
|
"PrismNET:8087"
|
|
)
|
|
|
|
for svc in "${services[@]}"; do
|
|
name="${svc%%:*}"
|
|
port="${svc##*:}"
|
|
echo -n "$name ($port): "
|
|
curl -s http://localhost:$port/health | jq -r '.data.status // "ERROR"'
|
|
done
|
|
```
|
|
|
|
### Verbose curl for Debugging
|
|
```bash
|
|
# Show request/response headers
|
|
curl -v http://localhost:8081/health
|
|
|
|
# Show timing information
|
|
curl -w "@-" -o /dev/null -s http://localhost:8081/health <<'EOF'
|
|
time_namelookup: %{time_namelookup}\n
|
|
time_connect: %{time_connect}\n
|
|
time_total: %{time_total}\n
|
|
EOF
|
|
```
|
|
|
|
### Pretty-print JSON Responses
|
|
```bash
|
|
# Install jq if not available
|
|
# Ubuntu/Debian: sudo apt-get install jq
|
|
# macOS: brew install jq
|
|
|
|
curl http://localhost:8087/api/v1/vpcs | jq '.'
|
|
```
|
|
|
|
---
|
|
|
|
## Migration from gRPC
|
|
|
|
If you have existing gRPC client code, here's how to migrate:
|
|
|
|
### gRPC (Before)
|
|
```rust
|
|
use chainfire_client::ChainFireClient;
|
|
|
|
let mut client = ChainFireClient::connect("http://localhost:50051").await?;
|
|
let response = client.get(tonic::Request::new(GetRequest {
|
|
key: "mykey".to_string(),
|
|
})).await?;
|
|
println!("Value: {}", response.into_inner().value);
|
|
```
|
|
|
|
### REST (After)
|
|
```bash
|
|
curl http://localhost:8081/api/v1/kv/mykey | jq -r '.data.value'
|
|
```
|
|
|
|
Or with any HTTP client library:
|
|
```python
|
|
import requests
|
|
|
|
response = requests.get('http://localhost:8081/api/v1/kv/mykey')
|
|
data = response.json()
|
|
print(f"Value: {data['data']['value']}")
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
All services return consistent error responses:
|
|
|
|
### Common HTTP Status Codes
|
|
|
|
| Code | Meaning | Example |
|
|
|------|---------|---------|
|
|
| 200 | OK | Successful GET/POST |
|
|
| 201 | Created | Resource created |
|
|
| 400 | Bad Request | Invalid JSON or missing required fields |
|
|
| 404 | Not Found | Resource doesn't exist |
|
|
| 409 | Conflict | Resource already exists or state conflict |
|
|
| 500 | Internal Server Error | Service error |
|
|
| 503 | Service Unavailable | Service not ready (e.g., Raft not leader) |
|
|
|
|
### Error Response Example
|
|
```bash
|
|
curl -X POST http://localhost:8087/api/v1/vpcs \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name": "invalid"}'
|
|
```
|
|
|
|
**Response (400 Bad Request):**
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "VALIDATION_ERROR",
|
|
"message": "cidr_block is required",
|
|
"details": {
|
|
"field": "cidr_block",
|
|
"constraint": "required"
|
|
}
|
|
},
|
|
"meta": {
|
|
"request_id": "req-12345",
|
|
"timestamp": "2025-12-12T08:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Handling Errors in Scripts
|
|
```bash
|
|
#!/bin/bash
|
|
response=$(curl -s -w "\n%{http_code}" http://localhost:8084/api/v1/vms/invalid-id)
|
|
body=$(echo "$response" | head -n -1)
|
|
status=$(echo "$response" | tail -n 1)
|
|
|
|
if [ "$status" -ne 200 ]; then
|
|
echo "Error: $(echo $body | jq -r '.error.message')"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Success: $body"
|
|
```
|
|
|
|
---
|
|
|
|
## Performance Considerations
|
|
|
|
### Connection Reuse
|
|
For multiple requests, reuse connections:
|
|
```bash
|
|
# Single connection for multiple requests
|
|
curl -K - <<EOF
|
|
url = http://localhost:8081/api/v1/kv/key1
|
|
url = http://localhost:8081/api/v1/kv/key2
|
|
url = http://localhost:8081/api/v1/kv/key3
|
|
EOF
|
|
```
|
|
|
|
### Batch Operations
|
|
Where possible, use range queries instead of individual requests:
|
|
```bash
|
|
# Bad: Multiple individual requests
|
|
curl http://localhost:8081/api/v1/kv/user:1
|
|
curl http://localhost:8081/api/v1/kv/user:2
|
|
curl http://localhost:8081/api/v1/kv/user:3
|
|
|
|
# Good: Single range query
|
|
curl "http://localhost:8081/api/v1/kv?prefix=user:"
|
|
```
|
|
|
|
### Parallel Requests
|
|
Use `xargs` or GNU `parallel` for concurrent requests:
|
|
```bash
|
|
# Parallel health checks
|
|
echo -e "8081\n8082\n8083\n8084\n8085\n8086\n8087" | \
|
|
xargs -I {} -P 7 curl -s http://localhost:{}/health
|
|
```
|
|
|
|
---
|
|
|
|
## OpenAPI / Swagger Specifications
|
|
|
|
OpenAPI specifications are available for each service (planned):
|
|
|
|
- `docs/api/openapi/chainfire.yaml`
|
|
- `docs/api/openapi/flaredb.yaml`
|
|
- `docs/api/openapi/iam.yaml`
|
|
- `docs/api/openapi/plasmavmc.yaml`
|
|
- `docs/api/openapi/k8shost.yaml`
|
|
- `docs/api/openapi/creditservice.yaml`
|
|
- `docs/api/openapi/prismnet.yaml`
|
|
|
|
You can import these into Postman, Insomnia, or generate client SDKs using [openapi-generator](https://github.com/OpenAPITools/openapi-generator).
|
|
|
|
---
|
|
|
|
## Postman Collection
|
|
|
|
A Postman collection with all endpoints and example requests is available:
|
|
- `docs/api/postman/photoncloud-rest-api.json` (planned)
|
|
|
|
Import this into Postman for interactive API exploration and testing.
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- **gRPC APIs:** See individual service `proto/` directories
|
|
- **Architecture:** `docs/architecture/ARCHITECTURE.md`
|
|
- **REST API Patterns:** `docs/specifications/rest-api-patterns.md`
|
|
- **Security:** `docs/security/AUTH.md` (when available)
|
|
- **Deployment:** `docs/deployment/` (when available)
|
|
|
|
---
|
|
|
|
## Support & Feedback
|
|
|
|
For questions, issues, or feature requests:
|
|
- **Project Repository:** `/home/centra/cloud/`
|
|
- **Task Tracking:** `docs/por/` (Plan of Record)
|
|
- **Active Task:** T050 REST API Implementation
|
|
|
|
**Last Updated:** 2025-12-12
|
|
**Documentation Version:** 1.0 (MVP-Alpha Phase)
|