Pass an explicit empty argv so cobra cannot reach os.Args

A nil argv lets cobra fall back to os.Args[1:], which under
`go test -args foo` turns the bare-invocation cases into
`certmanager foo` and resolves /opt/certmanager/config.yaml. Assert
the bare-invocation error on stderr so the fallback cannot hide.

Puppet gives the child a temp file as fd 1, not a pipe; say so.
This commit is contained in:
2026-09-22 23:48:59 +10:00
parent b0099991c0
commit 21990d9297
3 changed files with 14 additions and 6 deletions
+3 -3
View File
@@ -30,9 +30,9 @@ and `help` are the subcommands; every other first argument is a common name.
A bare invocation prints help and exits zero only when stdout is a terminal —
a pipe, a file, a socket, `/dev/null` and a closed fd 1 all exit non-zero with
nothing on stdout. Puppet's `generate()` reads stdout through a pipe, so there
a missing common name fails the compile rather than feeding help text into the
catalog.
nothing on stdout. Puppet's `generate()` collects stdout through a temp file,
so there a missing common name fails the compile rather than feeding help text
into the catalog.
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
+2 -2
View File
@@ -43,8 +43,8 @@ func runWith(args []string, stdout, stderr io.Writer, interactive bool) int {
return 0
}
// isTerminal reports whether w is a terminal. Puppet's generate() captures
// stdout through a pipe, so anything else is a machine caller. The check is a
// isTerminal reports whether w is a terminal. Puppet hands the child a temp
// file as fd 1, never a terminal, so anything else is a machine caller. The check is a
// terminal ioctl, not a character-device stat: /dev/null is a character device,
// and so is the /dev/null the Go runtime reopens onto a closed fd 1 at startup.
func isTerminal(w io.Writer) bool {
+9 -1
View File
@@ -869,10 +869,18 @@ func TestIsTerminalRejectsNonTerminals(t *testing.T) {
if isTerminal(f) {
t.Errorf("%s is not a terminal", name)
}
// An explicit empty argv, never nil: cobra falls back to os.Args[1:]
// for a nil one, which under `go test -args foo` would turn this into
// `certmanager foo` and issue against whatever Vault the host's
// config resolves to. The stderr assertion is what catches that.
var stderr bytes.Buffer
if code := run(nil, f, &stderr); code == 0 {
code := run([]string{}, f, &stderr)
if code == 0 {
t.Errorf("%s: bare invocation exit code = 0, want non-zero", name)
}
if want := "a common name is required"; !strings.Contains(stderr.String(), want) {
t.Errorf("%s: stderr = %q, want it to contain %q", name, stderr.String(), want)
}
}
}