From 8822778510bcd0ebc574e1994a484381915074aa Mon Sep 17 00:00:00 2001 From: Tsvetoslav Dimov <32335835+cecobask@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:49:33 +0100 Subject: [PATCH] refactor: map false minikube unused resources (#241) --- pkg/kor/clusterroles.go | 67 +++++++++++++++++++++++++++++++++++++++ pkg/kor/configmaps.go | 46 ++++++++++++++++++++++++--- pkg/kor/kor.go | 53 +++++++++++++++++++++++++++---- pkg/kor/secrets.go | 30 ++++++++++++++++-- pkg/kor/services.go | 11 ++++++- pkg/kor/storageclasses.go | 13 ++++++++ 6 files changed, 206 insertions(+), 14 deletions(-) diff --git a/pkg/kor/clusterroles.go b/pkg/kor/clusterroles.go index 14b71d8f..24c5783f 100644 --- a/pkg/kor/clusterroles.go +++ b/pkg/kor/clusterroles.go @@ -17,6 +17,69 @@ import ( "github.com/yonahd/kor/pkg/filters" ) +var exceptionClusterRoles = []ExceptionResource{ + { + ResourceName: "admin", + Namespace: "", + }, + { + ResourceName: "edit", + Namespace: "", + }, + { + ResourceName: "system:aggregate-to-admin", + Namespace: "", + }, + { + ResourceName: "system:aggregate-to-edit", + Namespace: "", + }, + { + ResourceName: "system:aggregate-to-view", + Namespace: "", + }, + { + ResourceName: "system:auth-delegator", + Namespace: "", + }, + { + ResourceName: "system:certificates.k8s.io:kube-apiserver-client-approver", + Namespace: "", + }, + { + ResourceName: "system:certificates.k8s.io:kube-apiserver-client-kubelet-approver", + Namespace: "", + }, + { + ResourceName: "system:certificates.k8s.io:kubelet-serving-approver", + Namespace: "", + }, + { + ResourceName: "system:certificates.k8s.io:legacy-unknown-approver", + Namespace: "", + }, + { + ResourceName: "system:heapster", + Namespace: "", + }, + { + ResourceName: "system:kube-aggregator", + Namespace: "", + }, + { + ResourceName: "system:kubelet-api-admin", + Namespace: "", + }, + { + ResourceName: "system:node-problem-detector", + Namespace: "", + }, + { + ResourceName: "view", + Namespace: "", + }, +} + func retrieveUsedClusterRoles(clientset kubernetes.Interface, filterOpts *filters.Options) ([]string, error) { //Get a list of all namespaces @@ -133,6 +196,10 @@ func retrieveClusterRoleNames(clientset kubernetes.Interface, filterOpts *filter continue } + if isResourceException(clusterRole.Name, "", exceptionClusterRoles) { + continue + } + names = append(names, clusterRole.Name) } return names, unusedClusterRoles, nil diff --git a/pkg/kor/configmaps.go b/pkg/kor/configmaps.go index d014aae8..ace803fb 100644 --- a/pkg/kor/configmaps.go +++ b/pkg/kor/configmaps.go @@ -14,9 +14,39 @@ import ( "github.com/yonahd/kor/pkg/filters" ) -var exceptionconfigmaps = []ExceptionResource{ - {ResourceName: "aws-auth", Namespace: "kube-system"}, - {ResourceName: "kube-root-ca.crt", Namespace: "*"}, +var exceptionConfigMaps = []ExceptionResource{ + { + ResourceName: "aws-auth", + Namespace: "kube-system", + }, + { + ResourceName: "kube-root-ca.crt", + Namespace: "*", + }, + { + ResourceName: "extension-apiserver-authentication", + Namespace: "kube-system", + }, + { + ResourceName: "kube-apiserver-legacy-service-account-token-tracking", + Namespace: "kube-system", + }, + { + ResourceName: "kubeadm-config", + Namespace: "kube-system", + }, + { + ResourceName: "kubelet-config", + Namespace: "kube-system", + }, + { + ResourceName: "kubernetes-dashboard-settings", + Namespace: "kubernetes-dashboard", + }, + { + ResourceName: "cluster-info", + Namespace: "kube-public", + }, } func retrieveUsedCM(clientset kubernetes.Interface, namespace string) ([]string, []string, []string, []string, []string, error) { @@ -75,7 +105,7 @@ func retrieveUsedCM(clientset kubernetes.Interface, namespace string) ([]string, } } - for _, resource := range exceptionconfigmaps { + for _, resource := range exceptionConfigMaps { if resource.Namespace == namespace || resource.Namespace == "*" { volumesCM = append(volumesCM, resource.ResourceName) } @@ -126,7 +156,13 @@ func processNamespaceCM(clientset kubernetes.Interface, namespace string, filter } var usedConfigMaps []string - slicesToAppend := [][]string{volumesCM, envCM, envFromCM, envFromContainerCM, envFromInitContainerCM} + slicesToAppend := [][]string{ + volumesCM, + envCM, + envFromCM, + envFromContainerCM, + envFromInitContainerCM, + } for _, slice := range slicesToAppend { usedConfigMaps = append(usedConfigMaps, slice...) diff --git a/pkg/kor/kor.go b/pkg/kor/kor.go index aead23fe..476bb9ef 100644 --- a/pkg/kor/kor.go +++ b/pkg/kor/kor.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "sort" + "strings" "github.com/olekukonko/tablewriter" apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" @@ -123,10 +124,16 @@ func FormatOutput(namespace string, resources []string, resourceType string, opt var buf bytes.Buffer table := tablewriter.NewWriter(&buf) - table.SetHeader([]string{"#", "Resource Name"}) + table.SetHeader([]string{ + "#", + "Resource Name", + }) for i, name := range resources { - table.Append([]string{fmt.Sprintf("%d", i+1), name}) + table.Append([]string{ + fmt.Sprintf("%d", i+1), + name, + }) } table.Render() @@ -138,7 +145,11 @@ func FormatOutputFromMap(namespace string, allDiffs map[string][]string, opts Op i := 0 var buf bytes.Buffer table := tablewriter.NewWriter(&buf) - table.SetHeader([]string{"#", "Resource Type", "Resource Name"}) + table.SetHeader([]string{ + "#", + "Resource Type", + "Resource Name", + }) // TODO parse resourceType, diff @@ -150,7 +161,11 @@ func FormatOutputFromMap(namespace string, allDiffs map[string][]string, opts Op allEmpty = false for _, val := range diff { - row := []string{fmt.Sprintf("%d", i+1), resourceType, val} + row := []string{ + fmt.Sprintf("%d", i+1), + resourceType, + val, + } table.Append(row) i += 1 } @@ -173,7 +188,11 @@ func FormatOutputAll(namespace string, allDiffs []ResourceDiff, opts Opts) strin i := 0 var buf bytes.Buffer table := tablewriter.NewWriter(&buf) - table.SetHeader([]string{"#", "Resource Type", "Resource Name"}) + table.SetHeader([]string{ + "#", + "Resource Type", + "Resource Name", + }) // TODO parse resourceType, diff @@ -185,7 +204,11 @@ func FormatOutputAll(namespace string, allDiffs []ResourceDiff, opts Opts) strin allEmpty = false for _, val := range data.diff { - row := []string{fmt.Sprintf("%d", i+1), data.resourceType, val} + row := []string{ + fmt.Sprintf("%d", i+1), + data.resourceType, + val, + } table.Append(row) i += 1 } @@ -245,3 +268,21 @@ func unusedResourceFormatter(outputFormat string, outputBuffer bytes.Buffer, opt } return string(jsonResponse), nil } + +func isResourceException(resourceName, namespace string, exceptions []ExceptionResource) bool { + var match bool + for _, e := range exceptions { + if e.ResourceName == resourceName && e.Namespace == namespace { + match = true + break + } + if strings.HasSuffix(e.ResourceName, "*") { + resourceNameMatched := strings.HasPrefix(resourceName, strings.TrimSuffix(e.ResourceName, "*")) + if resourceNameMatched && e.Namespace == namespace { + match = true + break + } + } + } + return match +} diff --git a/pkg/kor/secrets.go b/pkg/kor/secrets.go index 5943bad7..f5346bce 100644 --- a/pkg/kor/secrets.go +++ b/pkg/kor/secrets.go @@ -21,6 +21,25 @@ var exceptionSecretTypes = []string{ `kubernetes.io/service-account-token`, } +var exceptionSecrets = []ExceptionResource{ + { + ResourceName: "kubernetes-dashboard-certs", + Namespace: "kubernetes-dashboard", + }, + { + ResourceName: "kubernetes-dashboard-csrf", + Namespace: "kubernetes-dashboard", + }, + { + ResourceName: "kubernetes-dashboard-key-holder", + Namespace: "kubernetes-dashboard", + }, + { + ResourceName: "bootstrap-token-*", + Namespace: "kube-system", + }, +} + func retrieveIngressTLS(clientset kubernetes.Interface, namespace string) ([]string, error) { secretNames := make([]string, 0) ingressList, err := clientset.NetworkingV1().Ingresses(namespace).List(context.TODO(), metav1.ListOptions{}) @@ -121,7 +140,7 @@ func retrieveSecretNames(clientset kubernetes.Interface, namespace string, filte continue } - if !slices.Contains(exceptionSecretTypes, string(secret.Type)) { + if !slices.Contains(exceptionSecretTypes, string(secret.Type)) && !isResourceException(secret.Name, namespace, exceptionSecrets) { names = append(names, secret.Name) } } @@ -147,7 +166,14 @@ func processNamespaceSecret(clientset kubernetes.Interface, namespace string, fi } var usedSecrets []string - slicesToAppend := [][]string{envSecrets, envSecrets2, volumeSecrets, pullSecrets, tlsSecrets, initContainerEnvSecrets} + slicesToAppend := [][]string{ + envSecrets, + envSecrets2, + volumeSecrets, + pullSecrets, + tlsSecrets, + initContainerEnvSecrets, + } for _, slice := range slicesToAppend { usedSecrets = append(usedSecrets, slice...) diff --git a/pkg/kor/services.go b/pkg/kor/services.go index 1e73e440..be144e5e 100644 --- a/pkg/kor/services.go +++ b/pkg/kor/services.go @@ -13,6 +13,13 @@ import ( "github.com/yonahd/kor/pkg/filters" ) +var exceptionServices = []ExceptionResource{ + { + ResourceName: "k8s.io-minikube-hostpath", + Namespace: "kube-system", + }, +} + func ProcessNamespaceServices(clientset kubernetes.Interface, namespace string, filterOpts *filters.Options) ([]string, error) { endpointsList, err := clientset.CoreV1().Endpoints(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: filterOpts.IncludeLabels}) if err != nil { @@ -25,7 +32,9 @@ func ProcessNamespaceServices(clientset kubernetes.Interface, namespace string, if pass, _ := filter.Run(filterOpts); pass { continue } - + if isResourceException(endpoints.Name, namespace, exceptionServices) { + continue + } if endpoints.Labels["kor/used"] == "false" { endpointsWithoutSubsets = append(endpointsWithoutSubsets, endpoints.Name) continue diff --git a/pkg/kor/storageclasses.go b/pkg/kor/storageclasses.go index 82c0deea..906cb23f 100644 --- a/pkg/kor/storageclasses.go +++ b/pkg/kor/storageclasses.go @@ -14,6 +14,13 @@ import ( "github.com/yonahd/kor/pkg/filters" ) +var exceptionStorageClasses = []ExceptionResource{ + { + ResourceName: "standard", + Namespace: "", + }, +} + func retrieveUsedStorageClasses(clientset kubernetes.Interface) ([]string, error) { pvs, err := clientset.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{}) if err != nil { @@ -73,6 +80,12 @@ func processStorageClasses(clientset kubernetes.Interface, filterOpts *filters.O return nil, err } + for i, name := range storageClassNames { + if isResourceException(name, "", exceptionStorageClasses) { + storageClassNames = append(storageClassNames[:i], storageClassNames[i+1:]...) + } + } + diff := CalculateResourceDifference(usedStorageClasses, storageClassNames) diff = append(diff, unusedStorageClassNames...) return diff, nil