@@ -41,6 +41,12 @@ import (
4141 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
4242)
4343
44+ const (
45+ // Homer annotation prefixes
46+ serviceAnnotationPrefix = "service.homer.rajsingh.info/"
47+ itemAnnotationPrefix = "item.homer.rajsingh.info/"
48+ )
49+
4450// ClusterClient represents a client connection to a Kubernetes cluster
4551type ClusterClient struct {
4652 Name string
@@ -378,6 +384,9 @@ func (m *ClusterManager) discoverClusterIngresses(ctx context.Context, cluster *
378384 }
379385 clusterIngresses .Items [i ].Annotations ["homer.rajsingh.info/cluster" ] = cluster .Name
380386
387+ // Merge namespace annotations from the source cluster
388+ m .mergeNamespaceAnnotationsForIngress (ctx , cluster .Client , & clusterIngresses .Items [i ])
389+
381390 filtered = append (filtered , clusterIngresses .Items [i ])
382391 }
383392 }
@@ -410,6 +419,9 @@ func (m *ClusterManager) discoverClusterIngresses(ctx context.Context, cluster *
410419 }
411420 ingress .Annotations ["homer.rajsingh.info/cluster" ] = cluster .Name
412421
422+ // Merge namespace annotations from the source cluster
423+ m .mergeNamespaceAnnotationsForIngress (ctx , cluster .Client , ingress )
424+
413425 filtered = append (filtered , * ingress )
414426 }
415427
@@ -529,6 +541,9 @@ func (m *ClusterManager) discoverClusterHTTPRoutes(ctx context.Context, cluster
529541 clusterHTTPRoutes .Items [i ].Annotations ["homer.rajsingh.info/domain-filters" ] = strings .Join (domainFilters , "," )
530542 }
531543
544+ // Merge namespace annotations from the source cluster
545+ m .mergeNamespaceAnnotationsForHTTPRoute (ctx , cluster .Client , & clusterHTTPRoutes .Items [i ])
546+
532547 filtered = append (filtered , clusterHTTPRoutes .Items [i ])
533548 }
534549 }
@@ -572,7 +587,6 @@ func (m *ClusterManager) shouldIncludeHTTPRoute(ctx context.Context, cluster *Cl
572587 return false , err
573588 }
574589
575- matchedGateway := false
576590 for _ , parentRef := range httproute .Spec .ParentRefs {
577591 if parentRef .Kind != nil && string (* parentRef .Kind ) != gatewayKind {
578592 continue
@@ -593,16 +607,12 @@ func (m *ClusterManager) shouldIncludeHTTPRoute(ctx context.Context, cluster *Cl
593607 }
594608
595609 if selector .Matches (labels .Set (gateway .Labels )) {
596- matchedGateway = true
597610 m .log .V (1 ).Info ("HTTPRoute matched gateway selector" , "cluster" , cluster .Name , "httproute" , httproute .Name , "gateway" , parentRef .Name , "namespace" , namespace , "labels" , gateway .Labels )
598611 return true , nil
599- } else {
600- m .log .V (1 ).Info ("Gateway labels did not match selector" , "cluster" , cluster .Name , "httproute" , httproute .Name , "gateway" , parentRef .Name , "namespace" , namespace , "gatewayLabels" , gateway .Labels , "selector" , gatewaySelector )
601612 }
613+ m .log .V (1 ).Info ("Gateway labels did not match selector" , "cluster" , cluster .Name , "httproute" , httproute .Name , "gateway" , parentRef .Name , "namespace" , namespace , "gatewayLabels" , gateway .Labels , "selector" , gatewaySelector )
602614 }
603- if ! matchedGateway {
604- m .log .V (1 ).Info ("HTTPRoute did not match any gateway" , "cluster" , cluster .Name , "httproute" , httproute .Name , "parentRefs" , len (httproute .Spec .ParentRefs ))
605- }
615+ m .log .V (1 ).Info ("HTTPRoute did not match any gateway" , "cluster" , cluster .Name , "httproute" , httproute .Name , "parentRefs" , len (httproute .Spec .ParentRefs ))
606616 return false , nil
607617 }
608618
@@ -733,3 +743,63 @@ func matchesDomain(host, filter string) bool {
733743 }
734744 return false
735745}
746+
747+ // mergeNamespaceAnnotationsForIngress merges namespace annotations into an Ingress resource
748+ // Namespace annotations serve as defaults, resource annotations override
749+ func (m * ClusterManager ) mergeNamespaceAnnotationsForIngress (ctx context.Context , clusterClient client.Client , ingress * networkingv1.Ingress ) {
750+ // Fetch the namespace from the appropriate cluster
751+ namespace := & corev1.Namespace {}
752+ if err := clusterClient .Get (ctx , client.ObjectKey {Name : ingress .Namespace }, namespace ); err != nil {
753+ // If we can't get the namespace, just continue with existing annotations
754+ m .log .V (2 ).Info ("Could not fetch namespace for ingress" , "namespace" , ingress .Namespace , "ingress" , ingress .Name , "error" , err )
755+ return
756+ }
757+
758+ // Merge namespace annotations (namespace defaults, resource overrides)
759+ if ingress .Annotations == nil {
760+ ingress .Annotations = make (map [string ]string )
761+ }
762+
763+ // First, apply namespace annotations as defaults (only if not already set)
764+ for key , value := range namespace .Annotations {
765+ if len (key ) > len (serviceAnnotationPrefix ) && key [:len (serviceAnnotationPrefix )] == serviceAnnotationPrefix {
766+ if _ , exists := ingress .Annotations [key ]; ! exists {
767+ ingress .Annotations [key ] = value
768+ }
769+ } else if len (key ) > len (itemAnnotationPrefix ) && key [:len (itemAnnotationPrefix )] == itemAnnotationPrefix {
770+ if _ , exists := ingress .Annotations [key ]; ! exists {
771+ ingress .Annotations [key ] = value
772+ }
773+ }
774+ }
775+ }
776+
777+ // mergeNamespaceAnnotationsForHTTPRoute merges namespace annotations into an HTTPRoute resource
778+ // Namespace annotations serve as defaults, resource annotations override
779+ func (m * ClusterManager ) mergeNamespaceAnnotationsForHTTPRoute (ctx context.Context , clusterClient client.Client , httproute * gatewayv1.HTTPRoute ) {
780+ // Fetch the namespace from the appropriate cluster
781+ namespace := & corev1.Namespace {}
782+ if err := clusterClient .Get (ctx , client.ObjectKey {Name : httproute .Namespace }, namespace ); err != nil {
783+ // If we can't get the namespace, just continue with existing annotations
784+ m .log .V (2 ).Info ("Could not fetch namespace for httproute" , "namespace" , httproute .Namespace , "httproute" , httproute .Name , "error" , err )
785+ return
786+ }
787+
788+ // Merge namespace annotations (namespace defaults, resource overrides)
789+ if httproute .Annotations == nil {
790+ httproute .Annotations = make (map [string ]string )
791+ }
792+
793+ // First, apply namespace annotations as defaults (only if not already set)
794+ for key , value := range namespace .Annotations {
795+ if len (key ) > len (serviceAnnotationPrefix ) && key [:len (serviceAnnotationPrefix )] == serviceAnnotationPrefix {
796+ if _ , exists := httproute .Annotations [key ]; ! exists {
797+ httproute .Annotations [key ] = value
798+ }
799+ } else if len (key ) > len (itemAnnotationPrefix ) && key [:len (itemAnnotationPrefix )] == itemAnnotationPrefix {
800+ if _ , exists := httproute .Annotations [key ]; ! exists {
801+ httproute .Annotations [key ] = value
802+ }
803+ }
804+ }
805+ }
0 commit comments