diff --git a/cmd/kor/root.go b/cmd/kor/root.go index fa99d12e..b68d9057 100644 --- a/cmd/kor/root.go +++ b/cmd/kor/root.go @@ -3,6 +3,7 @@ package kor import ( "fmt" "os" + "strings" "github.com/spf13/cobra" "github.com/yonahd/kor/pkg/kor" @@ -15,6 +16,20 @@ var rootCmd = &cobra.Command{ kor can currently discover unused configmaps and secrets`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { + resourceNames := args[0] + + // Cheks whether the string contains a comma, indicating that it represents a list of resources + if strings.ContainsRune(resourceNames, 44) { + if outputFormat == "json" || outputFormat == "yaml" { + if response, err := kor.GetUnusedMultiStructured(includeExcludeLists, kubeconfig, outputFormat, resourceNames); err != nil { + fmt.Println(err) + } else { + fmt.Println(response) + } + } else { + kor.GetUnusedMulti(includeExcludeLists, kubeconfig, resourceNames) + } + } }, } diff --git a/pkg/kor/multi.go b/pkg/kor/multi.go new file mode 100644 index 00000000..c06f95ff --- /dev/null +++ b/pkg/kor/multi.go @@ -0,0 +1,108 @@ +package kor + +import ( + "encoding/json" + "fmt" + "strings" + + "k8s.io/client-go/kubernetes" + "sigs.k8s.io/yaml" +) + +func retrieveNamespaceDiffs(kubeClient *kubernetes.Clientset, namespace string, resourceList []string) []ResourceDiff { + var allDiffs []ResourceDiff + for _, resource := range resourceList { + switch resource { + case "cm", "configmap": + namespaceCMDiff := getUnusedCMs(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceCMDiff) + case "svc", "service", "services": + namespaceSVCDiff := getUnusedSVCs(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceSVCDiff) + case "scrt", "secret": + namespaceSecretDiff := getUnusedSecrets(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceSecretDiff) + case "sa", "serviceaccount": + namespaceSADiff := getUnusedServiceAccounts(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceSADiff) + case "deploy", "deployments": + namespaceDeploymentDiff := getUnusedDeployments(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceDeploymentDiff) + case "sts", "statefulsets": + namespaceStatefulsetDiff := getUnusedStatefulsets(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceStatefulsetDiff) + case "role": + namespaceRoleDiff := getUnusedRoles(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceRoleDiff) + case "hpa": + namespaceHpaDiff := getUnusedHpas(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceHpaDiff) + case "pvc": + namespacePvcDiff := getUnusedPvcs(kubeClient, namespace) + allDiffs = append(allDiffs, namespacePvcDiff) + case "ing", "ingress": + namespaceIngressDiff := getUnusedIngresses(kubeClient, namespace) + allDiffs = append(allDiffs, namespaceIngressDiff) + case "pdb": + namespacePdbDiff := getUnusedPdbs(kubeClient, namespace) + allDiffs = append(allDiffs, namespacePdbDiff) + } + } + return allDiffs +} + +func GetUnusedMulti(includeExcludeLists IncludeExcludeLists, kubeconfig, resourceNames string) { + var kubeClient *kubernetes.Clientset + var namespaces []string + + kubeClient = GetKubeClient(kubeconfig) + + resourceList := strings.Split(resourceNames, ",") + namespaces = SetNamespaceList(includeExcludeLists, kubeClient) + + for _, namespace := range namespaces { + allDiffs := retrieveNamespaceDiffs(kubeClient, namespace, resourceList) + output := FormatOutputAll(namespace, allDiffs) + fmt.Println(output) + fmt.Println() + } +} + +func GetUnusedMultiStructured(includeExcludeLists IncludeExcludeLists, kubeconfig, outputFormat, resourceNames string) (string, error) { + var kubeClient *kubernetes.Clientset + var namespaces []string + + kubeClient = GetKubeClient(kubeconfig) + + resourceList := strings.Split(resourceNames, ",") + namespaces = SetNamespaceList(includeExcludeLists, kubeClient) + + // Create the JSON response object + response := make(map[string]map[string][]string) + + for _, namespace := range namespaces { + allDiffs := retrieveNamespaceDiffs(kubeClient, namespace, resourceList) + // Store the unused resources for each resource type in the JSON response + resourceMap := make(map[string][]string) + for _, diff := range allDiffs { + resourceMap[diff.resourceType] = diff.diff + } + response[namespace] = resourceMap + } + + // Convert the response object to JSON + jsonResponse, err := json.MarshalIndent(response, "", " ") + if err != nil { + return "", err + } + + if outputFormat == "yaml" { + yamlResponse, err := yaml.JSONToYAML(jsonResponse) + if err != nil { + fmt.Printf("err: %v\n", err) + } + return string(yamlResponse), nil + } else { + return string(jsonResponse), nil + } +}