diff --git a/app/app.go b/app/app.go index 582c846ab..f4b7a8f88 100644 --- a/app/app.go +++ b/app/app.go @@ -15,6 +15,7 @@ import ( "github.com/abiosoft/colima/environment/container/ubuntu" "github.com/abiosoft/colima/environment/host" "github.com/abiosoft/colima/environment/vm/lima" + "github.com/abiosoft/colima/environment/vm/lima/limautil" log "github.com/sirupsen/logrus" ) @@ -208,7 +209,7 @@ func (c colimaApp) SSH(layer bool, args ...string) error { return c.guest.RunInteractive(args...) } - conf, err := lima.InstanceConfig() + conf, err := limautil.InstanceConfig() if err != nil { return err } @@ -216,7 +217,7 @@ func (c colimaApp) SSH(layer bool, args ...string) error { return c.guest.RunInteractive(args...) } - resp, err := lima.ShowSSH(config.CurrentProfile().ID, layer, "args") + resp, err := limautil.ShowSSH(config.CurrentProfile().ID, layer, "args") if err != nil { return fmt.Errorf("error getting ssh config: %w", err) } @@ -256,7 +257,7 @@ func (c colimaApp) Status() error { log.Println(config.CurrentProfile().DisplayName, "is running") log.Println("arch:", c.guest.Arch()) log.Println("runtime:", currentRuntime) - if conf, err := lima.InstanceConfig(); err == nil { + if conf, err := limautil.InstanceConfig(); err == nil { log.Println("mountType:", conf.MountType) } if currentRuntime == docker.Name { diff --git a/cmd/colima/main.go b/cmd/colima/main.go index 2c83730e1..d284f3f44 100644 --- a/cmd/colima/main.go +++ b/cmd/colima/main.go @@ -10,12 +10,12 @@ import ( _ "github.com/abiosoft/colima/cmd" // for other commands _ "github.com/abiosoft/colima/cmd/daemon" // for vmnet daemon _ "github.com/abiosoft/colima/embedded" // for embedded assets - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/gvproxy" - "github.com/abiosoft/colima/util" - "github.com/sirupsen/logrus" "github.com/abiosoft/colima/cmd/root" "github.com/abiosoft/colima/config" + "github.com/abiosoft/colima/daemon/process/gvproxy" + "github.com/abiosoft/colima/util" + "github.com/sirupsen/logrus" ) func main() { @@ -27,6 +27,7 @@ func main() { root.Execute() } } + func qemuWrapper(qemu string) { if profile := os.Getenv(config.SubprocessProfileEnvVar); profile != "" { config.SetProfile(profile) @@ -79,6 +80,12 @@ func qemuWrapper(qemu string) { cmd.ExtraFiles = append(cmd.ExtraFiles, fd) } - _ = cmd.Run() + err := cmd.Run() + if err != nil { + if err, ok := err.(*exec.ExitError); ok { + os.Exit(err.ExitCode()) + } + os.Exit(1) + } } diff --git a/cmd/daemon/cmd.go b/cmd/daemon/cmd.go index f9fa9c9e8..fc7139582 100644 --- a/cmd/daemon/cmd.go +++ b/cmd/daemon/cmd.go @@ -4,9 +4,9 @@ import ( "context" "time" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/gvproxy" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/vmnet" + "github.com/abiosoft/colima/daemon/process" + "github.com/abiosoft/colima/daemon/process/gvproxy" + "github.com/abiosoft/colima/daemon/process/vmnet" "github.com/abiosoft/colima/cmd/root" "github.com/abiosoft/colima/config" @@ -18,10 +18,6 @@ var daemonCmd = &cobra.Command{ Short: "daemon", Long: `runner for background daemons.`, Hidden: true, - PersistentPreRun: func(cmd *cobra.Command, args []string) { - cmd.SilenceUsage = true - cmd.SilenceErrors = true - }, } var startCmd = &cobra.Command{ @@ -31,8 +27,9 @@ var startCmd = &cobra.Command{ Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { config.SetProfile(args[0]) + ctx := cmd.Context() - var processes []daemon.Process + var processes []process.Process if daemonArgs.vmnet { processes = append(processes, vmnet.New()) } @@ -40,7 +37,7 @@ var startCmd = &cobra.Command{ processes = append(processes, gvproxy.New()) } - return start(cmd.Context(), processes) + return start(ctx, processes) }, } @@ -74,8 +71,11 @@ var statusCmd = &cobra.Command{ } var daemonArgs struct { - vmnet bool - gvproxy bool + vmnet bool + gvproxy bool + fsnotify bool + + verbose bool } func init() { @@ -87,4 +87,5 @@ func init() { startCmd.Flags().BoolVar(&daemonArgs.vmnet, "vmnet", false, "start vmnet") startCmd.Flags().BoolVar(&daemonArgs.gvproxy, "gvproxy", false, "start gvproxy") + startCmd.Flags().BoolVar(&daemonArgs.fsnotify, "fsnotify", false, "start fsnotify") } diff --git a/cmd/daemon/daemon.go b/cmd/daemon/daemon.go index c807c9327..66ad0be25 100644 --- a/cmd/daemon/daemon.go +++ b/cmd/daemon/daemon.go @@ -7,16 +7,17 @@ import ( "os/signal" "path/filepath" "strconv" + "sync" "syscall" "time" "github.com/abiosoft/colima/cli" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" + "github.com/abiosoft/colima/daemon/process" godaemon "github.com/sevlyar/go-daemon" "github.com/sirupsen/logrus" ) -var dir = daemon.Dir +var dir = process.Dir // daemonize creates the daemon and returns if this is a child process func daemonize() (ctx *godaemon.Context, child bool, err error) { @@ -49,7 +50,7 @@ func daemonize() (ctx *godaemon.Context, child bool, err error) { return ctx, true, nil } -func start(ctx context.Context, processes []daemon.Process) error { +func start(ctx context.Context, processes []process.Process) error { if status() == nil { logrus.Info("daemon already running, startup ignored") return nil @@ -75,7 +76,7 @@ func start(ctx context.Context, processes []daemon.Process) error { ctx, stop := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM) defer stop() - return daemon.Run(ctx, processes...) + return RunProcesses(ctx, processes...) } func stop(ctx context.Context) error { @@ -153,3 +154,32 @@ func Info() struct { LogFile: filepath.Join(dir, logFileName), } } + +// Run runs the daemon with background processes. +// NOTE: this must be called from the program entrypoint with minimal intermediary logic +// due to the creation of the daemon. +func RunProcesses(ctx context.Context, processes ...process.Process) error { + ctx, stop := context.WithCancel(ctx) + defer stop() + + var wg sync.WaitGroup + wg.Add(len(processes)) + + for _, bg := range processes { + go func(bg process.Process) { + err := bg.Start(ctx) + if err != nil { + logrus.Error(fmt.Errorf("error starting %s: %w", bg.Name(), err)) + stop() + } + wg.Done() + }(bg) + } + + <-ctx.Done() + logrus.Info("terminate signal received") + + wg.Wait() + + return ctx.Err() +} diff --git a/cmd/daemon/daemon_test.go b/cmd/daemon/daemon_test.go index 5d707c8b1..1b0934e6e 100644 --- a/cmd/daemon/daemon_test.go +++ b/cmd/daemon/daemon_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" + "github.com/abiosoft/colima/daemon/process" ) var testDir string @@ -19,22 +19,28 @@ func setDir(t *testing.T) { dir = func() string { return testDir } } -func TestStart(t *testing.T) { - setDir(t) - info := Info() - +func getProcesses() []process.Process { var addresses = []string{ "localhost", "127.0.0.1", } - t.Log("pidfile", info.PidFile) - - var processes []daemon.Process + var processes []process.Process for _, add := range addresses { processes = append(processes, &pinger{address: add}) } + return processes +} + +func TestStart(t *testing.T) { + setDir(t) + info := Info() + + processes := getProcesses() + + t.Log("pidfile", info.PidFile) + timeout := time.Second * 5 ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() @@ -54,6 +60,8 @@ func TestStart(t *testing.T) { default: if p, err := os.ReadFile(info.PidFile); err == nil && len(p) > 0 { break loop + } else if err != nil { + t.Logf("encountered err: %v", err) } time.Sleep(1 * time.Second) } @@ -79,7 +87,32 @@ func TestStart(t *testing.T) { } -var _ daemon.Process = (*pinger)(nil) +func TestRunProcesses(t *testing.T) { + processes := getProcesses() + + timeout := time.Second * 5 + ctx, cancel := context.WithTimeout(context.Background(), timeout) + + // start the processes + done := make(chan error, 1) + go func() { + done <- RunProcesses(ctx, processes...) + }() + + cancel() + + select { + case <-ctx.Done(): + if err := ctx.Err(); err != context.Canceled { + t.Error(err) + } + case err := <-done: + t.Error(err) + } + +} + +var _ process.Process = (*pinger)(nil) type pinger struct { address string @@ -98,7 +131,7 @@ func (p *pinger) Start(ctx context.Context) error { } // Start implements BgProcess -func (p *pinger) Dependencies() ([]daemon.Dependency, bool) { return nil, false } +func (p *pinger) Dependencies() ([]process.Dependency, bool) { return nil, false } func (p *pinger) run(ctx context.Context, command string, args ...string) error { cmd := exec.CommandContext(ctx, command, args...) diff --git a/cmd/list.go b/cmd/list.go index 8d5daf740..bf09f7d4e 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -6,7 +6,7 @@ import ( "text/tabwriter" "github.com/abiosoft/colima/cmd/root" - "github.com/abiosoft/colima/environment/vm/lima" + "github.com/abiosoft/colima/environment/vm/lima/limautil" "github.com/docker/go-units" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -26,7 +26,7 @@ var listCmd = &cobra.Command{ A new instance can be created during 'colima start' by specifying the '--profile' flag.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - instances, err := lima.Instances() + instances, err := limautil.Instances() if err != nil { return err } diff --git a/cmd/ssh-config.go b/cmd/ssh-config.go index 9c7bdb808..7afa0444d 100644 --- a/cmd/ssh-config.go +++ b/cmd/ssh-config.go @@ -5,7 +5,7 @@ import ( "github.com/abiosoft/colima/cmd/root" "github.com/abiosoft/colima/config" - "github.com/abiosoft/colima/environment/vm/lima" + "github.com/abiosoft/colima/environment/vm/lima/limautil" "github.com/spf13/cobra" ) @@ -16,7 +16,7 @@ var sshConfigCmd = &cobra.Command{ Long: `Show configuration of the SSH connection to the VM.`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - resp, err := lima.ShowSSH(config.CurrentProfile().ID, sshConfigCmdArgs.layer, sshConfigCmdArgs.format) + resp, err := limautil.ShowSSH(config.CurrentProfile().ID, sshConfigCmdArgs.layer, sshConfigCmdArgs.format) if err == nil { fmt.Println(resp.Output) } diff --git a/config/config.go b/config/config.go index c606d4e2f..5ae56da34 100644 --- a/config/config.go +++ b/config/config.go @@ -132,6 +132,17 @@ func (m Mount) CleanPath() (string, error) { return strings.TrimSuffix(str, "/") + "/", nil } +func (c Config) MountsOrDefault() []Mount { + if len(c.Mounts) > 0 { + return c.Mounts + } + + return []Mount{ + {Location: util.HomeDir(), Writable: true}, + {Location: filepath.Join("/tmp", CurrentProfile().ID), Writable: true}, + } +} + // Empty checks if the configuration is empty. func (c Config) Empty() bool { return c.Runtime == "" } // this may be better but not really needed. diff --git a/environment/vm/lima/network/network.go b/daemon/daemon.go similarity index 65% rename from environment/vm/lima/network/network.go rename to daemon/daemon.go index 29a462f78..938a66440 100644 --- a/environment/vm/lima/network/network.go +++ b/daemon/daemon.go @@ -1,4 +1,4 @@ -package network +package daemon import ( "context" @@ -6,18 +6,18 @@ import ( "os" "github.com/abiosoft/colima/config" + "github.com/abiosoft/colima/daemon/process" + "github.com/abiosoft/colima/daemon/process/gvproxy" + "github.com/abiosoft/colima/daemon/process/vmnet" "github.com/abiosoft/colima/environment" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/gvproxy" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/vmnet" ) -// Manager handles networking between the host and the vm. +// Manager handles running background processes. type Manager interface { Start(context.Context) error Stop(context.Context) error Running(ctx context.Context) (Status, error) - Dependencies(ctx context.Context) (deps daemon.Dependency, root bool) + Dependencies(ctx context.Context) (deps process.Dependency, root bool) } type Status struct { @@ -32,35 +32,35 @@ type processStatus struct { Error error } -// NewManager creates a new network manager. +// NewManager creates a new process manager. func NewManager(host environment.HostActions) Manager { - return &limaNetworkManager{ + return &processManager{ host: host, } } func CtxKey(s string) any { return struct{ key string }{key: s} } -var _ Manager = (*limaNetworkManager)(nil) +var _ Manager = (*processManager)(nil) -type limaNetworkManager struct { +type processManager struct { host environment.HostActions } -func (l limaNetworkManager) Dependencies(ctx context.Context) (deps daemon.Dependency, root bool) { +func (l processManager) Dependencies(ctx context.Context) (deps process.Dependency, root bool) { processes := processesFromCtx(ctx) - return daemon.Dependencies(processes...) + return process.Dependencies(processes...) } -func (l limaNetworkManager) init() error { +func (l processManager) init() error { // dependencies for network - if err := os.MkdirAll(daemon.Dir(), 0755); err != nil { + if err := os.MkdirAll(process.Dir(), 0755); err != nil { return fmt.Errorf("error preparing vmnet: %w", err) } return nil } -func (l limaNetworkManager) Running(ctx context.Context) (s Status, err error) { +func (l processManager) Running(ctx context.Context) (s Status, err error) { err = l.host.RunQuiet(os.Args[0], "daemon", "status", config.CurrentProfile().ShortName) if err != nil { return @@ -78,7 +78,7 @@ func (l limaNetworkManager) Running(ctx context.Context) (s Status, err error) { return } -func (l limaNetworkManager) Start(ctx context.Context) error { +func (l processManager) Start(ctx context.Context) error { _ = l.Stop(ctx) // this is safe, nothing is done when not running if err := l.init(); err != nil { @@ -93,10 +93,13 @@ func (l limaNetworkManager) Start(ctx context.Context) error { if opts.GVProxy { args = append(args, "--gvproxy") } + if opts.FSNotify { + args = append(args, "--fsnotify") + } return l.host.RunQuiet(args...) } -func (l limaNetworkManager) Stop(ctx context.Context) error { +func (l processManager) Stop(ctx context.Context) error { if s, err := l.Running(ctx); err != nil || !s.Running { return nil } @@ -104,12 +107,14 @@ func (l limaNetworkManager) Stop(ctx context.Context) error { } func optsFromCtx(ctx context.Context) struct { - Vmnet bool - GVProxy bool + Vmnet bool + GVProxy bool + FSNotify bool } { var opts = struct { - Vmnet bool - GVProxy bool + Vmnet bool + GVProxy bool + FSNotify bool }{} opts.Vmnet, _ = ctx.Value(CtxKey(vmnet.Name())).(bool) opts.GVProxy, _ = ctx.Value(CtxKey(gvproxy.Name())).(bool) @@ -117,8 +122,8 @@ func optsFromCtx(ctx context.Context) struct { return opts } -func processesFromCtx(ctx context.Context) []daemon.Process { - var processes []daemon.Process +func processesFromCtx(ctx context.Context) []process.Process { + var processes []process.Process opts := optsFromCtx(ctx) if opts.Vmnet { diff --git a/environment/vm/lima/network/daemon/gvproxy/deps.go b/daemon/process/gvproxy/deps.go similarity index 93% rename from environment/vm/lima/network/daemon/gvproxy/deps.go rename to daemon/process/gvproxy/deps.go index ee70cf745..79de7d528 100644 --- a/environment/vm/lima/network/daemon/gvproxy/deps.go +++ b/daemon/process/gvproxy/deps.go @@ -8,11 +8,11 @@ import ( "strings" "github.com/abiosoft/colima/config" + "github.com/abiosoft/colima/daemon/process" "github.com/abiosoft/colima/environment" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" ) -var _ daemon.Dependency = qemuBinsSymlinks{} +var _ process.Dependency = qemuBinsSymlinks{} // only these two are required for Lima var qemuBins = []string{"qemu-system-aarch64", "qemu-system-x86_64"} @@ -52,7 +52,7 @@ func (q qemuBinsSymlinks) Install(host environment.HostActions) error { return nil } -var _ daemon.Dependency = qemuShareDirSymlink{} +var _ process.Dependency = qemuShareDirSymlink{} type qemuShareDirSymlink struct{} diff --git a/environment/vm/lima/network/daemon/gvproxy/gvproxy.go b/daemon/process/gvproxy/gvproxy.go similarity index 91% rename from environment/vm/lima/network/daemon/gvproxy/gvproxy.go rename to daemon/process/gvproxy/gvproxy.go index a62518ad6..a35c434d5 100644 --- a/environment/vm/lima/network/daemon/gvproxy/gvproxy.go +++ b/daemon/process/gvproxy/gvproxy.go @@ -11,7 +11,7 @@ import ( "runtime" "strings" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" + "github.com/abiosoft/colima/daemon/process" "github.com/abiosoft/colima/util" "github.com/containers/gvisor-tap-vsock/pkg/transport" "github.com/containers/gvisor-tap-vsock/pkg/types" @@ -20,7 +20,7 @@ import ( ) // New creates a new Process for gvproxy. -func New() daemon.Process { +func New() process.Process { return &gvproxyProcess{} } @@ -39,12 +39,12 @@ func Info() struct { Socket Socket MacAddress string }{ - Socket: Socket(filepath.Join(daemon.Dir(), socketFileName)), + Socket: Socket(filepath.Join(process.Dir(), socketFileName)), MacAddress: MacAddress(), } } -var _ daemon.Process = (*gvproxyProcess)(nil) +var _ process.Process = (*gvproxyProcess)(nil) type gvproxyProcess struct{} @@ -56,10 +56,10 @@ func (*gvproxyProcess) Alive(context.Context) error { return nil } -// Name implements daemon.BgProcess +// Name implements daemon.Process func (*gvproxyProcess) Name() string { return Name() } -// Start implements daemon.BgProcess +// Start implements daemon.Process func (*gvproxyProcess) Start(ctx context.Context) error { info := Info() return run(ctx, info.Socket) @@ -87,7 +87,7 @@ func MacAddress() string { // there is not much concern about the precision of the uniqueness. // this can be revisited if macAddress == nil { - sum := util.SHA256Hash(daemon.Dir()) + sum := util.SHA256Hash(process.Dir()) macAddress = append(macAddress, baseHWAddr...) macAddress = append(macAddress, sum[0:3]...) } @@ -207,8 +207,8 @@ func searchDomains() []string { return nil } -func (gvproxyProcess) Dependencies() (deps []daemon.Dependency, root bool) { - return []daemon.Dependency{ +func (gvproxyProcess) Dependencies() (deps []process.Dependency, root bool) { + return []process.Dependency{ qemuBinsSymlinks{}, qemuShareDirSymlink{}, }, false diff --git a/environment/vm/lima/network/daemon/daemon.go b/daemon/process/process.go similarity index 69% rename from environment/vm/lima/network/daemon/daemon.go rename to daemon/process/process.go index 287e38b01..e23ef1eba 100644 --- a/environment/vm/lima/network/daemon/daemon.go +++ b/daemon/process/process.go @@ -1,15 +1,13 @@ -package daemon +package process import ( "context" "fmt" "path/filepath" - "sync" "github.com/abiosoft/colima/config" "github.com/abiosoft/colima/environment" - "github.com/sirupsen/logrus" ) // Process is a background process managed by the daemon. @@ -27,8 +25,8 @@ type Process interface { Dependencies() (deps []Dependency, root bool) } -// Dir is the directory for network related files. -func Dir() string { return filepath.Join(config.Dir(), "network") } +// Dir is the directory for daemon files. +func Dir() string { return filepath.Join(config.Dir(), "daemon") } // Dependency is a requirement to be fulfilled before a process can be started. type Dependency interface { @@ -83,32 +81,3 @@ func (p processDeps) Install(host environment.HostActions) error { return nil } - -// Run runs the daemon with background processes. -// NOTE: this must be called from the program entrypoint with minimal intermediary logic -// due to the creation of the daemon. -func Run(ctx context.Context, processes ...Process) error { - ctx, stop := context.WithCancel(ctx) - defer stop() - - var wg sync.WaitGroup - wg.Add(len(processes)) - - for _, bg := range processes { - go func(bg Process) { - err := bg.Start(ctx) - if err != nil { - logrus.Error(fmt.Errorf("error starting %s: %w", bg.Name(), err)) - stop() - } - wg.Done() - }(bg) - } - - <-ctx.Done() - logrus.Info("terminate signal received") - - wg.Wait() - - return ctx.Err() -} diff --git a/environment/vm/lima/network/daemon/vmnet/deps.go b/daemon/process/vmnet/deps.go similarity index 94% rename from environment/vm/lima/network/daemon/vmnet/deps.go rename to daemon/process/vmnet/deps.go index 682b8055f..01290729d 100644 --- a/environment/vm/lima/network/daemon/vmnet/deps.go +++ b/daemon/process/vmnet/deps.go @@ -8,12 +8,12 @@ import ( "runtime" "strings" + "github.com/abiosoft/colima/daemon/process" "github.com/abiosoft/colima/embedded" "github.com/abiosoft/colima/environment" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" ) -var _ daemon.Dependency = sudoerFile{} +var _ process.Dependency = sudoerFile{} type sudoerFile struct{} @@ -55,7 +55,7 @@ func (s sudoerFile) Install(host environment.HostActions) error { return nil } -var _ daemon.Dependency = vmnetFile{} +var _ process.Dependency = vmnetFile{} const BinaryPath = "/opt/colima/bin/vde_vmnet" const LibraryPath = "/opt/colima/lib/libvdeplug.3.dylib" @@ -113,7 +113,7 @@ func (v vmnetFile) Install(host environment.HostActions) error { return nil } -var _ daemon.Dependency = vmnetRunDir{} +var _ process.Dependency = vmnetRunDir{} type vmnetRunDir struct{} diff --git a/environment/vm/lima/network/daemon/vmnet/vmnet.go b/daemon/process/vmnet/vmnet.go similarity index 84% rename from environment/vm/lima/network/daemon/vmnet/vmnet.go rename to daemon/process/vmnet/vmnet.go index e82569624..8948eb1d9 100644 --- a/environment/vm/lima/network/daemon/vmnet/vmnet.go +++ b/daemon/process/vmnet/vmnet.go @@ -9,7 +9,7 @@ import ( "github.com/abiosoft/colima/cli" "github.com/abiosoft/colima/config" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon" + "github.com/abiosoft/colima/daemon/process" ) const ( @@ -18,10 +18,10 @@ const ( NetInterface = "col0" ) -var _ daemon.Process = (*vmnetProcess)(nil) +var _ process.Process = (*vmnetProcess)(nil) -func New() daemon.Process { return &vmnetProcess{} } -func Name() string { return "vmnet" } +func New() process.Process { return &vmnetProcess{} } +func Name() string { return "vmnet" } type vmnetProcess struct{} @@ -44,10 +44,10 @@ func (*vmnetProcess) Alive(ctx context.Context) error { return nil } -// Name implements daemon.BgProcess +// Name implements process.BgProcess func (*vmnetProcess) Name() string { return Name() } -// Start implements daemon.BgProcess +// Start implements process.BgProcess func (*vmnetProcess) Start(ctx context.Context) error { info := Info() ptp := info.PTPFile @@ -88,8 +88,8 @@ func (*vmnetProcess) Start(ctx context.Context) error { return nil } -func (vmnetProcess) Dependencies() (deps []daemon.Dependency, root bool) { - return []daemon.Dependency{ +func (vmnetProcess) Dependencies() (deps []process.Dependency, root bool) { + return []process.Dependency{ sudoerFile{}, vmnetFile{}, vmnetRunDir{}, @@ -124,6 +124,6 @@ func Info() struct { PTPFile string }{ PidFile: filepath.Join(runDir(), "vmnet-"+config.CurrentProfile().ShortName+".pid"), - PTPFile: filepath.Join(daemon.Dir(), "vmnet.ptp"), + PTPFile: filepath.Join(process.Dir(), "vmnet.ptp"), } } diff --git a/environment/container/kubernetes/k3s.go b/environment/container/kubernetes/k3s.go index c4382eb7d..c89bdf4a8 100644 --- a/environment/container/kubernetes/k3s.go +++ b/environment/container/kubernetes/k3s.go @@ -9,7 +9,7 @@ import ( "github.com/abiosoft/colima/environment" "github.com/abiosoft/colima/environment/container/containerd" "github.com/abiosoft/colima/environment/container/docker" - "github.com/abiosoft/colima/environment/vm/lima" + "github.com/abiosoft/colima/environment/vm/lima/limautil" "github.com/abiosoft/colima/util/downloader" "github.com/sirupsen/logrus" ) @@ -128,7 +128,7 @@ func installK3sCluster( } // replace ip address if networking is enabled - ipAddress := lima.IPAddress(config.CurrentProfile().ID) + ipAddress := limautil.IPAddress(config.CurrentProfile().ID) if ipAddress == "127.0.0.1" { args = append(args, "--flannel-iface", "eth0") } else { diff --git a/environment/container/kubernetes/kubeconfig.go b/environment/container/kubernetes/kubeconfig.go index 6b0400f66..fbb6c371d 100644 --- a/environment/container/kubernetes/kubeconfig.go +++ b/environment/container/kubernetes/kubeconfig.go @@ -9,13 +9,13 @@ import ( "github.com/abiosoft/colima/cli" "github.com/abiosoft/colima/config" - "github.com/abiosoft/colima/environment/vm/lima" + "github.com/abiosoft/colima/environment/vm/lima/limautil" ) const masterAddressKey = "master_address" func (c kubernetesRuntime) provisionKubeconfig(ctx context.Context) error { - ip := lima.IPAddress(config.CurrentProfile().ID) + ip := limautil.IPAddress(config.CurrentProfile().ID) if ip == c.guest.Get(masterAddressKey) { return nil } diff --git a/environment/container/ubuntu/provision.go b/environment/container/ubuntu/provision.go index 5133dcdd5..7bb43f64b 100644 --- a/environment/container/ubuntu/provision.go +++ b/environment/container/ubuntu/provision.go @@ -7,7 +7,6 @@ import ( "strconv" "github.com/abiosoft/colima/config" - "github.com/abiosoft/colima/util" ) type buildArgs struct { @@ -158,12 +157,7 @@ func (u ubuntuRuntime) createContainer(conf config.Config) error { "--volume", "/:/host", ) - mounts := conf.Mounts - if len(mounts) == 0 { - // TODO: should be not be repeated here but rather populated externally - mounts = append(mounts, config.Mount{Location: util.HomeDir()}) - mounts = append(mounts, config.Mount{Location: filepath.Join("/tmp", config.CurrentProfile().ID)}) - } + mounts := conf.MountsOrDefault() for _, m := range mounts { args = append(args, "--volume", m.Location+":"+m.Location) } diff --git a/environment/vm/lima/lima.go b/environment/vm/lima/lima.go index 62af85d7c..c2a9090d3 100644 --- a/environment/vm/lima/lima.go +++ b/environment/vm/lima/lima.go @@ -11,13 +11,14 @@ import ( "path/filepath" "time" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/gvproxy" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/vmnet" + "github.com/abiosoft/colima/daemon" + "github.com/abiosoft/colima/daemon/process/gvproxy" + "github.com/abiosoft/colima/daemon/process/vmnet" + "github.com/abiosoft/colima/environment/vm/lima/limautil" "github.com/abiosoft/colima/cli" "github.com/abiosoft/colima/config" "github.com/abiosoft/colima/environment" - "github.com/abiosoft/colima/environment/vm/lima/network" "github.com/abiosoft/colima/util" "github.com/abiosoft/colima/util/yamlutil" "github.com/sirupsen/logrus" @@ -46,7 +47,7 @@ func New(host environment.HostActions) environment.VM { host: host.WithEnv(envs...), home: home, CommandChain: cli.New("vm"), - network: network.NewManager(host), + daemon: daemon.NewManager(host), } } @@ -54,7 +55,6 @@ const ( limaInstanceEnvVar = "LIMA_INSTANCE" lima = "lima" limactl = "limactl" - layerEnvVar = "COLIMA_LAYER_SSH_PORT" ) func limaHome() (string, error) { @@ -96,7 +96,7 @@ type limaVM struct { home string // network between host and the vm - network network.Manager + daemon daemon.Manager } func (l limaVM) Dependencies() []string { @@ -105,14 +105,14 @@ func (l limaVM) Dependencies() []string { } } -func (l *limaVM) prepareNetwork(ctx context.Context, conf config.Network) (context.Context, error) { +func (l *limaVM) startDaemon(ctx context.Context, conf config.Config) (context.Context, error) { // limited to macOS for now if !util.MacOS() { return ctx, nil } - ctxKeyVmnet := network.CtxKey(vmnet.Name()) - ctxKeyGVProxy := network.CtxKey(gvproxy.Name()) + ctxKeyVmnet := daemon.CtxKey(vmnet.Name()) + ctxKeyGVProxy := daemon.CtxKey(gvproxy.Name()) // use a nested chain for convenience a := l.Init(ctx) @@ -121,10 +121,10 @@ func (l *limaVM) prepareNetwork(ctx context.Context, conf config.Network) (conte a.Stage("preparing network") a.Add(func() error { ctx = context.WithValue(ctx, ctxKeyGVProxy, true) - if conf.Address { + if conf.Network.Address { ctx = context.WithValue(ctx, ctxKeyVmnet, true) } - deps, root := l.network.Dependencies(ctx) + deps, root := l.daemon.Dependencies(ctx) if deps.Installed() { return nil } @@ -139,14 +139,14 @@ func (l *limaVM) prepareNetwork(ctx context.Context, conf config.Network) (conte }) a.Add(func() error { - return l.network.Start(ctx) + return l.daemon.Start(ctx) }) // delay to ensure that the vmnet is running - statusKey := "networkStatus" - if conf.Address { + statusKey := struct{ key string }{key: "networkStatus"} + if conf.Network.Address { a.Retry("", time.Second*3, 5, func(i int) error { - s, err := l.network.Running(ctx) + s, err := l.daemon.Running(ctx) ctx = context.WithValue(ctx, statusKey, s) if err != nil { return err @@ -166,7 +166,7 @@ func (l *limaVM) prepareNetwork(ctx context.Context, conf config.Network) (conte // network failure is not fatal if err := a.Exec(); err != nil { func() { - status, ok := ctx.Value(statusKey).(network.Status) + status, ok := ctx.Value(statusKey).(daemon.Status) if !ok { return } @@ -177,7 +177,7 @@ func (l *limaVM) prepareNetwork(ctx context.Context, conf config.Network) (conte for _, p := range status.Processes { if !p.Running { - ctx = context.WithValue(ctx, network.CtxKey(p.Name), false) + ctx = context.WithValue(ctx, daemon.CtxKey(p.Name), false) log.Warnln(fmt.Errorf("error starting %s: %w", p.Name, err)) } } @@ -185,7 +185,7 @@ func (l *limaVM) prepareNetwork(ctx context.Context, conf config.Network) (conte } // preserve gvproxy context - if gvproxyEnabled, _ := ctx.Value(network.CtxKey(gvproxy.Name())).(bool); gvproxyEnabled { + if gvproxyEnabled, _ := ctx.Value(daemon.CtxKey(gvproxy.Name())).(bool); gvproxyEnabled { l.host = l.host.WithEnv(gvproxy.SubProcessEnvVar + "=1") } @@ -200,7 +200,7 @@ func (l *limaVM) Start(ctx context.Context, conf config.Config) error { } a.Add(func() (err error) { - ctx, err = l.prepareNetwork(ctx, conf.Network) + ctx, err = l.startDaemon(ctx, conf) return err }) @@ -255,7 +255,7 @@ func (l limaVM) resume(ctx context.Context, conf config.Config) error { } a.Add(func() (err error) { - ctx, err = l.prepareNetwork(ctx, conf.Network) + ctx, err = l.startDaemon(ctx, conf) return err }) @@ -281,7 +281,7 @@ func (l limaVM) resume(ctx context.Context, conf config.Config) error { } func (l limaVM) Running(ctx context.Context) bool { - i, err := Instance() + i, err := limautil.Instance() if err != nil { logrus.Trace(fmt.Errorf("error retrieving running instance: %w", err)) return false @@ -301,7 +301,7 @@ func (l limaVM) Stop(ctx context.Context, force bool) error { if util.MacOS() { a.Retry("", time.Second*1, 10, func(retryCount int) error { - return l.network.Stop(ctx) + return l.daemon.Stop(ctx) }) } @@ -320,7 +320,7 @@ func (l limaVM) Teardown(ctx context.Context) error { if util.MacOS() { a.Retry("", time.Second*1, 10, func(retryCount int) error { - return l.network.Stop(ctx) + return l.daemon.Stop(ctx) }) } diff --git a/environment/vm/lima/cmds.go b/environment/vm/lima/limautil/limautil.go similarity index 98% rename from environment/vm/lima/cmds.go rename to environment/vm/lima/limautil/limautil.go index 556f83627..c33b48247 100644 --- a/environment/vm/lima/cmds.go +++ b/environment/vm/lima/limautil/limautil.go @@ -1,4 +1,4 @@ -package lima +package limautil import ( "bufio" @@ -16,6 +16,44 @@ import ( "gopkg.in/yaml.v3" ) +const ( + LayerEnvVar = "COLIMA_LAYER_SSH_PORT" +) + +// Instance returns current instance. +func Instance() (InstanceInfo, error) { + return getInstance(config.CurrentProfile().ID) +} + +// InstanceConfig returns the current instance config. +func InstanceConfig() (config.Config, error) { + i, err := Instance() + if err != nil { + return config.Config{}, err + } + return i.Config() +} + +// IPAddress returns the ip address for profile. +// It returns the PTP address if networking is enabled or falls back to 127.0.0.1. +// It is guaranteed to return a value. +// TODO: unnecessary round-trip is done to get instance details from Lima. +func IPAddress(profileID string) string { + // profile = toUserFriendlyName(profile) + + const fallback = "127.0.0.1" + instance, err := getInstance(profileID) + if err != nil { + return fallback + } + + if len(instance.Network) > 0 { + return getIPAddress(profileID, instance.Network[0].Interface) + } + + return fallback +} + // InstanceInfo is the information about a Lima instance type InstanceInfo struct { Name string `json:"name,omitempty"` @@ -61,25 +99,117 @@ func (i InstanceInfo) Config() (config.Config, error) { return c, nil } -// Lima statuses -const ( - limaStatusRunning = "Running" -) +// ShowSSH runs the show-ssh command in Lima. +// returns the ssh output, if in layer, and an error if any +func ShowSSH(profileID string, layer bool, format string) (resp struct { + Output string + IPAddress string + Layer bool +}, err error) { + var buf bytes.Buffer + cmd := cli.Command("limactl", "show-ssh", "--format", format, profileID) + cmd.Stdout = &buf + cmd.Stderr = os.Stderr -// Instance returns current instance. -func Instance() (InstanceInfo, error) { - return getInstance(config.CurrentProfile().ID) + if err := cmd.Run(); err != nil { + return resp, fmt.Errorf("error retrieving ssh config: %w", err) + } + + ip := IPAddress(profileID) + var port int + if layer { + port, _ = ubuntuSSHPort(profileID) + // if layer is active and public IP is available, use the fixed port + if port > 0 && ip != "127.0.0.1" { + port = 23 + } + } else { + ip = "127.0.0.1" + } + + out := buf.String() + switch format { + case "config": + out = replaceSSHConfig(out, profileID, ip, port) + case "cmd", "args": + out = replaceSSHCmd(out, profileID, ip, port) + default: + return resp, fmt.Errorf("unsupported format '%v'", format) + } + + resp.Output = out + resp.IPAddress = ip + resp.Layer = port > 0 + return resp, nil } -// InstanceConfig returns the current instance config. -func InstanceConfig() (config.Config, error) { - i, err := Instance() - if err != nil { - return config.Config{}, err +func replaceSSHCmd(cmd string, name string, ip string, port int) string { + var out []string + + for _, s := range strings.Fields(cmd) { + if port > 0 { + if strings.HasPrefix(s, "ControlPath=") { + s = "ControlPath=" + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock")) + } + if strings.HasPrefix(s, "Port=") { + s = "Port=" + strconv.Itoa(port) + } + if strings.HasPrefix(s, "Hostname=") { + s = "Hostname=" + ip + } + } + + out = append(out, s) } - return i.Config() + + if out[len(out)-1] == "lima-"+name { + out[len(out)-1] = ip + } + + return strings.Join(out, " ") +} +func replaceSSHConfig(conf string, name string, ip string, port int) string { + var out bytes.Buffer + scanner := bufio.NewScanner(strings.NewReader(conf)) + + hasPrefix := func(line, s string) (pad string, ok bool) { + if s != "" && strings.HasPrefix(strings.TrimSpace(line), s) { + return line[:strings.Index(line, s[:1])], true + } + return "", false + } + + for scanner.Scan() { + line := scanner.Text() + + if strings.HasPrefix(line, "Host ") { + line = "Host " + name + } + + if port > 0 { + if pad, ok := hasPrefix(line, "ControlPath "); ok { + line = pad + "ControlPath " + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock")) + } + + if pad, ok := hasPrefix(line, "Hostname "); ok { + line = pad + "Hostname " + ip + } + + if pad, ok := hasPrefix(line, "Port"); ok { + line = pad + "Port " + strconv.Itoa(port) + } + } + + _, _ = fmt.Fprintln(&out, line) + } + return out.String() } +// Lima statuses +const ( + limaStatusRunning = "Running" +) + func getInstance(profileID string) (InstanceInfo, error) { var i InstanceInfo var buf bytes.Buffer @@ -141,7 +271,6 @@ func Instances() ([]InstanceInfo, error) { return instances, nil } - func getIPAddress(profileID, interfaceName string) string { var buf bytes.Buffer // TODO: this should be less hacky @@ -156,7 +285,7 @@ func getIPAddress(profileID, interfaceName string) string { func ubuntuSSHPort(profileID string) (int, error) { var buf bytes.Buffer - cmd := cli.Command("limactl", "shell", profileID, "--", "sh", "-c", "echo $"+layerEnvVar) + cmd := cli.Command("limactl", "shell", profileID, "--", "sh", "-c", "echo $"+LayerEnvVar) cmd.Stdout = &buf if err := cmd.Run(); err != nil { @@ -175,10 +304,8 @@ func getRuntime(conf config.Config) string { var runtime string switch conf.Runtime { - case "docker": - runtime = "docker" - case "containerd": - runtime = "containerd" + case "docker", "containerd": + runtime = conf.Runtime default: return "" } @@ -188,129 +315,3 @@ func getRuntime(conf config.Config) string { } return runtime } - -// IPAddress returns the ip address for profile. -// It returns the PTP address if networking is enabled or falls back to 127.0.0.1. -// It is guaranteed to return a value. -// TODO: unnecessary round-trip is done to get instance details from Lima. -func IPAddress(profileID string) string { - // profile = toUserFriendlyName(profile) - - const fallback = "127.0.0.1" - instance, err := getInstance(profileID) - if err != nil { - return fallback - } - - if len(instance.Network) > 0 { - return getIPAddress(profileID, instance.Network[0].Interface) - } - - return fallback -} - -// ShowSSH runs the show-ssh command in Lima. -// returns the ssh output, if in layer, and an error if any -func ShowSSH(profileID string, layer bool, format string) (resp struct { - Output string - IPAddress string - Layer bool -}, err error) { - var buf bytes.Buffer - cmd := cli.Command("limactl", "show-ssh", "--format", format, profileID) - cmd.Stdout = &buf - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - return resp, fmt.Errorf("error retrieving ssh config: %w", err) - } - - ip := IPAddress(profileID) - var port int - if layer { - port, _ = ubuntuSSHPort(profileID) - // if layer is active and public IP is available, use the fixed port - if port > 0 && ip != "127.0.0.1" { - port = 23 - } - } else { - ip = "127.0.0.1" - } - - out := buf.String() - switch format { - case "config": - out = replaceSSHConfig(out, profileID, ip, port) - case "cmd", "args": - out = replaceSSHCmd(out, profileID, ip, port) - default: - return resp, fmt.Errorf("unsupported format '%v'", format) - } - - resp.Output = out - resp.IPAddress = ip - resp.Layer = port > 0 - return resp, nil -} - -func replaceSSHCmd(cmd string, name string, ip string, port int) string { - var out []string - - for _, s := range strings.Fields(cmd) { - if port > 0 { - if strings.HasPrefix(s, "ControlPath=") { - s = "ControlPath=" + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock")) - } - if strings.HasPrefix(s, "Port=") { - s = "Port=" + strconv.Itoa(port) - } - if strings.HasPrefix(s, "Hostname=") { - s = "Hostname=" + ip - } - } - - out = append(out, s) - } - - if out[len(out)-1] == "lima-"+name { - out[len(out)-1] = ip - } - - return strings.Join(out, " ") -} -func replaceSSHConfig(conf string, name string, ip string, port int) string { - var out bytes.Buffer - scanner := bufio.NewScanner(strings.NewReader(conf)) - - hasPrefix := func(line, s string) (pad string, ok bool) { - if s != "" && strings.HasPrefix(strings.TrimSpace(line), s) { - return line[:strings.Index(line, s[:1])], true - } - return "", false - } - - for scanner.Scan() { - line := scanner.Text() - - if strings.HasPrefix(line, "Host ") { - line = "Host " + name - } - - if port > 0 { - if pad, ok := hasPrefix(line, "ControlPath "); ok { - line = pad + "ControlPath " + strconv.Quote(filepath.Join(config.Dir(), "ssh.sock")) - } - - if pad, ok := hasPrefix(line, "Hostname "); ok { - line = pad + "Hostname " + ip - } - - if pad, ok := hasPrefix(line, "Port"); ok { - line = pad + "Port " + strconv.Itoa(port) - } - } - - _, _ = fmt.Fprintln(&out, line) - } - return out.String() -} diff --git a/environment/vm/lima/network/daemon/daemon_test.go b/environment/vm/lima/network/daemon/daemon_test.go deleted file mode 100644 index 2d57a22fa..000000000 --- a/environment/vm/lima/network/daemon/daemon_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package daemon - -import ( - "context" - "os" - "os/exec" - "testing" - "time" -) - -func TestStart(t *testing.T) { - var addresses = []string{ - "localhost", - "127.0.0.1", - } - - var processes []Process - for _, add := range addresses { - processes = append(processes, &pinger{address: add}) - } - - timeout := time.Second * 30 - ctx, cancel := context.WithTimeout(context.Background(), timeout) - - // start the processes - done := make(chan error, 1) - go func() { - done <- Run(ctx, processes...) - }() - - cancel() - - select { - case <-ctx.Done(): - if err := ctx.Err(); err != context.Canceled { - t.Error(err) - } - case err := <-done: - t.Error(err) - } - -} - -var _ Process = (*pinger)(nil) - -type pinger struct { - address string -} - -func (p pinger) Alive(ctx context.Context) error { - return nil -} - -// Name implements BgProcess -func (pinger) Name() string { return "pinger" } - -// Start implements BgProcess -func (p *pinger) Start(ctx context.Context) error { - return p.run(ctx, "ping", "-c10", p.address) -} - -// Start implements BgProcess -func (p *pinger) Dependencies() ([]Dependency, bool) { return nil, false } - -func (p *pinger) run(ctx context.Context, command string, args ...string) error { - cmd := exec.CommandContext(ctx, command, args...) - cmd.Stdout = os.Stderr - cmd.Stderr = os.Stderr - return cmd.Run() -} diff --git a/environment/vm/lima/yaml.go b/environment/vm/lima/yaml.go index dfba2e658..3abd2805a 100644 --- a/environment/vm/lima/yaml.go +++ b/environment/vm/lima/yaml.go @@ -10,15 +10,16 @@ import ( "strconv" "strings" - "github.com/abiosoft/colima/environment/vm/lima/network" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/gvproxy" - "github.com/abiosoft/colima/environment/vm/lima/network/daemon/vmnet" + "github.com/abiosoft/colima/daemon" + "github.com/abiosoft/colima/daemon/process/gvproxy" + "github.com/abiosoft/colima/daemon/process/vmnet" "gopkg.in/yaml.v3" "github.com/abiosoft/colima/config" "github.com/abiosoft/colima/embedded" "github.com/abiosoft/colima/environment" "github.com/abiosoft/colima/environment/container/docker" + "github.com/abiosoft/colima/environment/vm/lima/limautil" "github.com/abiosoft/colima/util" "github.com/sirupsen/logrus" ) @@ -60,11 +61,11 @@ func newConf(ctx context.Context, conf config.Config) (l Config, err error) { l.DNS = conf.Network.DNS if len(l.DNS) == 0 { - gvProxyEnabled, _ := ctx.Value(network.CtxKey(gvproxy.Name())).(bool) + gvProxyEnabled, _ := ctx.Value(daemon.CtxKey(gvproxy.Name())).(bool) if gvProxyEnabled { l.DNS = append(l.DNS, net.ParseIP(gvproxy.GatewayIP)) } - reachableIPAddress, _ := ctx.Value(network.CtxKey(vmnet.Name())).(bool) + reachableIPAddress, _ := ctx.Value(daemon.CtxKey(vmnet.Name())).(bool) if reachableIPAddress { l.DNS = append(l.DNS, net.ParseIP(vmnet.NetGateway)) } @@ -84,7 +85,7 @@ func newConf(ctx context.Context, conf config.Config) (l Config, err error) { // network setup { - reachableIPAddress, _ := ctx.Value(network.CtxKey(vmnet.Name())).(bool) + reachableIPAddress, _ := ctx.Value(daemon.CtxKey(vmnet.Name())).(bool) // network is currently limited to macOS. // gvproxy is cross platform but not needed on Linux as slirp is only erratic on macOS. @@ -128,7 +129,7 @@ func newConf(ctx context.Context, conf config.Config) (l Config, err error) { values.Vmnet.Interface = vmnet.NetInterface } - gvProxyEnabled, _ := ctx.Value(network.CtxKey(gvproxy.Name())).(bool) + gvProxyEnabled, _ := ctx.Value(daemon.CtxKey(gvproxy.Name())).(bool) if gvProxyEnabled { values.GVProxy.Enabled = true values.GVProxy.MacAddress = strings.ToUpper(gvproxy.MacAddress()) @@ -185,7 +186,7 @@ func newConf(ctx context.Context, conf config.Config) (l Config, err error) { if conf.Layer { port := util.RandomAvailablePort() // set port for future retrieval - l.Env[layerEnvVar] = strconv.Itoa(port) + l.Env[limautil.LayerEnvVar] = strconv.Itoa(port) // forward port l.PortForwards = append(l.PortForwards, PortForward{ diff --git a/go.mod b/go.mod index 2fb25ddc1..802a7e561 100644 --- a/go.mod +++ b/go.mod @@ -35,9 +35,10 @@ require ( require ( github.com/containers/gvisor-tap-vsock v0.3.0 github.com/docker/go-units v0.4.0 + github.com/fsnotify/fsnotify v1.5.4 github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.12 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/go.sum b/go.sum index f12972383..a37edf340 100644 --- a/go.sum +++ b/go.sum @@ -219,6 +219,8 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -890,8 +892,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/scripts/build.sh b/scripts/build.sh index c64a9e7f3..e7267ec9d 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -16,10 +16,12 @@ go build \ -o "$OUTPUT_DIR/$OUTPUT_BIN" \ ./cmd/colima -# sha256sum is not on macOS by default, use shasum +# sha256sum is not on macOS by default, use shasum if missing SHA256SUM=sha256sum if [[ "$OSTYPE" == "darwin"* ]]; then - SHA256SUM="shasum -a 256" + if ! command -v "${SHA256SUM}" &>/dev/null; then + SHA256SUM="shasum -a 256" + fi fi cd "${OUTPUT_DIR}" && ${SHA256SUM} "${OUTPUT_BIN}" >"${OUTPUT_BIN}.sha256sum" diff --git a/shell.nix b/shell.nix new file mode 100644 index 000000000..dbd40bc2d --- /dev/null +++ b/shell.nix @@ -0,0 +1,13 @@ +{ pkgs ? import { } }: + +pkgs.mkShell { + # nativeBuildInputs is usually what you want -- tools you need to run + nativeBuildInputs = with pkgs.buildPackages; [ + go_1_18 + git + coreutils + ]; + shellHook = '' + export CGO_ENABLED=0 + ''; +}