mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-19 07:33:18 +02:00
Replace SpoolBuddy self-update with SSH-based updates from Bambuddy
The daemon's self-update mechanism (git fetch/reset on its own code) was fragile: .git permission errors, self-modifying code mid-run, hardcoded main branch. Bambuddy now SSHes into the SpoolBuddy Pi and drives the update remotely — matching its own branch, with step-by-step progress via WebSocket. Install script updated with SSH access, sudoers entry, and --ssh-pubkey flag for pairing.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""SpoolBuddy device management API routes."""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
@@ -597,10 +598,17 @@ async def check_daemon_update(
|
||||
@router.post("/devices/{device_id}/update")
|
||||
async def trigger_daemon_update(
|
||||
device_id: str,
|
||||
req: dict | None = None,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User | None = RequirePermissionIfAuthEnabled(Permission.SETTINGS_UPDATE),
|
||||
):
|
||||
"""Trigger a daemon update on the SpoolBuddy device via pending_command."""
|
||||
"""Trigger a SpoolBuddy update over SSH.
|
||||
|
||||
Bambuddy SSHes into the device, pulls the matching branch, installs deps,
|
||||
and restarts the daemon. Progress is broadcast via WebSocket.
|
||||
"""
|
||||
from backend.app.services.spoolbuddy_ssh import perform_ssh_update
|
||||
|
||||
result = await db.execute(select(SpoolBuddyDevice).where(SpoolBuddyDevice.device_id == device_id))
|
||||
device = result.scalar_one_or_none()
|
||||
if not device:
|
||||
@@ -612,12 +620,11 @@ async def trigger_daemon_update(
|
||||
if device.update_status == "updating":
|
||||
return {"status": "already_updating", "message": "Update already in progress"}
|
||||
|
||||
device.pending_command = "update"
|
||||
device.update_status = "pending"
|
||||
device.update_message = "Waiting for device to pick up update command..."
|
||||
device.update_message = "Starting SSH update..."
|
||||
await db.commit()
|
||||
|
||||
logger.info("SpoolBuddy %s: update command queued", device_id)
|
||||
logger.info("SpoolBuddy %s: SSH update triggered (ip=%s)", device_id, device.ip_address)
|
||||
await ws_manager.broadcast(
|
||||
{
|
||||
"type": "spoolbuddy_update",
|
||||
@@ -626,7 +633,24 @@ async def trigger_daemon_update(
|
||||
}
|
||||
)
|
||||
|
||||
return {"status": "ok", "message": "Update command sent to device"}
|
||||
# Run the SSH update in the background
|
||||
asyncio.create_task(perform_ssh_update(device_id, device.ip_address))
|
||||
|
||||
return {"status": "ok", "message": "SSH update started"}
|
||||
|
||||
|
||||
@router.get("/ssh/public-key")
|
||||
async def get_ssh_public_key(
|
||||
_: User | None = RequirePermissionIfAuthEnabled(Permission.SETTINGS_READ),
|
||||
):
|
||||
"""Return the SSH public key for SpoolBuddy pairing."""
|
||||
from backend.app.services.spoolbuddy_ssh import get_public_key
|
||||
|
||||
try:
|
||||
key = await get_public_key()
|
||||
return {"public_key": key}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to get SSH key: {e}") from e
|
||||
|
||||
|
||||
@router.post("/devices/{device_id}/update-status")
|
||||
|
||||
Reference in New Issue
Block a user