Extract imagemgr subpackage with pure image helpers
Moves the stateless helpers of the image subsystem into internal/daemon/imagemgr: paths.go — path validators (ValidateRegisterPaths, ValidatePromotePaths), artifact staging (StageBootArtifacts, StageOptionalArtifactPath), metadata (BuildMetadataPackages, WritePackagesMetadata). build.go — ResizeRootfs, WriteBuildLog, and the full guest provisioning script generator (BuildProvisionScript, BuildModulesCommand and all private script-append helpers) along with the mise/tmux/opencode version constants. The orchestrator methods (BuildImage, RegisterImage, PromoteImage, DeleteImage, runImageBuildNative) stay on *Daemon: they still touch d.store, d.imageOpsMu, d.beginOperation, capability hooks, and fcproc-wrapped Daemon helpers — extracting them needs prerequisite phases (operation protocol, workdisk helpers, tap pool). This commit is strictly the pure-helper extraction that can land cleanly today. imagebuild.go shrinks from 453 -> 225 LOC (half gone). images.go shrinks from 450 -> 374 LOC. imagebuild_test.go updated to call the exported imagemgr.BuildProvisionScript. Zero behavior change; all tests green. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6e989914dd
commit
c13c8b11af
5 changed files with 380 additions and 326 deletions
108
internal/daemon/imagemgr/paths.go
Normal file
108
internal/daemon/imagemgr/paths.go
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Package imagemgr contains the pure helpers of the banger image subsystem:
|
||||
// path validators, artifact staging, managed-image metadata, and the guest
|
||||
// provisioning script generator used by image build.
|
||||
//
|
||||
// The orchestrator methods (BuildImage, RegisterImage, PromoteImage,
|
||||
// DeleteImage) still live in the daemon package and compose these helpers.
|
||||
package imagemgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"banger/internal/imagepreset"
|
||||
"banger/internal/system"
|
||||
)
|
||||
|
||||
// ValidateRegisterPaths checks that rootfs + kernel exist and that optional
|
||||
// artifacts, when provided, also exist.
|
||||
func ValidateRegisterPaths(rootfsPath, workSeedPath, kernelPath, initrdPath, modulesDir string) error {
|
||||
checks := system.NewPreflight()
|
||||
checks.RequireFile(rootfsPath, "rootfs image", `pass --rootfs <path>`)
|
||||
checks.RequireFile(kernelPath, "kernel image", `pass --kernel <path>`)
|
||||
if workSeedPath != "" {
|
||||
checks.RequireFile(workSeedPath, "work-seed image", `pass --work-seed <path> or rebuild the image with a work seed`)
|
||||
}
|
||||
if initrdPath != "" {
|
||||
checks.RequireFile(initrdPath, "initrd image", `pass --initrd <path>`)
|
||||
}
|
||||
if modulesDir != "" {
|
||||
checks.RequireDir(modulesDir, "kernel modules dir", `pass --modules <dir>`)
|
||||
}
|
||||
return checks.Err("image register failed")
|
||||
}
|
||||
|
||||
// ValidatePromotePaths checks that an existing registered image's artifacts
|
||||
// are still present before promoting it to daemon-owned storage.
|
||||
func ValidatePromotePaths(rootfsPath, kernelPath, initrdPath, modulesDir string) error {
|
||||
checks := system.NewPreflight()
|
||||
checks.RequireFile(rootfsPath, "rootfs image", `re-register the image with a valid rootfs`)
|
||||
checks.RequireFile(kernelPath, "kernel image", `re-register the image with a valid kernel`)
|
||||
if initrdPath != "" {
|
||||
checks.RequireFile(initrdPath, "initrd image", `re-register the image with a valid initrd`)
|
||||
}
|
||||
if modulesDir != "" {
|
||||
checks.RequireDir(modulesDir, "kernel modules dir", `re-register the image with a valid modules dir`)
|
||||
}
|
||||
return checks.Err("image promote failed")
|
||||
}
|
||||
|
||||
// StageBootArtifacts copies kernel/initrd/modules into artifactDir and
|
||||
// returns the staged paths. initrd and modules are optional; an empty source
|
||||
// returns an empty staged path.
|
||||
func StageBootArtifacts(ctx context.Context, runner system.CommandRunner, artifactDir, kernelSource, initrdSource, modulesSource string) (string, string, string, error) {
|
||||
kernelPath := filepath.Join(artifactDir, "kernel")
|
||||
if err := system.CopyFilePreferClone(kernelSource, kernelPath); err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
initrdPath := ""
|
||||
if strings.TrimSpace(initrdSource) != "" {
|
||||
initrdPath = filepath.Join(artifactDir, "initrd.img")
|
||||
if err := system.CopyFilePreferClone(initrdSource, initrdPath); err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
}
|
||||
modulesDir := ""
|
||||
if strings.TrimSpace(modulesSource) != "" {
|
||||
modulesDir = filepath.Join(artifactDir, "modules")
|
||||
if err := os.MkdirAll(modulesDir, 0o755); err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
if err := system.CopyDirContents(ctx, runner, modulesSource, modulesDir, false); err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
}
|
||||
return kernelPath, initrdPath, modulesDir, nil
|
||||
}
|
||||
|
||||
// StageOptionalArtifactPath returns the destination path for an optional
|
||||
// artifact in artifactDir, or "" when stagedPath is empty (artifact absent).
|
||||
func StageOptionalArtifactPath(artifactDir, stagedPath, name string) string {
|
||||
if strings.TrimSpace(stagedPath) == "" {
|
||||
return ""
|
||||
}
|
||||
return filepath.Join(artifactDir, name)
|
||||
}
|
||||
|
||||
// BuildMetadataPackages returns the canonical package set recorded for a
|
||||
// managed image build. The #feature:docker sentinel is appended when
|
||||
// docker is requested.
|
||||
func BuildMetadataPackages(docker bool) []string {
|
||||
packages := imagepreset.DebianBasePackages()
|
||||
if docker {
|
||||
packages = append(packages, "#feature:docker")
|
||||
}
|
||||
return packages
|
||||
}
|
||||
|
||||
// WritePackagesMetadata writes the hash of packages next to rootfsPath so
|
||||
// future builds can detect drift. Empty packages or rootfsPath is a no-op.
|
||||
func WritePackagesMetadata(rootfsPath string, packages []string) error {
|
||||
if rootfsPath == "" || len(packages) == 0 {
|
||||
return nil
|
||||
}
|
||||
metadataPath := rootfsPath + ".packages.sha256"
|
||||
return os.WriteFile(metadataPath, []byte(imagepreset.Hash(packages)+"\n"), 0o644)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue