feat: provision shared database as hidden infrastructure
The shared dcntrlized-db Postgres service is now treated as Maestro infrastructure: it is hidden from the service grid and auto-started before any app container when already installed. - Container model gains role/hidden/capabilities; registry items gain hidden; installed metadata persists manifest capabilities so stopped services still surface them. - Registry marks the shared database image as hidden (OCI annotation, label, or name fallback). - Compose label rewrite merges existing service labels instead of replacing them, so org.dcntrlized.role/hidden survive. - New infra helpers ensure the external dcntrlized_net network and start the database on the prod path and before each StartContainer. - Watcher skips manifest fetch for db-role containers and persists capabilities from the manifest. - spec.yaml documents the new fields.
This commit is contained in:
@@ -0,0 +1,389 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Dcntrlized Maestro API
|
||||
version: 1.0.0
|
||||
description: The API of the Maestro orchestration router. Maestro manages the lifecycle of Dcntrlized service containers and routes inter-service action calls to them.
|
||||
|
||||
components:
|
||||
schemas:
|
||||
ActionRequest:
|
||||
type: object
|
||||
properties:
|
||||
payload:
|
||||
type: object
|
||||
description: Action-specific parameters
|
||||
ActionResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
data:
|
||||
type: object
|
||||
|
||||
SuccessResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: "success"
|
||||
message:
|
||||
type: string
|
||||
|
||||
RegistryContainer:
|
||||
type: object
|
||||
required: [name, image]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: "keepnote"
|
||||
version:
|
||||
type: string
|
||||
example: "0.0.1"
|
||||
image:
|
||||
type: string
|
||||
example: "git.dcntrlized.org/Dcntrlized/keepnote/keepnote:0.0.1"
|
||||
digest:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
example: "KeepNote"
|
||||
vendor:
|
||||
type: string
|
||||
author:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
source:
|
||||
type: string
|
||||
revision:
|
||||
type: string
|
||||
licenses:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
documentation:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
hidden:
|
||||
type: boolean
|
||||
description: Hidden infrastructure containers (e.g. the shared dcntrlized-db) are excluded from the service grid.
|
||||
example: true
|
||||
|
||||
PortMapping:
|
||||
type: object
|
||||
properties:
|
||||
host:
|
||||
type: integer
|
||||
guest:
|
||||
type: integer
|
||||
|
||||
IPAddress:
|
||||
type: object
|
||||
properties:
|
||||
version:
|
||||
type: string
|
||||
enum: [v4, v6]
|
||||
address:
|
||||
type: string
|
||||
|
||||
Network:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
ipAddress:
|
||||
$ref: '#/components/schemas/IPAddress'
|
||||
mode:
|
||||
type: string
|
||||
enum: [bridge, host, none, overlay, ipvlan, macvlan]
|
||||
ports:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PortMapping'
|
||||
|
||||
Container:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
service_name:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
example: "db"
|
||||
hidden:
|
||||
type: boolean
|
||||
description: Hidden infrastructure containers (e.g. the shared dcntrlized-db) are excluded from the service grid.
|
||||
capabilities:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: "database"
|
||||
description: Capabilities declared by the service manifest (e.g. database).
|
||||
docker_name:
|
||||
type: string
|
||||
image:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
network:
|
||||
$ref: '#/components/schemas/Network'
|
||||
title:
|
||||
type: string
|
||||
vendor:
|
||||
type: string
|
||||
author:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
source:
|
||||
type: string
|
||||
|
||||
paths:
|
||||
/api/actions/{containerId}/{actionName}:
|
||||
parameters:
|
||||
- name: actionName
|
||||
in: path
|
||||
required: true
|
||||
description: The name of the specific action to execute
|
||||
schema:
|
||||
type: string
|
||||
- name: containerId
|
||||
in: path
|
||||
required: true
|
||||
description: The ID or name of the target container/service. Accepts a full or partial container ID, a container name, or the service name (matched case-insensitively).
|
||||
schema:
|
||||
type: string
|
||||
get:
|
||||
summary: Retrieve data or status from a service action
|
||||
tags: ["actions"]
|
||||
description: Forwards the request (method, headers, query string, and body) to the target container's /action/{actionName} endpoint. The target service is responsible for authentication; any client-supplied auth headers are forwarded as-is.
|
||||
responses:
|
||||
'200':
|
||||
description: Request successful
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ActionResponse'
|
||||
'400':
|
||||
description: Bad Request - Invalid input parameters
|
||||
'401':
|
||||
description: Unauthorized - the target service rejected the request
|
||||
'404':
|
||||
description: Action or container not found
|
||||
'500':
|
||||
description: Failed to forward the request to the container
|
||||
post:
|
||||
summary: Execute a state-changing action in the service
|
||||
tags: ["actions"]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ActionRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Action executed successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ActionResponse'
|
||||
'400':
|
||||
description: Bad Request - Invalid input parameters
|
||||
'401':
|
||||
description: Unauthorized - the target service rejected the request
|
||||
'404':
|
||||
description: Action or container not found
|
||||
'500':
|
||||
description: Failed to forward the request to the container
|
||||
put:
|
||||
summary: Update configuration for a specific action
|
||||
tags: ["actions"]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ActionRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Configuration updated
|
||||
'400':
|
||||
description: Bad Request - Invalid input parameters
|
||||
'401':
|
||||
description: Unauthorized - the target service rejected the request
|
||||
'404':
|
||||
description: Action or container not found
|
||||
'500':
|
||||
description: Failed to forward the request to the container
|
||||
delete:
|
||||
tags: ["actions"]
|
||||
summary: Reset or remove an action's state
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ActionRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Action state reset
|
||||
'400':
|
||||
description: Bad Request - Invalid input parameters
|
||||
'401':
|
||||
description: Unauthorized - the target service rejected the request
|
||||
'404':
|
||||
description: Action or container not found
|
||||
'500':
|
||||
description: Failed to forward the request to the container
|
||||
|
||||
/api/containers:
|
||||
get:
|
||||
summary: List the services Maestro manages
|
||||
tags: ["containers"]
|
||||
responses:
|
||||
'200':
|
||||
description: List of services
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Container'
|
||||
'500':
|
||||
description: Internal server error
|
||||
|
||||
/api/containers/install:
|
||||
post:
|
||||
summary: Install a service container (downloads the compose file and pulls the image)
|
||||
tags: ["containers"]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RegistryContainer'
|
||||
responses:
|
||||
'200':
|
||||
description: Container downloaded and image pulled successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuccessResponse'
|
||||
'400':
|
||||
description: Invalid JSON payload or missing required fields (name, image)
|
||||
'500':
|
||||
description: Failed to install container
|
||||
|
||||
/api/containers/uninstall:
|
||||
post:
|
||||
summary: Uninstall a service container and remove it from the cache
|
||||
tags: ["containers"]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [name]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Container uninstalled successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuccessResponse'
|
||||
'400':
|
||||
description: Invalid JSON payload or missing required field (name)
|
||||
'500':
|
||||
description: Failed to uninstall container
|
||||
|
||||
/api/containers/start:
|
||||
post:
|
||||
summary: Start a previously installed service container
|
||||
tags: ["containers"]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [name]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Container started successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuccessResponse'
|
||||
'400':
|
||||
description: Invalid JSON payload or missing required field (name)
|
||||
'500':
|
||||
description: Failed to start container
|
||||
|
||||
/api/containers/stop:
|
||||
post:
|
||||
summary: Stop a running service container
|
||||
tags: ["containers"]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [name]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Container stopped successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuccessResponse'
|
||||
'400':
|
||||
description: Invalid JSON payload or missing required field (name)
|
||||
'500':
|
||||
description: Failed to stop container
|
||||
|
||||
/api/registry:
|
||||
get:
|
||||
summary: List the services available in the Dcntrlized registry
|
||||
tags: ["registry"]
|
||||
responses:
|
||||
'200':
|
||||
description: List of registry services
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RegistryContainer'
|
||||
'500':
|
||||
description: Internal server error
|
||||
'502':
|
||||
description: Failed to connect to upstream registry
|
||||
|
||||
/api/ws:
|
||||
get:
|
||||
summary: WebSocket endpoint for live container events
|
||||
tags: ["containers"]
|
||||
description: Establishes a WebSocket connection that streams container lifecycle events as JSON.
|
||||
responses:
|
||||
'101':
|
||||
description: Switching Protocols - WebSocket upgrade
|
||||
Reference in New Issue
Block a user