99 "errors"
1010
1111 corev1 "k8s.io/api/core/v1"
12+ apierrors "k8s.io/apimachinery/pkg/api/errors"
1213 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1314 "k8s.io/apimachinery/pkg/types"
1415 "k8s.io/client-go/tools/clientcmd"
@@ -96,6 +97,16 @@ func (r *KubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
9697 },
9798 }}
9899 kubeconfig .Spec .Kubeconfig .CurrentContext = cluster .Name
100+
101+ // ensure the ClusterKubeconfig resource exists before any status patches happen later
102+ if err := r .Create (ctx , & kubeconfig ); err != nil {
103+ if ! apierrors .IsAlreadyExists (err ) {
104+ l .Error (err , "failed to create initial ClusterKubeconfig resource" )
105+ return ctrl.Result {}, err
106+ }
107+ } else {
108+ l .Info ("created initial ClusterKubeconfig resource" )
109+ }
99110 }
100111
101112 // get oidc info from organization
@@ -132,7 +143,27 @@ func (r *KubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
132143 }
133144
134145 // collect cluster connection data and update kubeconfig
135- rootKubeCfg := secret .Data [greenhouseapis .GreenHouseKubeConfigKey ]
146+ rootKubeCfg , hasKey := secret .Data [greenhouseapis .GreenHouseKubeConfigKey ]
147+ if ! hasKey || len (rootKubeCfg ) == 0 {
148+ kubeconfig .Status .Conditions .SetConditions (
149+ greenhousemetav1alpha1 .TrueCondition (
150+ v1alpha1 .KubeconfigReconcileFailedCondition ,
151+ "KubeconfigMissing" ,
152+ "secret data key greenhousekubeconfig missing or empty" ,
153+ ),
154+ )
155+ // patch status before returning on error
156+ result , perr := clientutil .PatchStatus (ctx , r .Client , & kubeconfig , func () error {
157+ kubeconfig .Status = calculateKubeconfigStatus (& kubeconfig )
158+ return nil
159+ })
160+ if perr != nil {
161+ log .FromContext (ctx ).Error (perr , "error setting status" )
162+ }
163+ l .Info ("status updated" , "result" , result )
164+ return ctrl.Result {}, nil
165+ }
166+
136167 kubeCfg , err := clientcmd .Load (rootKubeCfg )
137168 if err != nil {
138169 kubeconfig .Status .Conditions .SetConditions (greenhousemetav1alpha1 .TrueCondition (v1alpha1 .KubeconfigReconcileFailedCondition , "KubeconfigLoadError" , err .Error ()))
@@ -153,6 +184,25 @@ func (r *KubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
153184 clusterCfg = v
154185 break
155186 }
187+ if clusterCfg == nil {
188+ kubeconfig .Status .Conditions .SetConditions (
189+ greenhousemetav1alpha1 .TrueCondition (
190+ v1alpha1 .KubeconfigReconcileFailedCondition ,
191+ "KubeconfigInvalid" ,
192+ "no clusters found in kubeconfig" ,
193+ ),
194+ )
195+ // patch status before returning on error
196+ result , perr := clientutil .PatchStatus (ctx , r .Client , & kubeconfig , func () error {
197+ kubeconfig .Status = calculateKubeconfigStatus (& kubeconfig )
198+ return nil
199+ })
200+ if perr != nil {
201+ log .FromContext (ctx ).Error (perr , "error setting status" )
202+ }
203+ l .Info ("status updated" , "result" , result )
204+ return ctrl.Result {}, nil
205+ }
156206
157207 // collect oidc data and update kubeconfig
158208 result , err := clientutil .CreateOrPatch (ctx , r .Client , & kubeconfig , func () error {
0 commit comments