Skip to content

Commit

Permalink
feat: add delete flag (#120)
Browse files Browse the repository at this point in the history
* [wip] - still printing after resource deletion and missing other resources api call map

* [wip] - still printing after resource deletion and missing other resources api call map

* [wip] - still printing after resource deletion and missing other resources api call map

* [wip] - print deleted resource

* [wip] - fix some wrong naming

* [wip] - add DeleteResource test

* [wip] - fix tests

* finish up feature

* add deleteOpts to all resources

* fix: to lower PR review

* fix: opts PR review
  • Loading branch information
patricktalmeida authored Nov 3, 2023
1 parent d55b4a9 commit 5a55f44
Show file tree
Hide file tree
Showing 45 changed files with 431 additions and 222 deletions.
2 changes: 1 addition & 1 deletion cmd/kor/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var allCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedAll(includeExcludeLists,filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedAll(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/configmaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var configmapCmd = &cobra.Command{
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)
if response, err := kor.GetUnusedConfigmaps(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedConfigmaps(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var deployCmd = &cobra.Command{
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)
if response, err := kor.GetUnusedDeployments(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedDeployments(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var exporterCmd = &cobra.Command{
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)
kor.Exporter(includeExcludeLists, clientset, "json", slackOpts)
kor.Exporter(includeExcludeLists, clientset, "json", opts)

},
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/hpas.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var hpaCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedHpas(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedHpas(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/ingresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var ingressCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedIngresses(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedIngresses(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/pdbs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var pdbCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedPdbs(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedPdbs(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/pvc.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var pvcCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedPvcs(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedPvcs(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var roleCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedRoles(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedRoles(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
15 changes: 10 additions & 5 deletions cmd/kor/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var rootCmd = &cobra.Command{
fmt.Println(response)
}
} else {
kor.GetUnusedMulti(includeExcludeLists, kubeconfig, resourceNames, slackOpts)
kor.GetUnusedMulti(includeExcludeLists, kubeconfig, resourceNames, opts)
}
} else {
fmt.Printf("Subcommand %q was not found, try using 'kor --help' for available subcommands", args[0])
Expand All @@ -40,7 +40,7 @@ var (
outputFormat string
kubeconfig string
includeExcludeLists kor.IncludeExcludeLists
slackOpts kor.SlackOpts
opts kor.Opts
filterOptions = kor.NewFilterOptions()
)

Expand All @@ -50,9 +50,14 @@ func Execute() {
rootCmd.PersistentFlags().StringVarP(&includeExcludeLists.IncludeListStr, "include-namespaces", "n", "", "Namespaces to run on, splited by comma. Example: --include-namespace ns1,ns2,ns3. ")
rootCmd.PersistentFlags().StringVarP(&includeExcludeLists.ExcludeListStr, "exclude-namespaces", "e", "", "Namespaces to be excluded, splited by comma. Example: --exclude-namespace ns1,ns2,ns3. If --include-namespace is set, --exclude-namespaces will be ignored.")
rootCmd.PersistentFlags().StringVar(&outputFormat, "output", "table", "Output format (table, json or yaml)")
rootCmd.PersistentFlags().StringVar(&slackOpts.WebhookURL, "slack-webhook-url", "", "Slack webhook URL to send notifications to")
rootCmd.PersistentFlags().StringVar(&slackOpts.Channel, "slack-channel", "", "Slack channel to send notifications to. --slack-channel requires --slack-auth-token to be set.")
rootCmd.PersistentFlags().StringVar(&slackOpts.Token, "slack-auth-token", "", "Slack auth token to send notifications to. --slack-auth-token requires --slack-channel to be set.")
rootCmd.PersistentFlags().StringVar(&opts.WebhookURL, "slack-webhook-url", "", "Slack webhook URL to send notifications to")
rootCmd.PersistentFlags().StringVar(&opts.Channel, "slack-channel", "", "Slack channel to send notifications to. --slack-channel requires --slack-auth-token to be set.")
rootCmd.PersistentFlags().StringVar(&opts.Token, "slack-auth-token", "", "Slack auth token to send notifications to. --slack-auth-token requires --slack-channel to be set.")
rootCmd.PersistentFlags().BoolVar(&opts.DeleteFlag, "delete", false, "Delete unused resources")
rootCmd.PersistentFlags().BoolVar(&opts.NoInteractive, "no-interactive", false, "Do not prompt for confirmation when deleting resources. Be careful using this flag!")
rootCmd.PersistentFlags().StringVar(&opts.WebhookURL, "slack-webhook-url", "", "Slack webhook URL to send notifications to")
rootCmd.PersistentFlags().StringVar(&opts.Channel, "slack-channel", "", "Slack channel to send notifications to. --slack-channel requires --slack-auth-token to be set.")
rootCmd.PersistentFlags().StringVar(&opts.Token, "slack-auth-token", "", "Slack auth token to send notifications to. --slack-auth-token requires --slack-channel to be set.")
addFilterOptionsFlag(rootCmd, filterOptions)

if err := filterOptions.Validate(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var secretCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedSecrets(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedSecrets(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/serviceaccounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var serviceAccountCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedServiceAccounts(includeExcludeLists, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedServiceAccounts(includeExcludeLists, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var serviceCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedServices(includeExcludeLists, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedServices(includeExcludeLists, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kor/statefulsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var stsCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
clientset := kor.GetKubeClient(kubeconfig)

if response, err := kor.GetUnusedStatefulSets(includeExcludeLists, filterOptions, clientset, outputFormat, slackOpts); err != nil {
if response, err := kor.GetUnusedStatefulSets(includeExcludeLists, filterOptions, clientset, outputFormat, opts); err != nil {
fmt.Println(err)
} else {
fmt.Println(response)
Expand Down
58 changes: 29 additions & 29 deletions pkg/kor/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type ResourceDiff struct {
diff []string
}

func getUnusedCMs(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
cmDiff, err := processNamespaceCM(clientset, namespace, opts)
func getUnusedCMs(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
cmDiff, err := processNamespaceCM(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "configmaps", namespace, err)
}
Expand All @@ -37,8 +37,8 @@ func getUnusedSVCs(clientset kubernetes.Interface, namespace string) ResourceDif
return namespaceSVCDiff
}

func getUnusedSecrets(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
secretDiff, err := processNamespaceSecret(clientset, namespace, opts)
func getUnusedSecrets(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
secretDiff, err := processNamespaceSecret(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "secrets", namespace, err)
}
Expand All @@ -55,98 +55,98 @@ func getUnusedServiceAccounts(clientset kubernetes.Interface, namespace string)
return namespaceSADiff
}

func getUnusedDeployments(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
deployDiff, err := ProcessNamespaceDeployments(clientset, namespace, opts)
func getUnusedDeployments(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
deployDiff, err := ProcessNamespaceDeployments(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "deployments", namespace, err)
}
namespaceSADiff := ResourceDiff{"Deployment", deployDiff}
return namespaceSADiff
}

func getUnusedStatefulSets(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
stsDiff, err := ProcessNamespaceStatefulSets(clientset, namespace, opts)
func getUnusedStatefulSets(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
stsDiff, err := ProcessNamespaceStatefulSets(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "statefulSets", namespace, err)
}
namespaceSADiff := ResourceDiff{"StatefulSet", stsDiff}
return namespaceSADiff
}

func getUnusedRoles(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
roleDiff, err := processNamespaceRoles(clientset, namespace, opts)
func getUnusedRoles(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
roleDiff, err := processNamespaceRoles(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "roles", namespace, err)
}
namespaceSADiff := ResourceDiff{"Role", roleDiff}
return namespaceSADiff
}

func getUnusedHpas(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
hpaDiff, err := processNamespaceHpas(clientset, namespace, opts)
func getUnusedHpas(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
hpaDiff, err := processNamespaceHpas(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "hpas", namespace, err)
}
namespaceHpaDiff := ResourceDiff{"Hpa", hpaDiff}
return namespaceHpaDiff
}

func getUnusedPvcs(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
pvcDiff, err := processNamespacePvcs(clientset, namespace, opts)
func getUnusedPvcs(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
pvcDiff, err := processNamespacePvcs(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "pvcs", namespace, err)
}
namespacePvcDiff := ResourceDiff{"Pvc", pvcDiff}
return namespacePvcDiff
}

func getUnusedIngresses(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
ingressDiff, err := processNamespaceIngresses(clientset, namespace, opts)
func getUnusedIngresses(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
ingressDiff, err := processNamespaceIngresses(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "ingresses", namespace, err)
}
namespaceIngressDiff := ResourceDiff{"Ingress", ingressDiff}
return namespaceIngressDiff
}

func getUnusedPdbs(clientset kubernetes.Interface, namespace string, opts *FilterOptions) ResourceDiff {
pdbDiff, err := processNamespacePdbs(clientset, namespace, opts)
func getUnusedPdbs(clientset kubernetes.Interface, namespace string, filterOpts *FilterOptions) ResourceDiff {
pdbDiff, err := processNamespacePdbs(clientset, namespace, filterOpts)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", "pdbs", namespace, err)
}
namespacePdbDiff := ResourceDiff{"Pdb", pdbDiff}
return namespacePdbDiff
}

func GetUnusedAll(includeExcludeLists IncludeExcludeLists, opts *FilterOptions, clientset kubernetes.Interface, outputFormat string, slackOpts SlackOpts) (string, error) {
func GetUnusedAll(includeExcludeLists IncludeExcludeLists, filterOpts *FilterOptions, clientset kubernetes.Interface, outputFormat string, opts Opts) (string, error) {
var outputBuffer bytes.Buffer

namespaces := SetNamespaceList(includeExcludeLists, clientset)
response := make(map[string]map[string][]string)

for _, namespace := range namespaces {
var allDiffs []ResourceDiff
namespaceCMDiff := getUnusedCMs(clientset, namespace, opts)
namespaceCMDiff := getUnusedCMs(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespaceCMDiff)
namespaceSVCDiff := getUnusedSVCs(clientset, namespace)
allDiffs = append(allDiffs, namespaceSVCDiff)
namespaceSecretDiff := getUnusedSecrets(clientset, namespace, opts)
namespaceSecretDiff := getUnusedSecrets(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespaceSecretDiff)
namespaceSADiff := getUnusedServiceAccounts(clientset, namespace)
allDiffs = append(allDiffs, namespaceSADiff)
namespaceDeploymentDiff := getUnusedDeployments(clientset, namespace, opts)
namespaceDeploymentDiff := getUnusedDeployments(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespaceDeploymentDiff)
namespaceStatefulsetDiff := getUnusedStatefulSets(clientset, namespace, opts)
namespaceStatefulsetDiff := getUnusedStatefulSets(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespaceStatefulsetDiff)
namespaceRoleDiff := getUnusedRoles(clientset, namespace, opts)
namespaceRoleDiff := getUnusedRoles(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespaceRoleDiff)
namespaceHpaDiff := getUnusedHpas(clientset, namespace, opts)
namespaceHpaDiff := getUnusedHpas(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespaceHpaDiff)
namespacePvcDiff := getUnusedPvcs(clientset, namespace, opts)
namespacePvcDiff := getUnusedPvcs(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespacePvcDiff)
namespaceIngressDiff := getUnusedIngresses(clientset, namespace, opts)
namespaceIngressDiff := getUnusedIngresses(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespaceIngressDiff)
namespacePdbDiff := getUnusedPdbs(clientset, namespace, opts)
namespacePdbDiff := getUnusedPdbs(clientset, namespace, filterOpts)
allDiffs = append(allDiffs, namespacePdbDiff)

output := FormatOutputAll(namespace, allDiffs)
Expand All @@ -166,7 +166,7 @@ func GetUnusedAll(includeExcludeLists IncludeExcludeLists, opts *FilterOptions,
return "", err
}

unusedAll, err := unusedResourceFormatter(outputFormat, outputBuffer, slackOpts, jsonResponse)
unusedAll, err := unusedResourceFormatter(outputFormat, outputBuffer, opts, jsonResponse)
if err != nil {
fmt.Printf("err: %v\n", err)
}
Expand Down
12 changes: 7 additions & 5 deletions pkg/kor/configmaps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,15 @@ func TestGetUnusedConfigmapsStructured(t *testing.T) {
ExcludeListStr: "",
}

slackopts := SlackOpts{
WebhookURL: "",
Channel: "",
Token: "",
opts := Opts{
WebhookURL: "",
Channel: "",
Token: "",
DeleteFlag: false,
NoInteractive: true,
}

output, err := GetUnusedConfigmaps(includeExcludeLists, &FilterOptions{}, clientset, "json", slackopts)
output, err := GetUnusedConfigmaps(includeExcludeLists, &FilterOptions{}, clientset, "json", opts)
if err != nil {
t.Fatalf("Error calling GetUnusedConfigmapsStructured: %v", err)
}
Expand Down
Loading

0 comments on commit 5a55f44

Please sign in to comment.