Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/pkg/sshutil/format.go
2611 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package sshutil
5
6
import (
7
"fmt"
8
"io"
9
"strings"
10
11
"github.com/lima-vm/lima/v2/pkg/instance/hostname"
12
)
13
14
// FormatT specifies the format type.
15
type FormatT = string
16
17
const (
18
// FormatCmd prints the full ssh command line.
19
//
20
// ssh -o IdentityFile="/Users/example/.lima/_config/user" -o User=example -o Hostname=127.0.0.1 -o Port=60022 lima-default
21
FormatCmd = FormatT("cmd")
22
23
// FormatArgs is similar to FormatCmd but omits "ssh" and the destination address.
24
//
25
// -o IdentityFile="/Users/example/.lima/_config/user" -o User=example -o Hostname=127.0.0.1 -o Port=60022
26
FormatArgs = FormatT("args")
27
28
// FormatOptions prints the ssh option key value pairs.
29
//
30
// IdentityFile="/Users/example/.lima/_config/user"
31
// User=example
32
// Hostname=127.0.0.1
33
// Port=60022
34
FormatOptions = FormatT("options")
35
36
// FormatConfig uses the ~/.ssh/config format
37
//
38
// Host lima-default
39
// IdentityFile "/Users/example/.lima/_config/user "
40
// User example
41
// Hostname 127.0.0.1
42
// Port 60022
43
FormatConfig = FormatT("config")
44
45
// TODO: consider supporting "url" format (ssh://USER@HOSTNAME:PORT).
46
//
47
// TODO: consider supporting "json" format.
48
// It is unclear whether we can just map ssh "config" into JSON, as "config" has duplicated keys.
49
// (JSON supports duplicated keys too, but not all JSON implementations expect JSON with duplicated keys).
50
)
51
52
// Formats is the list of the supported formats.
53
var Formats = []FormatT{FormatCmd, FormatArgs, FormatOptions, FormatConfig}
54
55
func quoteOption(o string) string {
56
// make sure the shell doesn't swallow quotes in option values
57
if strings.ContainsRune(o, '"') {
58
o = "'" + o + "'"
59
}
60
return o
61
}
62
63
// Format formats the ssh options.
64
func Format(w io.Writer, sshPath, instName string, format FormatT, opts []string) error {
65
fakeHostname := hostname.FromInstName(instName) // TODO: support customization
66
switch format {
67
case FormatCmd:
68
args := []string{sshPath}
69
for _, o := range opts {
70
args = append(args, "-o", quoteOption(o))
71
}
72
args = append(args, fakeHostname)
73
// the args are similar to `limactl shell` but not exactly same. (e.g., lacks -t)
74
fmt.Fprintln(w, strings.Join(args, " ")) // no need to use shellescape.QuoteCommand
75
case FormatArgs:
76
var args []string
77
for _, o := range opts {
78
args = append(args, "-o", quoteOption(o))
79
}
80
fmt.Fprintln(w, strings.Join(args, " ")) // no need to use shellescape.QuoteCommand
81
case FormatOptions:
82
for _, o := range opts {
83
fmt.Fprintln(w, o)
84
}
85
case FormatConfig:
86
fmt.Fprintf(w, "Host %s\n", fakeHostname)
87
for _, o := range opts {
88
kv := strings.SplitN(o, "=", 2)
89
if len(kv) != 2 {
90
return fmt.Errorf("unexpected option %q", o)
91
}
92
fmt.Fprintf(w, " %s %s\n", kv[0], kv[1])
93
}
94
default:
95
return fmt.Errorf("unknown format: %q", format)
96
}
97
return nil
98
}
99
100