package plan import ( "context" "fmt" "path/filepath" "strings" "metis/pkg/image" "metis/pkg/inventory" "metis/pkg/writer" ) // BuildImageFile materializes a fully injected raw image for a node. func BuildImageFile(ctx context.Context, inv *inventory.Inventory, nodeName, cacheDir, output string) error { p, err := Build(inv, nodeName, output, cacheDir) if err != nil { return fmt.Errorf("build plan: %w", err) } _, class, err := inv.FindNode(nodeName) if err != nil { return fmt.Errorf("load node class: %w", err) } cacheImage := filepath.Join(cacheDir, cacheName(p.Image)) cacheImage, err = image.DownloadAndVerify(p.Image, cacheImage, class.Checksum) if err != nil { return fmt.Errorf("download image: %w", err) } if err := writer.WriteImage(ctx, cacheImage, output); err != nil { return fmt.Errorf("copy base image: %w", err) } files, err := Files(inv, nodeName) if err != nil { return fmt.Errorf("resolve files: %w", err) } if err := image.InjectRootFS(output, files); err != nil { return fmt.Errorf("inject rootfs: %w", err) } return nil } func cacheName(source string) string { base := filepath.Base(source) return strings.TrimSuffix(base, ".xz") }