@@ -1405,6 +1405,30 @@ func TestMatchesLabelFilter(t *testing.T) {
14051405 excludeLabels : nil ,
14061406 expected : false ,
14071407 },
1408+ "case sensitive - include label key case mismatch" : {
1409+ resourceLabels : map [string ]string {"App" : "test" },
1410+ includeLabels : map [string ]string {"app" : "test" },
1411+ excludeLabels : nil ,
1412+ expected : false ,
1413+ },
1414+ "case sensitive - include label value case mismatch" : {
1415+ resourceLabels : map [string ]string {"app" : "Test" },
1416+ includeLabels : map [string ]string {"app" : "test" },
1417+ excludeLabels : nil ,
1418+ expected : false ,
1419+ },
1420+ "case sensitive - exclude label key case mismatch" : {
1421+ resourceLabels : map [string ]string {"App" : "prod" },
1422+ includeLabels : nil ,
1423+ excludeLabels : map [string ]string {"app" : "prod" },
1424+ expected : true ,
1425+ },
1426+ "case sensitive - exclude label value case mismatch" : {
1427+ resourceLabels : map [string ]string {"app" : "Prod" },
1428+ includeLabels : nil ,
1429+ excludeLabels : map [string ]string {"app" : "prod" },
1430+ expected : true ,
1431+ },
14081432 }
14091433
14101434 for name , tc := range tests {
@@ -1460,6 +1484,30 @@ func TestMatchesAnnotationFilter(t *testing.T) {
14601484 excludeAnnotations : map [string ]string {"deprecated" : "" },
14611485 expected : false ,
14621486 },
1487+ "case sensitive - include annotation key case mismatch" : {
1488+ resourceAnnotations : map [string ]string {"Description" : "test" },
1489+ includeAnnotations : map [string ]string {"description" : "test" },
1490+ excludeAnnotations : nil ,
1491+ expected : false ,
1492+ },
1493+ "case sensitive - include annotation value case mismatch" : {
1494+ resourceAnnotations : map [string ]string {"description" : "Test" },
1495+ includeAnnotations : map [string ]string {"description" : "test" },
1496+ excludeAnnotations : nil ,
1497+ expected : false ,
1498+ },
1499+ "case sensitive - exclude annotation key case mismatch" : {
1500+ resourceAnnotations : map [string ]string {"Internal" : "true" },
1501+ includeAnnotations : nil ,
1502+ excludeAnnotations : map [string ]string {"internal" : "true" },
1503+ expected : true ,
1504+ },
1505+ "case sensitive - exclude annotation value case mismatch" : {
1506+ resourceAnnotations : map [string ]string {"internal" : "True" },
1507+ includeAnnotations : nil ,
1508+ excludeAnnotations : map [string ]string {"internal" : "true" },
1509+ expected : true ,
1510+ },
14631511 }
14641512
14651513 for name , tc := range tests {
@@ -1878,3 +1926,141 @@ func TestDynamicGatherer_Fetch_WithCombinedFilters(t *testing.T) {
18781926 })
18791927 }
18801928}
1929+
1930+ func TestDynamicGatherer_Fetch_WithLabelFilters_NativeResources (t * testing.T ) {
1931+ ctx := t .Context ()
1932+
1933+ tests := map [string ]struct {
1934+ config ConfigDynamic
1935+ addObjects []runtime.Object
1936+ expectedCount int
1937+ expectedNames []string
1938+ }{
1939+ "include labels on Pods - match by app label" : {
1940+ config : ConfigDynamic {
1941+ GroupVersionResource : schema.GroupVersionResource {Group : "" , Version : "v1" , Resource : "pods" },
1942+ IncludeResourcesByLabels : map [string ]string {"app" : "nginx" },
1943+ },
1944+ addObjects : []runtime.Object {
1945+ & corev1.Pod {
1946+ TypeMeta : metav1.TypeMeta {Kind : "Pod" , APIVersion : "v1" },
1947+ ObjectMeta : metav1.ObjectMeta {Name : "nginx-pod" , Namespace : "default" , UID : "uid-nginx" , Labels : map [string ]string {"app" : "nginx" }},
1948+ },
1949+ & corev1.Pod {
1950+ TypeMeta : metav1.TypeMeta {Kind : "Pod" , APIVersion : "v1" },
1951+ ObjectMeta : metav1.ObjectMeta {Name : "apache-pod" , Namespace : "default" , UID : "uid-apache" , Labels : map [string ]string {"app" : "apache" }},
1952+ },
1953+ & corev1.Pod {
1954+ TypeMeta : metav1.TypeMeta {Kind : "Pod" , APIVersion : "v1" },
1955+ ObjectMeta : metav1.ObjectMeta {Name : "no-label-pod" , Namespace : "default" , UID : "uid-no-label" },
1956+ },
1957+ },
1958+ expectedCount : 1 ,
1959+ expectedNames : []string {"nginx-pod" },
1960+ },
1961+ "exclude labels on Pods - exclude test environment" : {
1962+ config : ConfigDynamic {
1963+ GroupVersionResource : schema.GroupVersionResource {Group : "" , Version : "v1" , Resource : "pods" },
1964+ ExcludeResourcesByLabels : map [string ]string {"env" : "test" },
1965+ },
1966+ addObjects : []runtime.Object {
1967+ & corev1.Pod {
1968+ TypeMeta : metav1.TypeMeta {Kind : "Pod" , APIVersion : "v1" },
1969+ ObjectMeta : metav1.ObjectMeta {Name : "prod-pod" , Namespace : "default" , UID : "uid-prod" , Labels : map [string ]string {"env" : "prod" }},
1970+ },
1971+ & corev1.Pod {
1972+ TypeMeta : metav1.TypeMeta {Kind : "Pod" , APIVersion : "v1" },
1973+ ObjectMeta : metav1.ObjectMeta {Name : "test-pod" , Namespace : "default" , UID : "uid-test" , Labels : map [string ]string {"env" : "test" }},
1974+ },
1975+ },
1976+ expectedCount : 1 ,
1977+ expectedNames : []string {"prod-pod" },
1978+ },
1979+ "include labels on ConfigMaps - multiple label match" : {
1980+ config : ConfigDynamic {
1981+ GroupVersionResource : schema.GroupVersionResource {Group : "" , Version : "v1" , Resource : "configmaps" },
1982+ IncludeResourcesByLabels : map [string ]string {"app" : "web" , "tier" : "frontend" },
1983+ },
1984+ addObjects : []runtime.Object {
1985+ & corev1.ConfigMap {
1986+ TypeMeta : metav1.TypeMeta {Kind : "ConfigMap" , APIVersion : "v1" },
1987+ ObjectMeta : metav1.ObjectMeta {Name : "frontend-cm" , Namespace : "default" , UID : "uid-frontend" , Labels : map [string ]string {"app" : "web" , "tier" : "frontend" }},
1988+ },
1989+ & corev1.ConfigMap {
1990+ TypeMeta : metav1.TypeMeta {Kind : "ConfigMap" , APIVersion : "v1" },
1991+ ObjectMeta : metav1.ObjectMeta {Name : "backend-cm" , Namespace : "default" , UID : "uid-backend" , Labels : map [string ]string {"app" : "api" , "tier" : "backend" }},
1992+ },
1993+ & corev1.ConfigMap {
1994+ TypeMeta : metav1.TypeMeta {Kind : "ConfigMap" , APIVersion : "v1" },
1995+ ObjectMeta : metav1.ObjectMeta {Name : "partial-cm" , Namespace : "default" , UID : "uid-partial" , Labels : map [string ]string {"app" : "web" }},
1996+ },
1997+ },
1998+ expectedCount : 1 ,
1999+ expectedNames : []string {"frontend-cm" },
2000+ },
2001+ "exclude labels on ConfigMaps - exclude by key only" : {
2002+ config : ConfigDynamic {
2003+ GroupVersionResource : schema.GroupVersionResource {Group : "" , Version : "v1" , Resource : "configmaps" },
2004+ ExcludeResourcesByLabels : map [string ]string {"temporary" : "" },
2005+ },
2006+ addObjects : []runtime.Object {
2007+ & corev1.ConfigMap {
2008+ TypeMeta : metav1.TypeMeta {Kind : "ConfigMap" , APIVersion : "v1" },
2009+ ObjectMeta : metav1.ObjectMeta {Name : "app-config" , Namespace : "default" , UID : "uid-app-config" , Labels : map [string ]string {"app" : "myapp" }},
2010+ },
2011+ & corev1.ConfigMap {
2012+ TypeMeta : metav1.TypeMeta {Kind : "ConfigMap" , APIVersion : "v1" },
2013+ ObjectMeta : metav1.ObjectMeta {Name : "temp-config" , Namespace : "default" , UID : "uid-temp" , Labels : map [string ]string {"temporary" : "true" }},
2014+ },
2015+ },
2016+ expectedCount : 1 ,
2017+ expectedNames : []string {"app-config" },
2018+ },
2019+ }
2020+
2021+ for name , tc := range tests {
2022+ t .Run (name , func (t * testing.T ) {
2023+ clientset := fakeclientset .NewSimpleClientset (tc .addObjects ... )
2024+ dg , err := tc .config .newDataGathererWithClient (ctx , nil , clientset )
2025+ require .NoError (t , err )
2026+
2027+ dgd := dg .(* DataGathererDynamic )
2028+
2029+ // Start the data gatherer
2030+ go func () {
2031+ if err = dgd .Run (ctx ); err != nil {
2032+ t .Errorf ("unexpected client error: %+v" , err )
2033+ }
2034+ }()
2035+
2036+ err = dgd .WaitForCacheSync (ctx )
2037+ require .NoError (t , err )
2038+
2039+ // Give some time for the cache to populate
2040+ time .Sleep (200 * time .Millisecond )
2041+
2042+ data , count , err := dgd .Fetch ()
2043+ require .NoError (t , err )
2044+
2045+ assert .Equal (t , tc .expectedCount , count )
2046+
2047+ if len (tc .expectedNames ) > 0 {
2048+ dynamicData , ok := data .(* api.DynamicData )
2049+ require .True (t , ok , "data should be *api.DynamicData" )
2050+
2051+ actualNames := make ([]string , 0 , len (dynamicData .Items ))
2052+ for _ , item := range dynamicData .Items {
2053+ if ! item .DeletedAt .IsZero () {
2054+ continue
2055+ }
2056+ // For native resources, extract name from typed objects
2057+ if typedObj , ok := item .Resource .(metav1.Object ); ok {
2058+ actualNames = append (actualNames , typedObj .GetName ())
2059+ }
2060+ }
2061+
2062+ assert .ElementsMatch (t , tc .expectedNames , actualNames )
2063+ }
2064+ })
2065+ }
2066+ }
0 commit comments