fix: recover from panic in IsMinikubeKubernetes when kubeconfig extensions are plain strings#3217
fix: recover from panic in IsMinikubeKubernetes when kubeconfig extensions are plain strings#3217benmosher wants to merge 4 commits intodevspace-sh:mainfrom
Conversation
✅ Deploy Preview for devspace-docs ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
FWIW -- I am not a Go guy, so this is 100% Claude Code 😅 but this is a real problem I'm experiencing locally. and I rebuilt the binary against this patch, and I can build again 👍 so the fix does empirically work. |
…sions are plain strings
Some tools (e.g. Teleport) write kubeconfig cluster extensions as raw
YAML strings rather than structured objects. When devspace calls
runtime.DefaultUnstructuredConverter.ToUnstructured() on such an
extension, the k8s apimachinery reflection layer panics instead of
returning an error:
panic: reflect.Set: value of type string is not assignable to
type map[string]interface {}
Extract the per-extension check into a helper (isMinikubeExtension)
that uses recover() to catch the panic and treat unparseable extensions
as non-minikube, allowing the build to proceed normally.
Signed-off-by: Ben Mosher <ben.mosher@dbtlabs.com>
…anic
Covers the cases for IsMinikubeKubernetes:
- nil client / nil ClientConfig
- context name match ("minikube")
- structured extension with minikube provider
- structured extension with a different provider
- string-valued extension (e.g. written by Teleport) — must not panic
Signed-off-by: Ben Mosher <ben.mosher@dbtlabs.com>
Without noinline, newer Go versions inline isMinikubeExtension into its caller, which means the deferred recover() loses its own stack frame and cannot catch the panic from ToUnstructured. Signed-off-by: Ben Mosher <ben.mosher@dbtlabs.com>
0ce6070 to
cd266a5
Compare
| func isMinikubeExtension(extension runtime.Object) (result bool) { | ||
| defer func() { | ||
| if recover() != nil { | ||
| result = false | ||
| } | ||
| }() | ||
| ext, err := runtime.DefaultUnstructuredConverter.ToUnstructured(extension) | ||
| if err != nil { | ||
| return false | ||
| } | ||
| provider, ok := ext["provider"].(string) | ||
| return ok && provider == minikubeProvider | ||
| } |
There was a problem hiding this comment.
Here we are basically doing a "kind-of" try/catch when the method panics, which might hide other errors happening here with k8s runtime lib ("k8s.io/apimachinery/pkg/runtime").
What we could do is to detect if extension is a plain string here and add into a format runtime.DefaultUnstructuredConverter.ToUnstructured might handle. What do you think?
There was a problem hiding this comment.
ahh smart. because I can better speak Python, something like if isinstance(extension, Mapping): test vs try: extension["provider"]; except TypeError | KeyError | ...
There was a problem hiding this comment.
@danielbdias what do you think of it now? switched to using an explicit JSON unmarshal.
Detect plain-string kubeconfig extensions upfront by type-asserting to *runtime.Unknown and using json.Unmarshal, which returns an error for non-object JSON instead of panicking. This avoids a try/catch pattern that could silently swallow unrelated panics from the k8s runtime library. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ben Mosher <ben.mosher@dbtlabs.com>
Problem
When using a Teleport-managed kubeconfig,
devspace build(and any pipeline that callsbuild_images) panics and crashes:Root cause
Teleport writes kubeconfig cluster extensions as plain YAML strings, e.g.:
The Kubernetes spec says extension values should be structured objects.
runtime.DefaultUnstructuredConverter.ToUnstructured()uses reflection and assumes the extension value is a struct/map — it panics (rather than returning an error) when it encounters a plain string.Fix
Extract the per-extension check into a small helper
isMinikubeExtensionthat wraps theToUnstructuredcall withrecover(). A malformed/unparseable extension is treated as non-minikube and the build proceeds normally. No behaviour change on the happy path.Reproduction
devspace buildConfirmed on devspace v6.3.2 and v6.3.20.
Resolves #3218.