From 4981213d8a940ab3997575ca283d777d991ae1ef Mon Sep 17 00:00:00 2001 From: Jonathan Ogilvie Date: Fri, 2 Oct 2026 13:49:33 -0400 Subject: [PATCH] fix(render): warn on stderr when function runtimes can't be cleaned up StopFunctionRuntimes returns its error, but `crossplane render xr` and `crossplane render op` only reported it via log.Info, and the CLI's logger is a no-op unless --verbose is set. As a result both commands silently left Function containers behind when stopping them failed. Add WarnCleanupFailure, which writes a short warning (including the error) to a writer and does nothing for a nil error, and call it with kong's stderr from both commands' deferred cleanup alongside the existing log line. The exit code is unchanged. Fixes #399 Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Jonathan Ogilvie --- cmd/crossplane/render/op/cmd.go | 1 + cmd/crossplane/render/render.go | 12 ++++++++++++ cmd/crossplane/render/xr/cmd.go | 1 + 3 files changed, 14 insertions(+) diff --git a/cmd/crossplane/render/op/cmd.go b/cmd/crossplane/render/op/cmd.go index 63a045e2..c67a7853 100644 --- a/cmd/crossplane/render/op/cmd.go +++ b/cmd/crossplane/render/op/cmd.go @@ -221,6 +221,7 @@ func (c *Cmd) Run(k *kong.Context, log logging.Logger, sp terminal.SpinnerPrinte defer func() { if err := render.StopFunctionRuntimes(ctx, fnAddrs); err != nil { log.Info("Error stopping function runtimes", "error", err) + render.WarnCleanupFailure(k.Stderr, err) } }() diff --git a/cmd/crossplane/render/render.go b/cmd/crossplane/render/render.go index bed3f635..99109c9b 100644 --- a/cmd/crossplane/render/render.go +++ b/cmd/crossplane/render/render.go @@ -20,6 +20,8 @@ package render import ( "context" + "fmt" + "io" "strings" fnv1 "github.com/crossplane/function-sdk-go/proto/v1" @@ -196,3 +198,13 @@ func OverrideFunctionAnnotations(fns []pkgv1.Function, annotations []string) err } return nil } + +// WarnCleanupFailure writes a short warning about err to w. It does nothing if +// err is nil. Callers use it to surface function runtime cleanup failures that +// would otherwise only be visible with --verbose. +func WarnCleanupFailure(w io.Writer, err error) { + if err == nil { + return + } + _, _ = fmt.Fprintf(w, "warning: failed to clean up function runtimes; some resources (e.g. containers) may need to be removed manually: %v\n", err) +} diff --git a/cmd/crossplane/render/xr/cmd.go b/cmd/crossplane/render/xr/cmd.go index 0c2435cb..da3302bc 100644 --- a/cmd/crossplane/render/xr/cmd.go +++ b/cmd/crossplane/render/xr/cmd.go @@ -281,6 +281,7 @@ func (c *Cmd) Run(k *kong.Context, log logging.Logger, sp terminal.SpinnerPrinte defer func() { if err := render.StopFunctionRuntimes(ctx, fnAddrs); err != nil { log.Info("Error stopping function runtimes", "error", err) + render.WarnCleanupFailure(k.Stderr, err) } }()