# Requested Core-API Services for Core-AI Infrastructure Tools This document specifies the API endpoints needed by core-ai infrastructure tools. All requests from core-ai should go through core-api for centralized logging and access control. ## Context The core-ai service is implementing 9 infrastructure tools in 3 logical clusters: 1. **Container Lifecycle** (4 tools) - containers.py 2. **Service Management** (3 tools) - services.py 3. **Monitoring & Resources** (2 tools) - monitoring.py These tools need corresponding core-api REST endpoints to perform operations via Portainer. --- ## Cluster 1: Container Lifecycle Management ### 1.1 List Containers **Endpoint:** `GET /v1/infrastructure/containers` **Query Parameters:** - `status` (optional): Filter by status - "all", "running", "stopped", "paused" (default: "running") **Response:** ```json [ { "Id": "abc123...", "Names": ["/nginx"], "State": "running", "Status": "Up 3 days", "Image": "nginx:latest", "Ports": [ {"PrivatePort": 80, "PublicPort": 8080, "Type": "tcp"}, {"PrivatePort": 443, "PublicPort": 8443, "Type": "tcp"} ], "StartedAt": "2024-12-01T10:00:00Z" } ] ``` **Implementation Notes:** - Use `PortainerClient.list_containers(all_containers=True)` with Docker socket fallback - Filter results based on `status` query parameter - Return standard Docker API container list format --- ### 1.2 Manage Container **Endpoint:** `POST /v1/infrastructure/containers/{container}/{action}` **Path Parameters:** - `container`: Container name or ID (e.g., "nginx", "core-ai") - `action`: One of: "start", "stop", "restart", "pause", "unpause", "remove" **Response (Success):** ```json { "success": true, "action": "restart", "container": "nginx", "message": "Container restarted successfully" } ``` **Response (Error):** ```json { "success": false, "error": "Container not found", "message": "Container 'nginx2' not found. Available containers: nginx, core-ai, ollama" } ``` **Status Codes:** - `200` - Success - `304` - Not Modified (already in target state) - `404` - Container not found - `409` - Conflict (e.g., cannot remove running container) - `500` - Server error **Implementation Notes:** - For "restart": call stop then start - For actions not yet in PortainerClient (pause, unpause, remove): - Call Portainer API directly: `/api/endpoints/{endpoint_id}/docker/containers/{container_id}/{action}` - Handle partial name matching (case-insensitive) - Return helpful error messages suggesting `docker_list_containers()` when not found --- ### 1.3 Inspect Container **Endpoint:** `GET /v1/infrastructure/containers/{container}` **Path Parameters:** - `container`: Container name or ID **Query Parameters:** - `details` (optional): Level of detail - "summary" (default), "full", "resources" **Response:** ```json { "Id": "abc123...", "Name": "/nginx", "State": { "Status": "running", "Running": true, "StartedAt": "2024-12-01T10:00:00Z", "FinishedAt": "0001-01-01T00:00:00Z", "ExitCode": 0 }, "Config": { "Image": "nginx:latest", "Env": ["PATH=/usr/local/sbin:...", "NGINX_VERSION=1.25.0"], "Cmd": ["nginx", "-g", "daemon off;"] }, "NetworkSettings": { "Ports": { "80/tcp": [{"HostIp": "0.0.0.0", "HostPort": "8080"}], "443/tcp": [{"HostIp": "0.0.0.0", "HostPort": "8443"}] }, "Networks": { "bridge": { "IPAddress": "172.17.0.2", "Gateway": "172.17.0.1" } } }, "HostConfig": { "Memory": 536870912, "NanoCpus": 1000000000, "RestartPolicy": {"Name": "unless-stopped"} }, "Mounts": [ { "Type": "bind", "Source": "/host/path", "Destination": "/container/path" } ] } ``` **Implementation Notes:** - Use `PortainerClient.inspect_container(container)` which auto-detects endpoint and falls back to Docker socket - Return full Docker inspect response - The core-ai tool will handle formatting based on `details` level - Return 404 if container not found --- ### 1.4 Container Logs **Endpoint:** `GET /v1/infrastructure/containers/{container}/logs` **Path Parameters:** - `container`: Container name or ID **Query Parameters:** - `lines` (optional): Number of log lines (default: 50, max: 500) - `since` (optional): Time filter - "1h", "30m", or ISO timestamp **Response:** ```json { "container": "nginx", "lines_requested": 50, "since": null, "logs": "2024-12-04T10:00:00.123Z Starting nginx...\n2024-12-04T10:00:01.456Z Ready to accept connections\n..." } ``` **Implementation Notes:** - Access Docker API directly: `GET /v1.41/containers/{container}/logs` - Use Docker socket transport (httpx with uds) - Parameters: `stdout=true`, `stderr=true`, `tail={lines}`, `timestamps=true` - If `since` provided: add `since={unix_timestamp}` parameter - Strip Docker stream headers (8-byte binary prefix per line) - Return plain text logs with timestamps - Return 404 if container not found --- ## Cluster 2: Service Management ### 2.1 List Services **Endpoint:** `GET /v1/infrastructure/services` (already exists, may need enhancement) **Query Parameters:** - `stack` (optional): Filter by stack name **Response:** ```json [ { "name": "portainer", "stack_id": 1, "status": "active", "containers_running": 3, "containers_total": 3, "ports": [9000, 8000], "domains": ["portainer.example.com"] } ] ``` **Implementation Notes:** - Enhance existing `/infrastructure/services` endpoint if needed - Ensure it returns stack/service information from Portainer - Include container counts (running/total) --- ### 2.2 Manage Service **Endpoint:** `POST /v1/infrastructure/services/{service}/{action}` **Path Parameters:** - `service`: Service/stack name - `action`: One of: "start", "stop", "restart", "scale" **Request Body (for scale action):** ```json { "replicas": 3 } ``` **Response:** ```json { "success": true, "action": "restart", "service": "web", "message": "Service restarted successfully" } ``` **Implementation Notes:** - For "start"/"stop": Use Portainer stack start/stop API - For "restart": Stop then start the stack - For "scale": Update stack with new replica count - This may require updating stack compose file --- ### 2.3 Service Status **Endpoint:** `GET /v1/infrastructure/services/{service}/status` **Path Parameters:** - `service`: Service/stack name **Response:** ```json { "name": "web", "status": "active", "stack_id": 5, "containers": [ { "name": "web_app_1", "status": "running", "health": "healthy", "uptime": "2 days" } ], "replica_status": "3/3 running", "resources": { "memory_total": "1.2 GB", "cpu_usage": "15%" }, "recent_events": [ {"time": "2024-12-04T09:00:00Z", "action": "container_start", "container": "web_app_3"} ] } ``` **Implementation Notes:** - Get stack details from Portainer - Get individual container statuses - Calculate aggregate resource usage - May require querying Docker events API for recent events --- ## Cluster 3: Monitoring & Resources ### 3.1 System Resources **Endpoint:** `GET /v1/infrastructure/resources/system` **Response:** ```json { "cpu": { "cores": 8, "usage_percent": 45.2, "load_average": [2.5, 2.3, 2.1] }, "memory": { "total_bytes": 16777216000, "used_bytes": 8388608000, "available_bytes": 8388608000, "usage_percent": 50.0 }, "disk": { "total_bytes": 500000000000, "used_bytes": 250000000000, "available_bytes": 250000000000, "usage_percent": 50.0 }, "network": { "interfaces": { "eth0": { "rx_bytes": 1000000000, "tx_bytes": 500000000 } } } } ``` **Implementation Notes:** - Use Docker system info API: `GET /v1.41/system/df` - May also use `GET /v1.41/info` for system-wide stats - Calculate percentages and format nicely - Include load averages from system stats --- ### 3.2 Container Resources **Endpoint:** `GET /v1/infrastructure/resources/containers` **Query Parameters:** - `container` (optional): Specific container name/ID (if omitted, return all) **Response:** ```json [ { "name": "nginx", "cpu_percent": 5.2, "memory_usage_bytes": 45000000, "memory_limit_bytes": 100000000, "memory_percent": 45.0, "network_rx_bytes": 50000000, "network_tx_bytes": 25000000, "block_read_bytes": 10000000, "block_write_bytes": 5000000 } ] ``` **Implementation Notes:** - Use Docker stats API: `GET /v1.41/containers/{id}/stats?stream=false` - If `container` param provided: return single container stats - If omitted: return stats for all running containers - Calculate percentages where applicable - Stats API returns real-time metrics (one-time snapshot, not streaming) --- ## Implementation Priority **Phase 1 (Needed immediately for core-ai):** 1. `GET /v1/infrastructure/containers` - List containers 2. `POST /v1/infrastructure/containers/{container}/{action}` - Manage containers 3. `GET /v1/infrastructure/containers/{container}` - Inspect container 4. `GET /v1/infrastructure/containers/{container}/logs` - Container logs **Phase 2 (Needed for full infrastructure tools):** 5. `POST /v1/infrastructure/services/{service}/{action}` - Manage services 6. `GET /v1/infrastructure/services/{service}/status` - Service status 7. `GET /v1/infrastructure/resources/system` - System resources 8. `GET /v1/infrastructure/resources/containers` - Container resources --- ## Security & Access Control All endpoints should: - Log all requests (especially write operations) - Support OIDC authentication when enabled - Require admin privileges for destructive operations (remove, scale) - Rate limit to prevent abuse - Validate input parameters - Return sanitized errors (no sensitive data in error messages) --- ## Error Handling Standard error response format: ```json { "error": "ContainerNotFound", "message": "Container 'nginx2' not found", "details": { "container": "nginx2", "available_containers": ["nginx", "core-ai", "ollama"] } } ``` Common error codes: - `400` - Bad Request (invalid parameters) - `404` - Not Found (container/service doesn't exist) - `409` - Conflict (invalid state transition) - `500` - Internal Server Error (Portainer/Docker API failed) - `503` - Service Unavailable (Portainer/Docker not accessible) --- ## Testing Each endpoint should have: - Unit tests (mock Portainer client) - Integration tests (real Portainer/Docker) - Error case tests (not found, permission denied, etc.) - Performance tests (ensure response times < 2s) --- ## Questions / Decisions Needed 1. **Authentication**: Should container management require admin role, or allow read-only for all users? 2. **Rate Limiting**: What limits should be applied to prevent abuse? 3. **Caching**: Should container lists be cached? (TTL: 5s?) 4. **Async**: Should heavy operations (like logs) be async with job IDs? 5. **Webhooks**: Should operations emit events for monitoring? --- ## Notes - All endpoints follow RESTful conventions - Use existing PortainerClient methods where available - Fall back to Docker socket when Portainer doesn't have data - Log all operations with timestamps, user, and outcome - Consider adding `/v1/infrastructure/containers/search` for fuzzy name matching