v0.52.0: operator-opt-in CPU/RAM cap for the provisioned guest (-cores/-memory)

New -cores N / -memory M (MiB) flags for --selftest=bring-up|provision (0 = keep
golden default), flowed through bringUpSizing into reconcile.BringUpSpec so the
existing buildBringUpConfig emits cores/memory into the pre-start config PUT (the
cap lands before first boot). No engine change. New pure-function test
TestBuildBringUpConfig_ResourceCaps asserts the set + omit-when-zero cases
(red-proof run + reverted). go build/vet/test clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-01 08:03:57 +02:00
parent 1502ca644a
commit 0573ec95c1
4 changed files with 70 additions and 4 deletions
+27
View File
@@ -92,6 +92,33 @@ func TestBuildBringUpConfig_BackupFlagOnDataMount(t *testing.T) {
}
}
// The operator-opt-in CPU/RAM cap is emitted into the SAME pre-start config PUT (so the guest never
// boots uncapped), and — critically — is OMITTED when unset (0), so an uncapped provision keeps the
// golden's baked sizes instead of being shrunk to 0. Pure-function check on buildBringUpConfig.
func TestBuildBringUpConfig_ResourceCaps(t *testing.T) {
// caps set → both keys present, MiB integer for memory
capped := buildBringUpConfig(BringUpSpec{
Mode: ModeProvision, Cores: 2, MemoryMB: 4096,
}, scratchCfg())
if capped["cores"] != "2" {
t.Errorf("cores cap must be emitted: cores=%q", capped["cores"])
}
if capped["memory"] != "4096" {
t.Errorf("memory cap must be emitted (MiB): memory=%q", capped["memory"])
}
// caps unset (0) → NEITHER key present (omit-when-zero; else the guest would shrink to 0 cores)
uncapped := buildBringUpConfig(BringUpSpec{
Mode: ModeProvision, Cores: 0, MemoryMB: 0,
}, scratchCfg())
if _, ok := uncapped["cores"]; ok {
t.Errorf("cores must be ABSENT when unset (golden default), got %q", uncapped["cores"])
}
if _, ok := uncapped["memory"]; ok {
t.Errorf("memory must be ABSENT when unset (golden default), got %q", uncapped["memory"])
}
}
// The golden-carried Docker-data volume is grown via a SEPARATE resize on its mpN slot (B4),
// alongside (but distinct from) the rootfs grow.
func TestRunBringUp_StorageSplit_DataVolGrow(t *testing.T) {