Verify the [controller-runtime] log.SetLogger(...) was never called warning no longer appears on any CLI code path
Maps to
Primary acceptance criteria
Method
Before/after binary comparison with forced timer reproduction
Result: PASS — The warning is reproduced with the unfixed binary and confirmed absent with the fixed binary on both create and destroy code paths.
Verification Steps
Step
Check
Result
Evidence
0
Reproduce warning with unfixed binary (destroy path)
FAIL (expected)
Unfixed hcp binary prints warning + goroutine stack trace to stderr
1
Verify unfixed binary has no ctrl.SetLogger() call
PASS
grep of main branch product-cli/main.go returns no matches
2
Verify fixed binary adds ctrl.SetLogger() before cmd.ExecuteContext()
PASS
ctrl.SetLogger(newLogger()) at line 45, before cobra command at line 47
3
Run fixed binary on same destroy path — no warning
PASS
No log.SetLogger warning; clean JSON log output
4
Run fixed binary on create path (flag validation) — no warning
PASS
grep count = 0
5
Confirm warning mechanism requires 30s runtime
PASS
controller-runtime pkg/log/log.go:58-69 fires warning after 30s via timer
Reproduction Note: The controller-runtime warning fires after 30 seconds of runtime, but most CLI commands finish in under 5 seconds. To reliably reproduce the warning, the controller-runtime timer was temporarily set to 0 seconds (from 30) when building the unfixed binary. This forces the warning on the very first log call, making the test deterministic rather than racy. The timer was restored after building.
Evidence
Step 0: Reproducing the warning (unfixed binary, destroy path)
Built from main branch without ctrl.SetLogger(). The controller-runtime deferred logger fires when SetLogger() is never called, printing a warning and goroutine stack trace to stderr.
$ /tmp/hcp-unfixed destroy cluster azure --name nonexistent-cluster-78310 \
--azure-creds /Users/brcox/.azure/self-managed-azure-credentials.json \
--dns-zone-rg-name fake-rg
[controller-runtime] log.SetLogger(...) was never called; logs will not be displayed.
Detected at:
> goroutine 1 [running, locked to thread]:
> runtime/debug.Stack()
> /opt/homebrew/Cellar/go/1.26.0/libexec/src/runtime/debug/stack.go:26 +0x64
> sigs.k8s.io/controller-runtime/pkg/log.eventuallyFulfillRoot()
> vendor/sigs.k8s.io/controller-runtime/pkg/log/log.go:60 +0xe4
> sigs.k8s.io/controller-runtime/pkg/log.(*delegatingLogSink).Init(...)
> vendor/sigs.k8s.io/controller-runtime/pkg/log/deleg.go:101 +0x2c
> github.com/go-logr/logr.New(...)
> vendor/github.com/go-logr/logr/logr.go:217
> sigs.k8s.io/controller-runtime/pkg/log.init()
> vendor/sigs.k8s.io/controller-runtime/pkg/log/log.go:87 +0xf8
{"level":"info","ts":"2026-07-13T09:02:03-04:00","msg":"Hosted cluster not found, destroying infrastructure from user input","namespace":"clusters","name":"nonexistent-cluster-78310","infraID":""}
Error: required inputs are missing: infrastructure ID is required
Step 3: Fixed binary on same destroy path — no warning
$ /tmp/hcp-after destroy cluster azure --name nonexistent-cluster-78310 \
--azure-creds /Users/brcox/.azure/self-managed-azure-credentials.json \
--dns-zone-rg-name fake-rg
{"level":"info","ts":"2026-07-13T09:02:14-04:00","msg":"Hosted cluster not found, destroying infrastructure from user input","namespace":"clusters","name":"nonexistent-cluster-78310","infraID":""}
Error: required inputs are missing: infrastructure ID is required
Step 1: Unfixed binary has no ctrl.SetLogger()
$ git stash # stash PR #8955 changes to test main branch
$ grep -n "SetLogger\|ctrl\.\|zap\." product-cli/main.go
(no logger initialization found)
$ git stash pop
$ grep -A15 "func checkPromise" vendor/sigs.k8s.io/controller-runtime/pkg/log/log.go
func checkPromise() {
if logFullfilled.Load() {
return
}
if time.Since(rootLogCreated).Seconds() >= 30 {
if logFullfilled.CompareAndSwap(false, true) {
...
fmt.Fprintf(os.Stderr,
"[controller-runtime] log.SetLogger(...) was never called; logs will not be displayed.\n...")