@@ -18,6 +18,7 @@ import (
1818 "github.com/charmbracelet/lipgloss"
1919 "github.com/spf13/cobra"
2020 "golang.org/x/term"
21+ corev1 "k8s.io/api/core/v1"
2122 apierrors "k8s.io/apimachinery/pkg/api/errors"
2223 "k8s.io/apimachinery/pkg/api/meta"
2324 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -913,6 +914,24 @@ func installControllerDryRun(ctx context.Context, dynClient dynamic.Interface, m
913914 return nil
914915}
915916
917+ func ensureNamespace (ctx context.Context , kc * rest.Config , ns string ) error {
918+ clientset , err := kubernetes .NewForConfig (kc )
919+ if err != nil {
920+ return err
921+ }
922+ _ , err = clientset .CoreV1 ().Namespaces ().Get (ctx , ns , metav1.GetOptions {})
923+ if err == nil {
924+ return nil
925+ }
926+ if ! apierrors .IsNotFound (err ) {
927+ return err
928+ }
929+ _ , err = clientset .CoreV1 ().Namespaces ().Create (ctx , & corev1.Namespace {
930+ ObjectMeta : metav1.ObjectMeta {Name : ns },
931+ }, metav1.CreateOptions {})
932+ return err
933+ }
934+
916935// --- Main orchestration ---
917936
918937func installController (ctx context.Context , kc * rest.Config , yamlz []byte , ns string , dryRun , force , yes bool , kubeContext string ) error {
@@ -927,6 +946,13 @@ func installController(ctx context.Context, kc *rest.Config, yamlz []byte, ns st
927946 }
928947 mapper := restmapper .NewDeferredDiscoveryRESTMapper (memory .NewMemCacheClient (dc ))
929948
949+ // Ensure the target namespace exists before any server-side dry-run or
950+ // plan building — both paths use SSA dry-run patches that require the
951+ // namespace to be present for validation.
952+ if err := ensureNamespace (ctx , kc , ns ); err != nil {
953+ return fmt .Errorf ("failed to ensure namespace %q: %w" , ns , err )
954+ }
955+
930956 if dryRun {
931957 return installControllerDryRun (ctx , dynClient , mapper , yamlz , ns , force )
932958 }
0 commit comments