Old kernels removed by the box (R-1368, wrapper mode kernel-cleanup); security profiles refreshed after a kernel change (R-1388, mode profile-refresh); Go 1.27.4 (R-1391)
gates / gates (push) Successful in 40s
gates / gates (push) Successful in 40s
This commit is contained in:
1 parent
91a2924ad0
commit
cc63dd5204
11 files changed
+1542
-10
No files matched your search
@@ -0,0 +1,97 @@
|
||||
package osupdate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-agent/internal/hub"
|
||||
)
|
||||
|
||||
// ---- the security-profile refresh (R-1388, R-1301, `11` §5.12) ----
|
||||
|
||||
func profileCalls(w *fakeWrapper) []map[string]any {
|
||||
var m []map[string]any
|
||||
for _, p := range w.plans {
|
||||
if p["mode"] == "profile-refresh" {
|
||||
m = append(m, p)
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func refreshed() *WrapperReport {
|
||||
return &WrapperReport{ProfileRefresh: json.RawMessage(`{"outcome":"refreshed","kernel":"7.0.14-28-pve","rewritten":["f6da0254.0/usr.sbin.chronyd"],` +
|
||||
`"restarted":[{"unit":"chrony.service","program":"/usr/sbin/chronyd","rc":0,"active":true}],"seconds":0.5}`)}
|
||||
}
|
||||
|
||||
// One call, a host-layer plan that names NOTHING, and nothing to the hub.
|
||||
// COMPANION RED-PROOF (observed): add "units" to the plan → this test fails; drop the Appliance check → the BYO test fails.
|
||||
func TestProfileRefresh_OneCallNoNamesNoHubReport(t *testing.T) {
|
||||
w := &fakeWrapper{t: t, profileRep: refreshed()}
|
||||
l, h := newLeg(t, w, &hub.WireOSUpdate{Ring: 1, Enabled: true})
|
||||
if got := l.ProfileRefresh(context.Background(), "agent start", nil, 1, time.Second); got != "refreshed" {
|
||||
t.Fatalf("outcome = %q", got)
|
||||
}
|
||||
pc := profileCalls(w)
|
||||
if len(pc) != 1 {
|
||||
t.Fatalf("calls = %d", len(pc))
|
||||
}
|
||||
if len(pc[0]) != 3 || pc[0]["layer"] != LayerHost || pc[0]["release_id"] != "profile-refresh" {
|
||||
t.Fatalf("the plan carries more than release_id, layer and mode: %v", pc[0])
|
||||
}
|
||||
if len(h.reports) != 0 {
|
||||
t.Fatalf("the hub got a report: %+v", h.reports)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileRefresh_ByoHostIsNeverAsked(t *testing.T) {
|
||||
w := &fakeWrapper{t: t, profileRep: refreshed()}
|
||||
l, _ := newLeg(t, w, nil)
|
||||
l.Appliance = false
|
||||
if got := l.ProfileRefresh(context.Background(), "agent start", nil, 1, time.Second); got != "" || len(profileCalls(w)) != 0 {
|
||||
t.Fatalf("a BYO host was asked: %q %v", got, profileCalls(w))
|
||||
}
|
||||
}
|
||||
|
||||
// The heavy-op gate: busy → wait and ask again; still busy after the tries → not run (the next start asks again).
|
||||
// COMPANION RED-PROOF (observed): ignore `ok` from the gate → the "always busy" half fails.
|
||||
func TestProfileRefresh_WaitsForTheHeavyOpGate(t *testing.T) {
|
||||
w := &fakeWrapper{t: t, profileRep: refreshed()}
|
||||
l, _ := newLeg(t, w, nil)
|
||||
n, released := 0, 0
|
||||
gate := func() (func(), string, bool) {
|
||||
n++
|
||||
if n < 3 {
|
||||
return nil, "primary-backup", false
|
||||
}
|
||||
return func() { released++ }, "", true
|
||||
}
|
||||
if got := l.ProfileRefresh(context.Background(), "agent start", gate, 5, time.Minute); got != "refreshed" {
|
||||
t.Fatalf("outcome = %q after %d gate tries", got, n)
|
||||
}
|
||||
if n != 3 || released != 1 || len(profileCalls(w)) != 1 {
|
||||
t.Fatalf("gate tries %d, released %d, calls %d", n, released, len(profileCalls(w)))
|
||||
}
|
||||
w2 := &fakeWrapper{t: t, profileRep: refreshed()}
|
||||
l2, _ := newLeg(t, w2, nil)
|
||||
busy := func() (func(), string, bool) { return nil, "restore-test", false }
|
||||
if got := l2.ProfileRefresh(context.Background(), "agent start", busy, 3, time.Minute); got != "" || len(profileCalls(w2)) != 0 {
|
||||
t.Fatalf("ran beside a heavy operation: %q %d call(s)", got, len(profileCalls(w2)))
|
||||
}
|
||||
}
|
||||
|
||||
// An older wrapper refuses the mode: logged, nothing else. A failure is said as "failed".
|
||||
func TestProfileRefresh_RefusedAndFailed(t *testing.T) {
|
||||
w := &fakeWrapper{t: t, profileRep: &WrapperReport{Refused: json.RawMessage(`{"code":"R11","reason":"unknown mode 'profile-refresh'"}`)}}
|
||||
l, _ := newLeg(t, w, nil)
|
||||
if got := l.ProfileRefresh(context.Background(), "agent start", nil, 1, time.Second); got != "" {
|
||||
t.Fatalf("refused → %q", got)
|
||||
}
|
||||
w2 := &fakeWrapper{t: t, profileRep: &WrapperReport{Failed: json.RawMessage(`{"rc":1,"step":"profile-refresh"}`)}}
|
||||
l2, _ := newLeg(t, w2, nil)
|
||||
if got := l2.ProfileRefresh(context.Background(), "agent start", nil, 1, time.Second); got != "failed" {
|
||||
t.Fatalf("failed → %q", got)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user