Skip to content

feat(slm): implement autobot-backend Docker deployment API bridge (SLM → Ansible → Docker)#3416

Merged
mrveiss merged 2 commits intoDev_new_guifrom
issue-3407
Apr 3, 2026
Merged

feat(slm): implement autobot-backend Docker deployment API bridge (SLM → Ansible → Docker)#3416
mrveiss merged 2 commits intoDev_new_guifrom
issue-3407

Conversation

@mrveiss
Copy link
Copy Markdown
Owner

@mrveiss mrveiss commented Apr 3, 2026

Summary

  • models/infrastructure.py: new PortMapping, DockerContainerSpec, DockerDeploymentRequest, DockerDeploymentStatus Pydantic models
  • services/slm/deployment_orchestrator.py: SLMDeploymentOrchestrator — wraps SLM HTTP client to call POST /deployments with playbook + extra_vars built from container spec; provides deploy_docker(), get_deployment(), list_deployments()
  • api/slm/deployments.py: real implementation replacing mock-only stub — POST /api/v1/slm/deployments/docker, GET /api/v1/slm/deployments/{id}, GET /api/v1/slm/deployments
  • initialization/router_registry/feature_routers.py: registered the new SLM deployments router
  • deployments_api_test.py: updated to use SLMDeploymentOrchestrator with httpx test-double instead of raw MagicMock
  • docs/guides/slm-docker-ansible-deployment.md: added "Trigger from AutoBot Backend" section with Python example using the new endpoint

Closes #3407

)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

✅ SSOT Configuration Compliance: Passing

🎉 No hardcoded values detected that have SSOT config equivalents!

@mrveiss
Copy link
Copy Markdown
Owner Author

mrveiss commented Apr 3, 2026

Code review

Found 4 issues.

  1. Orchestrator singleton is never initialized — all 5 generic deployment endpoints always return 503 (init_orchestrator() is defined in the new module but never wired into initialization/lifespan.py or any app startup path; _orchestrator stays None for the lifetime of the process)
    https://github.com/mrveiss/AutoBot-AI/blob/b1b38a7c3a4f1af0164ca28e90d5bfc78cbdfd65/autobot-backend/services/slm/deployment_orchestrator.py#L850-L863

  2. execute_deployment sets ctx.status = RUNNING but starts no actual work — no async task is spawned, no SLM call is made; callers will see "running" status with nothing executing behind it

    @router.post("/{deployment_id}/cancel", summary="Cancel a deployment")
    async def cancel_deployment(
    deployment_id: str,
    orch: DeploymentOrchestrator = Depends(_require_orchestrator),

  3. deploy_docker bypasses the _require_orchestrator dependency and accesses orch._client directly to construct a SLMDeploymentOrchestrator — couples the API layer to a private implementation detail and duplicates the 503 guard logic inline

    from services.slm.deployment_orchestrator import SLMDeploymentOrchestrator
    slm_orch = SLMDeploymentOrchestrator(orch._client)
    result = await slm_orch.deploy_docker(request)
    logger.info(
    "Docker deployment triggered: %s on node %s",
    result.deployment_id,
    result.node_id,
    )
    return result

  4. Registry tuple uses "/v1" as the prefix — no other entry in FEATURE_ROUTER_CONFIGS uses /v1; app_factory mounts as /api/v1/slm/deployments/... which deviates from the established convention of domain-specific prefixes (e.g. "/conversations", "") and will create a path inconsistency if a real API versioning scheme is introduced later

    Args:
    module_path: Full Python module path (e.g., 'backend.api.workflow')
    prefix: URL prefix for the router (e.g., '/workflow')
    tags: List of OpenAPI tags for the router
    name: Human-readable name for logging

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

… fix deploy_docker dependency; remove /v1 prefix

- lifespan.py: call init_orchestrator(get_slm_client()) after SLM client init so the
  singleton is never None at request time
- deployment_orchestrator.py: implement execute_deployment() — transitions
  QUEUED→RUNNING, fans SLM create_deployment calls per target node,
  transitions to COMPLETED/FAILED
- deployments.py: execute_deployment API calls orch.execute_deployment() instead
  of setting ctx.status silently; deploy_docker uses get_slm_client() directly
  instead of accessing private orch._client
- feature_routers.py: remove non-standard /v1 prefix — router already prefixes
  /slm/deployments, yielding /api/slm/deployments to match all other routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mrveiss mrveiss merged commit 8707de5 into Dev_new_gui Apr 3, 2026
2 of 3 checks passed
@mrveiss mrveiss deleted the issue-3407 branch April 3, 2026 20:54
@mrveiss
Copy link
Copy Markdown
Owner Author

mrveiss commented Apr 3, 2026

Code review

Found 1 additional issue not covered by the existing review.

Missing authentication on all 7 deployment endpoints (score: 100)

None of the new routes in autobot-backend/api/slm/deployments.py have an auth dependency. Every other sensitive API endpoint in this codebase uses Depends(get_current_user) from auth_middleware. As written, anyone who can reach the backend can trigger, cancel, or roll back Docker deployments without a valid session.

Affected routes: POST /slm/deployments/docker, POST /slm/deployments, GET /slm/deployments, GET /slm/deployments/{id}, POST /slm/deployments/{id}/execute, POST /slm/deployments/{id}/cancel, POST /slm/deployments/{id}/rollback.

Fix: add current_user: dict = Depends(get_current_user) to each route handler (or apply it as a router-level dependency).

from auth_middleware import get_current_user

@router.post("/docker", ...)
async def deploy_docker(
    request: DockerDeploymentRequest,
    current_user: dict = Depends(get_current_user),
) -> DockerDeploymentStatus:

@router.post(
"/docker",
response_model=DockerDeploymentStatus,
status_code=status.HTTP_202_ACCEPTED,
summary="Trigger a Docker container deployment via SLM",
)
async def deploy_docker(request: DockerDeploymentRequest) -> DockerDeploymentStatus:
"""
Trigger deployment of one or more Docker containers on the target node.
The SLM runs the configured Ansible playbook (default:
deploy-hybrid-docker.yml) and returns a deployment record.
"""
orch = get_orchestrator()
if orch is None:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Deployment orchestrator not initialised",
)
from services.slm.deployment_orchestrator import SLMDeploymentOrchestrator
slm_orch = SLMDeploymentOrchestrator(orch._client)
result = await slm_orch.deploy_docker(request)
logger.info(
"Docker deployment triggered: %s on node %s",
result.deployment_id,
result.node_id,
)
return result


The 4 issues from the prior review (orchestrator never initialised, execute sets RUNNING but spawns no work, deploy_docker bypasses _require_orchestrator, /v1 prefix deviation) also stand.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant