Service config. Service logs. Service status.
This commit is contained in:
339
internal/contracts/services.go
Normal file
339
internal/contracts/services.go
Normal file
@@ -0,0 +1,339 @@
|
||||
// Package contracts contains API contracts for service management endpoints
|
||||
package contracts
|
||||
|
||||
import "time"
|
||||
|
||||
// ==============================
|
||||
// Request/Response Types
|
||||
// ==============================
|
||||
|
||||
// ServiceManifest represents basic service information
|
||||
type ServiceManifest struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Namespace string `json:"namespace"`
|
||||
ConfigReferences []string `json:"configReferences,omitempty"`
|
||||
ServiceConfig map[string]ConfigDefinition `json:"serviceConfig,omitempty"`
|
||||
}
|
||||
|
||||
// ConfigDefinition defines config that should be prompted during service setup
|
||||
type ConfigDefinition struct {
|
||||
Path string `json:"path"`
|
||||
Prompt string `json:"prompt"`
|
||||
Default string `json:"default"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// PodStatus represents the status of a single pod
|
||||
type PodStatus struct {
|
||||
Name string `json:"name"` // Pod name
|
||||
Status string `json:"status"` // Pod phase: Running, Pending, Failed, etc.
|
||||
Ready string `json:"ready"` // Ready containers e.g. "1/1", "0/1"
|
||||
Restarts int `json:"restarts"` // Container restart count
|
||||
Age string `json:"age"` // Human-readable age e.g. "2h", "5m"
|
||||
Node string `json:"node"` // Node name where pod is scheduled
|
||||
IP string `json:"ip,omitempty"` // Pod IP if available
|
||||
}
|
||||
|
||||
// DetailedServiceStatus provides comprehensive service status
|
||||
type DetailedServiceStatus struct {
|
||||
Name string `json:"name"` // Service name
|
||||
Namespace string `json:"namespace"` // Kubernetes namespace
|
||||
DeploymentStatus string `json:"deploymentStatus"` // "Ready", "Progressing", "Degraded", "NotFound"
|
||||
Replicas ReplicaStatus `json:"replicas"` // Desired/current/ready replicas
|
||||
Pods []PodStatus `json:"pods"` // Pod details
|
||||
Config map[string]interface{} `json:"config,omitempty"` // Current config from config.yaml
|
||||
Manifest *ServiceManifest `json:"manifest,omitempty"` // Service manifest if available
|
||||
LastUpdated time.Time `json:"lastUpdated"` // Timestamp of status
|
||||
}
|
||||
|
||||
// ReplicaStatus tracks deployment replica counts
|
||||
type ReplicaStatus struct {
|
||||
Desired int32 `json:"desired"` // Desired replica count
|
||||
Current int32 `json:"current"` // Current replica count
|
||||
Ready int32 `json:"ready"` // Ready replica count
|
||||
Available int32 `json:"available"` // Available replica count
|
||||
}
|
||||
|
||||
// ServiceLogsRequest query parameters for log retrieval
|
||||
type ServiceLogsRequest struct {
|
||||
Container string `json:"container,omitempty"` // Specific container name (optional)
|
||||
Tail int `json:"tail,omitempty"` // Number of lines from end (default: 100)
|
||||
Follow bool `json:"follow,omitempty"` // Stream logs via SSE
|
||||
Previous bool `json:"previous,omitempty"` // Get previous container logs
|
||||
Since string `json:"since,omitempty"` // RFC3339 or duration string e.g. "10m"
|
||||
}
|
||||
|
||||
// ServiceLogsResponse for non-streaming log retrieval
|
||||
type ServiceLogsResponse struct {
|
||||
Service string `json:"service"` // Service name
|
||||
Namespace string `json:"namespace"` // Kubernetes namespace
|
||||
Container string `json:"container,omitempty"` // Container name if specified
|
||||
Lines []string `json:"lines"` // Log lines
|
||||
Truncated bool `json:"truncated"` // Whether logs were truncated
|
||||
Timestamp time.Time `json:"timestamp"` // Response timestamp
|
||||
}
|
||||
|
||||
// ServiceLogsSSEEvent for streaming logs via Server-Sent Events
|
||||
type ServiceLogsSSEEvent struct {
|
||||
Type string `json:"type"` // "log", "error", "end"
|
||||
Line string `json:"line,omitempty"` // Log line content
|
||||
Error string `json:"error,omitempty"` // Error message if type="error"
|
||||
Container string `json:"container,omitempty"` // Container source
|
||||
Timestamp time.Time `json:"timestamp"` // Event timestamp
|
||||
}
|
||||
|
||||
// ServiceConfigUpdate request to update service configuration
|
||||
type ServiceConfigUpdate struct {
|
||||
Config map[string]interface{} `json:"config"` // Configuration updates
|
||||
Redeploy bool `json:"redeploy"` // Trigger recompilation/redeployment
|
||||
Fetch bool `json:"fetch"` // Fetch fresh templates before redeployment
|
||||
}
|
||||
|
||||
// ServiceConfigResponse response after config update
|
||||
type ServiceConfigResponse struct {
|
||||
Service string `json:"service"` // Service name
|
||||
Namespace string `json:"namespace"` // Kubernetes namespace
|
||||
Config map[string]interface{} `json:"config"` // Updated configuration
|
||||
Redeployed bool `json:"redeployed"` // Whether service was redeployed
|
||||
Message string `json:"message"` // Success/info message
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// Error Response
|
||||
// ==============================
|
||||
|
||||
// ErrorResponse standard error format for all endpoints
|
||||
type ErrorResponse struct {
|
||||
Error ErrorDetail `json:"error"`
|
||||
}
|
||||
|
||||
// ErrorDetail contains error information
|
||||
type ErrorDetail struct {
|
||||
Code string `json:"code"` // Machine-readable error code
|
||||
Message string `json:"message"` // Human-readable error message
|
||||
Details map[string]interface{} `json:"details,omitempty"` // Additional error context
|
||||
}
|
||||
|
||||
// Standard error codes
|
||||
const (
|
||||
ErrCodeNotFound = "SERVICE_NOT_FOUND"
|
||||
ErrCodeInstanceNotFound = "INSTANCE_NOT_FOUND"
|
||||
ErrCodeInvalidRequest = "INVALID_REQUEST"
|
||||
ErrCodeKubectlFailed = "KUBECTL_FAILED"
|
||||
ErrCodeConfigInvalid = "CONFIG_INVALID"
|
||||
ErrCodeDeploymentFailed = "DEPLOYMENT_FAILED"
|
||||
ErrCodeStreamingError = "STREAMING_ERROR"
|
||||
ErrCodeInternalError = "INTERNAL_ERROR"
|
||||
)
|
||||
|
||||
// ==============================
|
||||
// API Endpoint Specifications
|
||||
// ==============================
|
||||
|
||||
/*
|
||||
1. GET /api/v1/instances/{name}/services/{service}/status
|
||||
|
||||
Purpose: Returns comprehensive service status including pods and health
|
||||
Response Codes:
|
||||
- 200 OK: Service status retrieved successfully
|
||||
- 404 Not Found: Instance or service not found
|
||||
- 500 Internal Server Error: kubectl command failed
|
||||
|
||||
Example Request:
|
||||
GET /api/v1/instances/production/services/nginx/status
|
||||
|
||||
Example Response (200 OK):
|
||||
{
|
||||
"name": "nginx",
|
||||
"namespace": "nginx",
|
||||
"deploymentStatus": "Ready",
|
||||
"replicas": {
|
||||
"desired": 3,
|
||||
"current": 3,
|
||||
"ready": 3,
|
||||
"available": 3
|
||||
},
|
||||
"pods": [
|
||||
{
|
||||
"name": "nginx-7c5464c66d-abc123",
|
||||
"status": "Running",
|
||||
"ready": "1/1",
|
||||
"restarts": 0,
|
||||
"age": "2h",
|
||||
"node": "worker-1",
|
||||
"ip": "10.42.1.5"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"nginx.image": "nginx:1.21",
|
||||
"nginx.replicas": 3
|
||||
},
|
||||
"manifest": {
|
||||
"name": "nginx",
|
||||
"description": "NGINX web server",
|
||||
"namespace": "nginx"
|
||||
},
|
||||
"lastUpdated": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
|
||||
Example Error Response (404):
|
||||
{
|
||||
"error": {
|
||||
"code": "SERVICE_NOT_FOUND",
|
||||
"message": "Service nginx not found in instance production",
|
||||
"details": {
|
||||
"instance": "production",
|
||||
"service": "nginx"
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
2. GET /api/v1/instances/{name}/services/{service}/logs
|
||||
|
||||
Purpose: Retrieve or stream service logs
|
||||
Query Parameters:
|
||||
- container (string): Specific container name
|
||||
- tail (int): Number of lines from end (default: 100, max: 5000)
|
||||
- follow (bool): Stream logs via SSE (default: false)
|
||||
- previous (bool): Get previous container logs (default: false)
|
||||
- since (string): RFC3339 timestamp or duration (e.g. "10m")
|
||||
|
||||
Response Codes:
|
||||
- 200 OK: Logs retrieved successfully (or SSE stream started)
|
||||
- 400 Bad Request: Invalid query parameters
|
||||
- 404 Not Found: Instance, service, or container not found
|
||||
- 500 Internal Server Error: kubectl command failed
|
||||
|
||||
Example Request (buffered):
|
||||
GET /api/v1/instances/production/services/nginx/logs?tail=50
|
||||
|
||||
Example Response (200 OK):
|
||||
{
|
||||
"service": "nginx",
|
||||
"namespace": "nginx",
|
||||
"container": "nginx",
|
||||
"lines": [
|
||||
"2024/01/15 10:00:00 [notice] Configuration loaded",
|
||||
"2024/01/15 10:00:01 [info] Server started on port 80"
|
||||
],
|
||||
"truncated": false,
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
|
||||
Example Request (streaming):
|
||||
GET /api/v1/instances/production/services/nginx/logs?follow=true
|
||||
Accept: text/event-stream
|
||||
|
||||
Example SSE Response:
|
||||
data: {"type":"log","line":"2024/01/15 10:00:00 [notice] Configuration loaded","container":"nginx","timestamp":"2024-01-15T10:30:00Z"}
|
||||
|
||||
data: {"type":"log","line":"2024/01/15 10:00:01 [info] Request from 10.0.0.1","container":"nginx","timestamp":"2024-01-15T10:30:01Z"}
|
||||
|
||||
data: {"type":"error","error":"Container restarting","timestamp":"2024-01-15T10:30:02Z"}
|
||||
|
||||
data: {"type":"end","timestamp":"2024-01-15T10:30:03Z"}
|
||||
*/
|
||||
|
||||
/*
|
||||
3. PATCH /api/v1/instances/{name}/services/{service}/config
|
||||
|
||||
Purpose: Update service configuration in config.yaml and optionally redeploy
|
||||
Request Body: ServiceConfigUpdate (JSON)
|
||||
Response Codes:
|
||||
- 200 OK: Configuration updated successfully
|
||||
- 400 Bad Request: Invalid configuration
|
||||
- 404 Not Found: Instance or service not found
|
||||
- 500 Internal Server Error: Update or deployment failed
|
||||
|
||||
Example Request:
|
||||
PATCH /api/v1/instances/production/services/nginx/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"config": {
|
||||
"nginx.image": "nginx:1.22",
|
||||
"nginx.replicas": 5,
|
||||
"nginx.resources.memory": "512Mi"
|
||||
},
|
||||
"redeploy": true
|
||||
}
|
||||
|
||||
Example Response (200 OK):
|
||||
{
|
||||
"service": "nginx",
|
||||
"namespace": "nginx",
|
||||
"config": {
|
||||
"nginx.image": "nginx:1.22",
|
||||
"nginx.replicas": 5,
|
||||
"nginx.resources.memory": "512Mi"
|
||||
},
|
||||
"redeployed": true,
|
||||
"message": "Service configuration updated and redeployed successfully"
|
||||
}
|
||||
|
||||
Example Error Response (400):
|
||||
{
|
||||
"error": {
|
||||
"code": "CONFIG_INVALID",
|
||||
"message": "Invalid configuration: nginx.replicas must be a positive integer",
|
||||
"details": {
|
||||
"field": "nginx.replicas",
|
||||
"value": -1,
|
||||
"constraint": "positive integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// ==============================
|
||||
// Validation Rules
|
||||
// ==============================
|
||||
|
||||
/*
|
||||
Query Parameter Validation:
|
||||
|
||||
ServiceLogsRequest:
|
||||
- tail: Must be between 1 and 5000 (default: 100)
|
||||
- since: Must be valid RFC3339 timestamp or Go duration string (e.g. "5m", "1h")
|
||||
- container: Must match existing container name if specified
|
||||
- follow: When true, response uses Server-Sent Events (SSE)
|
||||
- previous: Cannot be combined with follow=true
|
||||
|
||||
ServiceConfigUpdate:
|
||||
- config: Must be valid YAML-compatible structure
|
||||
- config keys: Must follow service's expected configuration schema
|
||||
- redeploy: When true, triggers kustomize recompilation and kubectl apply
|
||||
|
||||
Path Parameters:
|
||||
- instance name: Must match existing instance directory
|
||||
- service name: Must match installed service name
|
||||
*/
|
||||
|
||||
// ==============================
|
||||
// HTTP Status Code Summary
|
||||
// ==============================
|
||||
|
||||
/*
|
||||
200 OK:
|
||||
- Service status retrieved successfully
|
||||
- Logs retrieved successfully (non-streaming)
|
||||
- Configuration updated successfully
|
||||
|
||||
400 Bad Request:
|
||||
- Invalid query parameters
|
||||
- Invalid configuration in request body
|
||||
- Validation errors
|
||||
|
||||
404 Not Found:
|
||||
- Instance does not exist
|
||||
- Service not installed in instance
|
||||
- Container name not found (for logs)
|
||||
|
||||
500 Internal Server Error:
|
||||
- kubectl command execution failed
|
||||
- File system operations failed
|
||||
- Unexpected errors during processing
|
||||
*/
|
||||
Reference in New Issue
Block a user