Skip to content

Commit a1f452d

Browse files
committed
Change limactl list --format json not to include empty objects
Unlike the YAML encoder, the JSON encoder will encode empty structs even when they have the `json:"omitempty"` tag (it will only emit nil pointers to structs). This commit repeatedly removes empty objects until the result no longer gets any shorter. It doesn't check for the omitempty tag, but we have that tag set on every struct. Example: this removes `"vmOpts":{"qemu":{},"vz":{"rosetta":{}}}`. Signed-off-by: Jan Dubois <[email protected]>
1 parent 86a7a5a commit a1f452d

File tree

3 files changed

+37
-37
lines changed

3 files changed

+37
-37
lines changed

cmd/limactl/list.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,25 +249,43 @@ func listAction(cmd *cobra.Command, args []string) error {
249249
}
250250

251251
if format == "json" {
252+
// The JSON encoder will create empty objects (YAML maps), even when they have the ",omitempty" tag.
253+
deleteEmptyObjects := `del(.. | select(tag == "!!map" and length == 0))`
254+
yqExpr += " | " + deleteEmptyObjects
255+
252256
encoderPrefs := yqlib.ConfiguredJSONPreferences.Copy()
253-
if isTTY {
254-
// Using non-0 indent means the instance will be printed over multiple lines,
255-
// so is no longer in JSON Lines format. This is a compromise for readability.
256-
encoderPrefs.Indent = 4
257-
encoderPrefs.ColorsEnabled = true
258-
} else {
259-
encoderPrefs.Indent = 0
260-
encoderPrefs.ColorsEnabled = false
261-
}
262-
encoder := yqlib.NewJSONEncoder(encoderPrefs)
257+
encoderPrefs.ColorsEnabled = false
258+
encoderPrefs.Indent = 0
259+
plainEncoder := yqlib.NewJSONEncoder(encoderPrefs)
260+
// Using non-0 indent means the instance will be printed over multiple lines,
261+
// so is no longer in JSON Lines format. This is a compromise for readability.
262+
encoderPrefs.Indent = 4
263+
encoderPrefs.ColorsEnabled = true
264+
colorEncoder := yqlib.NewJSONEncoder(encoderPrefs)
263265

264266
// Each line contains the JSON object for one Lima instance.
265267
scanner := bufio.NewScanner(buf)
266268
for scanner.Scan() {
267269
var str string
268-
if str, err = yqutil.EvaluateExpressionWithEncoder(yqExpr, scanner.Text(), encoder); err != nil {
270+
if str, err = yqutil.EvaluateExpressionWithEncoder(yqExpr, scanner.Text(), plainEncoder); err != nil {
269271
return err
270272
}
273+
// Repeatedly delete empty objects until there are none left.
274+
for {
275+
length := len(str)
276+
if str, err = yqutil.EvaluateExpressionWithEncoder(deleteEmptyObjects, str, plainEncoder); err != nil {
277+
return err
278+
}
279+
if len(str) >= length {
280+
break
281+
}
282+
}
283+
if isTTY {
284+
// pretty-print and colorize the output
285+
if str, err = yqutil.EvaluateExpressionWithEncoder(".", str, colorEncoder); err != nil {
286+
return err
287+
}
288+
}
271289
if _, err = fmt.Fprint(cmd.OutOrStdout(), str); err != nil {
272290
return err
273291
}

hack/bats/helpers/load.bash

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,3 @@ teardown() {
6060
assert_output_lines_count() {
6161
assert_equal "${#lines[@]}" "$1"
6262
}
63-
64-

hack/bats/tests/01-list.bats

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,6 @@ local_setup() {
2020
export LIMA_HOME="${LOCAL_LIMA_HOME:?}"
2121
}
2222

23-
# In Go templates "{{json .}}" will encode empty maps (e.g. "foo": {}) even if the
24-
# map has the "json:",omitempty" tag. "{{yaml .}}" does omit empty maps, so remove
25-
# them from the JSON output to make it comparable to the YAML one.
26-
#
27-
# TODO should we modify `limactl list` to remove empty maps by default
28-
# since we pass the output through yq anyways?
29-
canonical_json() {
30-
local empty_maps='.. | select(tag == "!!map" and length == 0)'
31-
while limactl yq --exit-status --input-format json "[${empty_maps}] | length > 0" <<<"$output" >/dev/null 2>&1; do
32-
run -0 limactl yq --input-format json --output-format json --indent 0 "del(${empty_maps})" <<<"$output"
33-
done
34-
35-
}
36-
3723
@test 'list with no running instances shows a warning and exits without error' {
3824
export LIMA_HOME="$BATS_TEST_TMPDIR"
3925
run_e -0 limactl list
@@ -93,20 +79,19 @@ canonical_json() {
9379
}
9480

9581
@test '--json is shorthand for --format json' {
96-
run -0 limactl ls --format json foo bar
82+
run -0 limactl ls foo bar --format json
9783
format_json=$output
9884

99-
run -0 limactl ls --json foo bar
85+
run -0 limactl ls foo bar --json
10086
assert_output "$format_json"
10187
}
10288

10389
@test '--format YAML returns YAML documents' {
104-
# save canonical JSON output with empty maps removed, for comparison
90+
# save JSON output for comparison
10591
run -0 limactl ls foo bar --format json
106-
canonical_json
10792
json=$output
10893

109-
run -0 limactl ls --format yaml foo bar
94+
run -0 limactl ls foo bar --format yaml
11095
yaml=$output
11196

11297
assert_line --regexp '^name: foo'
@@ -121,7 +106,7 @@ canonical_json() {
121106
run -0 limactl yq --input-format yaml --output-format json --indent 0 "." <<<"$yaml"
122107
assert_output_lines_count 2
123108

124-
# verify it matches the canonical JSON output
109+
# verify it matches the JSON output
125110
assert_output "$json"
126111

127112
}
@@ -148,14 +133,13 @@ canonical_json() {
148133
run -0 limactl yq --input-format json --output-format json --indent 0 "." <<<"$output"
149134
assert_output_lines_count 2
150135

151-
# compare to the regular --format json output
136+
# compare to the plain (uncolorized) json output
152137
assert_output "$json"
153138
}
154139

155140
@test 'YAML output to terminal is colorized, but semantically identical' {
156-
# save canonical output without colors and empty maps removed
141+
# save uncolorized JSON output
157142
run -0 limactl ls foo bar --format json
158-
canonical_json
159143
json=$output
160144

161145
# colorize output even when stdout is not a tty
@@ -179,7 +163,7 @@ canonical_json() {
179163
run -0 limactl yq --indent 0 --input-format yaml --output-format json "." <<<"$yaml"
180164
assert_output_lines_count 2
181165

182-
# verify it matches the canonical JSON output
166+
# verify it matches the JSON output
183167
assert_output "$json"
184168
}
185169

0 commit comments

Comments
 (0)