@@ -17,10 +17,11 @@ use kube::api::{
1717use kube:: client:: scope;
1818use kube:: runtime:: watcher:: { self , Config } ;
1919use kube:: { Api , Client } ;
20- use kube:: { Resource , api:: ResourceExt , runtime:: controller:: Action } ;
20+ use kube:: { Resource , api:: { ResourceExt , Patch } , runtime:: controller:: Action } ;
2121use serde:: Serialize ;
2222use serde_json:: Value ;
23- use tracing:: info;
23+ use serde_json:: json;
24+ use tracing:: { info, debug} ;
2425
2526use std:: sync:: Arc ;
2627
@@ -30,6 +31,7 @@ use super::controller::{
3031use super :: { BundleResult , ClusterSyncError , ClusterSyncResult } ;
3132
3233pub static CONTROLPLANE_READY_CONDITION : & str = "ControlPlaneReady" ;
34+ pub static FLEET_WORKSPACE_ANNOTATION : & str = "field.cattle.io/allow-fleetworkspace-creation-for-existing-namespace" ;
3335
3436pub struct FleetClusterBundle {
3537 template_sources : TemplateSources ,
@@ -285,4 +287,49 @@ impl Cluster {
285287
286288 Ok ( Action :: await_change ( ) )
287289 }
290+
291+ pub async fn reconcile_fleet_annotation_in_capi_ns ( obj : Arc < Cluster > , ctx : Arc < Context > ) -> crate :: Result < Action > {
292+ let deletion_timestamp = & obj. metadata . deletion_timestamp ;
293+ let namespace_name = obj. namespace ( ) . unwrap_or_default ( ) ;
294+ let namespaces = Api :: < Namespace > :: all ( ctx. client . clone ( ) ) ;
295+
296+ match deletion_timestamp {
297+ // If the cluster is being deleted, and this is the last CAPI cluster in this namespace, remove the fleet annotation.
298+ Some ( _) => {
299+ // List all other clusters in this namespace
300+ let clusters = Api :: < Cluster > :: namespaced ( ctx. client . clone ( ) , & namespace_name) ;
301+ let other_clusters = clusters
302+ . list ( & ListParams :: default ( ) . fields ( & format ! ( "metadata.namespace={},metadata.name!={}" , namespace_name, obj. name_any( ) ) ) )
303+ . await ?;
304+
305+ // If no other clusters are found in this namespace, remove the fleet annotation.
306+ if other_clusters. items . is_empty ( ) {
307+ let patch = json ! ( {
308+ "metadata" : {
309+ "annotations" : {
310+ FLEET_WORKSPACE_ANNOTATION : null
311+ }
312+ }
313+ } ) ;
314+ namespaces. patch_metadata ( & namespace_name, & PatchParams :: default ( ) , & Patch :: Merge ( & patch) ) . await ?;
315+ debug ! ( "Removed fleet annotation from namespace {}." , namespace_name) ;
316+ }
317+ } ,
318+ // If the cluster is not being deleted, ensure the fleet annotation is present.
319+ None => {
320+ let patch = json ! ( {
321+ "metadata" : {
322+ "annotations" : {
323+ FLEET_WORKSPACE_ANNOTATION : "true"
324+ }
325+ }
326+ } ) ;
327+ namespaces. patch_metadata ( & namespace_name, & PatchParams :: default ( ) , & Patch :: Merge ( & patch) ) . await ?;
328+ debug ! ( "Added fleet annotation to namespace {}." , namespace_name) ;
329+ }
330+ }
331+
332+ Ok ( Action :: await_change ( ) )
333+ }
288334}
335+
0 commit comments