Skip to content

fix(add): stop four more generators emitting empty lists - #1113

Open
VXNCXNX wants to merge 1 commit into
goss-org:masterfrom
VXNCXNX:fix/generators-empty-lists
Open

fix(add): stop four more generators emitting empty lists#1113
VXNCXNX wants to merge 1 commit into
goss-org:masterfrom
VXNCXNX:fix/generators-empty-lists

Conversation

@VXNCXNX

@VXNCXNX VXNCXNX commented Aug 15, 2026

Copy link
Copy Markdown
Contributor
Checklist
  • make test-all (UNIX) passes. CI will also test this (the Makefile has no test-all target; ran make test-short-all, which is fmt lint vet test, all green, plus golangci-lint run explicitly since the make step could not find the binary on PATH: 0 issues.. The Docker-based integration-tests/test.sh that diffs the updated fixtures was not run here)
  • unit and/or integration tests are included (if applicable)
  • documentation is changed or added (if applicable) (no docs change needed, this removes an empty list from generated output and does not alter documented behaviour)

Description of change

Same defect as #1111 and #1112, at the three remaining generators of that shape plus user. No separate issue is filed for this one.

What's broken

Four more generators write an empty list into the gossfile they produce, so validating goss's own output warns about it.

$ goss -g out.yaml add port tcp:9999
port:
    tcp:9999:
        listening: false
        ip: []

$ goss -g out.yaml validate
WARNING: tcp:9999: port.ip is an empty list, which asserts nothing and always passes.

Same for add dns on a host that does not resolve, add interface on an interface with no addresses, and add user for a user in no groups.

The fix

The fields are declared matcher, which is any, with omitempty. Assigning a typed nil slice into an any leaves the interface value non-nil, so omitempty does not fire and yaml.v3 writes []:

nil []string in an `any` field -> "a: []"
untyped nil                    -> "{}"

So each generator now only assigns when the slice is non-empty, letting omitempty drop the key. The system getters that produce these are DefPort.IP (var ips []string, no append when the port has no entries), DefDNS.Addrs (d.addrs stays nil for an unresolvable host), DefInterface.Addrs (var ret []string), and Groups, where the unix path starts from []string{}, non-nil and empty, and the windows path can return nil.

Ruled out and left alone: mount.opts and mount.vfs-opts, because a mounted filesystem always carries at least rw or ro and setup() errors out for a missing mountpoint, and service.runlevels, which NewService never assigns in the first place.

Fixtures

integration-tests/goss/*/goss-expected.yaml carried ip: [] for tcp:9999 and tcp6:80 on four distros. Those files are generated output diffed by integration-tests/test.sh under Docker, which go test does not run, so they are updated here the same way #1112 updated them. The hand-written inputs, and the opts: [] entries under tests/, which sit behind skip: true, are untouched.

Verification

A regression test per field asserting the key is absent from the marshalled yaml, plus a companion asserting a real value still survives, driven by minimal fake system.* implementations in the #1112 style. With the four guards reverted all four regression tests fail and all four companions still pass. go test ./... passes.

Disclosure: written with AI assistance (Claude Code). I reproduced the issue, ran the change and the verification myself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant