578cc33cc0
Wires the agent's enriched + swarm payloads through the docker.persist_host_
samples capability:
* Swarm topology — persist sample["swarm"] into docker_swarm_services /
docker_swarm_nodes (upsert + prune stale, host-scoped so two managers don't
clobber). Migration docker_005 adds services.placement_json for the
task→node placement the agent now reports.
* Lifecycle events — _derive_events (pure, unit-tested) diffs the newest
snapshot against stored per-container state: start / stop / die (non-zero
exit) / oom / health_change → docker_events rows. Skipped on a host's first
snapshot so the baseline doesn't emit a start per existing container.
* Alerts — record restart_count (always) and is_healthy (1.0/0.0, only when a
HEALTHCHECK exists) alongside cpu/mem, under host-scoped resource names;
METRIC_CATALOG[docker] gains restart_count + is_healthy so they're alertable.
host_agent ingest captures the newest sample's swarm object and threads it to
the capability (now persist_host_docker(session, host, snapshots, swarm=None));
invoked when containers OR swarm are present, under the same SAVEPOINT. Unit
tests cover the event-diff matrix; integration tests cover event derivation
across two snapshots and swarm topology round-trip (incl. placement).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Jg27rgypiW2efULXJDtMC
30 lines
993 B
Python
30 lines
993 B
Python
"""Docker swarm service placement column
|
|
|
|
Adds docker_swarm_services.placement_json — the task→node placement of a
|
|
service's running replicas, captured from the agent's swarm payload (a manager
|
|
sees every task, so this records cross-node placement the local container rows
|
|
can't). Additive column; no DROP+recreate.
|
|
|
|
Revision ID: docker_005_swarm_placement
|
|
Revises: docker_004_events_swarm
|
|
Create Date: 2026-06-19
|
|
"""
|
|
from typing import Sequence, Union
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision: str = "docker_005_swarm_placement"
|
|
down_revision: Union[str, None] = "docker_004_events_swarm"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.add_column("docker_swarm_services",
|
|
sa.Column("placement_json", sa.Text, nullable=False,
|
|
server_default="[]"))
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_column("docker_swarm_services", "placement_json")
|