Add experimental Void guest workflow and vsock agent
Make iterating on a Firecracker-friendly Void guest practical without replacing the Debian default image path. Add local Void rootfs build/register/verify plumbing, a language-agnostic dev package baseline, and guest SSH/work-disk hardening so new images use the runtime bundle key, keep a normal root bash environment, and repair stale nested /root layouts on restart. Replace the guest PING/PONG responder with an HTTP /healthz agent over vsock, rename the runtime bundle and config surface from ping helper to agent while still accepting the legacy keys, and route the post-SSH reminder through the new vm.health path. Validated with GOCACHE=/tmp/banger-gocache go test ./..., make build, bash -n customize.sh make-rootfs-void.sh, and git diff --check.
This commit is contained in:
parent
c8d9a122f9
commit
3ed78fdcfc
42 changed files with 2222 additions and 388 deletions
|
|
@ -246,6 +246,128 @@ func TestEnsureDefaultImageSkipsRewriteWhenCurrentArtifactsMissing(t *testing.T)
|
|||
}
|
||||
}
|
||||
|
||||
func TestRegisterImageCreatesUnmanagedImage(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
rootfs, kernel, initrd, modulesDir, _ := writeDefaultImageArtifacts(t, dir)
|
||||
workSeed := filepath.Join(dir, "rootfs-void.work-seed.ext4")
|
||||
packages := filepath.Join(dir, "packages.void")
|
||||
if err := os.WriteFile(workSeed, []byte("seed"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile(workSeed): %v", err)
|
||||
}
|
||||
if err := os.WriteFile(packages, []byte("base-minimal\nopenssh\n"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile(packages): %v", err)
|
||||
}
|
||||
db := openDefaultImageStore(t, dir)
|
||||
d := &Daemon{
|
||||
config: model.DaemonConfig{
|
||||
DefaultKernel: kernel,
|
||||
DefaultInitrd: initrd,
|
||||
DefaultModulesDir: modulesDir,
|
||||
},
|
||||
store: db,
|
||||
}
|
||||
|
||||
image, err := d.RegisterImage(context.Background(), api.ImageRegisterParams{
|
||||
Name: "void-exp",
|
||||
RootfsPath: rootfs,
|
||||
WorkSeedPath: workSeed,
|
||||
PackagesPath: packages,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("RegisterImage: %v", err)
|
||||
}
|
||||
if image.Managed {
|
||||
t.Fatal("registered image should be unmanaged")
|
||||
}
|
||||
if image.Name != "void-exp" || image.RootfsPath != rootfs || image.WorkSeedPath != workSeed || image.KernelPath != kernel {
|
||||
t.Fatalf("registered image = %+v", image)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterImageUpdatesExistingUnmanagedImageInPlace(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
_, kernel, initrd, modulesDir, _ := writeDefaultImageArtifacts(t, dir)
|
||||
newRootfs := filepath.Join(dir, "rootfs-void-next.ext4")
|
||||
newWorkSeed := filepath.Join(dir, "rootfs-void-next.work-seed.ext4")
|
||||
packages := filepath.Join(dir, "packages.void")
|
||||
for _, path := range []string{newRootfs, newWorkSeed} {
|
||||
if err := os.WriteFile(path, []byte("next"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile(%s): %v", path, err)
|
||||
}
|
||||
}
|
||||
if err := os.WriteFile(packages, []byte("base-minimal\n"), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile(packages): %v", err)
|
||||
}
|
||||
db := openDefaultImageStore(t, dir)
|
||||
now := time.Date(2026, time.March, 16, 12, 0, 0, 0, time.UTC)
|
||||
existing := model.Image{
|
||||
ID: "void-image-id",
|
||||
Name: "void-exp",
|
||||
Managed: false,
|
||||
RootfsPath: filepath.Join(dir, "old-rootfs.ext4"),
|
||||
KernelPath: kernel,
|
||||
InitrdPath: initrd,
|
||||
ModulesDir: modulesDir,
|
||||
PackagesPath: packages,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := db.UpsertImage(context.Background(), existing); err != nil {
|
||||
t.Fatalf("UpsertImage: %v", err)
|
||||
}
|
||||
d := &Daemon{
|
||||
config: model.DaemonConfig{
|
||||
DefaultKernel: kernel,
|
||||
DefaultInitrd: initrd,
|
||||
DefaultModulesDir: modulesDir,
|
||||
},
|
||||
store: db,
|
||||
}
|
||||
|
||||
image, err := d.RegisterImage(context.Background(), api.ImageRegisterParams{
|
||||
Name: "void-exp",
|
||||
RootfsPath: newRootfs,
|
||||
WorkSeedPath: newWorkSeed,
|
||||
PackagesPath: packages,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("RegisterImage: %v", err)
|
||||
}
|
||||
if image.ID != existing.ID || !image.CreatedAt.Equal(existing.CreatedAt) {
|
||||
t.Fatalf("updated image identity changed: %+v", image)
|
||||
}
|
||||
if image.RootfsPath != newRootfs || image.WorkSeedPath != newWorkSeed {
|
||||
t.Fatalf("updated image paths not applied: %+v", image)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterImageRejectsManagedOverwrite(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
rootfs, kernel, _, _, _ := writeDefaultImageArtifacts(t, dir)
|
||||
db := openDefaultImageStore(t, dir)
|
||||
now := time.Date(2026, time.March, 16, 12, 0, 0, 0, time.UTC)
|
||||
if err := db.UpsertImage(context.Background(), model.Image{
|
||||
ID: "managed-id",
|
||||
Name: "void-exp",
|
||||
Managed: true,
|
||||
RootfsPath: rootfs,
|
||||
KernelPath: kernel,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}); err != nil {
|
||||
t.Fatalf("UpsertImage: %v", err)
|
||||
}
|
||||
d := &Daemon{config: model.DaemonConfig{DefaultKernel: kernel}, store: db}
|
||||
|
||||
_, err := d.RegisterImage(context.Background(), api.ImageRegisterParams{
|
||||
Name: "void-exp",
|
||||
RootfsPath: rootfs,
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "cannot be updated via register") {
|
||||
t.Fatalf("RegisterImage(managed) error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func openDefaultImageStore(t *testing.T, dir string) *store.Store {
|
||||
t.Helper()
|
||||
db, err := store.Open(filepath.Join(dir, "state.db"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue