Skip to content

Commit 316ba9c

Browse files
authored
cli: ux improvements (#207)
* cli: accept profile name as arg for some commands * cli: remove obsolete --port-interface flag * vm: delegate port allocation to Lima * cli: add ssh-config * ssh-config: remove 'lima-' prefix from hostname
1 parent 5085352 commit 316ba9c

File tree

12 files changed

+82
-57
lines changed

12 files changed

+82
-57
lines changed

app/app.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package app
22

33
import (
44
"fmt"
5-
"strconv"
65

76
"github.com/abiosoft/colima/config"
87
"github.com/abiosoft/colima/environment"
@@ -75,9 +74,6 @@ func (c colimaApp) Start(conf config.Config) error {
7574
if err := c.setRuntime(conf.Runtime); err != nil {
7675
return fmt.Errorf("error setting current runtime: %w", err)
7776
}
78-
if err := c.setSSHPort(conf.VM.SSHPort); err != nil {
79-
return fmt.Errorf("error setting SSH port: %w", err)
80-
}
8177
// persist kubernetes version for future reference.
8278
if err := c.setKubernetesVersion(conf.Kubernetes.Version); err != nil {
8379
return fmt.Errorf("error setting kubernetes version: %w", err)
@@ -252,10 +248,6 @@ func (c colimaApp) setKubernetesVersion(version string) error {
252248
return c.guest.Set(environment.KubernetesVersionKey, version)
253249
}
254250

255-
func (c colimaApp) setSSHPort(sshPort int) error {
256-
return c.guest.Set(environment.SSHPortKey, strconv.Itoa(sshPort))
257-
}
258-
259251
func (c colimaApp) currentContainerEnvironments() ([]environment.Container, error) {
260252
var containers []environment.Container
261253

cmd/delete.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ var deleteCmdArgs struct {
1313

1414
// deleteCmd represents the delete command
1515
var deleteCmd = &cobra.Command{
16-
Use: "delete",
16+
Use: "delete [profile]",
1717
Short: "delete and teardown Colima",
1818
Long: `Delete and teardown Colima and all settings.
1919
2020
Use with caution. This deletes everything and a startup afterwards is like the
2121
initial startup of Colima.
2222
2323
If you simply want to reset the Kubernetes cluster, run 'colima kubernetes reset'.`,
24-
Args: cobra.NoArgs,
24+
Args: cobra.MaximumNArgs(1),
2525
RunE: func(cmd *cobra.Command, args []string) error {
2626
if !deleteCmdArgs.force {
2727
y := cli.Prompt("are you sure you want to delete " + config.Profile().DisplayName + " and all settings")

cmd/root/root.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ var rootCmd = &cobra.Command{
1515
Short: "container runtimes on macOS with minimal setup",
1616
Long: `Colima provides container runtimes on macOS with minimal setup.`,
1717
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
18+
19+
switch cmd.Name() {
20+
// special case handling for commands directly interacting with the VM
21+
// start, stop, delete, status, version, ssh-config
22+
case "start", "stop", "delete", "status", "version", "ssh-config":
23+
// if an arg is passed, assume it to be the profile (provided --profile is unset)
24+
// i.e. colima start docker == colima start --profile=docker
25+
if len(args) > 0 && !cmd.Flag("profile").Changed {
26+
rootCmdArgs.Profile = args[0]
27+
}
28+
}
1829
if rootCmdArgs.Profile != "" {
1930
config.SetProfile(rootCmdArgs.Profile)
2031
}

cmd/ssh-config.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package cmd
2+
3+
import (
4+
"github.com/abiosoft/colima/cmd/root"
5+
"github.com/abiosoft/colima/config"
6+
"github.com/abiosoft/colima/environment/vm/lima"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
// statusCmd represents the status command
11+
var sshConfigCmd = &cobra.Command{
12+
Use: "ssh-config [profile]",
13+
Short: "show SSH connection config",
14+
Long: `Show configuration of the SSH connection to the VM.`,
15+
Args: cobra.MaximumNArgs(1),
16+
RunE: func(cmd *cobra.Command, args []string) error {
17+
return lima.ShowSSH(config.Profile().ID, sshConfigCmdArgs.format)
18+
},
19+
}
20+
21+
var sshConfigCmdArgs struct {
22+
format string
23+
}
24+
25+
func init() {
26+
root.Cmd().AddCommand(sshConfigCmd)
27+
28+
sshConfigCmd.Flags().StringVarP(&sshConfigCmdArgs.format, "format", "f", "config", "format (config, cmd)")
29+
}

cmd/start.go

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cmd
22

33
import (
44
"fmt"
5-
"net"
65
"runtime"
76
"strings"
87

@@ -16,7 +15,7 @@ import (
1615

1716
// startCmd represents the start command
1817
var startCmd = &cobra.Command{
19-
Use: "start",
18+
Use: "start [profile]",
2019
Short: "start Colima",
2120
Long: `Start Colima with the specified container runtime (and kubernetes if --with-kubernetes is passed).
2221
The --runtime, --disk and --arch flags are only used on initial start and ignored on subsequent starts.
@@ -28,14 +27,11 @@ The --runtime, --disk and --arch flags are only used on initial start and ignore
2827
" colima start --cpu 4 --memory 8 --disk 100\n" +
2928
" colima start --arch aarch64\n" +
3029
" colima start --dns 1.1.1.1 --dns 8.8.8.8",
31-
Args: cobra.NoArgs,
30+
Args: cobra.MaximumNArgs(1),
3231
RunE: func(cmd *cobra.Command, args []string) error {
3332
return newApp().Start(startCmdArgs.Config)
3433
},
3534
PreRunE: func(cmd *cobra.Command, args []string) error {
36-
// set port
37-
startCmdArgs.VM.SSHPort = randomAvailablePort()
38-
3935
current, err := config.Load()
4036
if err != nil {
4137
// not fatal, will proceed with defaults
@@ -69,9 +65,6 @@ The --runtime, --disk and --arch flags are only used on initial start and ignore
6965
if !cmd.Flag("mount").Changed {
7066
startCmdArgs.VM.Mounts = current.VM.Mounts
7167
}
72-
if !cmd.Flag("port-interface").Changed {
73-
startCmdArgs.PortInterface = current.PortInterface
74-
}
7568
if !cmd.Flag("ssh-agent").Changed {
7669
startCmdArgs.VM.ForwardAgent = current.VM.ForwardAgent
7770
}
@@ -100,23 +93,9 @@ var startCmdArgs struct {
10093
config.Config
10194
}
10295

103-
func randomAvailablePort() int {
104-
listener, err := net.Listen("tcp", ":0")
105-
if err != nil {
106-
log.Fatal(fmt.Errorf("error picking an available port: %w", err))
107-
}
108-
109-
if err := listener.Close(); err != nil {
110-
log.Fatal(fmt.Errorf("error closing temporary port listener: %w", err))
111-
}
112-
113-
return listener.Addr().(*net.TCPAddr).Port
114-
}
115-
11696
func init() {
11797
runtimes := strings.Join(environment.ContainerRuntimes(), ", ")
11898
defaultArch := string(environment.Arch(runtime.GOARCH).Value())
119-
defaultPortInterface := net.ParseIP("0.0.0.0")
12099

121100
root.Cmd().AddCommand(startCmd)
122101
startCmd.Flags().StringVarP(&startCmdArgs.Runtime, "runtime", "r", docker.Name, "container runtime ("+runtimes+")")
@@ -128,9 +107,6 @@ func init() {
128107
// mounts
129108
startCmd.Flags().StringSliceVarP(&startCmdArgs.VM.Mounts, "mount", "v", nil, "directories to mount, suffix ':w' for writable")
130109

131-
// port forwarding
132-
startCmd.Flags().IPVarP(&startCmdArgs.PortInterface, "port-interface", "i", defaultPortInterface, "interface to use for forwarded ports")
133-
134110
// ssh agent
135111
startCmd.Flags().BoolVarP(&startCmdArgs.VM.ForwardAgent, "ssh-agent", "s", false, "forward SSH agent to the VM")
136112

cmd/status.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import (
77

88
// statusCmd represents the status command
99
var statusCmd = &cobra.Command{
10-
Use: "status",
10+
Use: "status [profile]",
1111
Short: "show the status of Colima",
1212
Long: `Show the status of Colima`,
13-
Args: cobra.NoArgs,
13+
Args: cobra.MaximumNArgs(1),
1414
RunE: func(cmd *cobra.Command, args []string) error {
1515
return newApp().Status()
1616
},

cmd/stop.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import (
77

88
// stopCmd represents the stop command
99
var stopCmd = &cobra.Command{
10-
Use: "stop",
10+
Use: "stop [profile]",
1111
Short: "stop Colima",
1212
Long: `Stop stops Colima to free up resources.
1313
1414
The state of the VM is persisted at stop. A start afterwards
1515
should return it back to its previous state.`,
16-
Args: cobra.NoArgs,
16+
Args: cobra.MaximumNArgs(1),
1717
RunE: func(cmd *cobra.Command, args []string) error {
1818
return newApp().Stop()
1919
},

cmd/version.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import (
1111

1212
// versionCmd represents the version command
1313
var versionCmd = &cobra.Command{
14-
Use: "version",
14+
Use: "version [profile]",
1515
Short: "print the version of Colima",
1616
Long: `Print the version of Colima`,
17-
Args: cobra.NoArgs,
17+
Args: cobra.MaximumNArgs(1),
1818
Run: func(cmd *cobra.Command, args []string) {
1919
version := config.AppVersion()
2020
fmt.Println(config.AppName, "version", version.Version)

config/config.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,6 @@ type Config struct {
156156

157157
// Kubernetes sets if kubernetes should be enabled.
158158
Kubernetes Kubernetes `yaml:"kubernetes"`
159-
160-
// Network address to forward VM ports to.
161-
PortInterface net.IP `yaml:"port_interface"`
162159
}
163160

164161
// Kubernetes is kubernetes configuration
@@ -174,8 +171,6 @@ type VM struct {
174171
Memory int `yaml:"memory"`
175172
Arch string `yaml:"arch"`
176173

177-
// auto generated
178-
SSHPort int `yaml:"-"`
179174
ForwardAgent bool `yaml:"forward_agent"`
180175

181176
// volume mounts

environment/vm.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ const (
1616
ContainerRuntimeKey = "runtime"
1717
// KubernetesVersionKey is the settings key for kubernetes version.
1818
KubernetesVersionKey = "kubernetes_version"
19-
// SSHPortKey is the settings for the VM SSH port.
20-
SSHPortKey = "ssh_port"
2119

2220
// BinfmtTarFile is the path in the VM to the binfmt oci image tar.
2321
// TODO: decide if this should reside somewhere else.

environment/vm/lima/lima.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,13 +412,37 @@ func Instances() ([]InstanceInfo, error) {
412412
}
413413

414414
// rename to local friendly names
415-
if i.Name == "colima" {
416-
i.Name = "default"
417-
}
418-
i.Name = strings.TrimPrefix(i.Name, "colima-")
415+
i.Name = toUserFriendlyName(i.Name)
419416

420417
instances = append(instances, i)
421418
}
422419

423420
return instances, nil
424421
}
422+
423+
// ShowSSH runs the show-ssh command in Lima.
424+
func ShowSSH(name, format string) error {
425+
var buf bytes.Buffer
426+
cmd := cli.Command("limactl", "show-ssh", "--format", format, name)
427+
cmd.Stdout = &buf
428+
cmd.Stderr = os.Stderr
429+
430+
if err := cmd.Run(); err != nil {
431+
return fmt.Errorf("error retrieving ssh config: %w", err)
432+
}
433+
434+
// TODO: this is a lazy approach, edge cases may not be covered
435+
from := "lima-" + name
436+
to := name
437+
out := strings.ReplaceAll(buf.String(), from, to)
438+
439+
fmt.Println(out)
440+
return nil
441+
}
442+
443+
func toUserFriendlyName(name string) string {
444+
if name == "colima" {
445+
name = "default"
446+
}
447+
return strings.TrimPrefix(name, "colima-")
448+
}

environment/vm/lima/yaml.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func newConf(conf config.Config) (l Config, err error) {
2525
l.Memory = fmt.Sprintf("%dGiB", conf.VM.Memory)
2626
l.Disk = fmt.Sprintf("%dGiB", conf.VM.Disk)
2727

28-
l.SSH = SSH{LocalPort: conf.VM.SSHPort, LoadDotSSHPubKeys: false, ForwardAgent: conf.VM.ForwardAgent}
28+
l.SSH = SSH{LocalPort: 0, LoadDotSSHPubKeys: false, ForwardAgent: conf.VM.ForwardAgent}
2929
l.Containerd = Containerd{System: false, User: false}
3030
l.Firmware.LegacyBIOS = false
3131

@@ -121,7 +121,7 @@ type Config struct {
121121
Memory string `yaml:"memory,omitempty"`
122122
Disk string `yaml:"disk,omitempty"`
123123
Mounts []Mount `yaml:"mounts,omitempty"`
124-
SSH SSH `yaml:"ssh,omitempty"`
124+
SSH SSH `yaml:"ssh"`
125125
Containerd Containerd `yaml:"containerd"`
126126
Env map[string]string `yaml:"env,omitempty"`
127127
DNS []net.IP `yaml:"-"` // will be handled manually by colima
@@ -142,11 +142,11 @@ type Mount struct {
142142
}
143143

144144
type SSH struct {
145-
LocalPort int `yaml:"localPort,omitempty"` // REQUIRED
145+
LocalPort int `yaml:"localPort"`
146146
// LoadDotSSHPubKeys loads ~/.ssh/*.pub in addition to $LIMA_HOME/_config/user.pub .
147147
// Default: true
148148
LoadDotSSHPubKeys bool `yaml:"loadDotSSHPubKeys"`
149-
ForwardAgent bool `yaml:"forwardAgent,omitempty"` // default: false
149+
ForwardAgent bool `yaml:"forwardAgent"` // default: false
150150
}
151151

152152
type Containerd struct {

0 commit comments

Comments
 (0)