hub v0.13.1 — DR recipe v1 drive-shape sync (test-data + regression guard only)
Tracks felhom-agent v0.39.0, which dropped role + restic_repo_coord from the host-half drives[]. Hub reads drives as json.RawMessage (verbatim passthrough) → no store/handler change needed. Dropped role from the store golden + drHostHalf fixture; re-synced the api host-report golden byte-identical with the agent copy (it previously lacked dr_recipe entirely). Added TestAssembleDRRecipe_V1DriveShape regression guard (demonstrated to fail when the fixture re-adds role, then reverted). No behavior change; redeploy optional. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+24
-1
@@ -131,5 +131,28 @@
|
||||
}
|
||||
],
|
||||
"cloudflared": { "status": "active" },
|
||||
"audit_tail": []
|
||||
"audit_tail": [],
|
||||
"dr_recipe": {
|
||||
"recipe_version": 1,
|
||||
"guests": [
|
||||
{ "vmid": 100, "cores": 2, "memory_bytes": 2147483648, "disk_bytes": 21474836480 }
|
||||
],
|
||||
"pbs": {
|
||||
"repo_id": "felhom-pbs",
|
||||
"namespace": "root",
|
||||
"latest_snapshot_id": "9001"
|
||||
},
|
||||
"drives": [
|
||||
{
|
||||
"durable_id": "uuid:0fc63daf-8483-4772-8e79-3d69d8477de4",
|
||||
"mount_path": "/mnt/usb-backup",
|
||||
"intent": "enrolled",
|
||||
"total_bytes": 2000000000000
|
||||
}
|
||||
],
|
||||
"pve_storage": [
|
||||
{ "name": "local-lvm", "type": "lvmthin", "content": "rootdir,images" },
|
||||
{ "name": "usb-backup", "type": "usb", "content": "backup" }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ const drHostHalf = `{
|
||||
"recipe_version": 1,
|
||||
"guests": [ { "vmid": 9201, "cores": 4, "memory_bytes": 12884901888, "disk_bytes": 34359738368 } ],
|
||||
"pbs": { "repo_id": "felhom-pbs", "namespace": "root", "latest_snapshot_id": "9201" },
|
||||
"drives": [ { "durable_id": "uuid:da9e7089-cf8e-4617-adcb-a377743fae00", "role": "bulk-data", "mount_path": "/mnt/felhom-usb", "intent": "enrolled", "total_bytes": 1000000000000 } ],
|
||||
"drives": [ { "durable_id": "uuid:da9e7089-cf8e-4617-adcb-a377743fae00", "mount_path": "/mnt/felhom-usb", "intent": "enrolled", "total_bytes": 1000000000000 } ],
|
||||
"pve_storage": [ { "name": "local-lvm", "type": "lvmthin", "content": "rootdir,images" }, { "name": "felhom-usb", "type": "usb", "content": "backup" } ]
|
||||
}`
|
||||
|
||||
@@ -104,6 +104,35 @@ func TestAssembleDRRecipe_MatchesGolden(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestAssembleDRRecipe_V1DriveShape is the regression guard for the v1 host-half drive shape
|
||||
// (agent v0.39.0 dropped role + restic_repo_coord): a stored host half whose drives carry NEITHER
|
||||
// field, but WHICH HAS a pbs block, must assemble cleanly — pbs present, drives passed through
|
||||
// verbatim (RawMessage passthrough means the hub needs no struct change for the dropped fields).
|
||||
func TestAssembleDRRecipe_V1DriveShape(t *testing.T) {
|
||||
const v1Host = `{
|
||||
"recipe_version": 1,
|
||||
"guests": [ { "vmid": 9201, "cores": 4, "memory_bytes": 12884901888, "disk_bytes": 34359738368 } ],
|
||||
"pbs": { "repo_id": "felhom-pbs", "namespace": "root", "latest_snapshot_id": "9201" },
|
||||
"drives": [ { "durable_id": "uuid:da9e7089", "mount_path": "/mnt/felhom-usb", "intent": "enrolled", "total_bytes": 1000000000000 } ],
|
||||
"pve_storage": [ { "name": "felhom-usb", "type": "usb", "content": "backup" } ]
|
||||
}`
|
||||
asm, err := AssembleDRRecipe(&DRRecipe{CustomerID: "c", RecipeVersion: 1, HostHalfJSON: v1Host})
|
||||
if err != nil {
|
||||
t.Fatalf("v1 host half failed to assemble: %v", err)
|
||||
}
|
||||
// pbs must survive the stitch.
|
||||
if !jsonContains(t, asm.PBS, "felhom-pbs") || !jsonContains(t, asm.PBS, "9201") {
|
||||
t.Errorf("pbs coord not carried through assembly: %s", asm.PBS)
|
||||
}
|
||||
// drives passed through verbatim, and carry NEITHER dropped field.
|
||||
if !jsonContains(t, asm.Drives, "uuid:da9e7089") {
|
||||
t.Errorf("drives not passed through: %s", asm.Drives)
|
||||
}
|
||||
if strings.Contains(string(asm.Drives), "role") || strings.Contains(string(asm.Drives), "restic_repo_coord") {
|
||||
t.Errorf("v1 drives must not carry role/restic_repo_coord: %s", asm.Drives)
|
||||
}
|
||||
}
|
||||
|
||||
// TestAssembleDRRecipe_IgnoreUnknownAndVersionSkew: a half carrying an UNKNOWN top-level field and a
|
||||
// HIGHER recipe_version still assembles (forward-compat), and recipe_version reflects the max.
|
||||
func TestAssembleDRRecipe_IgnoreUnknownAndVersionSkew(t *testing.T) {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
"drives": [
|
||||
{
|
||||
"durable_id": "uuid:da9e7089-cf8e-4617-adcb-a377743fae00",
|
||||
"role": "bulk-data",
|
||||
"mount_path": "/mnt/felhom-usb",
|
||||
"intent": "enrolled",
|
||||
"total_bytes": 1000000000000
|
||||
|
||||
Reference in New Issue
Block a user