@@ -300,6 +300,34 @@ label-selectors:
300300 t .Errorf ("LabelSelectors does not match: got=%+v want=%+v" , got , want )
301301 }
302302}
303+ func TestUnmarshalDynamicConfig_ExclusionRegex (t * testing.T ) {
304+ // Verify that the per-gatherer excludeAnnotationKeysRegex and
305+ // excludeLabelKeysRegex fields are parsed from YAML.
306+ textCfg := `
307+ resource-type:
308+ version: v1
309+ resource: secrets
310+ excludeAnnotationKeysRegex:
311+ - '^openshift\.io.*$'
312+ - '^kapp\.k14s\.io/.*$'
313+ excludeLabelKeysRegex:
314+ - '^company\.com/employee-id$'
315+ `
316+ cfg := ConfigDynamic {}
317+ if err := yaml .Unmarshal ([]byte (textCfg ), & cfg ); err != nil {
318+ t .Fatalf ("unexpected error: %+v" , err )
319+ }
320+
321+ expectedAnnot := []string {`^openshift\.io.*$` , `^kapp\.k14s\.io/.*$` }
322+ expectedLabel := []string {`^company\.com/employee-id$` }
323+
324+ if got , expected := cfg .ExcludeAnnotationKeysRegex , expectedAnnot ; ! reflect .DeepEqual (got , expected ) {
325+ t .Errorf ("ExcludeAnnotationKeysRegex: got=%v want=%v" , got , expected )
326+ }
327+ if got , expected := cfg .ExcludeLabelKeysRegex , expectedLabel ; ! reflect .DeepEqual (got , expected ) {
328+ t .Errorf ("ExcludeLabelKeysRegex: got=%v want=%v" , got , expected )
329+ }
330+ }
303331
304332func TestConfigDynamicValidate (t * testing.T ) {
305333 tests := []struct {
@@ -345,6 +373,20 @@ func TestConfigDynamicValidate(t *testing.T) {
345373 },
346374 ExpectedError : "invalid field selector 0: invalid selector: 'foo'; can't understand 'foo'" ,
347375 },
376+ {
377+ Config : ConfigDynamic {
378+ GroupVersionResource : schema.GroupVersionResource {Version : "v1" , Resource : "secrets" },
379+ ExcludeAnnotationKeysRegex : []string {`^[0-9$` },
380+ },
381+ ExpectedError : "invalid excludeAnnotationKeysRegex[0]" ,
382+ },
383+ {
384+ Config : ConfigDynamic {
385+ GroupVersionResource : schema.GroupVersionResource {Version : "v1" , Resource : "secrets" },
386+ ExcludeLabelKeysRegex : []string {`^[0-9$` },
387+ },
388+ ExpectedError : "invalid excludeLabelKeysRegex[0]" ,
389+ },
348390 }
349391
350392 for _ , test := range tests {
@@ -763,6 +805,48 @@ func TestDynamicGatherer_Fetch(t *testing.T) {
763805 map [string ]any {"prod" : "true" },
764806 )}},
765807 },
808+ "per-gatherer excludeAnnotationKeysRegex excludes matching resources entirely" : {
809+ // Resources annotated with openshift.io/* should not appear in the
810+ // output at all, not just have those keys stripped.
811+ config : ConfigDynamic {
812+ GroupVersionResource : schema.GroupVersionResource {Group : "" , Version : "v1" , Resource : "secrets" },
813+ ExcludeAnnotationKeysRegex : []string {`^openshift\.io.*$` },
814+ },
815+ addObjects : []* unstructured.Unstructured {
816+ getObjectAnnot ("v1" , "Secret" , "excluded" , "ns" ,
817+ map [string ]any {"openshift.io/discovery" : "ignore" , "other" : "kept" },
818+ map [string ]any {},
819+ ),
820+ getObjectAnnot ("v1" , "Secret" , "included" , "ns" ,
821+ map [string ]any {"other" : "kept" },
822+ map [string ]any {},
823+ ),
824+ },
825+ expected : []* api.GatheredResource {{Resource : getObjectAnnot ("v1" , "Secret" , "included" , "ns" ,
826+ map [string ]any {"other" : "kept" },
827+ map [string ]any {},
828+ )}},
829+ },
830+ "per-gatherer excludeLabelKeysRegex excludes matching resources entirely" : {
831+ config : ConfigDynamic {
832+ GroupVersionResource : schema.GroupVersionResource {Group : "" , Version : "v1" , Resource : "secrets" },
833+ ExcludeLabelKeysRegex : []string {`^discovery\.venafi\.com/exclude$` },
834+ },
835+ addObjects : []* unstructured.Unstructured {
836+ getObjectAnnot ("v1" , "Secret" , "excluded" , "ns" ,
837+ map [string ]any {},
838+ map [string ]any {"discovery.venafi.com/exclude" : "true" , "other" : "kept" },
839+ ),
840+ getObjectAnnot ("v1" , "Secret" , "included" , "ns" ,
841+ map [string ]any {},
842+ map [string ]any {"other" : "kept" },
843+ ),
844+ },
845+ expected : []* api.GatheredResource {{Resource : getObjectAnnot ("v1" , "Secret" , "included" , "ns" ,
846+ map [string ]any {},
847+ map [string ]any {"other" : "kept" },
848+ )}},
849+ },
766850 }
767851
768852 for name , tc := range tests {
@@ -967,6 +1051,55 @@ func compareEncryptedData(t *testing.T, privKey *stdrsa.PrivateKey, got *unstruc
9671051 unstructured .RemoveNestedField (got .Object , encryptedDataFieldName )
9681052}
9691053
1054+ // TestExcludeAnnotKeys_ExcludesResourcesFromUpload verifies that resources
1055+ // whose annotation keys match ExcludeAnnotKeys are dropped entirely from
1056+ // Fetch() results, not just have those keys stripped.
1057+ func TestExcludeAnnotKeys_ExcludesResourcesFromUpload (t * testing.T ) {
1058+ ctx := t .Context ()
1059+
1060+ gvrToListKind := map [schema.GroupVersionResource ]string {
1061+ {Group : "" , Version : "v1" , Resource : "secrets" }: "UnstructuredList" ,
1062+ }
1063+
1064+ // "excluded" has a matching annotation key; "included" does not.
1065+ excluded := getObjectAnnot ("v1" , "Secret" , "excluded" , "ns" ,
1066+ map [string ]any {"openshift.io/discovery" : "ignore" },
1067+ map [string ]any {},
1068+ )
1069+ included := getObjectAnnot ("v1" , "Secret" , "included" , "ns" ,
1070+ map [string ]any {"other" : "kept" },
1071+ map [string ]any {},
1072+ )
1073+
1074+ cl := fake .NewSimpleDynamicClientWithCustomListKinds (
1075+ runtime .NewScheme (), gvrToListKind , excluded , included ,
1076+ )
1077+
1078+ cfg := ConfigDynamic {
1079+ GroupVersionResource : schema.GroupVersionResource {Group : "" , Version : "v1" , Resource : "secrets" },
1080+ }
1081+ dg , err := cfg .newDataGathererWithClient (ctx , cl , nil )
1082+ require .NoError (t , err )
1083+
1084+ dgd := dg .(* DataGathererDynamic )
1085+ dgd .ExcludeAnnotKeys = []* regexp.Regexp {regexp .MustCompile (`^openshift\.io/.*$` )}
1086+
1087+ go func () { _ = dg .Run (ctx ) }()
1088+ require .NoError (t , dgd .WaitForCacheSync (ctx ))
1089+
1090+ res , count , err := dg .Fetch (ctx )
1091+ require .NoError (t , err )
1092+
1093+ data , ok := res .(* api.DynamicData )
1094+ require .True (t , ok )
1095+
1096+ assert .Equal (t , 1 , count , "only the non-matching resource should be returned" )
1097+ if assert .Len (t , data .Items , 1 ) {
1098+ got := data .Items [0 ].Resource .(* unstructured.Unstructured )
1099+ assert .Equal (t , "included" , got .GetName (), "the resource with matching annotation key should be excluded" )
1100+ }
1101+ }
1102+
9701103func TestDynamicGathererNativeResources_Fetch (t * testing.T ) {
9711104 // start a k8s client
9721105 // init the datagatherer's informer with the client
0 commit comments