Skip to content

Commit e16b62d

Browse files
committed
limactl shell: ask whether to start the instance if not running
Signed-off-by: Jan Dubois <[email protected]>
1 parent 9c21e15 commit e16b62d

File tree

4 files changed

+82
-36
lines changed

4 files changed

+82
-36
lines changed

cmd/limactl/edit.go

+5-30
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,9 @@ import (
1010
"github.com/lima-vm/lima/cmd/limactl/editflags"
1111
"github.com/lima-vm/lima/cmd/limactl/guessarg"
1212
"github.com/lima-vm/lima/pkg/editutil"
13-
"github.com/lima-vm/lima/pkg/instance"
1413
"github.com/lima-vm/lima/pkg/limayaml"
15-
networks "github.com/lima-vm/lima/pkg/networks/reconcile"
1614
"github.com/lima-vm/lima/pkg/store"
1715
"github.com/lima-vm/lima/pkg/store/filenames"
18-
"github.com/lima-vm/lima/pkg/uiutil"
1916
"github.com/lima-vm/lima/pkg/yqutil"
2017
"github.com/sirupsen/logrus"
2118
"github.com/spf13/cobra"
@@ -132,34 +129,12 @@ func editAction(cmd *cobra.Command, args []string) error {
132129
}
133130
if inst != nil {
134131
logrus.Infof("Instance %q configuration edited", inst.Name)
132+
if err := askToStart(cmd, inst.Name, false); err != nil {
133+
return err
134+
}
135135
}
136-
137-
if !tty {
138-
// use "start" to start it
139-
return nil
140-
}
141-
if inst == nil {
142-
// edited a limayaml file directly
143-
return nil
144-
}
145-
startNow, err := askWhetherToStart()
146-
if err != nil {
147-
return err
148-
}
149-
if !startNow {
150-
return nil
151-
}
152-
ctx := cmd.Context()
153-
err = networks.Reconcile(ctx, inst.Name)
154-
if err != nil {
155-
return err
156-
}
157-
return instance.Start(ctx, inst, "", false)
158-
}
159-
160-
func askWhetherToStart() (bool, error) {
161-
message := "Do you want to start the instance now? "
162-
return uiutil.Confirm(message, true)
136+
// inst is nil if edited a limayaml file directly
137+
return nil
163138
}
164139

165140
func editBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {

cmd/limactl/shell.go

+25-3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func newShellCommand() *cobra.Command {
5151
}
5252

5353
func shellAction(cmd *cobra.Command, args []string) error {
54+
_ = os.Setenv("_LIMACTL_SHELL_IN_ACTION", "")
5455
// simulate the behavior of double dash
5556
newArg := []string{}
5657
if len(args) >= 2 && args[1] == "--" {
@@ -68,15 +69,36 @@ func shellAction(cmd *cobra.Command, args []string) error {
6869
}
6970
}
7071

72+
tty, err := interactive(cmd)
73+
if err != nil {
74+
return err
75+
}
7176
inst, err := store.Inspect(instName)
7277
if err != nil {
73-
if errors.Is(err, os.ErrNotExist) {
78+
if !errors.Is(err, os.ErrNotExist) {
79+
return err
80+
}
81+
if !tty {
7482
return fmt.Errorf("instance %q does not exist, run `limactl create %s` to create a new instance", instName, instName)
7583
}
84+
if err := askToStart(cmd, instName, true); err != nil {
85+
return err
86+
}
87+
inst, err = store.Inspect(instName)
88+
} else if inst.Status == store.StatusStopped {
89+
if !tty {
90+
return fmt.Errorf("instance %q is stopped, run `limactl start %s` to start the instance", instName, instName)
91+
}
92+
if err := askToStart(cmd, instName, false); err != nil {
93+
return err
94+
}
95+
inst, err = store.Inspect(instName)
96+
}
97+
if err != nil {
7698
return err
7799
}
78-
if inst.Status == store.StatusStopped {
79-
return fmt.Errorf("instance %q is stopped, run `limactl start %s` to start the instance", instName, instName)
100+
if inst.Status != store.StatusRunning {
101+
return fmt.Errorf("instance %q status is not %q but %q", inst.Name, store.StatusRunning, inst.Status)
80102
}
81103

82104
// When workDir is explicitly set, the shell MUST have workDir as the cwd, or exit with an error.

cmd/limactl/start.go

+42
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/lima-vm/lima/pkg/templatestore"
2424
"github.com/lima-vm/lima/pkg/uiutil"
2525
"github.com/lima-vm/lima/pkg/yqutil"
26+
"github.com/mattn/go-isatty"
2627
"github.com/sirupsen/logrus"
2728
"github.com/spf13/cobra"
2829
)
@@ -529,3 +530,44 @@ func startBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobr
529530
compTmpl, _ := bashCompleteTemplateNames(cmd)
530531
return append(compInst, compTmpl...), cobra.ShellCompDirectiveDefault
531532
}
533+
534+
// interactive returns true if --tty is true and both STDIN and STDOUT are terminals
535+
func interactive(cmd *cobra.Command) (bool, error) {
536+
flags := cmd.Flags()
537+
tty, err := flags.GetBool("tty")
538+
if err != nil {
539+
return false, err
540+
}
541+
if !isatty.IsTerminal(os.Stdin.Fd()) && !isatty.IsCygwinTerminal(os.Stdin.Fd()) {
542+
tty = false
543+
}
544+
if !isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()) {
545+
tty = false
546+
}
547+
return tty, nil
548+
}
549+
550+
func askToStart(cmd *cobra.Command, instName string, create bool) error {
551+
var message string
552+
if create {
553+
message = fmt.Sprintf("Do you want to create and start the instance %q using the default template now?", instName)
554+
} else {
555+
message = fmt.Sprintf("Do you want to start the instance %q now?", instName)
556+
}
557+
ans, err := uiutil.Confirm(message, true)
558+
if !ans || err != nil {
559+
return err
560+
}
561+
562+
rootCmd := cmd.Root()
563+
if create {
564+
// The create command shows the template chooser UI, etc.
565+
rootCmd.SetArgs([]string{"create", instName})
566+
if err := rootCmd.Execute(); err != nil {
567+
return err
568+
}
569+
}
570+
// The start command reconciles the networks, etc.
571+
rootCmd.SetArgs([]string{"start", instName})
572+
return rootCmd.Execute()
573+
}

pkg/instance/start.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,17 @@ func watchHostAgentEvents(ctx context.Context, inst *store.Instance, haStdoutPat
307307
err = xerr
308308
return true
309309
}
310-
if *inst.Config.Plain {
311-
logrus.Infof("READY. Run `ssh -F %q %s` to open the shell.", inst.SSHConfigFile, inst.Hostname)
310+
// _LIMACTL_SHELL_IN_ACTION is set if `limactl shell` invoked `limactl start`.
311+
// In this case we shouldn't print "Run `lima` to open the shell",
312+
// because the user has already executed the `lima` command.
313+
if _, limactlShellInAction := os.LookupEnv("_LIMACTL_SHELL_IN_ACTION"); limactlShellInAction {
314+
logrus.Infof("READY.")
312315
} else {
313-
logrus.Infof("READY. Run `%s` to open the shell.", LimactlShellCmd(inst.Name))
316+
if *inst.Config.Plain {
317+
logrus.Infof("READY. Run `ssh -F %q %s` to open the shell.", inst.SSHConfigFile, inst.Hostname)
318+
} else {
319+
logrus.Infof("READY. Run `%s` to open the shell.", LimactlShellCmd(inst.Name))
320+
}
314321
}
315322
_ = ShowMessage(inst)
316323
err = nil

0 commit comments

Comments
 (0)