Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/cmd/limactl/list.go
1645 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package main
5
6
import (
7
"errors"
8
"fmt"
9
"os"
10
"reflect"
11
"sort"
12
"strings"
13
14
"github.com/cheggaaa/pb/v3/termutil"
15
"github.com/mattn/go-isatty"
16
"github.com/sirupsen/logrus"
17
"github.com/spf13/cobra"
18
19
"github.com/lima-vm/lima/v2/pkg/limatype"
20
"github.com/lima-vm/lima/v2/pkg/store"
21
)
22
23
func fieldNames() []string {
24
names := []string{}
25
var data store.FormatData
26
t := reflect.TypeOf(data)
27
for i := range t.NumField() {
28
f := t.Field(i)
29
if f.Anonymous {
30
for j := range f.Type.NumField() {
31
names = append(names, f.Type.Field(j).Name)
32
}
33
} else {
34
names = append(names, t.Field(i).Name)
35
}
36
}
37
return names
38
}
39
40
func newListCommand() *cobra.Command {
41
listCommand := &cobra.Command{
42
Use: "list [flags] [INSTANCE]...",
43
Aliases: []string{"ls"},
44
Short: "List instances of Lima",
45
Long: `List instances of Lima.
46
47
The output can be presented in one of several formats, using the --format <format> flag.
48
49
--format json - Output in JSON format
50
--format yaml - Output in YAML format
51
--format table - Output in table format
52
--format '{{ <go template> }}' - If the format begins and ends with '{{ }}', then it is used as a go template.
53
` + store.FormatHelp + `
54
The following legacy flags continue to function:
55
--json - equal to '--format json'`,
56
Args: WrapArgsError(cobra.ArbitraryArgs),
57
RunE: listAction,
58
ValidArgsFunction: listBashComplete,
59
GroupID: basicCommand,
60
}
61
62
listCommand.Flags().StringP("format", "f", "table", "Output format, one of: json, yaml, table, go-template")
63
listCommand.Flags().Bool("list-fields", false, "List fields available for format")
64
listCommand.Flags().Bool("json", false, "JSONify output")
65
listCommand.Flags().BoolP("quiet", "q", false, "Only show names")
66
listCommand.Flags().Bool("all-fields", false, "Show all fields")
67
68
return listCommand
69
}
70
71
func instanceMatches(arg string, instances []string) []string {
72
matches := []string{}
73
for _, instance := range instances {
74
if instance == arg {
75
matches = append(matches, instance)
76
}
77
}
78
return matches
79
}
80
81
// unmatchedInstancesError is created when unmatched instance names found.
82
type unmatchedInstancesError struct{}
83
84
// Error implements error.
85
func (unmatchedInstancesError) Error() string {
86
return "unmatched instances"
87
}
88
89
// ExitCode implements ExitCoder.
90
func (unmatchedInstancesError) ExitCode() int {
91
return 1
92
}
93
94
func listAction(cmd *cobra.Command, args []string) error {
95
ctx := cmd.Context()
96
quiet, err := cmd.Flags().GetBool("quiet")
97
if err != nil {
98
return err
99
}
100
format, err := cmd.Flags().GetString("format")
101
if err != nil {
102
return err
103
}
104
listFields, err := cmd.Flags().GetBool("list-fields")
105
if err != nil {
106
return err
107
}
108
jsonFormat, err := cmd.Flags().GetBool("json")
109
if err != nil {
110
return err
111
}
112
113
if jsonFormat {
114
format = "json"
115
}
116
117
// conflicts
118
if jsonFormat && cmd.Flags().Changed("format") {
119
return errors.New("option --json conflicts with option --format")
120
}
121
if listFields && cmd.Flags().Changed("format") {
122
return errors.New("option --list-fields conflicts with option --format")
123
}
124
125
if quiet && format != "table" {
126
return errors.New("option --quiet can only be used with '--format table'")
127
}
128
129
if listFields {
130
names := fieldNames()
131
sort.Strings(names)
132
fmt.Fprintln(cmd.OutOrStdout(), strings.Join(names, "\n"))
133
return nil
134
}
135
136
if err := store.Validate(); err != nil {
137
logrus.Warnf("The directory %q does not look like a valid Lima directory: %v", store.Directory(), err)
138
}
139
140
allInstances, err := store.Instances()
141
if err != nil {
142
return err
143
}
144
if len(args) == 0 && len(allInstances) == 0 {
145
logrus.Warn("No instance found. Run `limactl create` to create an instance.")
146
return nil
147
}
148
149
instanceNames := []string{}
150
unmatchedInstances := false
151
if len(args) > 0 {
152
for _, arg := range args {
153
matches := instanceMatches(arg, allInstances)
154
if len(matches) > 0 {
155
instanceNames = append(instanceNames, matches...)
156
} else {
157
logrus.Warnf("No instance matching %v found.", arg)
158
unmatchedInstances = true
159
}
160
}
161
} else {
162
instanceNames = allInstances
163
}
164
165
if quiet {
166
for _, instName := range instanceNames {
167
fmt.Fprintln(cmd.OutOrStdout(), instName)
168
}
169
if unmatchedInstances {
170
return unmatchedInstancesError{}
171
}
172
return nil
173
}
174
175
// get the state and config for all the requested instances
176
var instances []*limatype.Instance
177
for _, instanceName := range instanceNames {
178
instance, err := store.Inspect(ctx, instanceName)
179
if err != nil {
180
return fmt.Errorf("unable to load instance %s: %w", instanceName, err)
181
}
182
instances = append(instances, instance)
183
}
184
185
for _, instance := range instances {
186
if len(instance.Errors) > 0 {
187
logrus.WithField("errors", instance.Errors).Warnf("instance %q has errors", instance.Name)
188
}
189
}
190
191
allFields, err := cmd.Flags().GetBool("all-fields")
192
if err != nil {
193
return err
194
}
195
196
options := store.PrintOptions{AllFields: allFields}
197
out := cmd.OutOrStdout()
198
if out == os.Stdout {
199
if isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) {
200
if w, err := termutil.TerminalWidth(); err == nil {
201
options.TerminalWidth = w
202
}
203
}
204
}
205
206
err = store.PrintInstances(out, instances, format, &options)
207
if err == nil && unmatchedInstances {
208
return unmatchedInstancesError{}
209
}
210
return err
211
}
212
213
func listBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
214
return bashCompleteInstanceNames(cmd)
215
}
216
217