Something went wrong. Try again.
Social cloud hosting
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148package cli
import ( "fmt" "os" "os/exec" "path/filepath"
"github.com/neutrino2211/at-rund/internal/vm" "github.com/spf13/cobra")
var ( buildRuntime string buildTarget string)
var buildCmd = &cobra.Command{ Use: "build", Short: "Build runtime images", Long: `Builds container or Firecracker images from Nix runtime definitions.`, RunE: runBuild,}
func init() { buildCmd.Flags().StringVarP(&buildRuntime, "runtime", "r", "", "build specific runtime (default: all)") buildCmd.Flags().StringVarP(&buildTarget, "target", "t", "container", "build target: container or firecracker")}
func runBuild(cmd *cobra.Command, args []string) error { // Find runtimes to build flakePath := vm.GetFlakePath() if flakePath == "" { return fmt.Errorf("could not find nix/runtimes directory") }
var runtimes []string if buildRuntime != "" { runtimes = []string{buildRuntime} } else { entries, err := os.ReadDir(flakePath) if err != nil { return fmt.Errorf("failed to read runtimes directory: %w", err) } for _, e := range entries { if e.IsDir() { // Check if it has a flake.nix if _, err := os.Stat(filepath.Join(flakePath, e.Name(), "flake.nix")); err == nil { runtimes = append(runtimes, e.Name()) } } } }
if len(runtimes) == 0 { return fmt.Errorf("no runtimes found in %s", flakePath) }
fmt.Printf("Building %d runtime(s) for %s: %v\n\n", len(runtimes), buildTarget, runtimes)
switch buildTarget { case "container": return buildContainerImages(runtimes, flakePath) case "firecracker": return buildFirecrackerImages(runtimes, flakePath) default: return fmt.Errorf("unknown target: %s (valid: container, firecracker)", buildTarget) }}
func buildContainerImages(runtimes []string, flakePath string) error { // Check nix is available if _, err := exec.LookPath("nix"); err != nil { return fmt.Errorf("nix not found in PATH") }
// Check docker/podman is available containerRuntime := "docker" if _, err := exec.LookPath("docker"); err != nil { if _, err := exec.LookPath("podman"); err != nil { return fmt.Errorf("docker or podman required for container builds") } containerRuntime = "podman" }
for _, runtime := range runtimes { imageName := fmt.Sprintf("at-rund-%s:latest", runtime) fmt.Printf("Building %s...\n", imageName)
runtimeDir := filepath.Join(flakePath, runtime)
// Step 1: Build container image with Nix fmt.Printf(" [1/2] Building OCI image with Nix...\n") resultLink := filepath.Join(os.TempDir(), fmt.Sprintf("at-rund-%s-container", runtime))
nixCmd := exec.Command("nix", "build", runtimeDir+"#container", "--out-link", resultLink) nixCmd.Stdout = os.Stdout nixCmd.Stderr = os.Stderr if err := nixCmd.Run(); err != nil { return fmt.Errorf("nix build failed for %s: %w", runtime, err) }
// Step 2: Load into Docker/Podman fmt.Printf(" [2/2] Loading image into %s...\n", containerRuntime) loadCmd := exec.Command(containerRuntime, "load", "-i", resultLink) loadCmd.Stdout = os.Stdout loadCmd.Stderr = os.Stderr
if err := loadCmd.Run(); err != nil { return fmt.Errorf("failed to load image for %s: %w", runtime, err) }
// Clean up the result link os.Remove(resultLink)
fmt.Printf(" ✓ Built %s\n", imageName) }
fmt.Println("\nContainer images built successfully.") return nil}
func buildFirecrackerImages(runtimes []string, flakePath string) error { // Check nix is available if _, err := exec.LookPath("nix"); err != nil { return fmt.Errorf("nix not found in PATH") }
dir := configDir() imagesDir := filepath.Join(dir, "images")
for _, runtime := range runtimes { fmt.Printf("Building %s for Firecracker...\n", runtime)
outputDir := filepath.Join(imagesDir, runtime) if err := os.MkdirAll(outputDir, 0755); err != nil { return fmt.Errorf("failed to create output dir: %w", err) }
// TODO: Implement actual Firecracker image build // nix build path/to/runtime#firecracker -o ${outputDir} fmt.Printf(" [stub] Firecracker build not yet implemented\n") fmt.Printf(" [stub] Would output to %s/kernel, %s/rootfs.ext4\n", outputDir, outputDir) }
return nil}