Files
core-api/REQUESTED_SERVICES.md
T
2025-12-11 15:52:59 +01:00

11 KiB

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:

[
  {
    "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):

{
  "success": true,
  "action": "restart",
  "container": "nginx",
  "message": "Container restarted successfully"
}

Response (Error):

{
  "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:

{
  "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:

{
  "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:

[
  {
    "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):

{
  "replicas": 3
}

Response:

{
  "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:

{
  "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:

{
  "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:

[
  {
    "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:

{
  "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