diff --git a/cmd/lima-driver-qemu/main.go b/cmd/lima-driver-qemu/main.go index cce2a346437..17521850316 100644 --- a/cmd/lima-driver-qemu/main.go +++ b/cmd/lima-driver-qemu/main.go @@ -4,11 +4,13 @@ package main import ( + "context" + "github.com/lima-vm/lima/v2/pkg/driver/external/server" "github.com/lima-vm/lima/v2/pkg/driver/qemu" ) // To be used as an external driver for Lima. func main() { - server.Serve(qemu.New()) + server.Serve(context.Background(), qemu.New()) } diff --git a/cmd/lima-driver-vz/main_darwin.go b/cmd/lima-driver-vz/main_darwin.go index 83c61d183cb..02e597c2201 100644 --- a/cmd/lima-driver-vz/main_darwin.go +++ b/cmd/lima-driver-vz/main_darwin.go @@ -4,11 +4,13 @@ package main import ( + "context" + "github.com/lima-vm/lima/v2/pkg/driver/external/server" "github.com/lima-vm/lima/v2/pkg/driver/vz" ) // To be used as an external driver for Lima. func main() { - server.Serve(vz.New()) + server.Serve(context.Background(), vz.New()) } diff --git a/cmd/lima-driver-wsl2/main_windows.go b/cmd/lima-driver-wsl2/main_windows.go index 9e1d9b66a1b..279b7b0956e 100644 --- a/cmd/lima-driver-wsl2/main_windows.go +++ b/cmd/lima-driver-wsl2/main_windows.go @@ -4,11 +4,13 @@ package main import ( + "context" + "github.com/lima-vm/lima/v2/pkg/driver/external/server" "github.com/lima-vm/lima/v2/pkg/driver/wsl2" ) // To be used as an external driver for Lima. func main() { - server.Serve(wsl2.New()) + server.Serve(context.Background(), wsl2.New()) } diff --git a/cmd/lima-guestagent/daemon_linux.go b/cmd/lima-guestagent/daemon_linux.go index 35dbbd9041c..748196f0c52 100644 --- a/cmd/lima-guestagent/daemon_linux.go +++ b/cmd/lima-guestagent/daemon_linux.go @@ -62,7 +62,7 @@ func daemonAction(cmd *cobra.Command, _ []string) error { return ticker.C, ticker.Stop } - agent, err := guestagent.New(newTicker, tick*20) + agent, err := guestagent.New(ctx, newTicker, tick*20) if err != nil { return err } diff --git a/cmd/limactl/clone.go b/cmd/limactl/clone.go index 6870c73ba7c..0406008294c 100644 --- a/cmd/limactl/clone.go +++ b/cmd/limactl/clone.go @@ -46,7 +46,7 @@ func cloneAction(cmd *cobra.Command, args []string) error { } oldInstName, newInstName := args[0], args[1] - oldInst, err := store.Inspect(oldInstName) + oldInst, err := store.Inspect(ctx, oldInstName) if err != nil { if errors.Is(err, os.ErrNotExist) { return fmt.Errorf("instance %q not found", oldInstName) @@ -75,20 +75,20 @@ func cloneAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - y, err := limayaml.LoadWithWarnings(yBytes, filePath) + y, err := limayaml.LoadWithWarnings(ctx, yBytes, filePath) if err != nil { return err } if err := limayaml.Validate(y, true); err != nil { return saveRejectedYAML(yBytes, err) } - if err := limayaml.ValidateAgainstLatestConfig(yBytes, yContent); err != nil { + if err := limayaml.ValidateAgainstLatestConfig(ctx, yBytes, yContent); err != nil { return saveRejectedYAML(yBytes, err) } if err := os.WriteFile(filePath, yBytes, 0o644); err != nil { return err } - newInst, err = store.Inspect(newInst.Name) + newInst, err = store.Inspect(ctx, newInst.Name) if err != nil { return err } diff --git a/cmd/limactl/copy.go b/cmd/limactl/copy.go index 7ae3547463b..6d84353be32 100644 --- a/cmd/limactl/copy.go +++ b/cmd/limactl/copy.go @@ -89,11 +89,11 @@ func copyAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - legacySSH := sshutil.DetectOpenSSHVersion(sshExe).LessThan(*semver.New("8.0.0")) + legacySSH := sshutil.DetectOpenSSHVersion(ctx, sshExe).LessThan(*semver.New("8.0.0")) for _, arg := range args { if runtime.GOOS == "windows" { if filepath.IsAbs(arg) { - arg, err = ioutilx.WindowsSubsystemPath(arg) + arg, err = ioutilx.WindowsSubsystemPath(ctx, arg) if err != nil { return err } @@ -107,7 +107,7 @@ func copyAction(cmd *cobra.Command, args []string) error { scpArgs = append(scpArgs, arg) case 2: instName := path[0] - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { if errors.Is(err, os.ErrNotExist) { return fmt.Errorf("instance %q does not exist, run `limactl create %s` to create a new instance", instName, instName) @@ -144,7 +144,7 @@ func copyAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - sshOpts, err = sshutil.SSHOpts(sshExe, inst.Dir, *inst.Config.User.Name, false, false, false, false) + sshOpts, err = sshutil.SSHOpts(ctx, sshExe, inst.Dir, *inst.Config.User.Name, false, false, false, false) if err != nil { return err } @@ -155,7 +155,7 @@ func copyAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - sshOpts, err = sshutil.CommonOpts(sshExe, false) + sshOpts, err = sshutil.CommonOpts(ctx, sshExe, false) if err != nil { return err } diff --git a/cmd/limactl/delete.go b/cmd/limactl/delete.go index 53ab1ed661d..168f41d47ef 100644 --- a/cmd/limactl/delete.go +++ b/cmd/limactl/delete.go @@ -33,12 +33,13 @@ func newDeleteCommand() *cobra.Command { } func deleteAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() force, err := cmd.Flags().GetBool("force") if err != nil { return err } for _, instName := range args { - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { if errors.Is(err, os.ErrNotExist) { logrus.Warnf("Ignoring non-existent instance %q", instName) @@ -50,7 +51,7 @@ func deleteAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to delete instance %q: %w", instName, err) } if runtime.GOOS == "darwin" || runtime.GOOS == "linux" { - deleted, err := autostart.DeleteStartAtLoginEntry(runtime.GOOS, instName) + deleted, err := autostart.DeleteStartAtLoginEntry(ctx, runtime.GOOS, instName) if err != nil && !errors.Is(err, os.ErrNotExist) { logrus.WithError(err).Warnf("The autostart file for instance %q does not exist", instName) } else if deleted { diff --git a/cmd/limactl/disk.go b/cmd/limactl/disk.go index 7b6423d9dd7..1f8d8e5b7f7 100644 --- a/cmd/limactl/disk.go +++ b/cmd/limactl/disk.go @@ -71,6 +71,7 @@ $ limactl disk create DISK --size SIZE [--format qcow2] } func diskCreateAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() size, err := cmd.Flags().GetString("size") if err != nil { return err @@ -112,8 +113,8 @@ func diskCreateAction(cmd *cobra.Command, args []string) error { // qemu may not be available, use it only if needed. dataDisk := filepath.Join(diskDir, filenames.DataDisk) - diskUtil := proxyimgutil.NewDiskUtil() - err = diskUtil.CreateDisk(dataDisk, diskSize) + diskUtil := proxyimgutil.NewDiskUtil(ctx) + err = diskUtil.CreateDisk(ctx, dataDisk, diskSize) if err != nil { rerr := os.RemoveAll(diskDir) if rerr != nil { @@ -232,6 +233,7 @@ $ limactl disk delete DISK1 DISK2 ... } func diskDeleteAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() force, err := cmd.Flags().GetBool("force") if err != nil { return err @@ -243,7 +245,7 @@ func diskDeleteAction(cmd *cobra.Command, args []string) error { } var instances []*store.Instance for _, instName := range instNames { - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { continue } @@ -319,7 +321,8 @@ $ limactl disk unlock DISK1 DISK2 ... return diskUnlockCommand } -func diskUnlockAction(_ *cobra.Command, args []string) error { +func diskUnlockAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() for _, diskName := range args { disk, err := store.InspectDisk(diskName) if err != nil { @@ -334,7 +337,7 @@ func diskUnlockAction(_ *cobra.Command, args []string) error { continue } // if store.Inspect throws an error, the instance does not exist, and it is safe to unlock - inst, err := store.Inspect(disk.Instance) + inst, err := store.Inspect(ctx, disk.Instance) if err == nil { if len(inst.Errors) > 0 { logrus.Warnf("Cannot unlock disk %q, attached instance %q has errors: %+v", @@ -371,6 +374,7 @@ $ limactl disk resize DISK --size SIZE`, } func diskResizeAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() size, err := cmd.Flags().GetString("size") if err != nil { return err @@ -396,7 +400,7 @@ func diskResizeAction(cmd *cobra.Command, args []string) error { } if disk.Instance != "" { - inst, err := store.Inspect(disk.Instance) + inst, err := store.Inspect(ctx, disk.Instance) if err == nil { if inst.Status == store.StatusRunning { return fmt.Errorf("cannot resize disk %q used by running instance %q. Please stop the VM instance", diskName, disk.Instance) @@ -406,8 +410,8 @@ func diskResizeAction(cmd *cobra.Command, args []string) error { // qemu may not be available, use it only if needed. dataDisk := filepath.Join(disk.Dir, filenames.DataDisk) - diskUtil := proxyimgutil.NewDiskUtil() - err = diskUtil.ResizeDisk(dataDisk, diskSize) + diskUtil := proxyimgutil.NewDiskUtil(ctx) + err = diskUtil.ResizeDisk(ctx, dataDisk, diskSize) if err != nil { return fmt.Errorf("failed to resize disk %q: %w", diskName, err) } diff --git a/cmd/limactl/edit.go b/cmd/limactl/edit.go index 01268bcab60..8db0d8f78f1 100644 --- a/cmd/limactl/edit.go +++ b/cmd/limactl/edit.go @@ -38,6 +38,7 @@ func newEditCommand() *cobra.Command { } func editAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() var arg string if len(args) > 0 { arg = args[0] @@ -51,7 +52,7 @@ func editAction(cmd *cobra.Command, args []string) error { arg = DefaultInstanceName } if err := store.ValidateInstName(arg); err == nil { - inst, err = store.Inspect(arg) + inst, err = store.Inspect(ctx, arg) if err != nil { if errors.Is(err, os.ErrNotExist) { return fmt.Errorf("instance %q not found", arg) @@ -100,7 +101,7 @@ func editAction(cmd *cobra.Command, args []string) error { hdr += "# and an empty file will abort the edit.\n" hdr += "\n" hdr += editutil.GenerateEditorWarningHeader() - yBytes, err = editutil.OpenEditor(yContent, hdr) + yBytes, err = editutil.OpenEditor(ctx, yContent, hdr) if err != nil { return err } @@ -113,7 +114,7 @@ func editAction(cmd *cobra.Command, args []string) error { logrus.Info("Aborting, no changes made to the instance") return nil } - y, err := limayaml.LoadWithWarnings(yBytes, filePath) + y, err := limayaml.LoadWithWarnings(ctx, yBytes, filePath) if err != nil { return err } @@ -121,7 +122,7 @@ func editAction(cmd *cobra.Command, args []string) error { return saveRejectedYAML(yBytes, err) } - if err := limayaml.ValidateAgainstLatestConfig(yBytes, yContent); err != nil { + if err := limayaml.ValidateAgainstLatestConfig(ctx, yBytes, yContent); err != nil { return saveRejectedYAML(yBytes, err) } @@ -148,7 +149,6 @@ func editAction(cmd *cobra.Command, args []string) error { if !startNow { return nil } - ctx := cmd.Context() err = networks.Reconcile(ctx, inst.Name) if err != nil { return err @@ -156,7 +156,7 @@ func editAction(cmd *cobra.Command, args []string) error { // store.Inspect() syncs values between inst.YAML and the store. // This call applies the validated template to the store. - inst, err = store.Inspect(inst.Name) + inst, err = store.Inspect(ctx, inst.Name) if err != nil { return err } diff --git a/cmd/limactl/factory-reset.go b/cmd/limactl/factory-reset.go index a3c4faab825..b774aef1d29 100644 --- a/cmd/limactl/factory-reset.go +++ b/cmd/limactl/factory-reset.go @@ -30,13 +30,14 @@ func newFactoryResetCommand() *cobra.Command { return resetCommand } -func factoryResetAction(_ *cobra.Command, args []string) error { +func factoryResetAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := DefaultInstanceName if len(args) > 0 { instName = args[0] } - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { if errors.Is(err, os.ErrNotExist) { logrus.Infof("Instance %q not found", instName) @@ -69,7 +70,7 @@ func factoryResetAction(_ *cobra.Command, args []string) error { } } // Regenerate the cloud-config.yaml, to reflect any changes to the global _config - if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { + if err := cidata.GenerateCloudConfig(ctx, inst.Dir, instName, inst.Config); err != nil { logrus.Error(err) } diff --git a/cmd/limactl/hostagent.go b/cmd/limactl/hostagent.go index b937ede15cd..2033600a68f 100644 --- a/cmd/limactl/hostagent.go +++ b/cmd/limactl/hostagent.go @@ -103,7 +103,7 @@ func hostagentAction(cmd *cobra.Command, args []string) error { if showProgress { opts = append(opts, hostagent.WithCloudInitProgress(showProgress)) } - ha, err := hostagent.New(instName, stdout, signalCh, opts...) + ha, err := hostagent.New(ctx, instName, stdout, signalCh, opts...) if err != nil { return err } diff --git a/cmd/limactl/info.go b/cmd/limactl/info.go index 98649dad652..a1e831f0ee5 100644 --- a/cmd/limactl/info.go +++ b/cmd/limactl/info.go @@ -24,7 +24,8 @@ func newInfoCommand() *cobra.Command { } func infoAction(cmd *cobra.Command, _ []string) error { - info, err := limainfo.New() + ctx := cmd.Context() + info, err := limainfo.New(ctx) if err != nil { return err } diff --git a/cmd/limactl/list.go b/cmd/limactl/list.go index da4aa10fe1d..97c6afa57dc 100644 --- a/cmd/limactl/list.go +++ b/cmd/limactl/list.go @@ -91,6 +91,7 @@ func (unmatchedInstancesError) ExitCode() int { } func listAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() quiet, err := cmd.Flags().GetBool("quiet") if err != nil { return err @@ -173,7 +174,7 @@ func listAction(cmd *cobra.Command, args []string) error { // get the state and config for all the requested instances var instances []*store.Instance for _, instanceName := range instanceNames { - instance, err := store.Inspect(instanceName) + instance, err := store.Inspect(ctx, instanceName) if err != nil { return fmt.Errorf("unable to load instance %s: %w", instanceName, err) } diff --git a/cmd/limactl/protect.go b/cmd/limactl/protect.go index 5ba3348e959..014128a825e 100644 --- a/cmd/limactl/protect.go +++ b/cmd/limactl/protect.go @@ -27,10 +27,11 @@ The instance is not being protected against removal via '/bin/rm', Finder, etc.` return protectCommand } -func protectAction(_ *cobra.Command, args []string) error { +func protectAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() var errs []error for _, instName := range args { - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { errs = append(errs, fmt.Errorf("failed to inspect instance %q: %w", instName, err)) continue diff --git a/cmd/limactl/prune.go b/cmd/limactl/prune.go index 8fa2e7ddc93..a17f717e745 100644 --- a/cmd/limactl/prune.go +++ b/cmd/limactl/prune.go @@ -4,6 +4,7 @@ package main import ( + "context" "maps" "os" @@ -30,6 +31,7 @@ func newPruneCommand() *cobra.Command { } func pruneAction(cmd *cobra.Command, _ []string) error { + ctx := cmd.Context() keepReferred, err := cmd.Flags().GetBool("keep-referred") if err != nil { return err @@ -44,7 +46,7 @@ func pruneAction(cmd *cobra.Command, _ []string) error { if err != nil { return err } - knownLocations, err := knownLocations() + knownLocations, err := knownLocations(ctx) if err != nil { return err } @@ -62,7 +64,7 @@ func pruneAction(cmd *cobra.Command, _ []string) error { return nil } -func knownLocations() (map[string]limayaml.File, error) { +func knownLocations(ctx context.Context) (map[string]limayaml.File, error) { locations := make(map[string]limayaml.File) // Collect locations from instances @@ -71,7 +73,7 @@ func knownLocations() (map[string]limayaml.File, error) { return nil, err } for _, instanceName := range instances { - instance, err := store.Inspect(instanceName) + instance, err := store.Inspect(ctx, instanceName) if err != nil { return nil, err } @@ -88,7 +90,7 @@ func knownLocations() (map[string]limayaml.File, error) { if err != nil { return nil, err } - y, err := limayaml.Load(b, t.Name) + y, err := limayaml.Load(ctx, b, t.Name) if err != nil { return nil, err } diff --git a/cmd/limactl/restart.go b/cmd/limactl/restart.go index 67e862082a0..a46bd09e0be 100644 --- a/cmd/limactl/restart.go +++ b/cmd/limactl/restart.go @@ -25,12 +25,13 @@ func newRestartCommand() *cobra.Command { } func restartAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := DefaultInstanceName if len(args) > 0 { instName = args[0] } - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return err } @@ -40,7 +41,6 @@ func restartAction(cmd *cobra.Command, args []string) error { return err } - ctx := cmd.Context() if force { return instance.RestartForcibly(ctx, inst) } diff --git a/cmd/limactl/shell.go b/cmd/limactl/shell.go index 0eb85e52528..3019178fc6b 100644 --- a/cmd/limactl/shell.go +++ b/cmd/limactl/shell.go @@ -4,6 +4,7 @@ package main import ( + "context" "errors" "fmt" "os" @@ -78,7 +79,7 @@ func shellAction(cmd *cobra.Command, args []string) error { } } - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { if errors.Is(err, os.ErrNotExist) { return fmt.Errorf("instance %q does not exist, run `limactl create %s` to create a new instance", instName, instName) @@ -95,8 +96,6 @@ func shellAction(cmd *cobra.Command, args []string) error { return nil } - ctx := cmd.Context() - err = networks.Reconcile(ctx, inst.Name) if err != nil { return err @@ -107,7 +106,7 @@ func shellAction(cmd *cobra.Command, args []string) error { return err } - inst, err = store.Inspect(instName) + inst, err = store.Inspect(ctx, instName) if err != nil { return err } @@ -146,7 +145,7 @@ func shellAction(cmd *cobra.Command, args []string) error { } else if len(inst.Config.Mounts) > 0 || inst.VMType == limayaml.WSL2 { hostCurrentDir, err := os.Getwd() if err == nil && runtime.GOOS == "windows" { - hostCurrentDir, err = mountDirFromWindowsDir(inst, hostCurrentDir) + hostCurrentDir, err = mountDirFromWindowsDir(ctx, inst, hostCurrentDir) } if err == nil { changeDirCmd = fmt.Sprintf("cd %s", shellescape.Quote(hostCurrentDir)) @@ -156,7 +155,7 @@ func shellAction(cmd *cobra.Command, args []string) error { } hostHomeDir, err := os.UserHomeDir() if err == nil && runtime.GOOS == "windows" { - hostHomeDir, err = mountDirFromWindowsDir(inst, hostHomeDir) + hostHomeDir, err = mountDirFromWindowsDir(ctx, inst, hostHomeDir) } if err == nil { changeDirCmd = fmt.Sprintf("%s || cd %s", changeDirCmd, shellescape.Quote(hostHomeDir)) @@ -221,6 +220,7 @@ func shellAction(cmd *cobra.Command, args []string) error { } sshOpts, err := sshutil.SSHOpts( + ctx, sshExe, inst.Dir, *inst.Config.User.Name, @@ -244,7 +244,7 @@ func shellAction(cmd *cobra.Command, args []string) error { logLevel := "ERROR" // For versions older than OpenSSH 8.9p, LogLevel=QUIET was needed to // avoid the "Shared connection to 127.0.0.1 closed." message with -t. - olderSSH := sshutil.DetectOpenSSHVersion(sshExe).LessThan(*semver.New("8.9.0")) + olderSSH := sshutil.DetectOpenSSHVersion(ctx, sshExe).LessThan(*semver.New("8.9.0")) if olderSSH { logLevel = "QUIET" } @@ -265,12 +265,12 @@ func shellAction(cmd *cobra.Command, args []string) error { return sshCmd.Run() } -func mountDirFromWindowsDir(inst *store.Instance, dir string) (string, error) { +func mountDirFromWindowsDir(ctx context.Context, inst *store.Instance, dir string) (string, error) { if inst.VMType == limayaml.WSL2 { distroName := "lima-" + inst.Name - return ioutilx.WindowsSubsystemPathForLinux(dir, distroName) + return ioutilx.WindowsSubsystemPathForLinux(ctx, dir, distroName) } - return ioutilx.WindowsSubsystemPath(dir) + return ioutilx.WindowsSubsystemPath(ctx, dir) } func shellBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { diff --git a/cmd/limactl/show-ssh.go b/cmd/limactl/show-ssh.go index 4fcda4beb6f..ff53dff7475 100644 --- a/cmd/limactl/show-ssh.go +++ b/cmd/limactl/show-ssh.go @@ -77,13 +77,14 @@ Instead, use 'ssh -F %s/default/ssh.config lima-default' . } func showSSHAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() format, err := cmd.Flags().GetString("format") if err != nil { return err } instName := args[0] w := cmd.OutOrStdout() - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { if errors.Is(err, os.ErrNotExist) { return fmt.Errorf("instance %q does not exist, run `limactl create %s` to create a new instance", instName, instName) @@ -97,6 +98,7 @@ func showSSHAction(cmd *cobra.Command, args []string) error { return err } opts, err := sshutil.SSHOpts( + ctx, sshExe, inst.Dir, *inst.Config.User.Name, diff --git a/cmd/limactl/snapshot.go b/cmd/limactl/snapshot.go index aabd11d0bbe..c2fe8d45d14 100644 --- a/cmd/limactl/snapshot.go +++ b/cmd/limactl/snapshot.go @@ -47,9 +47,10 @@ func newSnapshotCreateCommand() *cobra.Command { } func snapshotCreateAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := args[0] - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return err } @@ -63,7 +64,6 @@ func snapshotCreateAction(cmd *cobra.Command, args []string) error { return errors.New("expected tag") } - ctx := cmd.Context() return snapshot.Save(ctx, inst, tag) } @@ -82,9 +82,10 @@ func newSnapshotDeleteCommand() *cobra.Command { } func snapshotDeleteAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := args[0] - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return err } @@ -98,7 +99,6 @@ func snapshotDeleteAction(cmd *cobra.Command, args []string) error { return errors.New("expected tag") } - ctx := cmd.Context() return snapshot.Del(ctx, inst, tag) } @@ -117,9 +117,10 @@ func newSnapshotApplyCommand() *cobra.Command { } func snapshotApplyAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := args[0] - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return err } @@ -133,7 +134,6 @@ func snapshotApplyAction(cmd *cobra.Command, args []string) error { return errors.New("expected tag") } - ctx := cmd.Context() return snapshot.Load(ctx, inst, tag) } @@ -152,9 +152,10 @@ func newSnapshotListCommand() *cobra.Command { } func snapshotListAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := args[0] - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return err } @@ -163,7 +164,6 @@ func snapshotListAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - ctx := cmd.Context() out, err := snapshot.List(ctx, inst) if err != nil { return err diff --git a/cmd/limactl/start-at-login_unix.go b/cmd/limactl/start-at-login_unix.go index 55d59ca4f1e..ad3e94d62ea 100644 --- a/cmd/limactl/start-at-login_unix.go +++ b/cmd/limactl/start-at-login_unix.go @@ -18,12 +18,13 @@ import ( ) func startAtLoginAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := DefaultInstanceName if len(args) > 0 { instName = args[0] } - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { if errors.Is(err, os.ErrNotExist) { logrus.Infof("Instance %q not found", instName) @@ -38,13 +39,13 @@ func startAtLoginAction(cmd *cobra.Command, args []string) error { return err } if startAtLogin { - if err := autostart.CreateStartAtLoginEntry(runtime.GOOS, inst.Name, inst.Dir); err != nil { + if err := autostart.CreateStartAtLoginEntry(ctx, runtime.GOOS, inst.Name, inst.Dir); err != nil { logrus.WithError(err).Warnf("Can't create an autostart file for instance %q", inst.Name) } else { logrus.Infof("The autostart file %q has been created or updated", autostart.GetFilePath(runtime.GOOS, inst.Name)) } } else { - deleted, err := autostart.DeleteStartAtLoginEntry(runtime.GOOS, instName) + deleted, err := autostart.DeleteStartAtLoginEntry(ctx, runtime.GOOS, instName) if err != nil { logrus.WithError(err).Warnf("The autostart file %q could not be deleted", instName) } else if deleted { diff --git a/cmd/limactl/start.go b/cmd/limactl/start.go index 1bfcf01098f..d1319ca9f42 100644 --- a/cmd/limactl/start.go +++ b/cmd/limactl/start.go @@ -104,6 +104,7 @@ See the examples in 'limactl create --help'. } func loadOrCreateInstance(cmd *cobra.Command, args []string, createOnly bool) (*store.Instance, error) { + ctx := cmd.Context() var arg string // can be empty if len(args) > 0 { arg = args[0] @@ -171,7 +172,7 @@ func loadOrCreateInstance(cmd *cobra.Command, args []string, createOnly bool) (* tmpl.Name = arg } // store.Inspect() will validate the template name (in case it has been set to arg) - inst, err := store.Inspect(tmpl.Name) + inst, err := store.Inspect(ctx, tmpl.Name) if err == nil { if createOnly { return nil, fmt.Errorf("instance %q already exists", tmpl.Name) @@ -183,7 +184,7 @@ func loadOrCreateInstance(cmd *cobra.Command, args []string, createOnly bool) (* } if len(yqExprs) > 0 { yq := yqutil.Join(yqExprs) - inst, err = applyYQExpressionToExistingInstance(inst, yq) + inst, err = applyYQExpressionToExistingInstance(ctx, inst, yq) if err != nil { return nil, fmt.Errorf("failed to apply yq expression %q to instance %q: %w", yq, tmpl.Name, err) } @@ -209,7 +210,7 @@ func loadOrCreateInstance(cmd *cobra.Command, args []string, createOnly bool) (* } if createOnly { // store.Inspect() will also validate the instance name - if _, err := store.Inspect(tmpl.Name); err == nil { + if _, err := store.Inspect(ctx, tmpl.Name); err == nil { return nil, fmt.Errorf("instance %q already exists", tmpl.Name) } } else if err := store.ValidateInstName(tmpl.Name); err != nil { @@ -241,7 +242,7 @@ func loadOrCreateInstance(cmd *cobra.Command, args []string, createOnly bool) (* return instance.Create(cmd.Context(), tmpl.Name, tmpl.Bytes, saveBrokenYAML) } -func applyYQExpressionToExistingInstance(inst *store.Instance, yq string) (*store.Instance, error) { +func applyYQExpressionToExistingInstance(ctx context.Context, inst *store.Instance, yq string) (*store.Instance, error) { if strings.TrimSpace(yq) == "" { return inst, nil } @@ -255,7 +256,7 @@ func applyYQExpressionToExistingInstance(inst *store.Instance, yq string) (*stor if err != nil { return nil, err } - y, err := limayaml.Load(yBytes, filePath) + y, err := limayaml.Load(ctx, yBytes, filePath) if err != nil { return nil, err } @@ -271,7 +272,7 @@ func applyYQExpressionToExistingInstance(inst *store.Instance, yq string) (*stor return nil, err } // Reload - return store.Inspect(inst.Name) + return store.Inspect(ctx, inst.Name) } func modifyInPlace(st *limatmpl.Template, yq string) error { @@ -331,7 +332,7 @@ func chooseNextCreatorState(ctx context.Context, tmpl *limatmpl.Template, yq str hdr += "\n" hdr += editutil.GenerateEditorWarningHeader() var err error - tmpl.Bytes, err = editutil.OpenEditor(tmpl.Bytes, hdr) + tmpl.Bytes, err = editutil.OpenEditor(ctx, tmpl.Bytes, hdr) tmpl.Config = nil if err != nil { return tmpl, err diff --git a/cmd/limactl/stop.go b/cmd/limactl/stop.go index d4414daff01..37a297784ac 100644 --- a/cmd/limactl/stop.go +++ b/cmd/limactl/stop.go @@ -26,12 +26,13 @@ func newStopCommand() *cobra.Command { } func stopAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() instName := DefaultInstanceName if len(args) > 0 { instName = args[0] } - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return err } @@ -40,7 +41,6 @@ func stopAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - ctx := cmd.Context() if force { instance.StopForcibly(inst) } else { diff --git a/cmd/limactl/sudoers_darwin.go b/cmd/limactl/sudoers_darwin.go index cfa5f464620..47992cb2847 100644 --- a/cmd/limactl/sudoers_darwin.go +++ b/cmd/limactl/sudoers_darwin.go @@ -4,6 +4,7 @@ package main import ( + "context" "errors" "fmt" "io" @@ -15,6 +16,7 @@ import ( ) func sudoersAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() nwCfg, err := networks.LoadConfig() if err != nil { return err @@ -29,7 +31,7 @@ func sudoersAction(cmd *cobra.Command, args []string) error { return err } if check { - return verifySudoAccess(nwCfg, args, cmd.OutOrStdout()) + return verifySudoAccess(ctx, nwCfg, args, cmd.OutOrStdout()) } switch len(args) { case 0: @@ -47,7 +49,7 @@ func sudoersAction(cmd *cobra.Command, args []string) error { return nil } -func verifySudoAccess(nwCfg networks.Config, args []string, stdout io.Writer) error { +func verifySudoAccess(ctx context.Context, nwCfg networks.Config, args []string, stdout io.Writer) error { var file string switch len(args) { case 0: @@ -61,7 +63,7 @@ func verifySudoAccess(nwCfg networks.Config, args []string, stdout io.Writer) er default: return errors.New("can check only a single sudoers file") } - if err := nwCfg.VerifySudoAccess(file); err != nil { + if err := nwCfg.VerifySudoAccess(ctx, file); err != nil { return err } fmt.Fprintf(stdout, "%q is up-to-date (or sudo doesn't require a password)\n", file) diff --git a/cmd/limactl/template.go b/cmd/limactl/template.go index b05a3f11cd2..6b8eb3675bc 100644 --- a/cmd/limactl/template.go +++ b/cmd/limactl/template.go @@ -4,6 +4,7 @@ package main import ( + "context" "errors" "fmt" "os" @@ -74,7 +75,7 @@ func newTemplateCopyCommand() *cobra.Command { return templateCopyCommand } -func fillDefaults(tmpl *limatmpl.Template) error { +func fillDefaults(ctx context.Context, tmpl *limatmpl.Template) error { limaDir, err := dirnames.LimaDir() if err != nil { return err @@ -82,7 +83,7 @@ func fillDefaults(tmpl *limatmpl.Template) error { // Load() will merge the template with override.yaml and default.yaml via FillDefaults(). // FillDefaults() needs the potential instance directory to validate host templates using {{.Dir}}. filePath := filepath.Join(limaDir, tmpl.Name+".yaml") - tmpl.Config, err = limayaml.Load(tmpl.Bytes, filePath) + tmpl.Config, err = limayaml.Load(ctx, tmpl.Bytes, filePath) if err == nil { tmpl.Bytes, err = limayaml.Marshal(tmpl.Config, false) } @@ -90,6 +91,7 @@ func fillDefaults(tmpl *limatmpl.Template) error { } func templateCopyAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() source := args[0] target := args[1] embed, err := cmd.Flags().GetBool("embed") @@ -137,7 +139,7 @@ func templateCopyAction(cmd *cobra.Command, args []string) error { } } if fill { - if err := fillDefaults(tmpl); err != nil { + if err := fillDefaults(ctx, tmpl); err != nil { return err } } @@ -177,6 +179,7 @@ func newTemplateYQCommand() *cobra.Command { } func templateYQAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() locator := args[0] expr := args[1] tmpl, err := limatmpl.Read(cmd.Context(), "", locator) @@ -189,7 +192,7 @@ func templateYQAction(cmd *cobra.Command, args []string) error { if err := tmpl.Embed(cmd.Context(), true, true); err != nil { return err } - if err := fillDefaults(tmpl); err != nil { + if err := fillDefaults(ctx, tmpl); err != nil { return err } out, err := yqutil.EvaluateExpressionPlain(expr, string(tmpl.Bytes)) @@ -211,6 +214,7 @@ func newTemplateValidateCommand() *cobra.Command { } func templateValidateAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() fill, err := cmd.Flags().GetBool("fill") if err != nil { return err @@ -238,7 +242,7 @@ func templateValidateAction(cmd *cobra.Command, args []string) error { // Load() will merge the template with override.yaml and default.yaml via FillDefaults(). // FillDefaults() needs the potential instance directory to validate host templates using {{.Dir}}. filePath := filepath.Join(limaDir, tmpl.Name+".yaml") - y, err := limayaml.Load(tmpl.Bytes, filePath) + y, err := limayaml.Load(ctx, tmpl.Bytes, filePath) if err != nil { return err } diff --git a/cmd/limactl/tunnel.go b/cmd/limactl/tunnel.go index 3796d0a681e..43f3555dac4 100644 --- a/cmd/limactl/tunnel.go +++ b/cmd/limactl/tunnel.go @@ -65,7 +65,7 @@ func tunnelAction(cmd *cobra.Command, args []string) error { } stdout, stderr := cmd.OutOrStdout(), cmd.ErrOrStderr() instName := args[0] - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { if errors.Is(err, os.ErrNotExist) { return fmt.Errorf("instance %q does not exist, run `limactl create %s` to create a new instance", instName, instName) @@ -89,6 +89,7 @@ func tunnelAction(cmd *cobra.Command, args []string) error { } sshOpts, err := sshutil.SSHOpts( + ctx, sshExe, inst.Dir, *inst.Config.User.Name, diff --git a/cmd/limactl/unprotect.go b/cmd/limactl/unprotect.go index dc8258f9aa9..99df11fda2a 100644 --- a/cmd/limactl/unprotect.go +++ b/cmd/limactl/unprotect.go @@ -25,10 +25,11 @@ func newUnprotectCommand() *cobra.Command { return unprotectCommand } -func unprotectAction(_ *cobra.Command, args []string) error { +func unprotectAction(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() var errs []error for _, instName := range args { - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { errs = append(errs, fmt.Errorf("failed to inspect instance %q: %w", instName, err)) continue diff --git a/pkg/autostart/autostart.go b/pkg/autostart/autostart.go index 9da5537ec0b..c2b15a82790 100644 --- a/pkg/autostart/autostart.go +++ b/pkg/autostart/autostart.go @@ -26,7 +26,7 @@ var systemdTemplate string var launchdTemplate string // CreateStartAtLoginEntry respect host OS arch and create unit file. -func CreateStartAtLoginEntry(hostOS, instName, workDir string) error { +func CreateStartAtLoginEntry(ctx context.Context, hostOS, instName, workDir string) error { unitPath := GetFilePath(hostOS, instName) if _, err := os.Stat(unitPath); err != nil && !errors.Is(err, os.ErrNotExist) { return err @@ -41,17 +41,17 @@ func CreateStartAtLoginEntry(hostOS, instName, workDir string) error { if err := os.WriteFile(unitPath, tmpl, 0o644); err != nil { return err } - return enableDisableService("enable", hostOS, GetFilePath(hostOS, instName)) + return enableDisableService(ctx, "enable", hostOS, GetFilePath(hostOS, instName)) } // DeleteStartAtLoginEntry respect host OS arch and delete unit file. // Return true, nil if unit file has been deleted. -func DeleteStartAtLoginEntry(hostOS, instName string) (bool, error) { +func DeleteStartAtLoginEntry(ctx context.Context, hostOS, instName string) (bool, error) { unitPath := GetFilePath(hostOS, instName) if _, err := os.Stat(unitPath); err != nil { return false, err } - if err := enableDisableService("disable", hostOS, GetFilePath(hostOS, instName)); err != nil { + if err := enableDisableService(ctx, "disable", hostOS, GetFilePath(hostOS, instName)); err != nil { return false, err } if err := os.Remove(unitPath); err != nil { @@ -78,8 +78,7 @@ func GetFilePath(hostOS, instName string) string { return fileTmpl } -func enableDisableService(action, hostOS, serviceWithPath string) error { - ctx := context.TODO() +func enableDisableService(ctx context.Context, action, hostOS, serviceWithPath string) error { // Get filename without extension filename := strings.TrimSuffix(path.Base(serviceWithPath), filepath.Ext(path.Base(serviceWithPath))) diff --git a/pkg/cidata/cidata.go b/pkg/cidata/cidata.go index 0bf39d3f9a1..0a8c57aa9c9 100644 --- a/pkg/cidata/cidata.go +++ b/pkg/cidata/cidata.go @@ -5,6 +5,7 @@ package cidata import ( "compress/gzip" + "context" "errors" "fmt" "io" @@ -115,7 +116,7 @@ func setupEnv(instConfigEnv map[string]string, propagateProxyEnv bool, slirpGate return env, nil } -func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort, vsockPort int, virtioPort string) (*TemplateArgs, error) { +func templateArgs(ctx context.Context, bootScripts bool, instDir, name string, instConfig *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort, vsockPort int, virtioPort string) (*TemplateArgs, error) { if err := limayaml.Validate(instConfig, false); err != nil { return nil, err } @@ -174,7 +175,7 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L // change instance id on every boot so network config will be processed again args.IID = fmt.Sprintf("iid-%d", time.Now().Unix()) - pubKeys, err := sshutil.DefaultPubKeys(*instConfig.SSH.LoadDotSSHPubKeys) + pubKeys, err := sshutil.DefaultPubKeys(ctx, *instConfig.SSH.LoadDotSSHPubKeys) if err != nil { return nil, err } @@ -332,8 +333,8 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L return &args, nil } -func GenerateCloudConfig(instDir, name string, instConfig *limayaml.LimaYAML) error { - args, err := templateArgs(false, instDir, name, instConfig, 0, 0, 0, "") +func GenerateCloudConfig(ctx context.Context, instDir, name string, instConfig *limayaml.LimaYAML) error { + args, err := templateArgs(ctx, false, instDir, name, instConfig, 0, 0, 0, "") if err != nil { return err } @@ -355,8 +356,8 @@ func GenerateCloudConfig(instDir, name string, instConfig *limayaml.LimaYAML) er return os.WriteFile(filepath.Join(instDir, filenames.CloudConfig), config, 0o444) } -func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, guestAgentBinary, nerdctlArchive string, vsockPort int, virtioPort string) error { - args, err := templateArgs(true, instDir, name, instConfig, udpDNSLocalPort, tcpDNSLocalPort, vsockPort, virtioPort) +func GenerateISO9660(ctx context.Context, instDir, name string, instConfig *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, guestAgentBinary, nerdctlArchive string, vsockPort int, virtioPort string) error { + args, err := templateArgs(ctx, true, instDir, name, instConfig, udpDNSLocalPort, tcpDNSLocalPort, vsockPort, virtioPort) if err != nil { return err } diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go index 7527039c50d..f9811f6e1c7 100644 --- a/pkg/driver/driver.go +++ b/pkg/driver/driver.go @@ -13,7 +13,7 @@ import ( // Lifecycle defines basic lifecycle operations. type Lifecycle interface { // Validate returns error if the current driver isn't support for given config - Validate() error + Validate(_ context.Context) error // Initialize is called on creating the instance for initialization. // (e.g., creating "vz-identifier" file) diff --git a/pkg/driver/external/client/methods.go b/pkg/driver/external/client/methods.go index ed846813c76..2b95f85f05d 100644 --- a/pkg/driver/external/client/methods.go +++ b/pkg/driver/external/client/methods.go @@ -17,12 +17,11 @@ import ( "github.com/lima-vm/lima/v2/pkg/store" ) -func (d *DriverClient) Validate() error { +func (d *DriverClient) Validate(ctx context.Context) error { d.logger.Debug("Validating driver for the given config") - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() - _, err := d.DriverSvc.Validate(ctx, &emptypb.Empty{}) if err != nil { d.logger.Errorf("Validation failed: %v", err) diff --git a/pkg/driver/external/server/methods.go b/pkg/driver/external/server/methods.go index f170c093d04..73cfafedcff 100644 --- a/pkg/driver/external/server/methods.go +++ b/pkg/driver/external/server/methods.go @@ -117,9 +117,9 @@ func (s *DriverServer) GetInfo(_ context.Context, _ *emptypb.Empty) (*pb.InfoRes }, nil } -func (s *DriverServer) Validate(_ context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { +func (s *DriverServer) Validate(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { s.logger.Debugf("Received Validate request") - err := s.driver.Validate() + err := s.driver.Validate(ctx) if err != nil { s.logger.Errorf("Validation failed: %v", err) return empty, err diff --git a/pkg/driver/external/server/server.go b/pkg/driver/external/server/server.go index 3f0e68708d3..a40d4b1b3b3 100644 --- a/pkg/driver/external/server/server.go +++ b/pkg/driver/external/server/server.go @@ -50,8 +50,7 @@ func (t *listenerTracker) Accept() (net.Conn, error) { return c, err } -func Serve(driver driver.Driver) { - ctx := context.TODO() +func Serve(ctx context.Context, driver driver.Driver) { logger := logrus.New() logger.SetLevel(logrus.DebugLevel) diff --git a/pkg/driver/qemu/entitlementutil/entitlementutil.go b/pkg/driver/qemu/entitlementutil/entitlementutil.go index 6d57b772a8a..f59785e065c 100644 --- a/pkg/driver/qemu/entitlementutil/entitlementutil.go +++ b/pkg/driver/qemu/entitlementutil/entitlementutil.go @@ -19,8 +19,7 @@ import ( // IsSigned returns an error if the binary is not signed, or the sign is invalid, // or not associated with the "com.apple.security.hypervisor" entitlement. -func IsSigned(qExe string) error { - ctx := context.TODO() +func IsSigned(ctx context.Context, qExe string) error { cmd := exec.CommandContext(ctx, "codesign", "--verify", qExe) out, err := cmd.CombinedOutput() logrus.WithError(err).Debugf("Executed %v: out=%q", cmd.Args, string(out)) @@ -40,8 +39,7 @@ func IsSigned(qExe string) error { return nil } -func Sign(qExe string) error { - ctx := context.TODO() +func Sign(ctx context.Context, qExe string) error { ent, err := os.CreateTemp("", "lima-qemu-entitlements-*.xml") if err != nil { return fmt.Errorf("failed to create a temporary file for signing QEMU binary: %w", err) @@ -85,8 +83,8 @@ func isColimaWrapper__useThisFunctionOnlyForPrintingHints__(qExe string) bool { // // On Homebrew, QEMU binaries are usually already signed, but Homebrew's signing infrastructure is broken for Intel as of August 2023. // https://github.com/lima-vm/lima/issues/1742 -func AskToSignIfNotSignedProperly(qExe string) { - if isSignedErr := IsSigned(qExe); isSignedErr != nil { +func AskToSignIfNotSignedProperly(ctx context.Context, qExe string) { + if isSignedErr := IsSigned(ctx, qExe); isSignedErr != nil { logrus.WithError(isSignedErr).Warnf("QEMU binary %q does not seem properly signed with the \"com.apple.security.hypervisor\" entitlement", qExe) if isColimaWrapper__useThisFunctionOnlyForPrintingHints__(qExe) { logrus.Info("Hint: the warning above is usually negligible for colima ( Printed due to https://github.com/abiosoft/colima/issues/796 )") @@ -101,7 +99,7 @@ func AskToSignIfNotSignedProperly(qExe string) { } } if ans { - if signErr := Sign(qExe); signErr != nil { + if signErr := Sign(ctx, qExe); signErr != nil { logrus.WithError(signErr).Warnf("Failed to sign %q", qExe) } else { logrus.Infof("Successfully signed %q with the \"com.apple.security.hypervisor\" entitlement", qExe) diff --git a/pkg/driver/qemu/qemu.go b/pkg/driver/qemu/qemu.go index 383fcce3ade..9f3c12d9851 100644 --- a/pkg/driver/qemu/qemu.go +++ b/pkg/driver/qemu/qemu.go @@ -103,7 +103,7 @@ func EnsureDisk(ctx context.Context, cfg Config) error { if err != nil { return err } - baseDiskInfo, err := qemuimgutil.GetInfo(baseDisk) + baseDiskInfo, err := qemuimgutil.GetInfo(ctx, baseDisk) if err != nil { return fmt.Errorf("failed to get the information of base disk %q: %w", baseDisk, err) } @@ -149,8 +149,7 @@ func sendHmpCommand(cfg Config, cmd, tag string) (string, error) { return rawClient.HumanMonitorCommand(hmc, nil) } -func execImgCommand(cfg Config, args ...string) (string, error) { - ctx := context.TODO() +func execImgCommand(ctx context.Context, cfg Config, args ...string) (string, error) { diffDisk := filepath.Join(cfg.InstanceDir, filenames.DiffDisk) args = append(args, diffDisk) logrus.Debugf("Running qemu-img %v command", args) @@ -162,7 +161,7 @@ func execImgCommand(cfg Config, args ...string) (string, error) { return string(b), err } -func Del(cfg Config, run bool, tag string) error { +func Del(ctx context.Context, cfg Config, run bool, tag string) error { if run { out, err := sendHmpCommand(cfg, "delvm", tag) // there can still be output, even if no error! @@ -172,11 +171,11 @@ func Del(cfg Config, run bool, tag string) error { return err } // -d deletes a snapshot - _, err := execImgCommand(cfg, "snapshot", "-d", tag) + _, err := execImgCommand(ctx, cfg, "snapshot", "-d", tag) return err } -func Save(cfg Config, run bool, tag string) error { +func Save(ctx context.Context, cfg Config, run bool, tag string) error { if run { out, err := sendHmpCommand(cfg, "savevm", tag) // there can still be output, even if no error! @@ -186,11 +185,11 @@ func Save(cfg Config, run bool, tag string) error { return err } // -c creates a snapshot - _, err := execImgCommand(cfg, "snapshot", "-c", tag) + _, err := execImgCommand(ctx, cfg, "snapshot", "-c", tag) return err } -func Load(cfg Config, run bool, tag string) error { +func Load(ctx context.Context, cfg Config, run bool, tag string) error { if run { out, err := sendHmpCommand(cfg, "loadvm", tag) // there can still be output, even if no error! @@ -200,12 +199,12 @@ func Load(cfg Config, run bool, tag string) error { return err } // -a applies a snapshot - _, err := execImgCommand(cfg, "snapshot", "-a", tag) + _, err := execImgCommand(ctx, cfg, "snapshot", "-a", tag) return err } // List returns a space-separated list of all snapshots, with header and newlines. -func List(cfg Config, run bool) (string, error) { +func List(ctx context.Context, cfg Config, run bool) (string, error) { if run { out, err := sendHmpCommand(cfg, "info", "snapshots") if err == nil { @@ -217,7 +216,7 @@ func List(cfg Config, run bool) (string, error) { } // -l lists all snapshots args := []string{"snapshot", "-l"} - out, err := execImgCommand(cfg, args...) + out, err := execImgCommand(ctx, cfg, args...) if err == nil { // remove the redundant heading, result is not machine-parseable out = strings.Replace(out, "Snapshot list:\n", "", 1) @@ -288,9 +287,8 @@ type features struct { CPUHelp []byte } -func inspectFeatures(exe, machine string) (*features, error) { +func inspectFeatures(ctx context.Context, exe, machine string) (*features, error) { var ( - ctx = context.TODO() f features stdout bytes.Buffer stderr bytes.Buffer @@ -474,12 +472,12 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er return "", nil, err } - features, err := inspectFeatures(exe, qemuMachine(*y.Arch)) + features, err := inspectFeatures(ctx, exe, qemuMachine(*y.Arch)) if err != nil { return "", nil, err } - version, err := getQemuVersion(exe) + version, err := getQemuVersion(ctx, exe) if err != nil { logrus.WithError(err).Warning("Failed to detect QEMU version") } else { @@ -720,7 +718,7 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er if diskSize, _ := units.RAMInBytes(*cfg.LimaYAML.Disk); diskSize > 0 { args = append(args, "-drive", fmt.Sprintf("file=%s,if=virtio,discard=on", diffDisk)) } else if !isBaseDiskCDROM { - baseDiskInfo, err := qemuimgutil.GetInfo(baseDisk) + baseDiskInfo, err := qemuimgutil.GetInfo(ctx, baseDisk) if err != nil { return "", nil, fmt.Errorf("failed to get the information of %q: %w", baseDisk, err) } @@ -977,8 +975,7 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er return exe, args, nil } -func FindVirtiofsd(qemuExe string) (string, error) { - ctx := context.TODO() +func FindVirtiofsd(ctx context.Context, qemuExe string) (string, error) { type vhostUserBackend struct { BackendType string `json:"type"` Binary string `json:"binary"` @@ -1135,9 +1132,8 @@ func parseQemuVersion(output string) (*semver.Version, error) { return &semver.Version{}, fmt.Errorf("failed to parse %v", output) } -func getQemuVersion(qemuExe string) (*semver.Version, error) { +func getQemuVersion(ctx context.Context, qemuExe string) (*semver.Version, error) { var ( - ctx = context.TODO() stdout bytes.Buffer stderr bytes.Buffer ) diff --git a/pkg/driver/qemu/qemu_driver.go b/pkg/driver/qemu/qemu_driver.go index 2ccdc1176be..8e7f49e28b1 100644 --- a/pkg/driver/qemu/qemu_driver.go +++ b/pkg/driver/qemu/qemu_driver.go @@ -73,9 +73,9 @@ func (l *LimaQemuDriver) Configure(inst *store.Instance) *driver.ConfiguredDrive } } -func (l *LimaQemuDriver) Validate() error { +func (l *LimaQemuDriver) Validate(ctx context.Context) error { if runtime.GOOS == "darwin" { - if err := l.checkBinarySignature(); err != nil { + if err := l.checkBinarySignature(ctx); err != nil { return err } } @@ -119,7 +119,7 @@ func (l *LimaQemuDriver) Start(_ context.Context) (chan error, error) { var vhostCmds []*exec.Cmd if *l.Instance.Config.MountType == limayaml.VIRTIOFS { - vhostExe, err := FindVirtiofsd(qExe) + vhostExe, err := FindVirtiofsd(ctx, qExe) if err != nil { return nil, err } @@ -270,7 +270,7 @@ func waitFileExists(path string, timeout time.Duration) error { // Ask the user to sign the qemu binary with the "com.apple.security.hypervisor" if needed. // Workaround for https://github.com/lima-vm/lima/issues/1742 -func (l *LimaQemuDriver) checkBinarySignature() error { +func (l *LimaQemuDriver) checkBinarySignature(ctx context.Context) error { macOSProductVersion, err := osutil.ProductVersion() if err != nil { return err @@ -282,7 +282,7 @@ func (l *LimaQemuDriver) checkBinarySignature() error { return fmt.Errorf("failed to find the QEMU binary for the architecture %q: %w", l.Instance.Arch, err) } if accel := Accel(l.Instance.Arch); accel == "hvf" { - entitlementutil.AskToSignIfNotSignedProperly(qExe) + entitlementutil.AskToSignIfNotSignedProperly(ctx, qExe) } } @@ -434,40 +434,40 @@ func logPipeRoutine(r io.Reader, header string) { } } -func (l *LimaQemuDriver) DeleteSnapshot(_ context.Context, tag string) error { +func (l *LimaQemuDriver) DeleteSnapshot(ctx context.Context, tag string) error { qCfg := Config{ Name: l.Instance.Name, InstanceDir: l.Instance.Dir, LimaYAML: l.Instance.Config, } - return Del(qCfg, l.Instance.Status == store.StatusRunning, tag) + return Del(ctx, qCfg, l.Instance.Status == store.StatusRunning, tag) } -func (l *LimaQemuDriver) CreateSnapshot(_ context.Context, tag string) error { +func (l *LimaQemuDriver) CreateSnapshot(ctx context.Context, tag string) error { qCfg := Config{ Name: l.Instance.Name, InstanceDir: l.Instance.Dir, LimaYAML: l.Instance.Config, } - return Save(qCfg, l.Instance.Status == store.StatusRunning, tag) + return Save(ctx, qCfg, l.Instance.Status == store.StatusRunning, tag) } -func (l *LimaQemuDriver) ApplySnapshot(_ context.Context, tag string) error { +func (l *LimaQemuDriver) ApplySnapshot(ctx context.Context, tag string) error { qCfg := Config{ Name: l.Instance.Name, InstanceDir: l.Instance.Dir, LimaYAML: l.Instance.Config, } - return Load(qCfg, l.Instance.Status == store.StatusRunning, tag) + return Load(ctx, qCfg, l.Instance.Status == store.StatusRunning, tag) } -func (l *LimaQemuDriver) ListSnapshots(_ context.Context) (string, error) { +func (l *LimaQemuDriver) ListSnapshots(ctx context.Context) (string, error) { qCfg := Config{ Name: l.Instance.Name, InstanceDir: l.Instance.Dir, LimaYAML: l.Instance.Config, } - return List(qCfg, l.Instance.Status == store.StatusRunning) + return List(ctx, qCfg, l.Instance.Status == store.StatusRunning) } func (l *LimaQemuDriver) GuestAgentConn(ctx context.Context) (net.Conn, string, error) { diff --git a/pkg/driver/vz/disk.go b/pkg/driver/vz/disk.go index 138e67dd079..35f28f520ec 100644 --- a/pkg/driver/vz/disk.go +++ b/pkg/driver/vz/disk.go @@ -18,14 +18,14 @@ import ( "github.com/lima-vm/lima/v2/pkg/store/filenames" ) -func EnsureDisk(_ context.Context, inst *store.Instance) error { +func EnsureDisk(ctx context.Context, inst *store.Instance) error { diffDisk := filepath.Join(inst.Dir, filenames.DiffDisk) if _, err := os.Stat(diffDisk); err == nil || !errors.Is(err, os.ErrNotExist) { // disk is already ensured return err } - diskUtil := proxyimgutil.NewDiskUtil() + diskUtil := proxyimgutil.NewDiskUtil(ctx) baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk) @@ -44,14 +44,14 @@ func EnsureDisk(_ context.Context, inst *store.Instance) error { return err } - err = diskUtil.MakeSparse(diffDiskF, 0) + err = diskUtil.MakeSparse(ctx, diffDiskF, 0) if err != nil { diffDiskF.Close() return fmt.Errorf("failed to create sparse diff disk %q: %w", diffDisk, err) } return diffDiskF.Close() } - if err = diskUtil.ConvertToRaw(baseDisk, diffDisk, &diskSize, false); err != nil { + if err = diskUtil.ConvertToRaw(ctx, baseDisk, diffDisk, &diskSize, false); err != nil { return fmt.Errorf("failed to convert %q to a raw disk %q: %w", baseDisk, diffDisk, err) } return err diff --git a/pkg/driver/vz/network_darwin.go b/pkg/driver/vz/network_darwin.go index 9dfda4a6d13..b841114ce58 100644 --- a/pkg/driver/vz/network_darwin.go +++ b/pkg/driver/vz/network_darwin.go @@ -43,8 +43,7 @@ func PassFDToUnix(unixSock string) (*os.File, error) { // DialQemu support connecting to QEMU supported network stack via unix socket. // Returns os.File, connected dgram connection to be used for vz. -func DialQemu(unixSock string) (*os.File, error) { - ctx := context.TODO() +func DialQemu(ctx context.Context, unixSock string) (*os.File, error) { var dialer net.Dialer unixConn, err := dialer.DialContext(ctx, "unix", unixSock) if err != nil { diff --git a/pkg/driver/vz/network_darwin_test.go b/pkg/driver/vz/network_darwin_test.go index 8a6659f585e..eb1538cfb63 100644 --- a/pkg/driver/vz/network_darwin_test.go +++ b/pkg/driver/vz/network_darwin_test.go @@ -36,7 +36,7 @@ func TestDialQemu(t *testing.T) { }() // Connect to the fake vmnet server. - client, err := DialQemu(listener.Addr().String()) + client, err := DialQemu(t.Context(), listener.Addr().String()) assert.NilError(t, err) t.Log("Connected to fake vment server") diff --git a/pkg/driver/vz/vm_darwin.go b/pkg/driver/vz/vm_darwin.go index 0889c29dc92..aec3a8a05ee 100644 --- a/pkg/driver/vz/vm_darwin.go +++ b/pkg/driver/vz/vm_darwin.go @@ -57,7 +57,7 @@ func startVM(ctx context.Context, inst *store.Instance, sshLocalPort int) (*virt return nil, nil, err } - machine, err := createVM(inst) + machine, err := createVM(ctx, inst) if err != nil { return nil, nil, err } @@ -161,7 +161,7 @@ func startUsernet(ctx context.Context, inst *store.Instance) (*usernet.Client, e return usernet.NewClient(endpointSock, subnetIP), err } -func createVM(inst *store.Instance) (*vz.VirtualMachine, error) { +func createVM(ctx context.Context, inst *store.Instance) (*vz.VirtualMachine, error) { vmConfig, err := createInitialConfig(inst) if err != nil { return nil, err @@ -175,11 +175,11 @@ func createVM(inst *store.Instance) (*vz.VirtualMachine, error) { return nil, err } - if err = attachNetwork(inst, vmConfig); err != nil { + if err = attachNetwork(ctx, inst, vmConfig); err != nil { return nil, err } - if err = attachDisks(inst, vmConfig); err != nil { + if err = attachDisks(ctx, inst, vmConfig); err != nil { return nil, err } @@ -302,7 +302,7 @@ func newVirtioNetworkDeviceConfiguration(attachment vz.NetworkDeviceAttachment, return networkConfig, nil } -func attachNetwork(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { +func attachNetwork(ctx context.Context, inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { var configurations []*vz.VirtioNetworkDeviceConfiguration // Configure default usernetwork with limayaml.MACAddress(inst.Dir) for eth0 interface @@ -390,7 +390,7 @@ func attachNetwork(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguratio return err } - clientFile, err := DialQemu(sock) + clientFile, err := DialQemu(ctx, sock) if err != nil { return err } @@ -402,7 +402,7 @@ func attachNetwork(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguratio } } } else if nw.Socket != "" { - clientFile, err := DialQemu(nw.Socket) + clientFile, err := DialQemu(ctx, nw.Socket) if err != nil { return err } @@ -434,7 +434,7 @@ func validateDiskFormat(diskPath string) error { return nil } -func attachDisks(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { +func attachDisks(ctx context.Context, inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) error { baseDiskPath := filepath.Join(inst.Dir, filenames.BaseDisk) diffDiskPath := filepath.Join(inst.Dir, filenames.DiffDisk) ciDataPath := filepath.Join(inst.Dir, filenames.CIDataISO) @@ -471,7 +471,7 @@ func attachDisks(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) } configurations = append(configurations, diffDisk) - diskUtil := proxyimgutil.NewDiskUtil() + diskUtil := proxyimgutil.NewDiskUtil(ctx) for _, d := range inst.Config.AdditionalDisks { diskName := d.Name @@ -492,7 +492,7 @@ func attachDisks(inst *store.Instance, vmConfig *vz.VirtualMachineConfiguration) // ConvertToRaw is a NOP if no conversion is needed logrus.Debugf("Converting extra disk %q to a raw disk (if it is not a raw)", extraDiskPath) - if err = diskUtil.ConvertToRaw(extraDiskPath, extraDiskPath, nil, true); err != nil { + if err = diskUtil.ConvertToRaw(ctx, extraDiskPath, extraDiskPath, nil, true); err != nil { return fmt.Errorf("failed to convert extra disk %q to a raw disk: %w", extraDiskPath, err) } extraDiskPathAttachment, err := vz.NewDiskImageStorageDeviceAttachmentWithCacheAndSync(extraDiskPath, false, diskImageCachingMode, vz.DiskImageSynchronizationModeFsync) diff --git a/pkg/driver/vz/vz_driver_darwin.go b/pkg/driver/vz/vz_driver_darwin.go index 7055c3cdbc0..17c70ca238c 100644 --- a/pkg/driver/vz/vz_driver_darwin.go +++ b/pkg/driver/vz/vz_driver_darwin.go @@ -96,7 +96,7 @@ func (l *LimaVzDriver) Configure(inst *store.Instance) *driver.ConfiguredDriver } } -func (l *LimaVzDriver) Validate() error { +func (l *LimaVzDriver) Validate(_ context.Context) error { macOSProductVersion, err := osutil.ProductVersion() if err != nil { return err diff --git a/pkg/driver/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go index 821f0b6bb4a..930a2b8424c 100644 --- a/pkg/driver/wsl2/wsl_driver_windows.go +++ b/pkg/driver/wsl2/wsl_driver_windows.go @@ -77,7 +77,7 @@ func (l *LimaWslDriver) Configure(inst *store.Instance) *driver.ConfiguredDriver } } -func (l *LimaWslDriver) Validate() error { +func (l *LimaWslDriver) Validate(_ context.Context) error { if *l.Instance.Config.MountType != limayaml.WSLMount { return fmt.Errorf("field `mountType` must be %q for WSL2 driver, got %q", limayaml.WSLMount, *l.Instance.Config.MountType) } @@ -196,7 +196,7 @@ func (l *LimaWslDriver) Unregister(ctx context.Context) error { // As of 08-01-2024, github.com/mdlayher/vsock does not natively support vsock on // Windows, so use the winio library to create the connection. func (l *LimaWslDriver) GuestAgentConn(ctx context.Context) (net.Conn, string, error) { - VMIDStr, err := windows.GetInstanceVMID(fmt.Sprintf("lima-%s", l.Instance.Name)) + VMIDStr, err := windows.GetInstanceVMID(ctx, fmt.Sprintf("lima-%s", l.Instance.Name)) if err != nil { return nil, "", err } diff --git a/pkg/editutil/editutil.go b/pkg/editutil/editutil.go index 4d6a3d96a20..462b791db8b 100644 --- a/pkg/editutil/editutil.go +++ b/pkg/editutil/editutil.go @@ -57,8 +57,7 @@ func GenerateEditorWarningHeader() string { // OpenEditor opens an editor, and returns the content (not path) of the modified yaml. // // OpenEditor returns nil when the file was saved as an empty file, optionally with whitespaces. -func OpenEditor(content []byte, hdr string) ([]byte, error) { - ctx := context.TODO() +func OpenEditor(ctx context.Context, content []byte, hdr string) ([]byte, error) { editor := editorcmd.Detect() if editor == "" { return nil, errors.New("could not detect a text editor binary, try setting $EDITOR") diff --git a/pkg/guestagent/guestagent_linux.go b/pkg/guestagent/guestagent_linux.go index cbef538dc5d..5b199131f56 100644 --- a/pkg/guestagent/guestagent_linux.go +++ b/pkg/guestagent/guestagent_linux.go @@ -24,7 +24,7 @@ import ( "github.com/lima-vm/lima/v2/pkg/guestagent/timesync" ) -func New(newTicker func() (<-chan time.Time, func()), iptablesIdle time.Duration) (Agent, error) { +func New(ctx context.Context, newTicker func() (<-chan time.Time, func()), iptablesIdle time.Duration) (Agent, error) { a := &agent{ newTicker: newTicker, kubernetesServiceWatcher: kubernetesservice.NewServiceWatcher(), @@ -39,7 +39,7 @@ func New(newTicker func() (<-chan time.Time, func()), iptablesIdle time.Duration return nil, err } logrus.Infof("Auditing is not available: %s", err) - return startGuestAgentRoutines(a, false), nil + return startGuestAgentRoutines(ctx, a, false), nil } auditStatus, err := auditClient.GetStatus() @@ -50,7 +50,7 @@ func New(newTicker func() (<-chan time.Time, func()), iptablesIdle time.Duration return nil, err } logrus.Infof("Auditing is not permitted: %s", err) - return startGuestAgentRoutines(a, false), nil + return startGuestAgentRoutines(ctx, a, false), nil } if auditStatus.Enabled == 0 { @@ -73,7 +73,7 @@ func New(newTicker func() (<-chan time.Time, func()), iptablesIdle time.Duration a.worthCheckingIPTables = true } logrus.Infof("Auditing enabled (%d)", auditStatus.Enabled) - return startGuestAgentRoutines(a, true), nil + return startGuestAgentRoutines(ctx, a, true), nil } // startGuestAgentRoutines sets worthCheckingIPTables to true if auditing is not supported, @@ -81,11 +81,11 @@ func New(newTicker func() (<-chan time.Time, func()), iptablesIdle time.Duration // // Auditing is not supported in a kernels and is not currently supported outside of the initial namespace, so does not work // from inside a container or WSL2 instance, for example. -func startGuestAgentRoutines(a *agent, supportsAuditing bool) *agent { +func startGuestAgentRoutines(ctx context.Context, a *agent, supportsAuditing bool) *agent { if !supportsAuditing { a.worthCheckingIPTables = true } - go a.kubernetesServiceWatcher.Start() + go a.kubernetesServiceWatcher.Start(ctx) go a.fixSystemTimeSkew() return a @@ -218,7 +218,7 @@ func (a *agent) Events(ctx context.Context, ch chan *api.Event) { } } -func (a *agent) LocalPorts(_ context.Context) ([]*api.IPPort, error) { +func (a *agent) LocalPorts(ctx context.Context) ([]*api.IPPort, error) { var res []*api.IPPort tcpParsed, err := procnettcp.ParseFiles() if err != nil { @@ -257,7 +257,7 @@ func (a *agent) LocalPorts(_ context.Context) ([]*api.IPPort, error) { var ipts []iptables.Entry if a.worthCheckingIPTables { - ipts, err = iptables.GetPorts() + ipts, err = iptables.GetPorts(ctx) if err != nil { return res, err } diff --git a/pkg/guestagent/iptables/iptables.go b/pkg/guestagent/iptables/iptables.go index 47369411cb3..fd2a8143c9f 100644 --- a/pkg/guestagent/iptables/iptables.go +++ b/pkg/guestagent/iptables/iptables.go @@ -37,7 +37,7 @@ type Entry struct { // -j DNAT this tells us it's the line doing the port forwarding. var findPortRegex = regexp.MustCompile(`-A\s+CNI-DN-\w*\s+(?:-d ((?:\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}))?(?:/32\s+)?-p (tcp)?.*--dport (\d+) -j DNAT`) -func GetPorts() ([]Entry, error) { +func GetPorts(ctx context.Context) ([]Entry, error) { // TODO: add support for ipv6 // Detect the location of iptables. If it is not installed skip the lookup @@ -63,7 +63,7 @@ func GetPorts() ([]Entry, error) { return nil, err } - return checkPortsOpen(pts) + return checkPortsOpen(ctx, pts) } func parsePortsFromRules(rules []string) ([]Entry, error) { @@ -127,8 +127,7 @@ func listNATRules(pth string) ([]string, error) { return rules, nil } -func checkPortsOpen(pts []Entry) ([]Entry, error) { - ctx := context.TODO() +func checkPortsOpen(ctx context.Context, pts []Entry) ([]Entry, error) { var entries []Entry for _, pt := range pts { if pt.TCP { diff --git a/pkg/guestagent/kubernetesservice/kubernetesservice.go b/pkg/guestagent/kubernetesservice/kubernetesservice.go index d84ee1a28a9..eec03ea1b5e 100644 --- a/pkg/guestagent/kubernetesservice/kubernetesservice.go +++ b/pkg/guestagent/kubernetesservice/kubernetesservice.go @@ -58,11 +58,11 @@ func (s *ServiceWatcher) getServiceInformer() cache.SharedIndexInformer { return s.serviceInformer } -func (s *ServiceWatcher) Start() { +func (s *ServiceWatcher) Start(ctx context.Context) { logrus.Info("Monitoring kubernetes services") const retryInterval = 10 * time.Second const pollImmediately = false - _ = wait.PollUntilContextCancel(context.TODO(), retryInterval, pollImmediately, func(ctx context.Context) (done bool, err error) { + _ = wait.PollUntilContextCancel(ctx, retryInterval, pollImmediately, func(ctx context.Context) (done bool, err error) { kubeClient, err := tryGetKubeClient() if err != nil { logrus.Tracef("failed to get kube client: %v, will retry in %v", err, retryInterval) diff --git a/pkg/hostagent/dns/dns.go b/pkg/hostagent/dns/dns.go index 976937dd5b4..6347580e6ae 100644 --- a/pkg/hostagent/dns/dns.go +++ b/pkg/hostagent/dns/dns.go @@ -142,9 +142,8 @@ func NewHandler(opts HandlerOptions) (dns.Handler, error) { return h, nil } -func (h *Handler) handleQuery(w dns.ResponseWriter, req *dns.Msg) { +func (h *Handler) handleQuery(ctx context.Context, w dns.ResponseWriter, req *dns.Msg) { var ( - ctx = context.TODO() reply dns.Msg handled bool ) @@ -340,7 +339,7 @@ func (h *Handler) handleDefault(w dns.ResponseWriter, req *dns.Msg) { func (h *Handler) ServeDNS(w dns.ResponseWriter, req *dns.Msg) { switch req.Opcode { case dns.OpcodeQuery: - h.handleQuery(w, req) + h.handleQuery(context.Background(), w, req) default: h.handleDefault(w, req) } diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 4347e9704bf..4cb8f95cd8d 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -110,14 +110,14 @@ func WithCloudInitProgress(enabled bool) Opt { // New creates the HostAgent. // // stdout is for emitting JSON lines of Events. -func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt) (*HostAgent, error) { +func New(ctx context.Context, instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt) (*HostAgent, error) { var o options for _, f := range opts { if err := f(&o); err != nil { return nil, err } } - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return nil, err } @@ -159,10 +159,10 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt vSockPort := limaDriver.Info().VsockPort virtioPort := limaDriver.Info().VirtioPort - if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { + if err := cidata.GenerateCloudConfig(ctx, inst.Dir, instName, inst.Config); err != nil { return nil, err } - if err := cidata.GenerateISO9660(inst.Dir, instName, inst.Config, udpDNSLocalPort, tcpDNSLocalPort, o.guestAgentBinary, o.nerdctlArchive, vSockPort, virtioPort); err != nil { + if err := cidata.GenerateISO9660(ctx, inst.Dir, instName, inst.Config, udpDNSLocalPort, tcpDNSLocalPort, o.guestAgentBinary, o.nerdctlArchive, vSockPort, virtioPort); err != nil { return nil, err } @@ -171,6 +171,7 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt return nil, err } sshOpts, err := sshutil.SSHOpts( + ctx, sshExe, inst.Dir, *inst.Config.User.Name, @@ -335,7 +336,7 @@ func (a *HostAgent) Run(ctx context.Context) error { // WSL instance SSH address isn't known until after VM start if *a.instConfig.VMType == limayaml.WSL2 { - sshAddr, err := store.GetSSHAddress(a.instName) + sshAddr, err := store.GetSSHAddress(ctx, a.instName) if err != nil { return err } @@ -472,7 +473,7 @@ sudo chown -R "${USER}" /run/host-services` } } if *a.instConfig.MountType == limayaml.REVSSHFS && !*a.instConfig.Plain { - mounts, err := a.setupMounts() + mounts, err := a.setupMounts(ctx) if err != nil { errs = append(errs, err) } diff --git a/pkg/hostagent/mount.go b/pkg/hostagent/mount.go index 575ff236966..92ea6e40c6e 100644 --- a/pkg/hostagent/mount.go +++ b/pkg/hostagent/mount.go @@ -4,6 +4,7 @@ package hostagent import ( + "context" "errors" "fmt" "os" @@ -20,13 +21,13 @@ type mount struct { close func() error } -func (a *HostAgent) setupMounts() ([]*mount, error) { +func (a *HostAgent) setupMounts(ctx context.Context) ([]*mount, error) { var ( res []*mount errs []error ) for _, f := range a.instConfig.Mounts { - m, err := a.setupMount(f) + m, err := a.setupMount(ctx, f) if err != nil { errs = append(errs, err) continue @@ -36,7 +37,7 @@ func (a *HostAgent) setupMounts() ([]*mount, error) { return res, errors.Join(errs...) } -func (a *HostAgent) setupMount(m limayaml.Mount) (*mount, error) { +func (a *HostAgent) setupMount(ctx context.Context, m limayaml.Mount) (*mount, error) { if err := os.MkdirAll(m.Location, 0o755); err != nil { return nil, err } @@ -53,7 +54,7 @@ func (a *HostAgent) setupMount(m limayaml.Mount) (*mount, error) { resolvedLocation := m.Location if runtime.GOOS == "windows" { var err error - resolvedLocation, err = ioutilx.WindowsSubsystemPath(m.Location) + resolvedLocation, err = ioutilx.WindowsSubsystemPath(ctx, m.Location) if err != nil { return nil, err } diff --git a/pkg/imgutil/manager.go b/pkg/imgutil/manager.go index a7f16ad7776..ffad032d003 100644 --- a/pkg/imgutil/manager.go +++ b/pkg/imgutil/manager.go @@ -4,20 +4,21 @@ package imgutil import ( + "context" "os" ) // ImageDiskManager defines the common operations for disk image utilities. type ImageDiskManager interface { // CreateDisk creates a new disk image with the specified size. - CreateDisk(disk string, size int64) error + CreateDisk(ctx context.Context, disk string, size int64) error // ResizeDisk resizes an existing disk image to the specified size. - ResizeDisk(disk string, size int64) error + ResizeDisk(ctx context.Context, disk string, size int64) error // ConvertToRaw converts a disk image to raw format. - ConvertToRaw(source, dest string, size *int64, allowSourceWithBackingFile bool) error + ConvertToRaw(ctx context.Context, source, dest string, size *int64, allowSourceWithBackingFile bool) error // MakeSparse makes a file sparse, starting from the specified offset. - MakeSparse(f *os.File, offset int64) error + MakeSparse(ctx context.Context, f *os.File, offset int64) error } diff --git a/pkg/imgutil/nativeimgutil/nativeimgutil.go b/pkg/imgutil/nativeimgutil/nativeimgutil.go index 64185b1cd78..3fda1ab0db1 100644 --- a/pkg/imgutil/nativeimgutil/nativeimgutil.go +++ b/pkg/imgutil/nativeimgutil/nativeimgutil.go @@ -5,6 +5,7 @@ package nativeimgutil import ( + "context" "errors" "fmt" "io" @@ -153,7 +154,7 @@ func makeSparse(f *os.File, offset int64) error { } // CreateDisk creates a new disk image with the specified size. -func (n *NativeImageUtil) CreateDisk(disk string, size int64) error { +func (n *NativeImageUtil) CreateDisk(_ context.Context, disk string, size int64) error { if _, err := os.Stat(disk); err == nil || !errors.Is(err, fs.ErrNotExist) { return err } @@ -167,17 +168,17 @@ func (n *NativeImageUtil) CreateDisk(disk string, size int64) error { } // ConvertToRaw converts a disk image to raw format. -func (n *NativeImageUtil) ConvertToRaw(source, dest string, size *int64, allowSourceWithBackingFile bool) error { +func (n *NativeImageUtil) ConvertToRaw(_ context.Context, source, dest string, size *int64, allowSourceWithBackingFile bool) error { return convertToRaw(source, dest, size, allowSourceWithBackingFile) } // ResizeDisk resizes an existing disk image to the specified size. -func (n *NativeImageUtil) ResizeDisk(disk string, size int64) error { +func (n *NativeImageUtil) ResizeDisk(_ context.Context, disk string, size int64) error { roundedSize := roundUp(size) return os.Truncate(disk, roundedSize) } // MakeSparse makes a file sparse, starting from the specified offset. -func (n *NativeImageUtil) MakeSparse(f *os.File, offset int64) error { +func (n *NativeImageUtil) MakeSparse(_ context.Context, f *os.File, offset int64) error { return makeSparse(f, offset) } diff --git a/pkg/imgutil/proxyimgutil/proxyimgutil.go b/pkg/imgutil/proxyimgutil/proxyimgutil.go index 735fb0bce3f..e08a5d2e2d1 100644 --- a/pkg/imgutil/proxyimgutil/proxyimgutil.go +++ b/pkg/imgutil/proxyimgutil/proxyimgutil.go @@ -4,6 +4,7 @@ package proxyimgutil import ( + "context" "errors" "os" "os/exec" @@ -20,7 +21,7 @@ type ImageDiskManager struct { } // NewDiskUtil returns a new instance of ImageDiskManager that uses both QEMU and native image utilities. -func NewDiskUtil() imgutil.ImageDiskManager { +func NewDiskUtil(_ context.Context) imgutil.ImageDiskManager { return &ImageDiskManager{ qemu: &qemuimgutil.QemuImageUtil{DefaultFormat: qemuimgutil.QemuImgFormat}, native: &nativeimgutil.NativeImageUtil{}, @@ -28,48 +29,48 @@ func NewDiskUtil() imgutil.ImageDiskManager { } // CreateDisk creates a new disk image with the specified size. -func (p *ImageDiskManager) CreateDisk(disk string, size int64) error { - err := p.qemu.CreateDisk(disk, size) +func (p *ImageDiskManager) CreateDisk(ctx context.Context, disk string, size int64) error { + err := p.qemu.CreateDisk(ctx, disk, size) if err == nil { return nil } if errors.Is(err, exec.ErrNotFound) { - return p.native.CreateDisk(disk, size) + return p.native.CreateDisk(ctx, disk, size) } return err } // ResizeDisk resizes an existing disk image to the specified size. -func (p *ImageDiskManager) ResizeDisk(disk string, size int64) error { - err := p.qemu.ResizeDisk(disk, size) +func (p *ImageDiskManager) ResizeDisk(ctx context.Context, disk string, size int64) error { + err := p.qemu.ResizeDisk(ctx, disk, size) if err == nil { return nil } if errors.Is(err, exec.ErrNotFound) { - return p.native.ResizeDisk(disk, size) + return p.native.ResizeDisk(ctx, disk, size) } return err } // ConvertToRaw converts a disk image to raw format. -func (p *ImageDiskManager) ConvertToRaw(source, dest string, size *int64, allowSourceWithBackingFile bool) error { - err := p.qemu.ConvertToRaw(source, dest, size, allowSourceWithBackingFile) +func (p *ImageDiskManager) ConvertToRaw(ctx context.Context, source, dest string, size *int64, allowSourceWithBackingFile bool) error { + err := p.qemu.ConvertToRaw(ctx, source, dest, size, allowSourceWithBackingFile) if err == nil { return nil } if errors.Is(err, exec.ErrNotFound) { - return p.native.ConvertToRaw(source, dest, size, allowSourceWithBackingFile) + return p.native.ConvertToRaw(ctx, source, dest, size, allowSourceWithBackingFile) } return err } -func (p *ImageDiskManager) MakeSparse(f *os.File, offset int64) error { - err := p.qemu.MakeSparse(f, offset) +func (p *ImageDiskManager) MakeSparse(ctx context.Context, f *os.File, offset int64) error { + err := p.qemu.MakeSparse(ctx, f, offset) if err == nil { return nil } if errors.Is(err, exec.ErrNotFound) { - return p.native.MakeSparse(f, offset) + return p.native.MakeSparse(ctx, f, offset) } return err } diff --git a/pkg/instance/clone.go b/pkg/instance/clone.go index 0e02197c28e..b2f3410b0f9 100644 --- a/pkg/instance/clone.go +++ b/pkg/instance/clone.go @@ -20,7 +20,7 @@ import ( "github.com/lima-vm/lima/v2/pkg/store/filenames" ) -func Clone(_ context.Context, oldInst *store.Instance, newInstName string) (*store.Instance, error) { +func Clone(ctx context.Context, oldInst *store.Instance, newInstName string) (*store.Instance, error) { if newInstName == "" { return nil, errors.New("got empty instName") } @@ -86,5 +86,5 @@ func Clone(_ context.Context, oldInst *store.Instance, newInstName string) (*sto return nil, err } - return store.Inspect(newInstName) + return store.Inspect(ctx, newInstName) } diff --git a/pkg/instance/create.go b/pkg/instance/create.go index 377f86382f4..d90646323b4 100644 --- a/pkg/instance/create.go +++ b/pkg/instance/create.go @@ -43,7 +43,7 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY } // limayaml.Load() needs to pass the store file path to limayaml.FillDefault() to calculate default MAC addresses filePath := filepath.Join(instDir, filenames.LimaYAML) - loadedInstConfig, err := limayaml.LoadWithWarnings(instConfig, filePath) + loadedInstConfig, err := limayaml.LoadWithWarnings(ctx, instConfig, filePath) if err != nil { return nil, err } @@ -63,14 +63,14 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY if err := os.WriteFile(filePath, instConfig, 0o644); err != nil { return nil, err } - if err := cidata.GenerateCloudConfig(instDir, instName, loadedInstConfig); err != nil { + if err := cidata.GenerateCloudConfig(ctx, instDir, instName, loadedInstConfig); err != nil { return nil, err } if err := os.WriteFile(filepath.Join(instDir, filenames.LimaVersion), []byte(version.Version), 0o444); err != nil { return nil, err } - inst, err := store.Inspect(instName) + inst, err := store.Inspect(ctx, instName) if err != nil { return nil, err } diff --git a/pkg/instance/start.go b/pkg/instance/start.go index 002f425f052..4f08219f46e 100644 --- a/pkg/instance/start.go +++ b/pkg/instance/start.go @@ -93,7 +93,7 @@ func Prepare(ctx context.Context, inst *store.Instance) (*Prepared, error) { return nil, fmt.Errorf("failed to create driver instance: %w", err) } - if err := limaDriver.Validate(); err != nil { + if err := limaDriver.Validate(ctx); err != nil { return nil, err } @@ -150,7 +150,7 @@ func Prepare(ctx context.Context, inst *store.Instance) (*Prepared, error) { } // Ensure diffDisk size matches the store - if err := prepareDiffDisk(inst); err != nil { + if err := prepareDiffDisk(ctx, inst); err != nil { return nil, err } @@ -438,7 +438,7 @@ func ShowMessage(inst *store.Instance) error { // prepareDiffDisk checks the disk size difference between inst.Disk and yaml.Disk. // If there is no diffDisk, return nil (the instance has not been initialized or started yet). -func prepareDiffDisk(inst *store.Instance) error { +func prepareDiffDisk(ctx context.Context, inst *store.Instance) error { diffDisk := filepath.Join(inst.Dir, filenames.DiffDisk) // Handle the instance initialization @@ -474,9 +474,9 @@ func prepareDiffDisk(inst *store.Instance) error { return errors.New("diffDisk: Shrinking is currently unavailable") } - diskUtil := proxyimgutil.NewDiskUtil() + diskUtil := proxyimgutil.NewDiskUtil(ctx) - err = diskUtil.ResizeDisk(diffDisk, inst.Disk) + err = diskUtil.ResizeDisk(ctx, diffDisk, inst.Disk) if err != nil { return err } diff --git a/pkg/instance/stop.go b/pkg/instance/stop.go index 2cc36c75beb..b2fb6d04ab0 100644 --- a/pkg/instance/stop.go +++ b/pkg/instance/stop.go @@ -85,7 +85,7 @@ func waitForInstanceShutdown(ctx context.Context, inst *store.Instance) error { for { select { case <-ticker.C: - updatedInst, err := store.Inspect(inst.Name) + updatedInst, err := store.Inspect(ctx, inst.Name) if err != nil { return fmt.Errorf("failed to inspect instance status: %w", err) } diff --git a/pkg/ioutilx/ioutilx.go b/pkg/ioutilx/ioutilx.go index 7c948413e29..b2eb68fa61d 100644 --- a/pkg/ioutilx/ioutilx.go +++ b/pkg/ioutilx/ioutilx.go @@ -50,8 +50,7 @@ func FromUTF16leToString(r io.Reader) (string, error) { return string(out), nil } -func WindowsSubsystemPath(orig string) (string, error) { - ctx := context.TODO() +func WindowsSubsystemPath(ctx context.Context, orig string) (string, error) { out, err := exec.CommandContext(ctx, "cygpath", filepath.ToSlash(orig)).CombinedOutput() if err != nil { logrus.WithError(err).Errorf("failed to convert path to mingw, maybe not using Git ssh?") @@ -60,8 +59,7 @@ func WindowsSubsystemPath(orig string) (string, error) { return strings.TrimSpace(string(out)), nil } -func WindowsSubsystemPathForLinux(orig, distro string) (string, error) { - ctx := context.TODO() +func WindowsSubsystemPathForLinux(ctx context.Context, orig, distro string) (string, error) { out, err := exec.CommandContext(ctx, "wsl", "-d", distro, "--exec", "wslpath", filepath.ToSlash(orig)).CombinedOutput() if err != nil { logrus.WithError(err).Errorf("failed to convert path to mingw, maybe wsl command is not operational?") diff --git a/pkg/limainfo/limainfo.go b/pkg/limainfo/limainfo.go index 19e5d7b07af..dda29025642 100644 --- a/pkg/limainfo/limainfo.go +++ b/pkg/limainfo/limainfo.go @@ -4,6 +4,7 @@ package limainfo import ( + "context" "errors" "io/fs" @@ -40,12 +41,12 @@ type GuestAgent struct { // New returns a LimaInfo object with the Lima version, a list of all Templates and their location, // the DefaultTemplate corresponding to template://default with all defaults filled in, the // LimaHome location, a list of all supported VMTypes, and a map of GuestAgents for each architecture. -func New() (*LimaInfo, error) { +func New(ctx context.Context) (*LimaInfo, error) { b, err := templatestore.Read(templatestore.Default) if err != nil { return nil, err } - y, err := limayaml.Load(b, "") + y, err := limayaml.Load(ctx, b, "") if err != nil { return nil, err } diff --git a/pkg/limayaml/defaults.go b/pkg/limayaml/defaults.go index 1ab059a7645..8a973128127 100644 --- a/pkg/limayaml/defaults.go +++ b/pkg/limayaml/defaults.go @@ -5,6 +5,7 @@ package limayaml import ( "bytes" + "context" "crypto/sha256" _ "embed" "errors" @@ -137,7 +138,7 @@ func defaultGuestInstallPrefix() string { // - Networks are appended in d, y, o order // - DNS are picked from the highest priority where DNS is not empty. // - CACertificates Files and Certs are uniquely appended in d, y, o order -func FillDefault(y, d, o *LimaYAML, filePath string, warn bool) { +func FillDefault(ctx context.Context, y, d, o *LimaYAML, filePath string, warn bool) { instDir := filepath.Dir(filePath) // existingLimaVersion can be empty if the instance was created with Lima prior to v0.20, @@ -184,22 +185,22 @@ func FillDefault(y, d, o *LimaYAML, filePath string, warn bool) { y.User.UID = o.User.UID } if y.User.Name == nil { - y.User.Name = ptr.Of(osutil.LimaUser(existingLimaVersion, warn).Username) + y.User.Name = ptr.Of(osutil.LimaUser(ctx, existingLimaVersion, warn).Username) warn = false } if y.User.Comment == nil { - y.User.Comment = ptr.Of(osutil.LimaUser(existingLimaVersion, warn).Name) + y.User.Comment = ptr.Of(osutil.LimaUser(ctx, existingLimaVersion, warn).Name) warn = false } if y.User.Home == nil { - y.User.Home = ptr.Of(osutil.LimaUser(existingLimaVersion, warn).HomeDir) + y.User.Home = ptr.Of(osutil.LimaUser(ctx, existingLimaVersion, warn).HomeDir) warn = false } if y.User.Shell == nil { y.User.Shell = ptr.Of("/bin/bash") } if y.User.UID == nil { - uidString := osutil.LimaUser(existingLimaVersion, warn).Uid + uidString := osutil.LimaUser(ctx, existingLimaVersion, warn).Uid if uid, err := strconv.ParseUint(uidString, 10, 32); err == nil { y.User.UID = ptr.Of(uint32(uid)) } else { @@ -778,7 +779,7 @@ func FillDefault(y, d, o *LimaYAML, filePath string, warn bool) { mountLocation := mounts[i].Location if runtime.GOOS == "windows" { var err error - mountLocation, err = ioutilx.WindowsSubsystemPath(mountLocation) + mountLocation, err = ioutilx.WindowsSubsystemPath(ctx, mountLocation) if err != nil { logrus.WithError(err).Warnf("Couldn't convert location %q into mount target", mounts[i].Location) } @@ -1189,7 +1190,7 @@ var hasSMEDarwin = sync.OnceValue(func() bool { return false } // golang.org/x/sys/cpu does not support inspecting the availability of SME yet - s, err := osutil.Sysctl("hw.optional.arm.FEAT_SME") + s, err := osutil.Sysctl(context.Background(), "hw.optional.arm.FEAT_SME") if err != nil { logrus.WithError(err).Debug("failed to check hw.optional.arm.FEAT_SME") } diff --git a/pkg/limayaml/defaults_test.go b/pkg/limayaml/defaults_test.go index 1b9998e6dbb..72031382236 100644 --- a/pkg/limayaml/defaults_test.go +++ b/pkg/limayaml/defaults_test.go @@ -65,7 +65,7 @@ func TestFillDefault(t *testing.T) { assert.NilError(t, err) limaHome, err := dirnames.LimaDir() assert.NilError(t, err) - user := osutil.LimaUser("0.0.0", false) + user := osutil.LimaUser(t.Context(), "0.0.0", false) user.HomeDir = fmt.Sprintf("/home/%s.linux", user.Username) uid, err := strconv.ParseUint(user.Uid, 10, 32) assert.NilError(t, err) @@ -226,7 +226,7 @@ func TestFillDefault(t *testing.T) { expect.Mounts = slices.Clone(y.Mounts) expect.Mounts[0].MountPoint = ptr.Of(expect.Mounts[0].Location) if runtime.GOOS == "windows" { - mountLocation, err := ioutilx.WindowsSubsystemPath(expect.Mounts[0].Location) + mountLocation, err := ioutilx.WindowsSubsystemPath(t.Context(), expect.Mounts[0].Location) if err == nil { expect.Mounts[0].MountPoint = ptr.Of(mountLocation) } @@ -322,7 +322,7 @@ func TestFillDefault(t *testing.T) { expect.NestedVirtualization = ptr.Of(false) - FillDefault(&y, &LimaYAML{}, &LimaYAML{}, filePath, false) + FillDefault(t.Context(), &y, &LimaYAML{}, &LimaYAML{}, filePath, false) assert.DeepEqual(t, &y, &expect, opts...) filledDefaults := y @@ -464,7 +464,7 @@ func TestFillDefault(t *testing.T) { expect.Mounts = slices.Clone(d.Mounts) expect.Mounts[0].MountPoint = ptr.Of(expect.Mounts[0].Location) if runtime.GOOS == "windows" { - mountLocation, err := ioutilx.WindowsSubsystemPath(expect.Mounts[0].Location) + mountLocation, err := ioutilx.WindowsSubsystemPath(t.Context(), expect.Mounts[0].Location) if err == nil { expect.Mounts[0].MountPoint = ptr.Of(mountLocation) } @@ -501,7 +501,7 @@ func TestFillDefault(t *testing.T) { expect.Plain = ptr.Of(false) y = LimaYAML{} - FillDefault(&y, &d, &LimaYAML{}, filePath, false) + FillDefault(t.Context(), &y, &d, &LimaYAML{}, filePath, false) assert.DeepEqual(t, &y, &expect, opts...) dExpect := expect @@ -540,7 +540,7 @@ func TestFillDefault(t *testing.T) { t.Logf("d.vmType=%q, y.vmType=%q, expect.vmType=%q", *d.VMType, *y.VMType, *expect.VMType) - FillDefault(&y, &d, &LimaYAML{}, filePath, false) + FillDefault(t.Context(), &y, &d, &LimaYAML{}, filePath, false) assert.DeepEqual(t, &y, &expect, opts...) // ------------------------------------------------------------------------------------ @@ -737,7 +737,7 @@ func TestFillDefault(t *testing.T) { expect.NestedVirtualization = ptr.Of(false) - FillDefault(&y, &d, &o, filePath, false) + FillDefault(t.Context(), &y, &d, &o, filePath, false) assert.DeepEqual(t, &y, &expect, opts...) } diff --git a/pkg/limayaml/load.go b/pkg/limayaml/load.go index f6d7914b6b9..6436d5852ea 100644 --- a/pkg/limayaml/load.go +++ b/pkg/limayaml/load.go @@ -4,6 +4,7 @@ package limayaml import ( + "context" "errors" "fmt" "os" @@ -18,18 +19,18 @@ import ( // Load loads the yaml and fulfills unspecified fields with the default values. // // Load does not validate. Use Validate for validation. -func Load(b []byte, filePath string) (*LimaYAML, error) { - return load(b, filePath, false) +func Load(ctx context.Context, b []byte, filePath string) (*LimaYAML, error) { + return load(ctx, b, filePath, false) } // LoadWithWarnings will call FillDefaults with warnings enabled (e.g. when // the username is not valid on Linux and must be replaced by "Lima"). // It is called when creating or editing an instance. -func LoadWithWarnings(b []byte, filePath string) (*LimaYAML, error) { - return load(b, filePath, true) +func LoadWithWarnings(ctx context.Context, b []byte, filePath string) (*LimaYAML, error) { + return load(ctx, b, filePath, true) } -func load(b []byte, filePath string, warn bool) (*LimaYAML, error) { +func load(ctx context.Context, b []byte, filePath string, warn bool) (*LimaYAML, error) { var y, d, o LimaYAML if err := Unmarshal(b, &y, fmt.Sprintf("main file %q", filePath)); err != nil { @@ -67,6 +68,6 @@ func load(b []byte, filePath string, warn bool) (*LimaYAML, error) { return nil, err } - FillDefault(&y, &d, &o, filePath, warn) + FillDefault(ctx, &y, &d, &o, filePath, warn) return &y, nil } diff --git a/pkg/limayaml/load_test.go b/pkg/limayaml/load_test.go index 8f96a069153..f35e49973c6 100644 --- a/pkg/limayaml/load_test.go +++ b/pkg/limayaml/load_test.go @@ -10,7 +10,7 @@ import ( ) func TestLoadEmpty(t *testing.T) { - _, err := Load([]byte{}, "empty.yaml") + _, err := Load(t.Context(), []byte{}, "empty.yaml") assert.NilError(t, err) } @@ -30,7 +30,7 @@ provision: #!/bin/sh echo three ` - _, err := Load([]byte(s), "error.yaml") + _, err := Load(t.Context(), []byte(s), "error.yaml") assert.ErrorContains(t, err, "map key-value is pre-defined") } @@ -39,7 +39,7 @@ func TestLoadDiskString(t *testing.T) { additionalDisks: - name ` - y, err := Load([]byte(s), "disk.yaml") + y, err := Load(t.Context(), []byte(s), "disk.yaml") assert.NilError(t, err) assert.Equal(t, len(y.AdditionalDisks), 1) assert.Equal(t, y.AdditionalDisks[0].Name, "name") @@ -56,7 +56,7 @@ additionalDisks: fsType: "xfs" fsArgs: ["-i","size=512"] ` - y, err := Load([]byte(s), "disk.yaml") + y, err := Load(t.Context(), []byte(s), "disk.yaml") assert.NilError(t, err) assert.Assert(t, len(y.AdditionalDisks) == 1) assert.Equal(t, y.AdditionalDisks[0].Name, "name") diff --git a/pkg/limayaml/validate.go b/pkg/limayaml/validate.go index 10157b4c907..fa787ba8bbc 100644 --- a/pkg/limayaml/validate.go +++ b/pkg/limayaml/validate.go @@ -4,6 +4,7 @@ package limayaml import ( + "context" "errors" "fmt" "net" @@ -602,11 +603,11 @@ func warnExperimental(y *LimaYAML) { // ValidateAgainstLatestConfig validates the values between the latest YAML and the updated(New) YAML. // This validates configuration rules that disallow certain changes, such as shrinking the disk. -func ValidateAgainstLatestConfig(yNew, yLatest []byte) error { +func ValidateAgainstLatestConfig(ctx context.Context, yNew, yLatest []byte) error { var n LimaYAML // Load the latest YAML and fill in defaults - l, err := LoadWithWarnings(yLatest, "") + l, err := LoadWithWarnings(ctx, yLatest, "") if err != nil { return err } diff --git a/pkg/limayaml/validate_test.go b/pkg/limayaml/validate_test.go index 390b2ec82f1..7cb1755c6d4 100644 --- a/pkg/limayaml/validate_test.go +++ b/pkg/limayaml/validate_test.go @@ -13,7 +13,7 @@ import ( ) func TestValidateEmpty(t *testing.T) { - y, err := Load([]byte{}, "empty.yaml") + y, err := Load(t.Context(), []byte{}, "empty.yaml") assert.NilError(t, err) err = Validate(y, false) assert.Error(t, err, "field `images` must be set") @@ -60,7 +60,7 @@ func TestValidateMinimumLimaVersion(t *testing.T) { version.Version = tt.currentVersion t.Cleanup(func() { version.Version = oldVersion }) - y, err := Load([]byte("minimumLimaVersion: "+tt.minimumLimaVersion+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte("minimumLimaVersion: "+tt.minimumLimaVersion+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -76,13 +76,13 @@ func TestValidateMinimumLimaVersion(t *testing.T) { func TestValidateDigest(t *testing.T) { images := `images: [{"location": "https://cloud-images.ubuntu.com/releases/oracular/release-20250701/ubuntu-24.10-server-cloudimg-amd64.img",digest: "69f31d3208895e5f646e345fbc95190e5e311ecd1359a4d6ee2c0b6483ceca03"}]` validProbe := `probes: [{"script": "#!foo"}]` - y, err := Load([]byte(validProbe+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(validProbe+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.Error(t, err, "field `images[0].digest` is invalid: 69f31d3208895e5f646e345fbc95190e5e311ecd1359a4d6ee2c0b6483ceca03: invalid checksum digest format") images2 := `images: [{"location": "https://cloud-images.ubuntu.com/releases/oracular/release-20250701/ubuntu-24.10-server-cloudimg-amd64.img",digest: "sha001:69f31d3208895e5f646e345fbc95190e5e311ecd1359a4d6ee2c0b6483ceca03"}]` - y2, err := Load([]byte(validProbe+"\n"+images2), "lima.yaml") + y2, err := Load(t.Context(), []byte(validProbe+"\n"+images2), "lima.yaml") assert.NilError(t, err) err = Validate(y2, false) assert.Error(t, err, "field `images[0].digest` is invalid: sha001:69f31d3208895e5f646e345fbc95190e5e311ecd1359a4d6ee2c0b6483ceca03: unsupported digest algorithm") @@ -91,21 +91,21 @@ func TestValidateDigest(t *testing.T) { func TestValidateProbes(t *testing.T) { images := `images: [{"location": "/"}]` validProbe := `probes: [{"script": "#!foo"}]` - y, err := Load([]byte(validProbe+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(validProbe+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.NilError(t, err) invalidProbe := `probes: [{"script": "foo"}]` - y, err = Load([]byte(invalidProbe+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(invalidProbe+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.Error(t, err, "field `probe[0].script` must start with a '#!' line") invalidProbe = `probes: [{file: {digest: decafbad}}]` - y, err = Load([]byte(invalidProbe+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(invalidProbe+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -116,28 +116,28 @@ func TestValidateProbes(t *testing.T) { func TestValidateProvisionMode(t *testing.T) { images := `images: [{location: /}]` provisionBoot := `provision: [{mode: boot, script: "touch /tmp/param-$PARAM_BOOT"}]` - y, err := Load([]byte(provisionBoot+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(provisionBoot+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.NilError(t, err) provisionUser := `provision: [{mode: user, script: "touch /tmp/param-$PARAM_USER"}]` - y, err = Load([]byte(provisionUser+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(provisionUser+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.NilError(t, err) provisionDependency := `provision: [{mode: ansible, script: "touch /tmp/param-$PARAM_DEPENDENCY"}]` - y, err = Load([]byte(provisionDependency+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(provisionDependency+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.NilError(t, err) provisionInvalid := `provision: [{mode: invalid}]` - y, err = Load([]byte(provisionInvalid+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(provisionInvalid+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -148,21 +148,21 @@ func TestValidateProvisionMode(t *testing.T) { func TestValidateProvisionData(t *testing.T) { images := `images: [{location: /}]` validData := `provision: [{mode: data, path: /tmp, content: hello}]` - y, err := Load([]byte(validData+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(validData+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.NilError(t, err) invalidData := `provision: [{mode: data, content: hello}]` - y, err = Load([]byte(invalidData+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(invalidData+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) assert.Error(t, err, "field `provision[0].path` must not be empty when mode is \"data\"") invalidData = `provision: [{mode: data, path: /tmp, content: hello, permissions: 9}]` - y, err = Load([]byte(invalidData+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(invalidData+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -177,7 +177,7 @@ additionalDisks: - name: "disk1" - name: "disk2" ` - y, err := Load([]byte(validDisks+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(validDisks+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -187,7 +187,7 @@ additionalDisks: additionalDisks: - name: "" ` - y, err = Load([]byte(invalidDisks+"\n"+images), "lima.yaml") + y, err = Load(t.Context(), []byte(invalidDisks+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -203,7 +203,7 @@ func TestValidateParamName(t *testing.T) { `param: {"Name_123": "value"}`, } for _, param := range validParam { - y, err := Load([]byte(param+"\n"+validProvision+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(param+"\n"+validProvision+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -217,7 +217,7 @@ func TestValidateParamName(t *testing.T) { `param: {"Last.Name": "value"}`, } for _, param := range invalidParam { - y, err := Load([]byte(param+"\n"+invalidProvision+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(param+"\n"+invalidProvision+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -235,7 +235,7 @@ func TestValidateParamValue(t *testing.T) { `param: {"name": "Symbols ½ and emoji → 👀"}`, } for _, param := range validParam { - y, err := Load([]byte(param+"\n"+provision+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(param+"\n"+provision+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -247,7 +247,7 @@ func TestValidateParamValue(t *testing.T) { `param: {"name": "\r"}`, } for _, param := range invalidParam { - y, err := Load([]byte(param+"\n"+provision+"\n"+images), "lima.yaml") + y, err := Load(t.Context(), []byte(param+"\n"+provision+"\n"+images), "lima.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -258,7 +258,7 @@ func TestValidateParamValue(t *testing.T) { func TestValidateParamIsUsed(t *testing.T) { paramYaml := `param: name: value` - _, err := Load([]byte(paramYaml), "paramIsNotUsed.yaml") + _, err := Load(t.Context(), []byte(paramYaml), "paramIsNotUsed.yaml") assert.Error(t, err, "field `param` key \"name\" is not used in any provision, probe, copyToHost, or portForward") fieldsUsingParam := []string{ @@ -274,7 +274,7 @@ func TestValidateParamIsUsed(t *testing.T) { `portForwards: [{"guestSocket": "/tmp", "hostSocket": "/tmp/{{ .Param.name }}"}]`, } for _, fieldUsingParam := range fieldsUsingParam { - _, err = Load([]byte(fieldUsingParam+"\n"+paramYaml), "paramIsUsed.yaml") + _, err = Load(t.Context(), []byte(fieldUsingParam+"\n"+paramYaml), "paramIsUsed.yaml") // assert.NilError(t, err) } @@ -293,7 +293,7 @@ func TestValidateParamIsUsed(t *testing.T) { `portForwards: [{"guestSocket": "/var/run/docker.sock", "hostSocket": "{{.Dir}}/sock/docker-{{if eq .Param.rootful \"true\"}}rootful{{else}}rootless{{end}}.sock"}]`, } for _, fieldUsingIfParamRootfulTrue := range fieldsUsingIfParamRootfulTrue { - _, err = Load([]byte(fieldUsingIfParamRootfulTrue+"\n"+rootfulYaml), "paramIsUsed.yaml") + _, err = Load(t.Context(), []byte(fieldUsingIfParamRootfulTrue+"\n"+rootfulYaml), "paramIsUsed.yaml") // assert.NilError(t, err) } @@ -302,7 +302,7 @@ func TestValidateParamIsUsed(t *testing.T) { rootFulYaml := `param: rootFul: true` for _, fieldUsingIfParamRootfulTrue := range fieldsUsingIfParamRootfulTrue { - _, err = Load([]byte(fieldUsingIfParamRootfulTrue+"\n"+rootFulYaml), "paramIsUsed.yaml") + _, err = Load(t.Context(), []byte(fieldUsingIfParamRootfulTrue+"\n"+rootFulYaml), "paramIsUsed.yaml") // assert.Error(t, err, "field `param` key \"rootFul\" is not used in any provision, probe, copyToHost, or portForward") } @@ -325,7 +325,7 @@ provision: content: test ` - y, err := Load([]byte(yamlWithMultipleErrors), "multiple-errors.yaml") + y, err := Load(t.Context(), []byte(yamlWithMultipleErrors), "multiple-errors.yaml") assert.NilError(t, err) err = Validate(y, false) @@ -379,7 +379,7 @@ func TestValidateAgainstLatestConfig(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := ValidateAgainstLatestConfig([]byte(tt.yNew), []byte(tt.yLatest)) + err := ValidateAgainstLatestConfig(t.Context(), []byte(tt.yNew), []byte(tt.yLatest)) if tt.wantErr == nil { assert.NilError(t, err) } else { diff --git a/pkg/networks/reconcile/reconcile.go b/pkg/networks/reconcile/reconcile.go index be259cc3833..c35755719e1 100644 --- a/pkg/networks/reconcile/reconcile.go +++ b/pkg/networks/reconcile/reconcile.go @@ -34,7 +34,7 @@ func Reconcile(ctx context.Context, newInst string) error { } activeNetwork := make(map[string]bool, 3) for _, instName := range instances { - instance, err := store.Inspect(instName) + instance, err := store.Inspect(ctx, instName) if err != nil { return err } @@ -67,8 +67,7 @@ func Reconcile(ctx context.Context, newInst string) error { return nil } -func sudo(user, group, command string) error { - ctx := context.TODO() +func sudo(ctx context.Context, user, group, command string) error { args := []string{"--user", user, "--group", group, "--non-interactive"} args = append(args, strings.Split(command, " ")...) var stdout, stderr bytes.Buffer @@ -83,8 +82,8 @@ func sudo(user, group, command string) error { return nil } -func makeVarRun(cfg *networks.Config) error { - err := sudo("root", "wheel", cfg.MkdirCmd()) +func makeVarRun(ctx context.Context, cfg *networks.Config) error { + err := sudo(ctx, "root", "wheel", cfg.MkdirCmd()) if err != nil { return err } @@ -113,7 +112,7 @@ func makeVarRun(cfg *networks.Config) error { } func startDaemon(ctx context.Context, cfg *networks.Config, name, daemon string) error { - if err := makeVarRun(cfg); err != nil { + if err := makeVarRun(ctx, cfg); err != nil { return err } networksDir, err := dirnames.LimaNetworksDir() @@ -165,12 +164,12 @@ var validation struct { err error } -func validateConfig(cfg *networks.Config) error { +func validateConfig(ctx context.Context, cfg *networks.Config) error { validation.Do(func() { // make sure all cfg.Paths.* are secure validation.err = cfg.Validate() if validation.err == nil { - validation.err = cfg.VerifySudoAccess(cfg.Paths.Sudoers) + validation.err = cfg.VerifySudoAccess(ctx, cfg.Paths.Sudoers) } }) return validation.err @@ -195,7 +194,7 @@ func startNetwork(ctx context.Context, cfg *networks.Config, name string) error return nil } - if err := validateConfig(cfg); err != nil { + if err := validateConfig(ctx, cfg); err != nil { return err } var daemons []string @@ -247,14 +246,14 @@ func stopNetwork(ctx context.Context, cfg *networks.Config, name string) error { pid, _ := store.ReadPIDFile(cfg.PIDFile(name, daemon)) if pid != 0 { logrus.Infof("Stopping %s daemon for %q network", daemon, name) - if err := validateConfig(cfg); err != nil { + if err := validateConfig(ctx, cfg); err != nil { return err } user, err := cfg.User(daemon) if err != nil { return err } - err = sudo(user.User, user.Group, cfg.StopCmd(name, daemon)) + err = sudo(ctx, user.User, user.Group, cfg.StopCmd(name, daemon)) if err != nil { return err } diff --git a/pkg/networks/sudoers.go b/pkg/networks/sudoers.go index 81bbd2065eb..3fca65a9729 100644 --- a/pkg/networks/sudoers.go +++ b/pkg/networks/sudoers.go @@ -57,8 +57,7 @@ func Sudoers() (string, error) { return sb.String(), nil } -func (c *Config) passwordLessSudo() error { - ctx := context.TODO() +func (c *Config) passwordLessSudo(ctx context.Context) error { // Flush cached sudo password cmd := exec.CommandContext(ctx, "sudo", "-k") if err := cmd.Run(); err != nil { @@ -84,9 +83,9 @@ func (c *Config) passwordLessSudo() error { return nil } -func (c *Config) VerifySudoAccess(sudoersFile string) error { +func (c *Config) VerifySudoAccess(ctx context.Context, sudoersFile string) error { if sudoersFile == "" { - err := c.passwordLessSudo() + err := c.passwordLessSudo(ctx) if err == nil { logrus.Debug("sudo doesn't seem to require a password") return nil @@ -100,7 +99,7 @@ func (c *Config) VerifySudoAccess(sudoersFile string) error { // Default networks.yaml specifies /etc/sudoers.d/lima file. Don't throw an error when the // file doesn't exist, as long as password-less sudo still works. if errors.Is(err, os.ErrNotExist) { - err = c.passwordLessSudo() + err = c.passwordLessSudo(ctx) if err == nil { logrus.Debugf("%q does not exist, but sudo doesn't seem to require a password", sudoersFile) return nil diff --git a/pkg/osutil/machineid.go b/pkg/osutil/machineid.go index dce2d12f301..f6c00037782 100644 --- a/pkg/osutil/machineid.go +++ b/pkg/osutil/machineid.go @@ -19,7 +19,7 @@ import ( ) var MachineID = sync.OnceValue(func() string { - x, err := machineID() + x, err := machineID(context.Background()) if err == nil && x != "" { return x } @@ -31,8 +31,7 @@ var MachineID = sync.OnceValue(func() string { return hostname }) -func machineID() (string, error) { - ctx := context.TODO() +func machineID(ctx context.Context) (string, error) { if runtime.GOOS == "darwin" { ioPlatformExpertDeviceCmd := exec.CommandContext(ctx, "/usr/sbin/ioreg", "-a", "-d2", "-c", "IOPlatformExpertDevice") ioPlatformExpertDevice, err := ioPlatformExpertDeviceCmd.CombinedOutput() diff --git a/pkg/osutil/osutil_unix.go b/pkg/osutil/osutil_unix.go index 9e5d14704ff..cf00ff69237 100644 --- a/pkg/osutil/osutil_unix.go +++ b/pkg/osutil/osutil_unix.go @@ -25,8 +25,7 @@ func SignalName(sig os.Signal) string { return unix.SignalName(sig.(syscall.Signal)) } -func Sysctl(name string) (string, error) { - ctx := context.TODO() +func Sysctl(ctx context.Context, name string) (string, error) { var stderrBuf bytes.Buffer cmd := exec.CommandContext(ctx, "sysctl", "-n", name) cmd.Stderr = &stderrBuf diff --git a/pkg/osutil/osutil_windows.go b/pkg/osutil/osutil_windows.go index d16de1f3964..a5ed533d988 100644 --- a/pkg/osutil/osutil_windows.go +++ b/pkg/osutil/osutil_windows.go @@ -4,6 +4,7 @@ package osutil import ( + "context" "errors" "fmt" "io/fs" @@ -53,6 +54,6 @@ func SignalName(sig os.Signal) string { } } -func Sysctl(_ string) (string, error) { +func Sysctl(_ context.Context, _ string) (string, error) { return "", errors.New("sysctl: unimplemented on Windows") } diff --git a/pkg/osutil/user.go b/pkg/osutil/user.go index bd840c1b411..3589b858819 100644 --- a/pkg/osutil/user.go +++ b/pkg/osutil/user.go @@ -102,7 +102,7 @@ var ( warnings []string ) -func LimaUser(limaVersion string, warn bool) *user.User { +func LimaUser(ctx context.Context, limaVersion string, warn bool) *user.User { once.Do(func() { limaUser = currentUser if !regexUsername.MatchString(limaUser.Username) { @@ -113,7 +113,7 @@ func LimaUser(limaVersion string, warn bool) *user.User { } limaUser.HomeDir = "/home/{{.User}}.linux" if runtime.GOOS == "windows" { - idu, err := call([]string{"id", "-u"}) + idu, err := call(ctx, []string{"id", "-u"}) if err != nil { logrus.Debug(err) } @@ -127,7 +127,7 @@ func LimaUser(limaVersion string, warn bool) *user.User { warnings = append(warnings, warning) limaUser.Uid = formatUidGid(uid) } - idg, err := call([]string{"id", "-g"}) + idg, err := call(ctx, []string{"id", "-g"}) if err != nil { logrus.Debug(err) } @@ -161,8 +161,7 @@ func LimaUser(limaVersion string, warn bool) *user.User { return &u } -func call(args []string) (string, error) { - ctx := context.TODO() +func call(ctx context.Context, args []string) (string, error) { cmd := exec.CommandContext(ctx, args[0], args[1:]...) out, err := cmd.Output() if err != nil { diff --git a/pkg/osutil/user_test.go b/pkg/osutil/user_test.go index 0cf1cc57f64..1acf8290d9d 100644 --- a/pkg/osutil/user_test.go +++ b/pkg/osutil/user_test.go @@ -18,7 +18,7 @@ const limaVersion = "1.0.0" func TestLimaUserAdminNew(t *testing.T) { currentUser.Username = "admin" once = new(sync.Once) - user := LimaUser(limaVersion, false) + user := LimaUser(t.Context(), limaVersion, false) assert.Equal(t, user.Username, fallbackUser) } @@ -26,21 +26,21 @@ func TestLimaUserAdminNew(t *testing.T) { func TestLimaUserAdminOld(t *testing.T) { currentUser.Username = "admin" once = new(sync.Once) - user := LimaUser("0.23.0", false) + user := LimaUser(t.Context(), "0.23.0", false) assert.Equal(t, user.Username, "admin") } func TestLimaUserInvalid(t *testing.T) { currentUser.Username = "use@example.com" once = new(sync.Once) - user := LimaUser(limaVersion, false) + user := LimaUser(t.Context(), limaVersion, false) assert.Equal(t, user.Username, fallbackUser) } func TestLimaUserUid(t *testing.T) { currentUser.Username = fallbackUser once = new(sync.Once) - user := LimaUser(limaVersion, false) + user := LimaUser(t.Context(), limaVersion, false) _, err := strconv.Atoi(user.Uid) assert.NilError(t, err) } @@ -48,7 +48,7 @@ func TestLimaUserUid(t *testing.T) { func TestLimaUserGid(t *testing.T) { currentUser.Username = fallbackUser once = new(sync.Once) - user := LimaUser(limaVersion, false) + user := LimaUser(t.Context(), limaVersion, false) _, err := strconv.Atoi(user.Gid) assert.NilError(t, err) } @@ -56,7 +56,7 @@ func TestLimaUserGid(t *testing.T) { func TestLimaHomeDir(t *testing.T) { currentUser.Username = fallbackUser once = new(sync.Once) - user := LimaUser(limaVersion, false) + user := LimaUser(t.Context(), limaVersion, false) // check for absolute unix path (/home) assert.Assert(t, path.IsAbs(user.HomeDir), user.HomeDir) } diff --git a/pkg/qemuimgutil/qemuimgutil.go b/pkg/qemuimgutil/qemuimgutil.go index 9df2a019986..7e364cb0ac2 100644 --- a/pkg/qemuimgutil/qemuimgutil.go +++ b/pkg/qemuimgutil/qemuimgutil.go @@ -49,8 +49,7 @@ type InfoFormatSpecific struct { Data json.RawMessage `json:"data,omitempty"` // since QEMU 1.7 } -func resizeDisk(disk, format string, size int64) error { - ctx := context.TODO() +func resizeDisk(ctx context.Context, disk, format string, size int64) error { args := []string{"resize", "-f", format, disk, strconv.FormatInt(size, 10)} cmd := exec.CommandContext(ctx, "qemu-img", args...) if out, err := cmd.CombinedOutput(); err != nil { @@ -104,14 +103,14 @@ type InfoFormatSpecificDataVmdkExtent struct { ClusterSize int `json:"cluster-size,omitempty"` // since QEMU 1.7 } -func convertToRaw(source, dest string) error { +func convertToRaw(ctx context.Context, source, dest string) error { if source != dest { - return execQemuImgConvert(source, dest) + return execQemuImgConvert(ctx, source, dest) } // If source == dest, we need to use a temporary file to avoid file locking issues - info, err := getInfo(source) + info, err := getInfo(ctx, source) if err != nil { return fmt.Errorf("failed to get info for source disk %q: %w", source, err) } @@ -122,15 +121,14 @@ func convertToRaw(source, dest string) error { tempFile := dest + ".lima-qemu-convert.tmp" defer os.Remove(tempFile) - if err := execQemuImgConvert(source, tempFile); err != nil { + if err := execQemuImgConvert(ctx, source, tempFile); err != nil { return err } return os.Rename(tempFile, dest) } -func execQemuImgConvert(source, dest string) error { - ctx := context.TODO() +func execQemuImgConvert(ctx context.Context, source, dest string) error { var stdout, stderr bytes.Buffer cmd := exec.CommandContext(ctx, "qemu-img", "convert", "-O", "raw", source, dest) cmd.Stdout = &stdout @@ -150,8 +148,7 @@ func parseInfo(b []byte) (*Info, error) { return &imgInfo, nil } -func getInfo(f string) (*Info, error) { - ctx := context.TODO() +func getInfo(ctx context.Context, f string) (*Info, error) { var stdout, stderr bytes.Buffer cmd := exec.CommandContext(ctx, "qemu-img", "info", "--output=json", "--force-share", f) cmd.Stdout = &stdout @@ -164,8 +161,7 @@ func getInfo(f string) (*Info, error) { } // CreateDisk creates a new disk image with the specified size. -func (q *QemuImageUtil) CreateDisk(disk string, size int64) error { - ctx := context.TODO() +func (q *QemuImageUtil) CreateDisk(ctx context.Context, disk string, size int64) error { if _, err := os.Stat(disk); err == nil || !errors.Is(err, fs.ErrNotExist) { // disk already exists return err @@ -180,22 +176,22 @@ func (q *QemuImageUtil) CreateDisk(disk string, size int64) error { } // ResizeDisk resizes an existing disk image to the specified size. -func (q *QemuImageUtil) ResizeDisk(disk string, size int64) error { - info, err := getInfo(disk) +func (q *QemuImageUtil) ResizeDisk(ctx context.Context, disk string, size int64) error { + info, err := getInfo(ctx, disk) if err != nil { return fmt.Errorf("failed to get info for disk %q: %w", disk, err) } - return resizeDisk(disk, info.Format, size) + return resizeDisk(ctx, disk, info.Format, size) } // MakeSparse is a stub implementation as the qemu package doesn't provide this functionality. -func (q *QemuImageUtil) MakeSparse(_ *os.File, _ int64) error { +func (q *QemuImageUtil) MakeSparse(_ context.Context, _ *os.File, _ int64) error { return nil } // GetInfo retrieves the information of a disk image. -func GetInfo(path string) (*Info, error) { - qemuInfo, err := getInfo(path) +func GetInfo(ctx context.Context, path string) (*Info, error) { + qemuInfo, err := getInfo(ctx, path) if err != nil { return nil, err } @@ -204,9 +200,9 @@ func GetInfo(path string) (*Info, error) { } // ConvertToRaw converts a disk image to raw format. -func (q *QemuImageUtil) ConvertToRaw(source, dest string, size *int64, allowSourceWithBackingFile bool) error { +func (q *QemuImageUtil) ConvertToRaw(ctx context.Context, source, dest string, size *int64, allowSourceWithBackingFile bool) error { if !allowSourceWithBackingFile { - info, err := getInfo(source) + info, err := getInfo(ctx, source) if err != nil { return fmt.Errorf("failed to get info for source disk %q: %w", source, err) } @@ -215,18 +211,18 @@ func (q *QemuImageUtil) ConvertToRaw(source, dest string, size *int64, allowSour } } - if err := convertToRaw(source, dest); err != nil { + if err := convertToRaw(ctx, source, dest); err != nil { return err } if size != nil { - destInfo, err := getInfo(dest) + destInfo, err := getInfo(ctx, dest) if err != nil { return fmt.Errorf("failed to get info for converted disk %q: %w", dest, err) } if *size > destInfo.VSize { - return resizeDisk(dest, "raw", *size) + return resizeDisk(ctx, dest, "raw", *size) } } diff --git a/pkg/registry/registry_test.go b/pkg/registry/registry_test.go index 4abd3a54159..c872e62d4ca 100644 --- a/pkg/registry/registry_test.go +++ b/pkg/registry/registry_test.go @@ -27,7 +27,7 @@ func newMockDriver(name string) *mockDriver { var _ driver.Driver = (*mockDriver)(nil) -func (m *mockDriver) Validate() error { return nil } +func (m *mockDriver) Validate(_ context.Context) error { return nil } func (m *mockDriver) Initialize(_ context.Context) error { return nil } func (m *mockDriver) CreateDisk(_ context.Context) error { return nil } func (m *mockDriver) Start(_ context.Context) (chan error, error) { return nil, nil } diff --git a/pkg/sshutil/sshutil.go b/pkg/sshutil/sshutil.go index 53d60ab5467..103da56442a 100644 --- a/pkg/sshutil/sshutil.go +++ b/pkg/sshutil/sshutil.go @@ -91,8 +91,7 @@ func readPublicKey(f string) (PubKey, error) { // // When loadDotSSH is true, ~/.ssh/*.pub will be appended to make the VM accessible without specifying // an identity explicitly. -func DefaultPubKeys(loadDotSSH bool) ([]PubKey, error) { - ctx := context.TODO() +func DefaultPubKeys(ctx context.Context, loadDotSSH bool) ([]PubKey, error) { // Read $LIMA_HOME/_config/user.pub configDir, err := dirnames.LimaConfigDir() if err != nil { @@ -110,7 +109,7 @@ func DefaultPubKeys(loadDotSSH bool) ([]PubKey, error) { // no passphrase, no user@host comment privPath := filepath.Join(configDir, filenames.UserPrivateKey) if runtime.GOOS == "windows" { - privPath, err = ioutilx.WindowsSubsystemPath(privPath) + privPath, err = ioutilx.WindowsSubsystemPath(ctx, privPath) if err != nil { return err } @@ -186,7 +185,7 @@ var sshInfo struct { // // The result always contains the IdentityFile option. // The result never contains the Port option. -func CommonOpts(sshExe SSHExe, useDotSSH bool) ([]string, error) { +func CommonOpts(ctx context.Context, sshExe SSHExe, useDotSSH bool) ([]string, error) { configDir, err := dirnames.LimaConfigDir() if err != nil { return nil, err @@ -197,7 +196,7 @@ func CommonOpts(sshExe SSHExe, useDotSSH bool) ([]string, error) { return nil, err } var opts []string - idf, err := identityFileEntry(privateKeyPath) + idf, err := identityFileEntry(ctx, privateKeyPath) if err != nil { return nil, err } @@ -232,7 +231,7 @@ func CommonOpts(sshExe SSHExe, useDotSSH bool) ([]string, error) { // Fail on permission-related and other path errors return nil, err } - idf, err = identityFileEntry(privateKeyPath) + idf, err = identityFileEntry(ctx, privateKeyPath) if err != nil { return nil, err } @@ -252,7 +251,7 @@ func CommonOpts(sshExe SSHExe, useDotSSH bool) ([]string, error) { sshInfo.Do(func() { sshInfo.aesAccelerated = detectAESAcceleration() - sshInfo.openSSH = detectOpenSSHInfo(sshExe) + sshInfo.openSSH = detectOpenSSHInfo(ctx, sshExe) }) if sshInfo.openSSH.GSSAPISupported { @@ -284,9 +283,9 @@ func CommonOpts(sshExe SSHExe, useDotSSH bool) ([]string, error) { return opts, nil } -func identityFileEntry(privateKeyPath string) (string, error) { +func identityFileEntry(ctx context.Context, privateKeyPath string) (string, error) { if runtime.GOOS == "windows" { - privateKeyPath, err := ioutilx.WindowsSubsystemPath(privateKeyPath) + privateKeyPath, err := ioutilx.WindowsSubsystemPath(ctx, privateKeyPath) if err != nil { return "", err } @@ -296,18 +295,18 @@ func identityFileEntry(privateKeyPath string) (string, error) { } // SSHOpts adds the following options to CommonOptions: User, ControlMaster, ControlPath, ControlPersist. -func SSHOpts(sshExe SSHExe, instDir, username string, useDotSSH, forwardAgent, forwardX11, forwardX11Trusted bool) ([]string, error) { +func SSHOpts(ctx context.Context, sshExe SSHExe, instDir, username string, useDotSSH, forwardAgent, forwardX11, forwardX11Trusted bool) ([]string, error) { controlSock := filepath.Join(instDir, filenames.SSHSock) if len(controlSock) >= osutil.UnixPathMax { return nil, fmt.Errorf("socket path %q is too long: >= UNIX_PATH_MAX=%d", controlSock, osutil.UnixPathMax) } - opts, err := CommonOpts(sshExe, useDotSSH) + opts, err := CommonOpts(ctx, sshExe, useDotSSH) if err != nil { return nil, err } controlPath := fmt.Sprintf(`ControlPath="%s"`, controlSock) if runtime.GOOS == "windows" { - controlSock, err = ioutilx.WindowsSubsystemPath(controlSock) + controlSock, err = ioutilx.WindowsSubsystemPath(ctx, controlSock) if err != nil { return nil, err } @@ -370,9 +369,8 @@ var ( openSSHInfosRW sync.RWMutex ) -func detectOpenSSHInfo(sshExe SSHExe) openSSHInfo { +func detectOpenSSHInfo(ctx context.Context, sshExe SSHExe) openSSHInfo { var ( - ctx = context.TODO() info openSSHInfo exe sshExecutable stderr bytes.Buffer @@ -410,8 +408,8 @@ func detectOpenSSHInfo(sshExe SSHExe) openSSHInfo { return info } -func DetectOpenSSHVersion(sshExe SSHExe) semver.Version { - return detectOpenSSHInfo(sshExe).Version +func DetectOpenSSHVersion(ctx context.Context, sshExe SSHExe) semver.Version { + return detectOpenSSHInfo(ctx, sshExe).Version } // detectValidPublicKey returns whether content represent a public key. diff --git a/pkg/sshutil/sshutil_test.go b/pkg/sshutil/sshutil_test.go index 4b8b81cca80..da879784b4d 100644 --- a/pkg/sshutil/sshutil_test.go +++ b/pkg/sshutil/sshutil_test.go @@ -11,7 +11,7 @@ import ( ) func TestDefaultPubKeys(t *testing.T) { - keys, _ := DefaultPubKeys(true) + keys, _ := DefaultPubKeys(t.Context(), true) t.Logf("found %d public keys", len(keys)) for _, key := range keys { t.Logf("%s: %q", key.Filename, key.Content) diff --git a/pkg/store/fuzz_test.go b/pkg/store/fuzz_test.go index 9d2c4930d10..62b007d5203 100644 --- a/pkg/store/fuzz_test.go +++ b/pkg/store/fuzz_test.go @@ -18,7 +18,7 @@ func FuzzLoadYAMLByFilePath(f *testing.F) { localFile := filepath.Join(t.TempDir(), "yaml_file.yml") err := os.WriteFile(localFile, fileContents, 0o600) assert.NilError(t, err) - _, _ = LoadYAMLByFilePath(localFile) + _, _ = LoadYAMLByFilePath(t.Context(), localFile) }) } @@ -34,6 +34,6 @@ func FuzzInspect(f *testing.F) { assert.NilError(t, err) err = os.WriteFile(limaVersionFile, limaVersion, 0o600) assert.NilError(t, err) - _, _ = Inspect("fuzz-instance") + _, _ = Inspect(t.Context(), "fuzz-instance") }) } diff --git a/pkg/store/instance.go b/pkg/store/instance.go index 0de2c3f69a7..04e6b49c35e 100644 --- a/pkg/store/instance.go +++ b/pkg/store/instance.go @@ -71,7 +71,7 @@ type Instance struct { // Inspect returns err only when the instance does not exist (os.ErrNotExist). // Other errors are returned as *Instance.Errors. -func Inspect(instName string) (*Instance, error) { +func Inspect(ctx context.Context, instName string) (*Instance, error) { inst := &Instance{ Name: instName, // TODO: support customizing hostname @@ -86,7 +86,7 @@ func Inspect(instName string) (*Instance, error) { // Make sure inst.Dir is set, even when YAML validation fails inst.Dir = instDir yamlPath := filepath.Join(instDir, filenames.LimaYAML) - y, err := LoadYAMLByFilePath(yamlPath) + y, err := LoadYAMLByFilePath(ctx, yamlPath) if err != nil { if errors.Is(err, os.ErrNotExist) { return nil, err @@ -114,7 +114,7 @@ func Inspect(instName string) (*Instance, error) { inst.Status = StatusBroken inst.Errors = append(inst.Errors, fmt.Errorf("failed to connect to %q: %w", haSock, err)) } else { - ctx, cancel := context.WithTimeout(context.TODO(), 3*time.Second) + ctx, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() info, err := haClient.Info(ctx) if err != nil { @@ -150,7 +150,7 @@ func Inspect(instName string) (*Instance, error) { inst.Protected = true } - inspectStatus(instDir, inst, y) + inspectStatus(ctx, instDir, inst, y) tmpl, err := template.New("format").Parse(y.Message) if err != nil { diff --git a/pkg/store/instance_unix.go b/pkg/store/instance_unix.go index 41ded92c368..71aaa3dfde6 100644 --- a/pkg/store/instance_unix.go +++ b/pkg/store/instance_unix.go @@ -5,12 +5,16 @@ package store -import "github.com/lima-vm/lima/v2/pkg/limayaml" +import ( + "context" -func inspectStatus(instDir string, inst *Instance, y *limayaml.LimaYAML) { + "github.com/lima-vm/lima/v2/pkg/limayaml" +) + +func inspectStatus(_ context.Context, instDir string, inst *Instance, y *limayaml.LimaYAML) { inspectStatusWithPIDFiles(instDir, inst, y) } -func GetSSHAddress(_ string) (string, error) { +func GetSSHAddress(_ context.Context, _ string) (string, error) { return "127.0.0.1", nil } diff --git a/pkg/store/instance_windows.go b/pkg/store/instance_windows.go index cf79b7cb96e..b9e963ba1b1 100644 --- a/pkg/store/instance_windows.go +++ b/pkg/store/instance_windows.go @@ -14,7 +14,7 @@ import ( "github.com/lima-vm/lima/v2/pkg/limayaml" ) -func inspectStatus(instDir string, inst *Instance, y *limayaml.LimaYAML) { +func inspectStatus(ctx context.Context, instDir string, inst *Instance, y *limayaml.LimaYAML) { if inst.VMType == limayaml.WSL2 { status, err := GetWslStatus(inst.Name) if err != nil { @@ -27,7 +27,7 @@ func inspectStatus(instDir string, inst *Instance, y *limayaml.LimaYAML) { inst.SSHLocalPort = 22 if inst.Status == StatusRunning { - sshAddr, err := GetSSHAddress(inst.Name) + sshAddr, err := GetSSHAddress(ctx, inst.Name) if err == nil { inst.SSHAddress = sshAddr } else { @@ -124,8 +124,7 @@ func GetWslStatus(instName string) (string, error) { // 168.1.1.1 [10.0.0.1] // But busybox hostname does not implement --all-ip-addresses: // hostname: unrecognized option: I -func GetSSHAddress(instName string) (string, error) { - ctx := context.TODO() +func GetSSHAddress(ctx context.Context, instName string) (string, error) { distroName := "lima-" + instName // Ubuntu cmd := exec.CommandContext(ctx, "wsl.exe", "-d", distroName, "bash", "-c", `hostname -I | cut -d ' ' -f1`) diff --git a/pkg/store/store.go b/pkg/store/store.go index 24816d30286..7a4f27c1ce9 100644 --- a/pkg/store/store.go +++ b/pkg/store/store.go @@ -4,6 +4,7 @@ package store import ( + "context" "errors" "fmt" "os" @@ -131,7 +132,7 @@ func DiskDir(name string) (string, error) { } // LoadYAMLByFilePath loads and validates the yaml. -func LoadYAMLByFilePath(filePath string) (*limayaml.LimaYAML, error) { +func LoadYAMLByFilePath(ctx context.Context, filePath string) (*limayaml.LimaYAML, error) { // We need to use the absolute path because it may be used to determine hostSocket locations. absPath, err := filepath.Abs(filePath) if err != nil { @@ -141,7 +142,7 @@ func LoadYAMLByFilePath(filePath string) (*limayaml.LimaYAML, error) { if err != nil { return nil, err } - y, err := limayaml.Load(yContent, absPath) + y, err := limayaml.Load(ctx, yContent, absPath) if err != nil { return nil, err } diff --git a/pkg/sysprof/sysprof_darwin.go b/pkg/sysprof/sysprof_darwin.go index 7340f310ba6..02be83fbf38 100644 --- a/pkg/sysprof/sysprof_darwin.go +++ b/pkg/sysprof/sysprof_darwin.go @@ -16,7 +16,7 @@ import ( ) var NetworkData = sync.OnceValues(func() ([]NetworkDataType, error) { - b, err := SystemProfiler("SPNetworkDataType") + b, err := SystemProfiler(context.Background(), "SPNetworkDataType") if err != nil { return nil, err } @@ -27,8 +27,7 @@ var NetworkData = sync.OnceValues(func() ([]NetworkDataType, error) { return networkData.SPNetworkDataType, nil }) -func SystemProfiler(dataType string) ([]byte, error) { - ctx := context.TODO() +func SystemProfiler(ctx context.Context, dataType string) ([]byte, error) { exe, err := exec.LookPath("system_profiler") if err != nil { // $PATH may lack /usr/sbin diff --git a/pkg/windows/process_windows.go b/pkg/windows/process_windows.go index 85261b91edb..1817a109e58 100644 --- a/pkg/windows/process_windows.go +++ b/pkg/windows/process_windows.go @@ -15,8 +15,7 @@ type CommandLineJSON []struct { } // GetProcessCommandLine returns a slice of string containing all commandlines for a given process name. -func GetProcessCommandLine(name string) ([]string, error) { - ctx := context.TODO() +func GetProcessCommandLine(ctx context.Context, name string) ([]string, error) { out, err := exec.CommandContext(ctx, "powershell.exe", "-nologo", diff --git a/pkg/windows/wsl_util_windows.go b/pkg/windows/wsl_util_windows.go index 33e92d91432..cc105789720 100644 --- a/pkg/windows/wsl_util_windows.go +++ b/pkg/windows/wsl_util_windows.go @@ -4,6 +4,7 @@ package windows import ( + "context" "fmt" "regexp" "strings" @@ -13,13 +14,13 @@ import ( var vmIDRegex = regexp.MustCompile(`--vm-id\s\{(?P.{36})\}`) // GetInstanceVMID returns the VM ID of a running WSL instance. -func GetInstanceVMID(instanceName string) (string, error) { +func GetInstanceVMID(ctx context.Context, instanceName string) (string, error) { distroID, err := GetDistroID(instanceName) if err != nil { return "", err } - cmdLines, err := GetProcessCommandLine("wslhost.exe") + cmdLines, err := GetProcessCommandLine(ctx, "wslhost.exe") if err != nil { return "", err }