@@ -1030,7 +1030,7 @@ func (r *ReconcileArgoCD) setResourceWatches(bldr *builder.Builder, clusterResou
10301030 }
10311031
10321032 // Watch for changes to primary resource ArgoCD
1033- bldr .For (& argoproj.ArgoCD {}, builder .WithPredicates (deleteNotificationsPred , r .argoCDNamespaceManagementFilterPredicate (), r . argoCDSpecLabelAndAnnotationCleanupPredicate () ))
1033+ bldr .For (& argoproj.ArgoCD {}, builder .WithPredicates (deleteNotificationsPred , r .argoCDNamespaceManagementFilterPredicate ()))
10341034
10351035 // Watch for changes to ConfigMap sub-resources owned by ArgoCD instances.
10361036 bldr .Owns (& corev1.ConfigMap {})
@@ -1245,335 +1245,6 @@ func (r *ReconcileArgoCD) namespaceFilterPredicate() predicate.Predicate {
12451245 }
12461246}
12471247
1248- // DropMetadata stores metadata about removed labels for a specific resource type
1249- type DropMetadata struct {
1250- Resource string `json:"resource"`
1251- LabelKeys []string `json:"labelKeys"`
1252- AnnotationKeys []string `json:"annotationKeys"`
1253- }
1254-
1255- // Global map to store removed labels per namespace
1256- // Key: namespace, Value: slice of DropMetadata for different resources
1257- var DropMetadataStore = make (map [string ][]DropMetadata )
1258-
1259- // addDropMetadata adds removed label information to the DropMetadataStore for a specific namespace
1260- func addDropMetadata (namespace , resource string , labelKeys , annotationKeys []string ) {
1261- if len (labelKeys ) == 0 && len (annotationKeys ) == 0 {
1262- return
1263- }
1264-
1265- dropMeta := DropMetadata {
1266- Resource : resource ,
1267- LabelKeys : labelKeys ,
1268- AnnotationKeys : annotationKeys ,
1269- }
1270-
1271- if DropMetadataStore [namespace ] == nil {
1272- DropMetadataStore [namespace ] = []DropMetadata {}
1273- }
1274-
1275- // Check if the resource already exists in the slice and update it
1276- found := false
1277- for i , existing := range DropMetadataStore [namespace ] {
1278- if existing .Resource == resource {
1279- // Merge keys if resource already exists
1280- mergedLabelKeys := mergeKeys (existing .LabelKeys , dropMeta .LabelKeys )
1281- DropMetadataStore [namespace ][i ].LabelKeys = mergedLabelKeys
1282-
1283- mergedAnnotationKeys := mergeKeys (existing .AnnotationKeys , dropMeta .AnnotationKeys )
1284- DropMetadataStore [namespace ][i ].AnnotationKeys = mergedAnnotationKeys
1285-
1286- found = true
1287- break
1288- }
1289- }
1290-
1291- if ! found {
1292- DropMetadataStore [namespace ] = append (DropMetadataStore [namespace ], dropMeta )
1293- }
1294- }
1295-
1296- // mergeKeys is a helper function thatefficiently merges two string slices, ensuring unique keys in the result.
1297- func mergeKeys (existingKeys , newKeys []string ) []string {
1298- if len (newKeys ) == 0 {
1299- return existingKeys // No new keys to merge, return existing keys
1300- }
1301-
1302- keySet := make (map [string ]bool , len (existingKeys )+ len (newKeys ))
1303-
1304- // Add existing keys to the set
1305- for _ , key := range existingKeys {
1306- keySet [key ] = true
1307- }
1308-
1309- // Add new keys to the set
1310- for _ , key := range newKeys {
1311- keySet [key ] = true
1312- }
1313-
1314- // Convert set back to slice
1315- var mergedKeys []string
1316- for key := range keySet {
1317- mergedKeys = append (mergedKeys , key )
1318- }
1319- return mergedKeys
1320- }
1321-
1322- // getDropMetadataForNamespace retrieves all DropMetadata for a specific namespace
1323- func getDropMetadataForNamespace (namespace string ) []DropMetadata {
1324- return DropMetadataStore [namespace ]
1325- }
1326-
1327- // removeDropMetadataForNamespace removes all DropMetadata for a specific namespace
1328- func removeDropMetadataForNamespace (namespace string ) {
1329- delete (DropMetadataStore , namespace )
1330- }
1331-
1332- // processDropMetadataForCleanup processes the DropMetadata store and cleans up removed labels and annotations from resources
1333- func (r * ReconcileArgoCD ) processDropMetadataForCleanup (argocd * argoproj.ArgoCD ) {
1334- namespace := argocd .GetNamespace ()
1335- dropMetadataList := getDropMetadataForNamespace (namespace )
1336-
1337- for _ , dropMeta := range dropMetadataList {
1338- if err := r .cleanupLabelsAndAnnotationsFromResourceType (argocd , dropMeta ); err != nil {
1339- log .Error (err , "failed to cleanup labels and annotations from resource type" ,
1340- "resource" , dropMeta .Resource )
1341- continue
1342- }
1343- }
1344-
1345- // Clear the DropMetadata for this namespace after cleanup
1346- removeDropMetadataForNamespace (namespace )
1347- }
1348-
1349- // cleanupLabelsAndAnnotationsFromResourceType removes labels and annotations from specific resource types
1350- func (r * ReconcileArgoCD ) cleanupLabelsAndAnnotationsFromResourceType (argocd * argoproj.ArgoCD , dropMeta DropMetadata ) error {
1351-
1352- switch dropMeta .Resource {
1353- case "server-deployment" :
1354- // Clean up from ArgoCD server deployment only
1355- deploymentName := fmt .Sprintf ("%s-server" , argocd .Name )
1356- if err := r .cleanupLabelsAndAnnotationsFromDeployment (argocd , deploymentName , dropMeta .LabelKeys , dropMeta .AnnotationKeys ); err != nil {
1357- return fmt .Errorf ("failed to cleanup labels from server deployment: %w" , err )
1358- }
1359-
1360- case "repo-deployment" :
1361- // Clean up from ArgoCD repo server deployment only
1362- deploymentName := fmt .Sprintf ("%s-repo-server" , argocd .Name )
1363- if err := r .cleanupLabelsAndAnnotationsFromDeployment (argocd , deploymentName , dropMeta .LabelKeys , dropMeta .AnnotationKeys ); err != nil {
1364- return fmt .Errorf ("failed to cleanup labels from repo deployment: %w" , err )
1365- }
1366-
1367- case "applicationset-deployment" :
1368- // Clean up from ArgoCD applicationset controller deployment only
1369- deploymentName := fmt .Sprintf ("%s-applicationset-controller" , argocd .Name )
1370- if err := r .cleanupLabelsAndAnnotationsFromDeployment (argocd , deploymentName , dropMeta .LabelKeys , dropMeta .AnnotationKeys ); err != nil {
1371- return fmt .Errorf ("failed to cleanup labels from applicationset deployment: %w" , err )
1372- }
1373-
1374- case "notifications-deployment" :
1375- // Clean up from ArgoCD notifications controller deployment only
1376- if argocd .Spec .Notifications .Enabled {
1377- deploymentName := fmt .Sprintf ("%s-notifications-controller" , argocd .Name )
1378- if err := r .cleanupLabelsAndAnnotationsFromDeployment (argocd , deploymentName , dropMeta .LabelKeys , dropMeta .AnnotationKeys ); err != nil {
1379- return fmt .Errorf ("failed to cleanup labels from notifications deployment: %w" , err )
1380- }
1381- }
1382-
1383- case "controller-statefulset" :
1384- // Clean up from ArgoCD application controller StatefulSet
1385- statefulSetName := fmt .Sprintf ("%s-application-controller" , argocd .Name )
1386- if err := r .cleanupLabelsAndAnnotationsFromStatefulSet (argocd , statefulSetName , dropMeta .LabelKeys , dropMeta .AnnotationKeys ); err != nil {
1387- return fmt .Errorf ("failed to cleanup labels from controller statefulset: %w" , err )
1388- }
1389-
1390- default :
1391- log .Info ("Unknown resource type for cleanup" , "resourceType" , dropMeta .Resource )
1392- }
1393-
1394- return nil
1395- }
1396-
1397- // cleanupLabelsFromDeployment removes labels from a specific deployment
1398- func (r * ReconcileArgoCD ) cleanupLabelsAndAnnotationsFromDeployment (argocd * argoproj.ArgoCD , deploymentName string , labelsToRemove , annotationsToRemove []string ) error {
1399- namespace := argocd .GetNamespace ()
1400- deployment := & appsv1.Deployment {}
1401- key := types.NamespacedName {Namespace : namespace , Name : deploymentName }
1402-
1403- if err := r .Get (context .TODO (), key , deployment ); err != nil {
1404- if apierrors .IsNotFound (err ) {
1405- log .Info ("Deployment not found, skipping label cleanup" , "name" , deploymentName )
1406- return nil // Deployment doesn't exist, skip
1407- }
1408- return fmt .Errorf ("failed to get deployment %s: %w" , deploymentName , err )
1409- }
1410-
1411- // Work on pod template labels and annotations directly, not deployment metadata labels
1412- currentLabels := deployment .Spec .Template .Labels
1413- currentAnnotations := deployment .Spec .Template .Annotations
1414- if currentLabels == nil && currentAnnotations == nil {
1415- return nil // No labels or annotations to remove
1416- }
1417-
1418- modifiedLabels := false
1419- modifiedAnnotations := false
1420- for _ , labelKey := range labelsToRemove {
1421- if _ , exists := currentLabels [labelKey ]; exists {
1422- delete (currentLabels , labelKey )
1423- modifiedLabels = true
1424- }
1425- }
1426-
1427- for _ , annotationKey := range annotationsToRemove {
1428- if _ , exists := currentAnnotations [annotationKey ]; exists {
1429- delete (currentAnnotations , annotationKey )
1430- modifiedAnnotations = true
1431- }
1432- }
1433-
1434- if modifiedLabels {
1435- deployment .Spec .Template .Labels = currentLabels
1436- }
1437- if modifiedAnnotations {
1438- deployment .Spec .Template .Annotations = currentAnnotations
1439- }
1440-
1441- if modifiedLabels || modifiedAnnotations {
1442- if err := r .Update (context .TODO (), deployment ); err != nil {
1443- log .Error (err , "failed to update deployment after removing labels and annotations" , "name" , deploymentName )
1444- return err
1445- }
1446- }
1447- return nil
1448- }
1449-
1450- // cleanupLabelsFromStatefulSet removes labels from a specific statefulset
1451- func (r * ReconcileArgoCD ) cleanupLabelsAndAnnotationsFromStatefulSet (argocd * argoproj.ArgoCD , statefulSetName string , labelsToRemove , annotationsToRemove []string ) error {
1452- namespace := argocd .GetNamespace ()
1453- statefulSet := & appsv1.StatefulSet {}
1454- key := types.NamespacedName {Namespace : namespace , Name : statefulSetName }
1455-
1456- if err := r .Get (context .TODO (), key , statefulSet ); err != nil {
1457- if apierrors .IsNotFound (err ) {
1458- log .Info ("StatefulSet not found, skipping label and annotation cleanup" , "name" , statefulSetName )
1459- return nil // StatefulSet doesn't exist, nothing to clean
1460- }
1461- return fmt .Errorf ("failed to get statefulset %s: %w" , statefulSetName , err )
1462- }
1463-
1464- // Work on pod template labels directly, not StatefulSet metadata labels
1465- currentLabels := statefulSet .Spec .Template .Labels
1466- currentAnnotations := statefulSet .Spec .Template .Annotations
1467- if currentLabels == nil && currentAnnotations == nil {
1468- return nil // No labels or annotations to remove
1469- }
1470-
1471- modifiedLabels := false
1472- modifiedAnnotations := false
1473- for _ , labelKey := range labelsToRemove {
1474- if _ , exists := currentLabels [labelKey ]; exists {
1475- delete (currentLabels , labelKey )
1476- modifiedLabels = true
1477- }
1478- }
1479- for _ , annotationKey := range annotationsToRemove {
1480- if _ , exists := currentAnnotations [annotationKey ]; exists {
1481- delete (currentAnnotations , annotationKey )
1482- modifiedAnnotations = true
1483- }
1484- }
1485-
1486- if modifiedLabels {
1487- statefulSet .Spec .Template .Labels = currentLabels
1488- }
1489- if modifiedAnnotations {
1490- statefulSet .Spec .Template .Annotations = currentAnnotations
1491- }
1492-
1493- if modifiedLabels || modifiedAnnotations {
1494- if err := r .Update (context .TODO (), statefulSet ); err != nil {
1495- log .Error (err , "failed to update statefulset after removing labels and annotations" , "name" , statefulSetName )
1496- return err
1497- }
1498- }
1499-
1500- return nil
1501- }
1502-
1503- // argoCDSpecLabelCleanupPredicate tracks label changes in ArgoCD CR specs and cleans up removed labels from managed resources
1504- func (r * ReconcileArgoCD ) argoCDSpecLabelAndAnnotationCleanupPredicate () predicate.Predicate {
1505- return predicate.Funcs {
1506- UpdateFunc : func (e event.UpdateEvent ) bool {
1507- newCR , ok := e .ObjectNew .(* argoproj.ArgoCD )
1508- if ! ok {
1509- return false
1510- }
1511- oldCR , ok := e .ObjectOld .(* argoproj.ArgoCD )
1512- if ! ok {
1513- return false
1514- }
1515-
1516- // Track removed labels from each component spec
1517- r .calculateRemovedSpecLabelsAndAnnotations (oldCR , newCR )
1518-
1519- return true // Trigger reconciliation for ArgoCD updates
1520- },
1521- }
1522- }
1523-
1524- // calculateRemovedSpecLabels compares old and new ArgoCD specs and tracks removed labels by resource type
1525- func (r * ReconcileArgoCD ) calculateRemovedSpecLabelsAndAnnotations (oldCR , newCR * argoproj.ArgoCD ) {
1526- // Add nil checks to prevent panic
1527- if r == nil || oldCR == nil || newCR == nil {
1528- return
1529- }
1530- //removedLabels := make(map[string]string)
1531- namespace := newCR .GetNamespace ()
1532-
1533- // Helper function to check and store removed labels for a specific resource
1534- checkAndStoreRemovedLabels := func (oldLabels , oldAnnotations , newLabels , newAnnotations map [string ]string , resourceType string ) {
1535- var removedLabelKeys []string
1536- var removedAnnotationKeys []string
1537- for key := range oldLabels {
1538- if newLabels == nil || newLabels [key ] == "" {
1539- removedLabelKeys = append (removedLabelKeys , key )
1540- }
1541- }
1542- for key := range oldAnnotations {
1543- if newAnnotations == nil || newAnnotations [key ] == "" {
1544- removedAnnotationKeys = append (removedAnnotationKeys , key )
1545- }
1546- }
1547- // Store removed keys for this resource type in the namespace
1548- if len (removedLabelKeys ) > 0 || len (removedAnnotationKeys ) > 0 {
1549- addDropMetadata (namespace , resourceType , removedLabelKeys , removedAnnotationKeys )
1550- }
1551- }
1552-
1553- // Check Server labels
1554- checkAndStoreRemovedLabels (oldCR .Spec .Server .Labels , oldCR .Spec .Server .Annotations , newCR .Spec .Server .Labels , newCR .Spec .Server .Annotations , "server-deployment" )
1555-
1556- // Check Repo Server labels
1557- checkAndStoreRemovedLabels (oldCR .Spec .Repo .Labels , oldCR .Spec .Repo .Annotations , newCR .Spec .Repo .Labels , newCR .Spec .Repo .Annotations , "repo-deployment" )
1558-
1559- // Check Controller labels (StatefulSet)
1560- checkAndStoreRemovedLabels (oldCR .Spec .Controller .Labels , oldCR .Spec .Controller .Annotations , newCR .Spec .Controller .Labels , newCR .Spec .Controller .Annotations , "controller-statefulset" )
1561-
1562- // Check ApplicationSet labels
1563- if oldCR .Spec .ApplicationSet != nil && newCR .Spec .ApplicationSet != nil {
1564- checkAndStoreRemovedLabels (oldCR .Spec .ApplicationSet .Labels , oldCR .Spec .ApplicationSet .Annotations , newCR .Spec .ApplicationSet .Labels , newCR .Spec .ApplicationSet .Annotations , "applicationset-deployment" )
1565- }
1566-
1567- // Check Notifications labels (if we add support for notifications labels in the future)
1568- // if oldCR.Spec.Notifications != nil && newCR.Spec.Notifications != nil {
1569- // checkAndStoreRemovedLabels(oldCR.Spec.Notifications.Labels, newCR.Spec.Notifications.Labels, "notifications-deployment")
1570- // }
1571-
1572- // Note: Notifications and Prometheus specs don't have Labels fields currently
1573- // If they are added in the future, the logic can be uncommented and updated
1574-
1575- }
1576-
15771248// deleteRBACsForNamespace deletes the RBACs when the label from the namespace is removed.
15781249func deleteRBACsForNamespace (sourceNS string , k8sClient kubernetes.Interface ) error {
15791250 log .Info (fmt .Sprintf ("Removing the RBACs created for the namespace: %s" , sourceNS ))
0 commit comments