Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 0 additions & 54 deletions cli/output.go

This file was deleted.

4 changes: 2 additions & 2 deletions cmd/image/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package image
import (
"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon-macos/cli"
"github.com/cocoonstack/cocoon/cmd/cliutil"
)

// Actions is the image-subcommand surface, backed by cocoon's cloudimg store.
Expand All @@ -27,7 +27,7 @@ func Command(h Actions) *cobra.Command {
pull.Flags().Bool("force", false, "re-pull even if already present")

list := &cobra.Command{Use: "list", Aliases: []string{"ls"}, Short: "List images", RunE: h.List}
cli.AddFormatFlag(list)
cliutil.AddFormatFlag(list)
inspect := &cobra.Command{Use: "inspect REF", Short: "Show one image (JSON)", Args: cobra.ExactArgs(1), RunE: h.Inspect}
rm := &cobra.Command{Use: "rm REF [REF...]", Short: "Remove image(s)", Args: cobra.MinimumNArgs(1), RunE: h.RM}

Expand Down
15 changes: 5 additions & 10 deletions cmd/image/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package image

import (
"fmt"
"strings"
"text/tabwriter"
"time"

"github.com/projecteru2/core/log"
"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon/cmd/cliutil"
"github.com/cocoonstack/cocoon/progress"

"github.com/cocoonstack/cocoon-macos/cli"
"github.com/cocoonstack/cocoon-macos/home"
)

Expand All @@ -34,7 +33,7 @@ func (h *Handler) Pull(cmd *cobra.Command, args []string) error {
}
ref := args[0]
force, _ := cmd.Flags().GetBool("force")
if isURL(ref) {
if cliutil.IsURL(ref) {
return s.Pull(ctx, ref, force, progress.Nop)
}
// mirror the URL path's idempotency: skip the multi-GiB registry download when already present
Expand Down Expand Up @@ -66,11 +65,11 @@ func (h *Handler) List(cmd *cobra.Command, _ []string) error {
if err != nil {
return err
}
return cli.OutputFormatted(cmd, imgs, func(w *tabwriter.Writer) {
return cliutil.OutputFormatted(cmd, imgs, func(w *tabwriter.Writer) {
fmt.Fprintln(w, "NAME\tTYPE\tSIZE\tDIGEST\tCREATED") //nolint:errcheck
for _, img := range imgs {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", //nolint:errcheck
img.Name, img.Type, cli.FormatSize(img.Size),
img.Name, img.Type, cliutil.FormatSize(img.Size),
shortDigest(img.ID), img.CreatedAt.Local().Format(time.DateTime))
}
})
Expand All @@ -89,7 +88,7 @@ func (h *Handler) Inspect(cmd *cobra.Command, args []string) error {
if img == nil {
return fmt.Errorf("image not found: %s", args[0])
}
return cli.OutputJSON(img)
return cliutil.OutputJSON(img)
}

// RM deletes one or more images from the store, printing each removed ref.
Expand All @@ -108,10 +107,6 @@ func (h *Handler) RM(cmd *cobra.Command, args []string) error {
return nil
}

func isURL(s string) bool {
return strings.HasPrefix(s, "http://") || strings.HasPrefix(s, "https://")
}

func shortDigest(id string) string {
const maxLen = 19 // "sha256:" + 12 hex chars, the conventional short-digest length
if len(id) > maxLen {
Expand Down
3 changes: 2 additions & 1 deletion cmd/vm/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon/cmd/cliutil"
"github.com/cocoonstack/cocoon/utils"

"github.com/cocoonstack/cocoon-macos/home"
Expand Down Expand Up @@ -41,7 +42,7 @@ func (h *Handler) Clone(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
copied, err := copyDataDisks(dir, srcRec.DataDisks)
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions cmd/vm/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package vm
import (
"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon-macos/cli"
"github.com/cocoonstack/cocoon/cmd/cliutil"
)

// Actions mirrors cocoon's cmd/vm Actions interface, trimmed to the v0.1 macOS
Expand Down Expand Up @@ -64,7 +64,7 @@ func Command(h Actions) *cobra.Command {
Short: "List VMs with status",
RunE: h.List,
}
cli.AddFormatFlag(listCmd)
cliutil.AddFormatFlag(listCmd)

inspectCmd := &cobra.Command{
Use: "inspect VM",
Expand Down
8 changes: 4 additions & 4 deletions cmd/vm/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (

"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon/config"
"github.com/cocoonstack/cocoon/images/cloudimg"
"github.com/cocoonstack/cocoon/cmd/cliutil"
"github.com/cocoonstack/cocoon/images"
"github.com/cocoonstack/cocoon/lock/flock"
"github.com/cocoonstack/cocoon/types"
"github.com/cocoonstack/cocoon/utils"
Expand Down Expand Up @@ -74,7 +74,7 @@ func scaffoldVM(cmd *cobra.Command, name, image, varsSrc, varsName string) (dir,
return "", "", "", "", err
}
overlay = filepath.Join(dir, "disk.qcow2")
if err = bakeOverlay(home.Ctx(cmd), base, overlay); err != nil {
if err = bakeOverlay(cliutil.CommandContext(cmd), base, overlay); err != nil {
return "", "", "", "", err
}
ovmfVars = filepath.Join(dir, varsName)
Expand Down Expand Up @@ -174,7 +174,7 @@ func resolveBase(cmd *cobra.Command, image, name string) (string, string, error)
// UEFI firmware exists (it targets cloud-hypervisor). cocoon-macos boots via OVMF + OpenCore and
// DISCARDS that BootConfig, so the file is never read — it only unblocks Config's validation.
func ensureCloudimgFirmware(cmd *cobra.Command) {
fw := cloudimg.NewConfig(&config.Config{RootDir: home.Dir(cmd)}).FirmwarePath()
fw := images.FirmwarePath(home.Dir(cmd))
if utils.ValidFile(fw) {
return
}
Expand Down
11 changes: 6 additions & 5 deletions cmd/vm/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/projecteru2/core/log"
"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon/cmd/cliutil"
"github.com/cocoonstack/cocoon/utils"

"github.com/cocoonstack/cocoon-macos/home"
Expand Down Expand Up @@ -43,7 +44,7 @@ func (h *Handler) Run(cmd *cobra.Command, args []string) error {
// Start boots one or more previously-created VMs, reusing each persisted TAP/netns
// across stop/start (only rm tears those down).
func (h *Handler) Start(cmd *cobra.Command, args []string) error {
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
for _, n := range args {
dir := home.VMDir(cmd, n)
if err := withVMLock(ctx, dir, func() error {
Expand All @@ -66,7 +67,7 @@ func (h *Handler) Start(cmd *cobra.Command, args []string) error {
// Stop terminates one or more running VMs. --force skips the ACPI grace window (immediate SIGKILL).
func (h *Handler) Stop(cmd *cobra.Command, args []string) error {
grace := graceFromFlags(cmd)
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
for _, n := range args {
dir := home.VMDir(cmd, n)
if err := withVMLock(ctx, dir, func() error {
Expand All @@ -90,7 +91,7 @@ func (h *Handler) Stop(cmd *cobra.Command, args []string) error {
// (immediate SIGKILL), which also reaps a wedged qemu.
func (h *Handler) RM(cmd *cobra.Command, args []string) error {
grace := graceFromFlags(cmd)
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
for _, n := range args {
dir := home.VMDir(cmd, n)
if _, err := os.Stat(dir); os.IsNotExist(err) {
Expand Down Expand Up @@ -135,7 +136,7 @@ func (h *Handler) create(cmd *cobra.Command, image string) (*record, error) {
if err != nil {
return nil, err
}
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
cpus, _ := cmd.Flags().GetInt("cpus")
mem, _ := cmd.Flags().GetString("memory")
vnc, _ := cmd.Flags().GetInt("vnc")
Expand Down Expand Up @@ -165,7 +166,7 @@ func (h *Handler) create(cmd *cobra.Command, image string) (*record, error) {

// launch boots qemu for the record's spec, records the PID, and applies the VNC password (if any).
func (h *Handler) launch(cmd *cobra.Command, dir string, r *record) error {
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
logger := log.WithFunc("cmd.vm.launch")
if hostIsAMD() {
// macOS reads MSRs an AMD host lacks; without kvm.ignore_msrs KVM injects #GP. Best-effort,
Expand Down
5 changes: 3 additions & 2 deletions cmd/vm/net_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/projecteru2/core/log"
"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon/cmd/cliutil"
"github.com/cocoonstack/cocoon/config"
"github.com/cocoonstack/cocoon/network"
"github.com/cocoonstack/cocoon/network/bridge"
Expand Down Expand Up @@ -59,7 +60,7 @@ func provisionNet(cmd *cobra.Command, r *record) (tap, netns, mac string, err er
if err != nil {
return "", "", "", err
}
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
// CPU=1 => NetNumQueues yields a single-queue TAP matching QEMU's single-queue -netdev tap,ifname=
vmCfg := &types.VMConfig{Config: types.Config{CPU: 1}, Name: r.Name}
nsPath, err := provider.Prepare(ctx, r.VMID, vmCfg)
Expand All @@ -83,7 +84,7 @@ func teardownNet(cmd *cobra.Command, r *record) {
if !r.TapOwned {
return
}
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
// warn instead of failing: rm must proceed, but a leaked TAP/netns should leave a trail
if provider, err := newProvider(cmd, r); err != nil {
log.WithFunc("cmd.vm.teardownNet").Warnf(ctx, "teardown network for %s: %v", r.VMID, err)
Expand Down
18 changes: 14 additions & 4 deletions cmd/vm/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import (
"path/filepath"
"strconv"
"text/tabwriter"
"time"

"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon-macos/cli"
"github.com/cocoonstack/cocoon/cmd/cliutil"

"github.com/cocoonstack/cocoon-macos/home"
)

Expand All @@ -24,12 +26,12 @@ func (h *Handler) List(cmd *cobra.Command, _ []string) error {
recs = append(recs, r)
}
}
return cli.OutputFormatted(cmd, recs, func(w *tabwriter.Writer) {
return cliutil.OutputFormatted(cmd, recs, func(w *tabwriter.Writer) {
fmt.Fprintln(w, "NAME\tSTATE\tCPU\tMEM\tNET\tVNC\tSSH\tIMAGE\tCREATED") //nolint:errcheck
for _, r := range recs {
fmt.Fprintf(w, "%s\t%s\t%d\t%sM\t%s\t%s\t%s\t%s\t%s\n", //nolint:errcheck
r.Name, vmState(r), r.CPUs, r.Memory, cmp.Or(r.NetMode, netUser),
vncCol(r), sshCol(r), r.Image, cli.FormatTime(r.Created))
vncCol(r), sshCol(r), r.Image, formatTime(r.Created))
}
})
}
Expand All @@ -40,7 +42,7 @@ func (h *Handler) Inspect(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
return cli.OutputJSON(r)
return cliutil.OutputJSON(r)
}

// Console prints the VNC endpoint and SSH command for reaching a VM ("-" when disabled),
Expand Down Expand Up @@ -82,3 +84,11 @@ func sshCol(r *record) string {
}
return strconv.Itoa(r.SSHPort)
}

// formatTime renders the record's RFC3339 Created stamp as local time.DateTime; raw on parse failure.
func formatTime(s string) string {
if t, err := time.Parse(time.RFC3339, s); err == nil {
return t.Local().Format(time.DateTime)
}
return s
}
6 changes: 4 additions & 2 deletions cmd/vm/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/spf13/cobra"

"github.com/cocoonstack/cocoon/cmd/cliutil"

"github.com/cocoonstack/cocoon-macos/home"
"github.com/cocoonstack/cocoon-macos/qemu"
)
Expand All @@ -14,7 +16,7 @@ import (
// the image, and +invtsc blocks the live-migration codepath savevm relies on).
func (h *Handler) Snapshot(cmd *cobra.Command, args []string) error {
dir := home.VMDir(cmd, args[0])
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
tag, _ := cmd.Flags().GetString("tag")
if tag == "" {
tag = "snap-" + time.Now().Format("20060102-150405")
Expand Down Expand Up @@ -45,7 +47,7 @@ func (h *Handler) Snapshot(cmd *cobra.Command, args []string) error {
// which stops it, reverts, and relaunches.
func (h *Handler) Restore(cmd *cobra.Command, args []string) error {
dir := home.VMDir(cmd, args[0])
ctx := home.Ctx(cmd)
ctx := cliutil.CommandContext(cmd)
var tag string
if err := withVMLock(ctx, dir, func() error {
r, err := loadRec(dir)
Expand Down
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module github.com/cocoonstack/cocoon-macos

go 1.25.6
go 1.26.4

require (
github.com/cocoonstack/cocoon v0.4.2
github.com/cocoonstack/cocoon v0.4.5
github.com/docker/go-units v0.5.0
github.com/opencontainers/image-spec v1.1.1
github.com/projecteru2/core v0.0.0-20241016125006-ff909eefe04c
Expand Down Expand Up @@ -38,10 +38,12 @@ require (
github.com/vishvananda/netlink v1.3.1 // indirect
github.com/vishvananda/netns v0.0.5 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/net v0.50.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.28.0 // indirect
google.golang.org/grpc v1.69.0 // indirect
google.golang.org/protobuf v1.36.7 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/tools v0.42.0 // indirect
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
)
Loading
Loading