v0.42.0: agentic controller update — in-guest image swap + rollback (Phase 1)
New local-API POST /controller/swap (+ GET /controller/swap/status), withGuest- scoped: the agent records the previous image, confirms the target is present, rewrites /etc/felhom-controller-image, restarts felhom-controller-bootstrap.service, verifies the new controller is healthy (docker inspect, <=90s), and ROLLS BACK to the previous image if not. Single-flight per guest; strict image-ref validation; crash-safety state file. GuestBinder.GuestExec is the pct-exec seam. --selftest=controller-swap exercises it directly. Tests: happy/rollback-on-unhealthy(+red-proof)/image-absent/no-healthcheck/ bad-image-400/single-flight-409. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TtXesNa2LGbMmE4DNL6SE7
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-agent/internal/proxmox"
|
||||
@@ -110,3 +111,16 @@ func (b *GuestBinder) run(ctx context.Context, name string, args ...string) erro
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GuestExec runs a command INSIDE the guest via `pct exec <vmid> -- <args...>` and returns its stdout.
|
||||
// It is the single guest-exec seam the controller-swap primitive composes over (cat the image file,
|
||||
// docker image-inspect, write the file, systemctl restart, docker inspect health) — reusing the same
|
||||
// fenced root runner as the bind ops rather than hand-rolling pct. The guest must be running.
|
||||
func (b *GuestBinder) GuestExec(ctx context.Context, vmid int, args ...string) (string, error) {
|
||||
pctArgs := append([]string{"exec", strconv.Itoa(vmid), "--"}, args...)
|
||||
out, stderr, err := b.runner.Run(ctx, "pct", pctArgs...)
|
||||
if err != nil {
|
||||
return string(out), fmt.Errorf("pct exec %d %v: %w: %s", vmid, args, err, strings.TrimSpace(string(stderr)))
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user