@@ -317,6 +317,363 @@ func TestExtractResourceListFromReading(t *testing.T) {
317317 }
318318}
319319
320+ // TestConvertDataReadings_ConfigMaps tests that configmaps are correctly converted.
321+ func TestConvertDataReadings_ConfigMaps (t * testing.T ) {
322+ extractorFunctions := map [string ]func (* api.DataReading , * dataupload.Snapshot ) error {
323+ "ark/discovery" : extractClusterIDAndServerVersionFromReading ,
324+ "ark/configmaps" : func (reading * api.DataReading , snapshot * dataupload.Snapshot ) error {
325+ return extractResourceListFromReading (reading , & snapshot .ConfigMaps )
326+ },
327+ }
328+
329+ readings := []* api.DataReading {
330+ {
331+ DataGatherer : "ark/discovery" ,
332+ Data : & api.DiscoveryData {
333+ ClusterID : "test-cluster-id" ,
334+ ServerVersion : & version.Info {
335+ GitVersion : "v1.21.0" ,
336+ },
337+ },
338+ },
339+ {
340+ DataGatherer : "ark/configmaps" ,
341+ Data : & api.DynamicData {
342+ Items : []* api.GatheredResource {
343+ {
344+ Resource : & unstructured.Unstructured {
345+ Object : map [string ]any {
346+ "apiVersion" : "v1" ,
347+ "kind" : "ConfigMap" ,
348+ "metadata" : map [string ]any {
349+ "name" : "conjur-connect" ,
350+ "namespace" : "conjur" ,
351+ "labels" : map [string ]any {
352+ "conjur.org/name" : "conjur-connect-configmap" ,
353+ },
354+ },
355+ "data" : map [string ]any {
356+ "config.yaml" : "some-config-data" ,
357+ },
358+ },
359+ },
360+ },
361+ {
362+ Resource : & unstructured.Unstructured {
363+ Object : map [string ]any {
364+ "apiVersion" : "v1" ,
365+ "kind" : "ConfigMap" ,
366+ "metadata" : map [string ]any {
367+ "name" : "another-configmap" ,
368+ "namespace" : "default" ,
369+ "labels" : map [string ]any {
370+ "conjur.org/name" : "conjur-connect-configmap" ,
371+ },
372+ },
373+ "data" : map [string ]any {
374+ "setting" : "value" ,
375+ },
376+ },
377+ },
378+ },
379+ // Deleted configmap should be ignored
380+ {
381+ DeletedAt : api.Time {Time : time .Now ()},
382+ Resource : & unstructured.Unstructured {
383+ Object : map [string ]any {
384+ "apiVersion" : "v1" ,
385+ "kind" : "ConfigMap" ,
386+ "metadata" : map [string ]any {
387+ "name" : "deleted-configmap" ,
388+ "namespace" : "default" ,
389+ },
390+ },
391+ },
392+ },
393+ },
394+ },
395+ },
396+ }
397+
398+ var snapshot dataupload.Snapshot
399+ err := convertDataReadings (extractorFunctions , readings , & snapshot )
400+ require .NoError (t , err )
401+
402+ // Verify the snapshot contains the expected data
403+ assert .Equal (t , "test-cluster-id" , snapshot .ClusterID )
404+ assert .Equal (t , "v1.21.0" , snapshot .K8SVersion )
405+ require .Len (t , snapshot .ConfigMaps , 2 , "should have 2 configmaps (deleted one should be excluded)" )
406+
407+ // Verify the first configmap
408+ cm1 , ok := snapshot .ConfigMaps [0 ].(* unstructured.Unstructured )
409+ require .True (t , ok , "configmap should be unstructured" )
410+ assert .Equal (t , "ConfigMap" , cm1 .GetKind ())
411+ assert .Equal (t , "conjur-connect" , cm1 .GetName ())
412+ assert .Equal (t , "conjur" , cm1 .GetNamespace ())
413+
414+ // Verify the second configmap
415+ cm2 , ok := snapshot .ConfigMaps [1 ].(* unstructured.Unstructured )
416+ require .True (t , ok , "configmap should be unstructured" )
417+ assert .Equal (t , "ConfigMap" , cm2 .GetKind ())
418+ assert .Equal (t , "another-configmap" , cm2 .GetName ())
419+ assert .Equal (t , "default" , cm2 .GetNamespace ())
420+ }
421+
422+ // TestConvertDataReadings_ServiceAccounts tests that serviceaccounts are correctly converted.
423+ func TestConvertDataReadings_ServiceAccounts (t * testing.T ) {
424+ extractorFunctions := map [string ]func (* api.DataReading , * dataupload.Snapshot ) error {
425+ "ark/discovery" : extractClusterIDAndServerVersionFromReading ,
426+ "ark/serviceaccounts" : func (reading * api.DataReading , snapshot * dataupload.Snapshot ) error {
427+ return extractResourceListFromReading (reading , & snapshot .ServiceAccounts )
428+ },
429+ }
430+
431+ readings := []* api.DataReading {
432+ {
433+ DataGatherer : "ark/discovery" ,
434+ Data : & api.DiscoveryData {
435+ ClusterID : "test-cluster-id" ,
436+ ServerVersion : & version.Info {
437+ GitVersion : "v1.22.0" ,
438+ },
439+ },
440+ },
441+ {
442+ DataGatherer : "ark/serviceaccounts" ,
443+ Data : & api.DynamicData {
444+ Items : []* api.GatheredResource {
445+ {
446+ Resource : & unstructured.Unstructured {
447+ Object : map [string ]any {
448+ "apiVersion" : "v1" ,
449+ "kind" : "ServiceAccount" ,
450+ "metadata" : map [string ]any {
451+ "name" : "default" ,
452+ "namespace" : "default" ,
453+ },
454+ },
455+ },
456+ },
457+ {
458+ Resource : & unstructured.Unstructured {
459+ Object : map [string ]any {
460+ "apiVersion" : "v1" ,
461+ "kind" : "ServiceAccount" ,
462+ "metadata" : map [string ]any {
463+ "name" : "app-sa" ,
464+ "namespace" : "production" ,
465+ "labels" : map [string ]any {
466+ "app" : "myapp" ,
467+ },
468+ },
469+ },
470+ },
471+ },
472+ },
473+ },
474+ },
475+ }
476+
477+ var snapshot dataupload.Snapshot
478+ err := convertDataReadings (extractorFunctions , readings , & snapshot )
479+ require .NoError (t , err )
480+
481+ assert .Equal (t , "test-cluster-id" , snapshot .ClusterID )
482+ assert .Equal (t , "v1.22.0" , snapshot .K8SVersion )
483+ require .Len (t , snapshot .ServiceAccounts , 2 )
484+
485+ sa1 , ok := snapshot .ServiceAccounts [0 ].(* unstructured.Unstructured )
486+ require .True (t , ok )
487+ assert .Equal (t , "ServiceAccount" , sa1 .GetKind ())
488+ assert .Equal (t , "default" , sa1 .GetName ())
489+ }
490+
491+ // TestConvertDataReadings_Roles tests that roles are correctly converted.
492+ func TestConvertDataReadings_Roles (t * testing.T ) {
493+ extractorFunctions := map [string ]func (* api.DataReading , * dataupload.Snapshot ) error {
494+ "ark/discovery" : extractClusterIDAndServerVersionFromReading ,
495+ "ark/roles" : func (reading * api.DataReading , snapshot * dataupload.Snapshot ) error {
496+ return extractResourceListFromReading (reading , & snapshot .Roles )
497+ },
498+ }
499+
500+ readings := []* api.DataReading {
501+ {
502+ DataGatherer : "ark/discovery" ,
503+ Data : & api.DiscoveryData {
504+ ClusterID : "rbac-cluster" ,
505+ ServerVersion : & version.Info {
506+ GitVersion : "v1.23.0" ,
507+ },
508+ },
509+ },
510+ {
511+ DataGatherer : "ark/roles" ,
512+ Data : & api.DynamicData {
513+ Items : []* api.GatheredResource {
514+ {
515+ Resource : & unstructured.Unstructured {
516+ Object : map [string ]any {
517+ "apiVersion" : "rbac.authorization.k8s.io/v1" ,
518+ "kind" : "Role" ,
519+ "metadata" : map [string ]any {
520+ "name" : "pod-reader" ,
521+ "namespace" : "default" ,
522+ "labels" : map [string ]any {
523+ "rbac.authorization.k8s.io/aggregate-to-view" : "true" ,
524+ },
525+ },
526+ "rules" : []any {
527+ map [string ]any {
528+ "apiGroups" : []any {"" },
529+ "resources" : []any {"pods" },
530+ "verbs" : []any {"get" , "list" },
531+ },
532+ },
533+ },
534+ },
535+ },
536+ // Deleted role should be excluded
537+ {
538+ DeletedAt : api.Time {Time : time .Now ()},
539+ Resource : & unstructured.Unstructured {
540+ Object : map [string ]any {
541+ "apiVersion" : "rbac.authorization.k8s.io/v1" ,
542+ "kind" : "Role" ,
543+ "metadata" : map [string ]any {
544+ "name" : "deleted-role" ,
545+ "namespace" : "default" ,
546+ },
547+ },
548+ },
549+ },
550+ },
551+ },
552+ },
553+ }
554+
555+ var snapshot dataupload.Snapshot
556+ err := convertDataReadings (extractorFunctions , readings , & snapshot )
557+ require .NoError (t , err )
558+
559+ assert .Equal (t , "rbac-cluster" , snapshot .ClusterID )
560+ require .Len (t , snapshot .Roles , 1 , "deleted role should be excluded" )
561+
562+ role , ok := snapshot .Roles [0 ].(* unstructured.Unstructured )
563+ require .True (t , ok )
564+ assert .Equal (t , "Role" , role .GetKind ())
565+ assert .Equal (t , "pod-reader" , role .GetName ())
566+ }
567+
568+ // TestConvertDataReadings_MultipleResources tests conversion with multiple resource types.
569+ func TestConvertDataReadings_MultipleResources (t * testing.T ) {
570+ extractorFunctions := map [string ]func (* api.DataReading , * dataupload.Snapshot ) error {
571+ "ark/discovery" : extractClusterIDAndServerVersionFromReading ,
572+ "ark/configmaps" : func (reading * api.DataReading , snapshot * dataupload.Snapshot ) error {
573+ return extractResourceListFromReading (reading , & snapshot .ConfigMaps )
574+ },
575+ "ark/serviceaccounts" : func (reading * api.DataReading , snapshot * dataupload.Snapshot ) error {
576+ return extractResourceListFromReading (reading , & snapshot .ServiceAccounts )
577+ },
578+ "ark/deployments" : func (reading * api.DataReading , snapshot * dataupload.Snapshot ) error {
579+ return extractResourceListFromReading (reading , & snapshot .Deployments )
580+ },
581+ }
582+
583+ readings := []* api.DataReading {
584+ {
585+ DataGatherer : "ark/discovery" ,
586+ Data : & api.DiscoveryData {
587+ ClusterID : "multi-resource-cluster" ,
588+ ServerVersion : & version.Info {
589+ GitVersion : "v1.24.0" ,
590+ },
591+ },
592+ },
593+ {
594+ DataGatherer : "ark/configmaps" ,
595+ Data : & api.DynamicData {
596+ Items : []* api.GatheredResource {
597+ {
598+ Resource : & unstructured.Unstructured {
599+ Object : map [string ]any {
600+ "apiVersion" : "v1" ,
601+ "kind" : "ConfigMap" ,
602+ "metadata" : map [string ]any {
603+ "name" : "app-config" ,
604+ "namespace" : "default" ,
605+ },
606+ },
607+ },
608+ },
609+ },
610+ },
611+ },
612+ {
613+ DataGatherer : "ark/serviceaccounts" ,
614+ Data : & api.DynamicData {
615+ Items : []* api.GatheredResource {
616+ {
617+ Resource : & unstructured.Unstructured {
618+ Object : map [string ]any {
619+ "apiVersion" : "v1" ,
620+ "kind" : "ServiceAccount" ,
621+ "metadata" : map [string ]any {
622+ "name" : "app-sa" ,
623+ "namespace" : "default" ,
624+ },
625+ },
626+ },
627+ },
628+ },
629+ },
630+ },
631+ {
632+ DataGatherer : "ark/deployments" ,
633+ Data : & api.DynamicData {
634+ Items : []* api.GatheredResource {
635+ {
636+ Resource : & unstructured.Unstructured {
637+ Object : map [string ]any {
638+ "apiVersion" : "apps/v1" ,
639+ "kind" : "Deployment" ,
640+ "metadata" : map [string ]any {
641+ "name" : "web-app" ,
642+ "namespace" : "default" ,
643+ },
644+ },
645+ },
646+ },
647+ },
648+ },
649+ },
650+ }
651+
652+ var snapshot dataupload.Snapshot
653+ err := convertDataReadings (extractorFunctions , readings , & snapshot )
654+ require .NoError (t , err )
655+
656+ // Verify all resources are present
657+ assert .Equal (t , "multi-resource-cluster" , snapshot .ClusterID )
658+ assert .Equal (t , "v1.24.0" , snapshot .K8SVersion )
659+ require .Len (t , snapshot .ConfigMaps , 1 )
660+ require .Len (t , snapshot .ServiceAccounts , 1 )
661+ require .Len (t , snapshot .Deployments , 1 )
662+
663+ // Verify each resource type
664+ cm , ok := snapshot .ConfigMaps [0 ].(* unstructured.Unstructured )
665+ require .True (t , ok )
666+ assert .Equal (t , "app-config" , cm .GetName ())
667+
668+ sa , ok := snapshot .ServiceAccounts [0 ].(* unstructured.Unstructured )
669+ require .True (t , ok )
670+ assert .Equal (t , "app-sa" , sa .GetName ())
671+
672+ deploy , ok := snapshot .Deployments [0 ].(* unstructured.Unstructured )
673+ require .True (t , ok )
674+ assert .Equal (t , "web-app" , deploy .GetName ())
675+ }
676+
320677// TestConvertDataReadings tests the convertDataReadings function.
321678func TestConvertDataReadings (t * testing.T ) {
322679 simpleExtractorFunctions := map [string ]func (* api.DataReading , * dataupload.Snapshot ) error {
0 commit comments