ac112c956e
MinAgent coupling: felhom-controller v0.143.0 gates its guest-memory-resize UI on this agent (FeatureGuestMemoryResize, MinAgent 0.90.0). R-24 guest RAM resize (internal/localapi/guestmemory.go): self-scoped GET/POST /guest/memory. Agent enforces every bound FRESH per request (min 2048, max host_total-2048, shrink floor max(2048, usage+512)); applies via PVE SetConfig — live cgroup apply, no reboot (Phase-0 proven on the nested demo box). Verify-after-apply re-reads maxmem before claiming success. New narrow MemoryOps seam (GuestAPI untouched); Options.Memory nil -> 503. Memory only. R-28 fast-tick (internal/fasttick): while any desired-state item is unapplied - including the pre-tunnel window a hub poke can't reach - pulse the shared out-of-band trigger every 30s, self-disarm on convergence. Four cached sources (desired-gen==0, reconcile Planned-Pending>0, pbsdr waiting_secret only, wgtunnel desired-not-operational); LOUD pbsdr states + pending_signature excluded. Seams: reconcile.Engine.LastResult() + wgtunnel.Manager.TunnelConvergence() (cached, no per-tick exec). Guests-0/0: hypothesis REFUTED live (9201 IS a pool member; 0/0 was the pre-provision window; PoolAddVMID re-assert already covers restore-over-existing). No code change; the fast-tick mitigates the window. Tests + red-proofs (i floor guard, ii max guard, iii always-pulse) all restored green.
33 lines
846 B
Go
33 lines
846 B
Go
package reconcile
|
||
|
||
import (
|
||
"context"
|
||
"testing"
|
||
|
||
"gitea.dooplex.hu/admin/felhom-agent/internal/proxmox"
|
||
)
|
||
|
||
// LastResult (v0.90.0, R-28 fast-tick source): false until the first successful pass, then it
|
||
// mirrors the pass Result. The fast-tick reads Planned − Pending > 0 off it.
|
||
func TestEngine_LastResult(t *testing.T) {
|
||
api := &fakeAPI{
|
||
lxc: []proxmox.Guest{{VMID: 100, Status: "running"}},
|
||
cfg: map[int]proxmox.GuestConfig{100: {Cores: 2}},
|
||
}
|
||
e, _, _ := newEngine(t, api, EmptyProvider{})
|
||
|
||
if _, ok := e.LastResult(); ok {
|
||
t.Fatal("LastResult ok=true before any pass, want false")
|
||
}
|
||
|
||
e.reconcileOnce(context.Background())
|
||
|
||
res, ok := e.LastResult()
|
||
if !ok {
|
||
t.Fatal("LastResult not recorded after a reconcile pass")
|
||
}
|
||
if res.Planned != 0 || res.Pending != 0 {
|
||
t.Errorf("converged pass recorded drift: %+v", res)
|
||
}
|
||
}
|