Repository: yonahd/kor (go)

Issue:
Filter flags are not working --older-than , --newer-than
**Describe the bug**
The filter options doesn't seem to work, no matter what pass using one of these 2 , I always get the same (all) resources `--older-than , --newer-than`

**To Reproduce**

```
./kor.exe replicaset --include-namespaces testing --show-reason --older-than=1000h
```

**Expected behavior**
show only the older replicasets

**OS version, architecture and kor version**
Windows



Pull request:
Fix: Add filters to replicasets
<!-- Please read [CONTRIBUTING.md](CONTRIBUTING.md) for additional information on contributing to this repository! -->

<!--
  !!!! README !!!! Please fill this out.

  Please follow conventional commit naming conventions:

  https://www.conventionalcommits.org/en/v1.0.0/#summary
-->

<!-- A short description of what your PR does and what it solves. -->

## What this PR does / why we need it?
This adds the filters to replicasets 

## PR Checklist

- [ ] This PR adds K8s exceptions (false positives)
- [x] This PR adds new code
- [ ] This PR includes tests for new/existing code
- [ ] This PR adds docs
<!-- - [ ] This PR does something else -->

## GitHub Issue

Closes #318 


Patch:
diff --git a/pkg/kor/clusterroles.go b/pkg/kor/clusterroles.go
index 8c2fbd4..ee3dd6d 100644
--- a/pkg/kor/clusterroles.go
+++ b/pkg/kor/clusterroles.go
@@ -44,9 +44,6 @@ func retrieveUsedClusterRoles(clientset kubernetes.Interface, filterOpts *filter
 	usedClusterRoles := make(map[string]bool)
 
 	for _, rb := range roleBindingsAllNameSpaces {
-		if pass, _ := filter.Run(filterOpts); pass {
-			continue
-		}
 		usedClusterRoles[rb.RoleRef.Name] = true
 		if rb.RoleRef.Kind == "ClusterRole" {
 			usedClusterRoles[rb.RoleRef.Name] = true
@@ -61,9 +58,6 @@ func retrieveUsedClusterRoles(clientset kubernetes.Interface, filterOpts *filter
 	}
 
 	for _, crb := range clusterRoleBindings.Items {
-		if pass, _ := filter.Run(filterOpts); pass {
-			continue
-		}
 		usedClusterRoles[crb.RoleRef.Name] = true
 	}
 
diff --git a/pkg/kor/finalizers.go b/pkg/kor/finalizers.go
index ac6cab5..7c80598 100644
--- a/pkg/kor/finalizers.go
+++ b/pkg/kor/finalizers.go
@@ -47,7 +47,7 @@ func retrievePendingDeletionResources(resourceTypes []*metav1.APIResourceList, d
 					continue
 				}
 				for _, item := range resourceList.Items {
-					if pass, _ := filter.Run(filterOpts); pass {
+					if pass, _ := filter.SetObject(&item).Run(filterOpts); pass {
 						continue
 					}
 					if CheckFinalizers(item.GetFinalizers(), item.GetDeletionTimestamp()) {
diff --git a/pkg/kor/formatter.go b/pkg/kor/formatter.go
index fdfd432..092593b 100644
--- a/pkg/kor/formatter.go
+++ b/pkg/kor/formatter.go
@@ -148,7 +148,7 @@ func formatOutputForResource(resource string, resources map[string][]ResourceInf
 		}
 	}
 	table.Render()
-	return fmt.Sprintf("Unused %ss:\n%s", resource, buf.String())
+	return fmt.Sprintf("Unused %ss:\n%s\n", resource, buf.String())
 }
 
 func appendResources(resources map[string]map[string][]ResourceInfo, resourceType, namespace string, diff []ResourceInfo) {
diff --git a/pkg/kor/ingresses.go b/pkg/kor/ingresses.go
index 47dba18..f73b070 100644
--- a/pkg/kor/ingresses.go
+++ b/pkg/kor/ingresses.go
@@ -36,7 +36,7 @@ func retrieveUsedIngress(clientset kubernetes.Interface, namespace string, filte
 	usedIngresses := []string{}
 
 	for _, ingress := range ingresses.Items {
-		if pass, _ := filter.Run(filterOpts); pass {
+		if pass, _ := filter.SetObject(&ingress).Run(filterOpts); pass {
 			continue
 		}
 
diff --git a/pkg/kor/multi.go b/pkg/kor/multi.go
index fcf1651..2d29c0e 100644
--- a/pkg/kor/multi.go
+++ b/pkg/kor/multi.go
@@ -97,64 +97,62 @@ func retrieveNamespaceDiffs(clientset kubernetes.Interface, namespace string, re
 }
 
 func GetUnusedMulti(resourceNames string, filterOpts *filters.Options, clientset kubernetes.Interface, apiExtClient apiextensionsclientset.Interface, dynamicClient dynamic.Interface, outputFormat string, opts Opts) (string, error) {
-	var allDiffs []ResourceDiff
-	var outputBuffer bytes.Buffer
-	var unusedMulti string
 	resourceList := strings.Split(resourceNames, ",")
 	namespaces := filterOpts.Namespaces(clientset)
-	response := make(map[string]map[string][]ResourceInfo)
+	resources := make(map[string]map[string][]ResourceInfo)
 	var err error
 
 	noNamespaceDiff, resourceList := retrieveNoNamespaceDiff(clientset, apiExtClient, dynamicClient, resourceList, filterOpts)
 	if len(noNamespaceDiff) != 0 {
 		for _, diff := range noNamespaceDiff {
 			if len(diff.diff) != 0 {
-				output := FormatOutputAll("", []ResourceDiff{diff}, opts)
-				outputBuffer.WriteString(output)
-
-				resourceMap := make(map[string][]ResourceInfo)
-				resourceMap[diff.resourceType] = diff.diff
-				response[""] = resourceMap
+				if opts.DeleteFlag {
+					if diff.diff, err = DeleteResource(diff.diff, clientset, "", diff.resourceType, opts.NoInteractive); err != nil {
+						fmt.Fprintf(os.Stderr, "Failed to delete %s %s: %v\n", diff.resourceType, diff.diff, err)
+					}
+				}
+				switch opts.GroupBy {
+				case "namespace":
+					resources[""] = make(map[string][]ResourceInfo)
+					resources[""][diff.resourceType] = diff.diff
+				case "resource":
+					appendResources(resources, diff.resourceType, "", diff.diff)
+				}
 			}
 		}
-
-		resourceMap := make(map[string][]ResourceInfo)
-		for _, diff := range noNamespaceDiff {
-			resourceMap[diff.resourceType] = diff.diff
-		}
-		response[""] = resourceMap
-
 	}
 
 	for _, namespace := range namespaces {
-		allDiffs = retrieveNamespaceDiffs(clientset, namespace, resourceList, filterOpts)
-
-		if opts.DeleteFlag {
-			for _, diff := range allDiffs {
+		allDiffs := retrieveNamespaceDiffs(clientset, namespace, resourceList, filterOpts)
+		for _, diff := range allDiffs {
+			if opts.DeleteFlag {
 				if diff.diff, err = DeleteResource(diff.diff, clientset, namespace, diff.resourceType, opts.NoInteractive); err != nil {
 					fmt.Fprintf(os.Stderr, "Failed to delete %s %s in namespace %s: %v\n", diff.resourceType, diff.diff, namespace, err)
 				}
 			}
-
-		}
-		output := FormatOutputAll(namespace, allDiffs, opts)
-		if output != "" {
-			outputBuffer.WriteString(output)
-
-			resourceMap := make(map[string][]ResourceInfo)
-			for _, diff := range allDiffs {
-				resourceMap[diff.resourceType] = diff.diff
+			switch opts.GroupBy {
+			case "namespace":
+				resources[namespace] = make(map[string][]ResourceInfo)
+				resources[namespace][diff.resourceType] = diff.diff
+			case "resource":
+				appendResources(resources, diff.resourceType, namespace, diff.diff)
 			}
-			response[namespace] = resourceMap
 		}
 	}
 
-	jsonResponse, err := json.MarshalIndent(response, "", "  ")
-	if err != nil {
-		return "", err
+	var outputBuffer bytes.Buffer
+	var jsonResponse []byte
+	switch outputFormat {
+	case "table":
+		outputBuffer = FormatOutput(resources, opts)
+	case "json", "yaml":
+		var err error
+		if jsonResponse, err = json.MarshalIndent(resources, "", "  "); err != nil {
+			return "", err
+		}
 	}
 
-	unusedMulti, err = unusedResourceFormatter(outputFormat, outputBuffer, opts, jsonResponse)
+	unusedMulti, err := unusedResourceFormatter(outputFormat, outputBuffer, opts, jsonResponse)
 	if err != nil {
 		fmt.Printf("err: %v\n", err)
 	}
diff --git a/pkg/kor/replicaset.go b/pkg/kor/replicaset.go
index 6040be4..1dab798 100644
--- a/pkg/kor/replicaset.go
+++ b/pkg/kor/replicaset.go
@@ -22,7 +22,7 @@ func processNamespaceReplicaSets(clientset kubernetes.Interface, namespace strin
 	var unusedReplicaSetNames []ResourceInfo
 
 	for _, replicaSet := range replicaSetList.Items {
-		if pass, _ := filter.Run(filterOpts); pass {
+		if pass, _ := filter.SetObject(&replicaSet).Run(filterOpts); pass {
 			continue
 		}
 
diff --git a/pkg/kor/roles.go b/pkg/kor/roles.go
index 638ed71..3fe837a 100644
--- a/pkg/kor/roles.go
+++ b/pkg/kor/roles.go
@@ -18,7 +18,7 @@ import (
 //go:embed exceptions/roles/roles.json
 var rolesConfig []byte
 
-func retrieveUsedRoles(clientset kubernetes.Interface, namespace string, filterOpts *filters.Options) ([]string, error) {
+func retrieveUsedRoles(clientset kubernetes.Interface, namespace string) ([]string, error) {
 	// Get a list of all role bindings in the specified namespace
 	roleBindings, err := clientset.RbacV1().RoleBindings(namespace).List(context.TODO(), metav1.ListOptions{})
 	if err != nil {
@@ -27,10 +27,6 @@ func retrieveUsedRoles(clientset kubernetes.Interface, namespace string, filterO
 
 	usedRoles := make(map[string]bool)
 	for _, rb := range roleBindings.Items {
-		if pass, _ := filter.Run(filterOpts); pass {
-			continue
-		}
-
 		usedRoles[rb.RoleRef.Name] = true
 	}
 
@@ -78,7 +74,7 @@ func retrieveRoleNames(clientset kubernetes.Interface, namespace string, filterO
 }
 
 func processNamespaceRoles(clientset kubernetes.Interface, namespace string, filterOpts *filters.Options) ([]ResourceInfo, error) {
-	usedRoles, err := retrieveUsedRoles(clientset, namespace, filterOpts)
+	usedRoles, err := retrieveUsedRoles(clientset, namespace)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/kor/services.go b/pkg/kor/services.go
index 4efc1ca..13e0903 100644
--- a/pkg/kor/services.go
+++ b/pkg/kor/services.go
@@ -31,7 +31,7 @@ func processNamespaceServices(clientset kubernetes.Interface, namespace string,
 	var endpointsWithoutSubsets []ResourceInfo
 
 	for _, endpoints := range endpointsList.Items {
-		if pass, _ := filter.Run(filterOpts); pass {
+		if pass, _ := filter.SetObject(&endpoints).Run(filterOpts); pass {
 			continue
 		}
 
diff --git a/pkg/kor/statefulsets.go b/pkg/kor/statefulsets.go
index 29b86ef..0bc8841 100644
--- a/pkg/kor/statefulsets.go
+++ b/pkg/kor/statefulsets.go
@@ -22,7 +22,7 @@ func processNamespaceStatefulSets(clientset kubernetes.Interface, namespace stri
 	var statefulSetsWithoutReplicas []ResourceInfo
 
 	for _, statefulSet := range statefulSetsList.Items {
-		if pass, _ := filter.Run(filterOpts); pass {
+		if pass, _ := filter.SetObject(&statefulSet).Run(filterOpts); pass {
 			continue
 		}
 


Test patch:
diff --git a/pkg/kor/roles_test.go b/pkg/kor/roles_test.go
index b847f33..05143bf 100644
--- a/pkg/kor/roles_test.go
+++ b/pkg/kor/roles_test.go
@@ -63,7 +63,7 @@ func createTestRoles(t *testing.T) *fake.Clientset {
 func TestRetrieveUsedRoles(t *testing.T) {
 	clientset := createTestRoles(t)
 
-	usedRoles, err := retrieveUsedRoles(clientset, testNamespace, &filters.Options{})
+	usedRoles, err := retrieveUsedRoles(clientset, testNamespace)
 	if err != nil {
 		t.Errorf("Expected no error, got %v", err)
 	}