Skip to content

Commit 3cfd618

Browse files
authored
Merge pull request #1281 from AkihiroSuda/dev
Make sure `limactl list --json` to print line-delimited JSON
2 parents c734ba8 + 820b787 commit 3cfd618

File tree

3 files changed

+71
-22
lines changed

3 files changed

+71
-22
lines changed

pkg/store/instance.go

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

33
import (
44
"context"
5-
"encoding/json"
65
"errors"
76
"fmt"
87
"io"
@@ -18,11 +17,11 @@ import (
1817
"time"
1918

2019
"github.com/docker/go-units"
21-
"github.com/goccy/go-yaml"
2220
hostagentclient "github.com/lima-vm/lima/pkg/hostagent/api/client"
2321
"github.com/lima-vm/lima/pkg/limayaml"
2422
"github.com/lima-vm/lima/pkg/store/dirnames"
2523
"github.com/lima-vm/lima/pkg/store/filenames"
24+
"github.com/lima-vm/lima/pkg/textutil"
2625
)
2726

2827
type Status = string
@@ -238,17 +237,9 @@ func AddGlobalFields(inst *Instance) (FormatData, error) {
238237
func PrintInstances(w io.Writer, instances []*Instance, format string) error {
239238
switch format {
240239
case "json":
241-
b, err := json.Marshal(instances)
242-
if err != nil {
243-
return err
244-
}
245-
fmt.Fprintln(w, string(b))
240+
format = "{{json .}}"
246241
case "yaml":
247-
b, err := yaml.Marshal(instances)
248-
if err != nil {
249-
return err
250-
}
251-
fmt.Fprintln(w, string(b))
242+
format = "{{yaml .}}"
252243
case "table":
253244
w := tabwriter.NewWriter(w, 4, 8, 4, ' ', 0)
254245
fmt.Fprintln(w, "NAME\tSTATUS\tSSH\tVMTYPE\tARCH\tCPUS\tMEMORY\tDISK\tDIR")
@@ -278,18 +269,18 @@ func PrintInstances(w io.Writer, instances []*Instance, format string) error {
278269
}
279270
return w.Flush()
280271
default:
281-
tmpl, err := template.New("format").Parse(format)
272+
// NOP
273+
}
274+
tmpl, err := template.New("format").Funcs(textutil.TemplateFuncMap).Parse(format)
275+
if err != nil {
276+
return fmt.Errorf("invalid go template: %w", err)
277+
}
278+
for _, instance := range instances {
279+
err = tmpl.Execute(w, instance)
282280
if err != nil {
283-
return fmt.Errorf("invalid go template: %w", err)
284-
}
285-
for _, instance := range instances {
286-
err = tmpl.Execute(w, instance)
287-
if err != nil {
288-
return err
289-
}
290-
fmt.Fprintln(w)
281+
return err
291282
}
292-
return nil
283+
fmt.Fprintln(w)
293284
}
294285
return nil
295286
}

pkg/textutil/textutil.go

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

33
import (
44
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"strings"
58
"text/template"
9+
10+
"github.com/goccy/go-yaml"
611
)
712

813
// ExecuteTemplate executes a text/template template.
@@ -17,3 +22,24 @@ func ExecuteTemplate(tmpl string, args interface{}) ([]byte, error) {
1722
}
1823
return b.Bytes(), nil
1924
}
25+
26+
// TemplateFuncMap is a text/template FuncMap.
27+
var TemplateFuncMap = template.FuncMap{
28+
"json": func(v interface{}) string {
29+
var b bytes.Buffer
30+
enc := json.NewEncoder(&b)
31+
enc.SetEscapeHTML(false)
32+
if err := enc.Encode(v); err != nil {
33+
panic(fmt.Errorf("failed to marshal as JSON: %+v: %w", v, err))
34+
}
35+
return strings.TrimSuffix(b.String(), "\n")
36+
},
37+
"yaml": func(v interface{}) string {
38+
var b bytes.Buffer
39+
enc := yaml.NewEncoder(&b)
40+
if err := enc.Encode(v); err != nil {
41+
panic(fmt.Errorf("failed to marshal as YAML: %+v: %w", v, err))
42+
}
43+
return "---\n" + strings.TrimSuffix(b.String(), "\n")
44+
},
45+
}

pkg/textutil/textutil_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package textutil
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
"text/template"
7+
8+
"gotest.tools/v3/assert"
9+
)
10+
11+
func TestTemplateFuncs(t *testing.T) {
12+
type X struct {
13+
Foo int `json:"foo" yaml:"foo"`
14+
Bar string `json:"bar" yaml:"bar"`
15+
}
16+
x := X{Foo: 42, Bar: "hello"}
17+
18+
testCases := map[string]string{
19+
"{{json .}}": `{"foo":42,"bar":"hello"}`,
20+
"{{yaml .}}": `---
21+
foo: 42
22+
bar: hello`,
23+
}
24+
25+
for format, expected := range testCases {
26+
tmpl, err := template.New("format").Funcs(TemplateFuncMap).Parse(format)
27+
assert.NilError(t, err)
28+
var b bytes.Buffer
29+
assert.NilError(t, tmpl.Execute(&b, x))
30+
assert.Equal(t, expected, b.String())
31+
}
32+
}

0 commit comments

Comments
 (0)