Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kor for openSUSE:Factory checked in 
at 2023-12-11 21:50:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kor (Old)
 and      /work/SRC/openSUSE:Factory/.kor.new.25432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kor"

Mon Dec 11 21:50:30 2023 rev:8 rq:1132354 version:0.3.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/kor/kor.changes  2023-11-30 22:02:35.667891075 
+0100
+++ /work/SRC/openSUSE:Factory/.kor.new.25432/kor.changes       2023-12-11 
21:50:40.991821013 +0100
@@ -1,0 +2,11 @@
+Sun Dec 10 19:15:44 UTC 2023 - [email protected]
+
+- Update to version 0.3.2:
+  * Add labels to all templates. (#174)
+  * Fix command in templates. (#175)
+  * Fix exporterInterval variable. (#176)
+  * feat: find evicted pods (#173)
+  * feat: add jobs cleaner (#168)
+  * Add discord server to Readme (#171)
+
+-------------------------------------------------------------------

Old:
----
  kor-0.3.1.obscpio

New:
----
  kor-0.3.2.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kor.spec ++++++
--- /var/tmp/diff_new_pack.ORjqk5/_old  2023-12-11 21:50:42.527877897 +0100
+++ /var/tmp/diff_new_pack.ORjqk5/_new  2023-12-11 21:50:42.531878046 +0100
@@ -19,7 +19,7 @@
 %define __arch_install_post export NO_BRP_STRIP_DEBUG=true
 
 Name:           kor
-Version:        0.3.1
+Version:        0.3.2
 Release:        0
 Summary:        Tool to discover unused Kubernetes Resources
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.ORjqk5/_old  2023-12-11 21:50:42.575879675 +0100
+++ /var/tmp/diff_new_pack.ORjqk5/_new  2023-12-11 21:50:42.575879675 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/yonahd/kor</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v0.3.1</param>
+    <param name="revision">v0.3.2</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.ORjqk5/_old  2023-12-11 21:50:42.603880712 +0100
+++ /var/tmp/diff_new_pack.ORjqk5/_new  2023-12-11 21:50:42.607880860 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/yonahd/kor</param>
-              <param 
name="changesrevision">a459be1a0dfcf5d96ab0ed8c86ec8dc2d675de39</param></service></servicedata>
+              <param 
name="changesrevision">d5ad46865819f405591a7c37f34b631f8d756c89</param></service></servicedata>
 (No newline at EOF)
 

++++++ kor-0.3.1.obscpio -> kor-0.3.2.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/README.md new/kor-0.3.2/README.md
--- old/kor-0.3.1/README.md     2023-11-29 19:52:39.000000000 +0100
+++ new/kor-0.3.2/README.md     2023-12-09 22:04:13.000000000 +0100
@@ -2,6 +2,8 @@
 ![GitHub release (with 
filter)](https://img.shields.io/github/v/release/yonahd/kor?color=green&link=https://github.com/yonahd/kor/releases)
 ![Docker Pulls](https://img.shields.io/docker/pulls/yonahdissen/kor)
 
[![codecov](https://codecov.io/gh/yonahd/kor/branch/main/graph/badge.svg?token=tNKcOjlxLo)](https://codecov.io/gh/yonahd/kor)
+[![Discord](https://discord.com/api/guilds/1159544275722321990/embed.png)](https://discord.gg/ajptYPwcJY)
+ 
 
 
 # Kor - Kubernetes Orphaned Resources Finder
@@ -22,6 +24,8 @@
 - PDBs
 - CRDs
 - PVs
+- Pods
+- Jobs
 
 ![Kor Screenshot](/images/screenshot.png)
 
@@ -82,11 +86,13 @@
 - `statefulsets` - Gets unused StatefulSets for the specified namespace or all 
namespaces.
 - `role` - Gets unused Roles for the specified namespace or all namespaces.
 - `hpa` - Gets unused HPAs for the specified namespace or all namespaces.
+- `pods` - Gets unused Pods for the specified namespace or all namespaces.
 - `pvc` - Gets unused PVCs for the specified namespace or all namespaces.
 - `pv` - Gets unused PVs in the cluster(non namespaced resource).
 - `ingress` - Gets unused Ingresses for the specified namespace or all 
namespaces.
 - `pdb` - Gets unused PDBs for the specified namespace or all namespaces.
 - `crd` - Gets unused CRDs in the cluster(non namespaced resource).
+- `jobs` - Gets unused jobs for the specified namespace or all namespaces.
 - `exporter` - Export Prometheus metrics.
 
 ### Supported Flags
@@ -122,10 +128,10 @@
 
 ## Supported resources and limitations
 
-| Resource        | What it looks for                                          
                                                                                
                                                                                
       | Known False Positives  ⚠️                                          
                                                           |
+| Resource        | What it looks for                                          
                                                                                
                                                                                
       | Known False Positives  ⚠️                                          
                                                          |
 
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
 | ConfigMaps      | ConfigMaps not used in the following places:<br/>- 
Pods<br/>- Containers<br/>- ConfigMaps used through Volumes<br/>- ConfigMaps 
used through environment variables                                              
                  | ConfigMaps used by resources which don't explicitly state 
them in the config.<br/> e.g Grafana dashboards loaded dynamically OPA policies 
fluentd configs |
-| Secrets         | Secrets not used in the following places:<br/>- Pods<br/>- 
Containers<br/>- Secrets used through volumes<br/>- Secrets used through 
environment variables<br/>- Secrets used by Ingress TLS<br/>- Secrets used by 
ServiceAccounts |    Secrets used by resources which don't explicitly state 
them in the config                                                              
                                                           |
+| Secrets         | Secrets not used in the following places:<br/>- Pods<br/>- 
Containers<br/>- Secrets used through volumes<br/>- Secrets used through 
environment variables<br/>- Secrets used by Ingress TLS<br/>- Secrets used by 
ServiceAccounts |    Secrets used by resources which don't explicitly state 
them in the config                                                              
                                                          |
 | Services        | Services with no endpoints                                 
                                                                                
                                                                                
       |                                                                        
                                                      |
 | Deployments     | Deployments with no Replicas                               
                                                                                
                                                                                
       |                                                                        
                                                      |
 | ServiceAccounts | ServiceAccounts unused by Pods<br/>ServiceAccounts unused 
by roleBinding or clusterRoleBinding                                            
                                                                                
        |                                                                       
                                                       |
@@ -137,7 +143,7 @@
 | CRDs            | CRDs not used the cluster                                  
                                                                                
                                                                                
       |                                                                        
                                                      |
 | Pvs             | PVs not bound to a PVC                                     
                                                                                
                                                                                
       |                                                                        
                                                      |
 | Pdbs            | PDBs not used in Deployments<br/> PDBs not used in 
StatefulSets                                                                    
                                                                                
               |                                                                
                                                              |
-
+| Jobs            | Jobs status is completed                                   
                                                                                
                                                                                
       |                                                                        
                                                      |
 
 ## Deleting Unused resources
 If you want to delete resources in an interactive way using Kor you can run:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/Chart.yaml 
new/kor-0.3.2/charts/kor/Chart.yaml
--- old/kor-0.3.1/charts/kor/Chart.yaml 2023-11-29 19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/Chart.yaml 2023-12-09 22:04:13.000000000 +0100
@@ -15,10 +15,10 @@
 # This is the chart version. This version number should be incremented each 
time you make changes
 # to the chart and its templates, including the app version.
 # Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 0.1.2
+version: 0.1.3
 
 # This is the version number of the application being deployed. This version 
number should be
 # incremented each time you make changes to the application. Versions are not 
expected to
 # follow Semantic Versioning. They should reflect the version the application 
is using.
 # It is recommended to use it with quotes.
-appVersion: "0.2.8"
+appVersion: "0.3.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/templates/cronjob.yaml 
new/kor-0.3.2/charts/kor/templates/cronjob.yaml
--- old/kor-0.3.1/charts/kor/templates/cronjob.yaml     2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/templates/cronjob.yaml     2023-12-09 
22:04:13.000000000 +0100
@@ -4,6 +4,7 @@
 metadata:
   name: {{ .Release.Name }}
   labels:
+    {{- include "kor.labels" . | nindent 4 }}
     app: {{ .Release.Name }}
 spec:
   schedule: {{ .Values.cronJob.schedule }}
@@ -17,9 +18,13 @@
           containers:
             - name: {{ .Release.Name }}-container
               image: {{ .Values.cronJob.image.repository }}:{{ 
.Values.cronJob.image.tag }}
-              command: ["/bin/sh", "-c"]
+              command:
+                {{- toYaml .Values.cronJob.command | nindent 16 }}
+              args:
+                {{- toYaml .Values.cronJob.args | nindent 16 }}
               {{- if .Values.cronJob.slackWebhookUrl }}
-              args: ["{{ .Values.cronJob.command }} --slack-webhook-url 
$SLACK_WEBHOOK_URL"]
+                - '--slack-webhook-url'
+                - "${SLACK_WEBHOOK_URL}"
               env:
                 - name: SLACK_WEBHOOK_URL
                   valueFrom:
@@ -27,15 +32,16 @@
                       name: {{ .Release.Name }}-slack-webhook-url-secret
                       key: slack-webhook-url
               {{- else if and .Values.cronJob.slackChannel 
.Values.cronJob.slackAuthToken }}
-              args: ["{{ .Values.cronJob.command }} --slack-channel {{ 
.Values.cronJob.slackChannel }} --slack-auth-token $SLACK_AUTH_TOKEN"]
+                - '--slack-channel'
+                - {{ .Values.cronJob.slackChannel | quote }}
+                - '--slack-auth-token'
+                - "${SLACK_AUTH_TOKEN}"
               env:
                 - name: SLACK_AUTH_TOKEN
                   valueFrom:
                     secretKeyRef:
                       name: {{ .Release.Name }}-slack-auth-token-secret
                       key: slack-auth-token
-              {{- else }}
-              args: ["{{ .Values.cronJob.command }}"]
               {{- end }}
               {{- if .Values.cronJob.env }}
               env:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/templates/deployment.yaml 
new/kor-0.3.2/charts/kor/templates/deployment.yaml
--- old/kor-0.3.1/charts/kor/templates/deployment.yaml  2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/templates/deployment.yaml  2023-12-09 
22:04:13.000000000 +0100
@@ -4,6 +4,7 @@
 metadata:
   name: {{ .Values.prometheusExporter.name }}
   labels:
+    {{- include "kor.labels" . | nindent 4 }}
     app: {{ .Values.prometheusExporter.name }}
 spec:
   {{- with .Values.prometheusExporter.deployment.imagePullSecrets }}
@@ -27,8 +28,10 @@
             {{ toYaml . | nindent 12 }}
           {{- end }}
           image: "{{ .Values.prometheusExporter.deployment.image.repository 
}}:{{ .Values.prometheusExporter.deployment.image.tag }}"
-          command: ["/bin/sh", "-c"]
-          args: ["{{ .Values.prometheusExporter.deployment.command }}"]
+          command:
+            {{- toYaml .Values.prometheusExporter.command | nindent 12 }}
+          args:
+            {{- toYaml .Values.prometheusExporter.args | nindent 12 }}
           ports:
           - containerPort: 8080
             name: http
@@ -40,7 +43,7 @@
           {{- if .Values.prometheusExporter.exporterInterval }}
           env:
           - name: EXPORTER_INTERVAL
-            value: {{ .Values.prometheusExporter.exporterInterval }}
+            value: {{ .Values.prometheusExporter.exporterInterval | quote}}
           {{- end}}
       {{- with .Values.prometheusExporter.deployment.nodeSelector }}
       nodeSelector:
@@ -63,4 +66,4 @@
       securityContext: 
         {{- toYaml . | nindent 8}}
       {{- end }}
-{{- end }}
\ No newline at end of file
+{{- end }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/templates/role.yaml 
new/kor-0.3.2/charts/kor/templates/role.yaml
--- old/kor-0.3.1/charts/kor/templates/role.yaml        2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/templates/role.yaml        2023-12-09 
22:04:13.000000000 +0100
@@ -3,6 +3,8 @@
 kind: Role
 metadata:
   name: {{ include "kor.serviceAccountName" . }}-read-resources-role
+  labels:
+    {{- include "kor.labels" . | nindent 4 }}
 rules:
   - apiGroups: ["*"]
     resources:
@@ -32,6 +34,8 @@
 kind: ClusterRole
 metadata:
   name: {{ include "kor.serviceAccountName" . }}-read-resources-clusterrole
+    labels:
+    {{- include "kor.labels" . | nindent 4 }}
 rules:
   - apiGroups: ["*"]
     resources:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/templates/rolebinding.yaml 
new/kor-0.3.2/charts/kor/templates/rolebinding.yaml
--- old/kor-0.3.1/charts/kor/templates/rolebinding.yaml 2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/templates/rolebinding.yaml 2023-12-09 
22:04:13.000000000 +0100
@@ -3,6 +3,8 @@
 kind: RoleBinding
 metadata:
   name: {{ include "kor.serviceAccountName" . }}-read-resources-role-binding
+  labels:
+    {{- include "kor.labels" . | nindent 4 }}
 subjects:
   - kind: ServiceAccount
     name: {{ include "kor.serviceAccountName" . }}
@@ -15,6 +17,8 @@
 kind: ClusterRoleBinding
 metadata:
   name: {{ include "kor.serviceAccountName" . 
}}-read-resources-clusterrolebinding
+  labels:
+    {{- include "kor.labels" . | nindent 4 }}
 subjects:
   - kind: ServiceAccount
     name: {{ include "kor.serviceAccountName" . }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/templates/secret.yaml 
new/kor-0.3.2/charts/kor/templates/secret.yaml
--- old/kor-0.3.1/charts/kor/templates/secret.yaml      2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/templates/secret.yaml      2023-12-09 
22:04:13.000000000 +0100
@@ -4,6 +4,8 @@
 kind: Secret
 metadata:
   name: {{ .Release.Name }}-slack-auth-token-secret
+  labels:
+    {{- include "kor.labels" . | nindent 4 }}
 type: Opaque
 data:
   slack-auth-token: {{ .Values.cronJob.slackAuthToken | b64enc | quote }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/templates/service.yaml 
new/kor-0.3.2/charts/kor/templates/service.yaml
--- old/kor-0.3.1/charts/kor/templates/service.yaml     2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/templates/service.yaml     2023-12-09 
22:04:13.000000000 +0100
@@ -8,6 +8,7 @@
     prometheus.io/path: /metrics
     prometheus.io/port: "8080"
   labels:
+    {{- include "kor.labels" . | nindent 4 }}
     app: {{ .Values.prometheusExporter.name }}
 spec:
   type: {{ .Values.prometheusExporter.service.type }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/templates/servicemonitor.yaml 
new/kor-0.3.2/charts/kor/templates/servicemonitor.yaml
--- old/kor-0.3.1/charts/kor/templates/servicemonitor.yaml      2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/charts/kor/templates/servicemonitor.yaml      2023-12-09 
22:04:13.000000000 +0100
@@ -3,6 +3,7 @@
 kind: ServiceMonitor
 metadata:
   labels:
+    {{- include "kor.labels" . | nindent 4 }}
     app: {{ .Values.prometheusExporter.name }}
   name: {{ .Values.prometheusExporter.name }}
 {{- if .Values.prometheusExporter.serviceMonitor.namespace }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/charts/kor/values.yaml 
new/kor-0.3.2/charts/kor/values.yaml
--- old/kor-0.3.1/charts/kor/values.yaml        2023-11-29 19:52:39.000000000 
+0100
+++ new/kor-0.3.2/charts/kor/values.yaml        2023-12-09 22:04:13.000000000 
+0100
@@ -6,7 +6,10 @@
     repository: yonahdissen/kor
     tag: latest
   # e.g. kor configmap --include-namespace default,other-ns
-  command: kor all
+  command:
+    - kor
+  args:
+    - all
   slackWebhookUrl: ""
   slackChannel: ""
   slackAuthToken: ""
@@ -19,11 +22,14 @@
   name: kor-exporter
   # time in minutes, default is 10 minutes
   exporterInterval: ""
+  command:
+    - kor
+  args:
+    - exporter
   deployment:
     image:
       repository: yonahdissen/kor
       tag: latest
-    command: kor exporter
     restartPolicy: Always
     imagePullPolicy: Always
     imagePullSecrets: []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/cmd/kor/jobs.go 
new/kor-0.3.2/cmd/kor/jobs.go
--- old/kor-0.3.1/cmd/kor/jobs.go       1970-01-01 01:00:00.000000000 +0100
+++ new/kor-0.3.2/cmd/kor/jobs.go       2023-12-09 22:04:13.000000000 +0100
@@ -0,0 +1,29 @@
+package kor
+
+import (
+       "fmt"
+
+       "github.com/spf13/cobra"
+       "github.com/yonahd/kor/pkg/kor"
+       "github.com/yonahd/kor/pkg/utils"
+)
+
+var jobCmd = &cobra.Command{
+       Use:     "job",
+       Aliases: []string{"job", "jobs"},
+       Short:   "Gets unused jobs",
+       Args:    cobra.ExactArgs(0),
+       Run: func(cmd *cobra.Command, args []string) {
+               clientset := kor.GetKubeClient(kubeconfig)
+               if response, err := kor.GetUnusedJobs(includeExcludeLists, 
filterOptions, clientset, outputFormat, opts); err != nil {
+                       fmt.Println(err)
+               } else {
+                       utils.PrintLogo(outputFormat)
+                       fmt.Println(response)
+               }
+       },
+}
+
+func init() {
+       rootCmd.AddCommand(jobCmd)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/cmd/kor/pods.go 
new/kor-0.3.2/cmd/kor/pods.go
--- old/kor-0.3.1/cmd/kor/pods.go       1970-01-01 01:00:00.000000000 +0100
+++ new/kor-0.3.2/cmd/kor/pods.go       2023-12-09 22:04:13.000000000 +0100
@@ -0,0 +1,29 @@
+package kor
+
+import (
+       "fmt"
+
+       "github.com/spf13/cobra"
+       "github.com/yonahd/kor/pkg/kor"
+       "github.com/yonahd/kor/pkg/utils"
+)
+
+var podCmd = &cobra.Command{
+       Use:     "pod",
+       Aliases: []string{"po", "pods"},
+       Short:   "Gets unused pods",
+       Args:    cobra.ExactArgs(0),
+       Run: func(cmd *cobra.Command, args []string) {
+               clientset := kor.GetKubeClient(kubeconfig)
+               if response, err := kor.GetUnusedPods(includeExcludeLists, 
filterOptions, clientset, outputFormat, opts); err != nil {
+                       fmt.Println(err)
+               } else {
+                       utils.PrintLogo(outputFormat)
+                       fmt.Println(response)
+               }
+       },
+}
+
+func init() {
+       rootCmd.AddCommand(podCmd)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/all.go new/kor-0.3.2/pkg/kor/all.go
--- old/kor-0.3.1/pkg/kor/all.go        2023-11-29 19:52:39.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/all.go        2023-12-09 22:04:13.000000000 +0100
@@ -138,6 +138,24 @@
        return allPvDiff
 }
 
+func getUnusedPods(clientset kubernetes.Interface, namespace string, 
filterOpts *FilterOptions) ResourceDiff {
+       podDiff, err := ProcessNamespacePods(clientset, namespace, filterOpts)
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", 
"pods", namespace, err)
+       }
+       namespacePodDiff := ResourceDiff{"Pod", podDiff}
+       return namespacePodDiff
+}
+
+func getUnusedJobs(clientset kubernetes.Interface, namespace string, 
filterOpts *FilterOptions) ResourceDiff {
+       jobDiff, err := ProcessNamespaceJobs(clientset, namespace, filterOpts)
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Failed to get %s namespace %s: %v\n", 
"jobs", namespace, err)
+       }
+       namespaceSADiff := ResourceDiff{"Job", jobDiff}
+       return namespaceSADiff
+}
+
 func GetUnusedAll(includeExcludeLists IncludeExcludeLists, filterOpts 
*FilterOptions, clientset kubernetes.Interface, apiExtClient 
apiextensionsclientset.Interface, dynamicClient dynamic.Interface, outputFormat 
string, opts Opts) (string, error) {
        var outputBuffer bytes.Buffer
 
@@ -168,6 +186,8 @@
                allDiffs = append(allDiffs, namespaceIngressDiff)
                namespacePdbDiff := getUnusedPdbs(clientset, namespace, 
filterOpts)
                allDiffs = append(allDiffs, namespacePdbDiff)
+               namespaceJobDiff := getUnusedJobs(clientset, namespace, 
filterOpts)
+               allDiffs = append(allDiffs, namespaceJobDiff)
 
                output := FormatOutputAll(namespace, allDiffs, opts)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/create_test_resources.go 
new/kor-0.3.2/pkg/kor/create_test_resources.go
--- old/kor-0.3.1/pkg/kor/create_test_resources.go      2023-11-29 
19:52:39.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/create_test_resources.go      2023-12-09 
22:04:13.000000000 +0100
@@ -3,6 +3,7 @@
 import (
        appsv1 "k8s.io/api/apps/v1"
        autoscalingv2 "k8s.io/api/autoscaling/v2"
+       batchv1 "k8s.io/api/batch/v1"
        corev1 "k8s.io/api/core/v1"
        networkingv1 "k8s.io/api/networking/v1"
        policyv1 "k8s.io/api/policy/v1"
@@ -259,3 +260,26 @@
                },
        }
 }
+
+func CreateTestJob(namespace, name string, status *batchv1.JobStatus) 
*batchv1.Job {
+       return &batchv1.Job{
+               ObjectMeta: v1.ObjectMeta{
+                       Name:      name,
+                       Namespace: namespace,
+               },
+               Spec: batchv1.JobSpec{
+                       Template: corev1.PodTemplateSpec{
+                               Spec: corev1.PodSpec{
+                                       Containers: []corev1.Container{
+                                               {
+                                                       Name:  "test",
+                                                       Image: "test",
+                                               },
+                                       },
+                                       RestartPolicy: 
corev1.RestartPolicyNever,
+                               },
+                       },
+               },
+               Status: *status,
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/delete.go 
new/kor-0.3.2/pkg/kor/delete.go
--- old/kor-0.3.1/pkg/kor/delete.go     2023-11-29 19:52:39.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/delete.go     2023-12-09 22:04:13.000000000 +0100
@@ -7,6 +7,8 @@
        "reflect"
        "strings"
 
+       batchv1 "k8s.io/api/batch/v1"
+
        appsv1 "k8s.io/api/apps/v1"
        autoscalingv1 "k8s.io/api/autoscaling/v1"
        corev1 "k8s.io/api/core/v1"
@@ -55,6 +57,12 @@
                "PV": func(clientset kubernetes.Interface, namespace, name 
string) error {
                        return 
clientset.CoreV1().PersistentVolumes().Delete(context.TODO(), name, 
metav1.DeleteOptions{})
                },
+               "Pod": func(clientset kubernetes.Interface, namespace, name 
string) error {
+                       return 
clientset.CoreV1().Pods(namespace).Delete(context.TODO(), name, 
metav1.DeleteOptions{})
+               },
+               "Job": func(clientset kubernetes.Interface, namespace, name 
string) error {
+                       return 
clientset.BatchV1().Jobs(namespace).Delete(context.TODO(), name, 
metav1.DeleteOptions{})
+               },
        }
 
        return deleteResourceApiMap
@@ -108,6 +116,10 @@
                return 
clientset.CoreV1().ServiceAccounts(namespace).Update(context.TODO(), 
resource.(*corev1.ServiceAccount), metav1.UpdateOptions{})
        case "PV":
                return 
clientset.CoreV1().PersistentVolumes().Update(context.TODO(), 
resource.(*corev1.PersistentVolume), metav1.UpdateOptions{})
+       case "Pod":
+               return 
clientset.CoreV1().Pods(namespace).Update(context.TODO(), 
resource.(*corev1.Pod), metav1.UpdateOptions{})
+       case "Job":
+               return 
clientset.BatchV1().Jobs(namespace).Update(context.TODO(), 
resource.(*batchv1.Job), metav1.UpdateOptions{})
        }
        return nil, fmt.Errorf("resource type '%s' is not supported", 
resourceType)
 }
@@ -138,6 +150,10 @@
                return 
clientset.CoreV1().ServiceAccounts(namespace).Get(context.TODO(), resourceName, 
metav1.GetOptions{})
        case "PV":
                return 
clientset.CoreV1().PersistentVolumes().Get(context.TODO(), resourceName, 
metav1.GetOptions{})
+       case "Pod":
+               return clientset.CoreV1().Pods(namespace).Get(context.TODO(), 
resourceName, metav1.GetOptions{})
+       case "Job":
+               return clientset.BatchV1().Jobs(namespace).Get(context.TODO(), 
resourceName, metav1.GetOptions{})
        }
        return nil, fmt.Errorf("resource type '%s' is not supported", 
resourceType)
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/jobs.go 
new/kor-0.3.2/pkg/kor/jobs.go
--- old/kor-0.3.1/pkg/kor/jobs.go       1970-01-01 01:00:00.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/jobs.go       2023-12-09 22:04:13.000000000 +0100
@@ -0,0 +1,85 @@
+package kor
+
+import (
+       "bytes"
+       "context"
+       "encoding/json"
+       "fmt"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/client-go/kubernetes"
+       "os"
+)
+
+func ProcessNamespaceJobs(clientset kubernetes.Interface, namespace string, 
filterOpts *FilterOptions) ([]string, error) {
+       jobsList, err := 
clientset.BatchV1().Jobs(namespace).List(context.TODO(), metav1.ListOptions{})
+       if err != nil {
+               return nil, err
+       }
+
+       var unusedJobNames []string
+
+       for _, job := range jobsList.Items {
+               if job.Labels["kor/used"] == "true" {
+                       continue
+               }
+
+               // checks if the resource has any labels that match the 
excluded selector specified in opts.ExcludeLabels.
+               // If it does, the resource is skipped.
+               if excluded, _ := HasExcludedLabel(job.Labels, 
filterOpts.ExcludeLabels); excluded {
+                       continue
+               }
+               // checks if the resource's age (measured from its last 
modified time) matches the included criteria
+               // specified by the filter options.
+               if included, _ := HasIncludedAge(job.CreationTimestamp, 
filterOpts); !included {
+                       continue
+               }
+
+               // if the job has completionTime and succeeded count greater 
than zero, think the job is completed
+               if job.Status.CompletionTime != nil && job.Status.Succeeded > 0 
{
+                       unusedJobNames = append(unusedJobNames, job.Name)
+               }
+       }
+
+       return unusedJobNames, nil
+}
+
+func GetUnusedJobs(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 {
+               diff, err := ProcessNamespaceJobs(clientset, namespace, 
filterOpts)
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "Failed to process namespace %s: 
%v\n", namespace, err)
+                       continue
+               }
+
+               if opts.DeleteFlag {
+                       if diff, err = DeleteResource(diff, clientset, 
namespace, "Job", opts.NoInteractive); err != nil {
+                               fmt.Fprintf(os.Stderr, "Failed to delete Job %s 
in namespace %s: %v\n", diff, namespace, err)
+                       }
+               }
+               output := FormatOutput(namespace, diff, "Job", opts)
+               if output != "" {
+                       outputBuffer.WriteString(output)
+                       outputBuffer.WriteString("\n")
+
+                       resourceMap := make(map[string][]string)
+                       resourceMap["Jobs"] = diff
+                       response[namespace] = resourceMap
+               }
+       }
+
+       jsonResponse, err := json.MarshalIndent(response, "", "  ")
+       if err != nil {
+               return "", err
+       }
+
+       unusedJobs, err := unusedResourceFormatter(outputFormat, outputBuffer, 
opts, jsonResponse)
+       if err != nil {
+               fmt.Printf("err: %v\n", err)
+       }
+
+       return unusedJobs, nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/jobs_test.go 
new/kor-0.3.2/pkg/kor/jobs_test.go
--- old/kor-0.3.1/pkg/kor/jobs_test.go  1970-01-01 01:00:00.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/jobs_test.go  2023-12-09 22:04:13.000000000 +0100
@@ -0,0 +1,108 @@
+package kor
+
+import (
+       "context"
+       "encoding/json"
+       appsv1 "k8s.io/api/apps/v1"
+       batchv1 "k8s.io/api/batch/v1"
+       corev1 "k8s.io/api/core/v1"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/client-go/kubernetes/fake"
+       "k8s.io/client-go/kubernetes/scheme"
+       "reflect"
+       "testing"
+       "time"
+)
+
+func createTestJobs(t *testing.T) *fake.Clientset {
+       clientset := fake.NewSimpleClientset()
+
+       _, err := clientset.CoreV1().Namespaces().Create(context.TODO(), 
&corev1.Namespace{
+               ObjectMeta: v1.ObjectMeta{Name: testNamespace},
+       }, v1.CreateOptions{})
+
+       if err != nil {
+               t.Fatalf("Error creating namespace %s: %v", testNamespace, err)
+       }
+
+       job1 := CreateTestJob(testNamespace, "test-job1", &batchv1.JobStatus{
+               Succeeded: 0,
+               Failed:    1,
+       })
+       job2 := CreateTestJob(testNamespace, "test-job2", &batchv1.JobStatus{
+               Succeeded:      1,
+               Failed:         0,
+               CompletionTime: &v1.Time{Time: time.Now()},
+       })
+
+       _, err = clientset.BatchV1().Jobs(testNamespace).Create(context.TODO(), 
job1, v1.CreateOptions{})
+       if err != nil {
+               t.Fatalf("Error creating fake job: %v", err)
+       }
+
+       _, err = clientset.BatchV1().Jobs(testNamespace).Create(context.TODO(), 
job2, v1.CreateOptions{})
+       if err != nil {
+               t.Fatalf("Error creating fake job: %v", err)
+       }
+       return clientset
+}
+
+func TestProcessNamespaceJobs(t *testing.T) {
+       clientset := createTestJobs(t)
+
+       completedJobs, err := ProcessNamespaceJobs(clientset, testNamespace, 
&FilterOptions{})
+       if err != nil {
+               t.Errorf("Expected no error, got %v", err)
+       }
+
+       if len(completedJobs) != 1 {
+               t.Errorf("Expected 1 job been completed, got %d", 
len(completedJobs))
+       }
+
+       if completedJobs[0] != "test-job2" {
+               t.Errorf("job2', got %s", completedJobs[0])
+       }
+}
+
+func TestGetUnusedJobsStructured(t *testing.T) {
+       clientset := createTestJobs(t)
+
+       includeExcludeLists := IncludeExcludeLists{
+               IncludeListStr: "",
+               ExcludeListStr: "",
+       }
+
+       opts := Opts{
+               WebhookURL:    "",
+               Channel:       "",
+               Token:         "",
+               DeleteFlag:    false,
+               NoInteractive: true,
+       }
+
+       output, err := GetUnusedJobs(includeExcludeLists, &FilterOptions{}, 
clientset, "json", opts)
+       if err != nil {
+               t.Fatalf("Error calling GetUnusedJobsStructured: %v", err)
+       }
+
+       expectedOutput := map[string]map[string][]string{
+               testNamespace: {
+                       "Jobs": {"test-job2"},
+               },
+       }
+
+       var actualOutput map[string]map[string][]string
+       if err := json.Unmarshal([]byte(output), &actualOutput); err != nil {
+               t.Fatalf("Error unmarshaling actual output: %v", err)
+       }
+
+       if !reflect.DeepEqual(expectedOutput, actualOutput) {
+               t.Errorf("Expected output does not match actual output")
+       }
+}
+
+func init() {
+       scheme.Scheme = runtime.NewScheme()
+       _ = appsv1.AddToScheme(scheme.Scheme)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/multi.go 
new/kor-0.3.2/pkg/kor/multi.go
--- old/kor-0.3.1/pkg/kor/multi.go      2023-11-29 19:52:39.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/multi.go      2023-12-09 22:04:13.000000000 +0100
@@ -68,6 +68,10 @@
                        diffResult = getUnusedIngresses(clientset, namespace, 
filterOpts)
                case "pdb", "poddisruptionbudget", "poddisruptionbudgets":
                        diffResult = getUnusedPdbs(clientset, namespace, 
filterOpts)
+               case "po", "pod", "pods":
+                       diffResult = getUnusedPods(clientset, namespace, 
filterOpts)
+               case "job", "jobs":
+                       diffResult = getUnusedJobs(clientset, namespace, 
filterOpts)
                default:
                        fmt.Printf("resource type %q is not supported\n", 
resource)
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/pods.go 
new/kor-0.3.2/pkg/kor/pods.go
--- old/kor-0.3.1/pkg/kor/pods.go       1970-01-01 01:00:00.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/pods.go       2023-12-09 22:04:13.000000000 +0100
@@ -0,0 +1,87 @@
+package kor
+
+import (
+       "bytes"
+       "context"
+       "encoding/json"
+       "fmt"
+       "os"
+
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/client-go/kubernetes"
+)
+
+func ProcessNamespacePods(clientset kubernetes.Interface, namespace string, 
filterOpts *FilterOptions) ([]string, error) {
+       podsList, err := 
clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
+       if err != nil {
+               return nil, err
+       }
+
+       var evictedPods []string
+
+       for _, pod := range podsList.Items {
+               if pod.Labels["kor/used"] == "true" {
+                       continue
+               }
+
+               // checks if the resource has any labels that match the 
excluded selector specified in opts.ExcludeLabels.
+               // If it does, the resource is skipped.
+               if excluded, _ := HasExcludedLabel(pod.Labels, 
filterOpts.ExcludeLabels); excluded {
+                       continue
+               }
+               // checks if the resource's age (measured from its last 
modified time) matches the included criteria
+               // specified by the filter options.
+               if included, _ := HasIncludedAge(pod.CreationTimestamp, 
filterOpts); !included {
+                       continue
+               }
+
+               if pod.Status.Phase == corev1.PodFailed && pod.Status.Reason == 
"Evicted" {
+                       evictedPods = append(evictedPods, pod.Name)
+               }
+
+       }
+
+       return evictedPods, nil
+}
+
+func GetUnusedPods(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 {
+               diff, err := ProcessNamespacePods(clientset, namespace, 
filterOpts)
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "Failed to process namespace %s: 
%v\n", namespace, err)
+                       continue
+               }
+
+               if opts.DeleteFlag {
+                       if diff, err = DeleteResource(diff, clientset, 
namespace, "Pod", opts.NoInteractive); err != nil {
+                               fmt.Fprintf(os.Stderr, "Failed to delete Pod %s 
in namespace %s: %v\n", diff, namespace, err)
+                       }
+               }
+               output := FormatOutput(namespace, diff, "Pods", opts)
+               if output != "" {
+                       outputBuffer.WriteString(output)
+                       outputBuffer.WriteString("\n")
+
+                       resourceMap := make(map[string][]string)
+                       resourceMap["Pods"] = diff
+                       response[namespace] = resourceMap
+               }
+       }
+
+       jsonResponse, err := json.MarshalIndent(response, "", "  ")
+       if err != nil {
+               return "", err
+       }
+
+       unusedPods, err := unusedResourceFormatter(outputFormat, outputBuffer, 
opts, jsonResponse)
+       if err != nil {
+               fmt.Printf("err: %v\n", err)
+       }
+
+       return unusedPods, nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kor-0.3.1/pkg/kor/pods_test.go 
new/kor-0.3.2/pkg/kor/pods_test.go
--- old/kor-0.3.1/pkg/kor/pods_test.go  1970-01-01 01:00:00.000000000 +0100
+++ new/kor-0.3.2/pkg/kor/pods_test.go  2023-12-09 22:04:13.000000000 +0100
@@ -0,0 +1,146 @@
+package kor
+
+import (
+       "context"
+       "encoding/json"
+       "reflect"
+       "testing"
+
+       corev1 "k8s.io/api/core/v1"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+
+       fake "k8s.io/client-go/kubernetes/fake"
+       "k8s.io/client-go/kubernetes/scheme"
+)
+
+func createTestPods(t *testing.T) *fake.Clientset {
+       clientset := fake.NewSimpleClientset()
+
+       _, err := clientset.CoreV1().Namespaces().Create(context.TODO(), 
&corev1.Namespace{
+               ObjectMeta: v1.ObjectMeta{Name: testNamespace},
+       }, v1.CreateOptions{})
+
+       if err != nil {
+               t.Fatalf("Error creating namespace %s: %v", testNamespace, err)
+       }
+
+       pod1 := CreateTestPod(testNamespace, "pod-1", "", nil)
+       pod1.Status = corev1.PodStatus{
+               Phase:   corev1.PodRunning,
+               Reason:  "",
+               Message: "",
+       }
+       pod2 := CreateTestPod(testNamespace, "pod-2", "", nil)
+       pod2.Status = corev1.PodStatus{
+               Phase:   corev1.PodFailed,
+               Reason:  "Evicted",
+               Message: "",
+       }
+
+       pod3 := CreateTestPod(testNamespace, "pod-3", "", nil)
+       pod3.Status = corev1.PodStatus{
+               Phase:   corev1.PodFailed,
+               Reason:  "CrashLoopBackOff",
+               Message: "",
+       }
+
+       pod4 := CreateTestPod(testNamespace, "pod-4", "", nil)
+       pod4.Status = corev1.PodStatus{
+               Phase:   corev1.PodSucceeded,
+               Reason:  "",
+               Message: "",
+       }
+
+       pod5 := CreateTestPod(testNamespace, "pod-5", "", nil)
+       pod5.Labels = map[string]string{"kor/used": "true"}
+       pod5.Status = corev1.PodStatus{
+               Phase:   corev1.PodFailed,
+               Reason:  "Evicted",
+               Message: "",
+       }
+
+       pod6 := CreateTestPod(testNamespace, "pod-6", "", nil)
+       pod6.Labels = map[string]string{"kor/used": "false"}
+       pod6.Status = corev1.PodStatus{
+               Phase:   corev1.PodFailed,
+               Reason:  "Evicted",
+               Message: "",
+       }
+
+       pods := []*corev1.Pod{pod1, pod2, pod3, pod4, pod5, pod6}
+
+       // Add test pods to the clientset
+       for _, pod := range pods {
+               _, err = 
clientset.CoreV1().Pods(pod.Namespace).Create(context.TODO(), pod, 
v1.CreateOptions{})
+               if err != nil {
+                       t.Fatalf("Error creating fake pod: %v", err)
+               }
+       }
+
+       return clientset
+}
+
+func TestProcessNamespacePods(t *testing.T) {
+       clientset := createTestPods(t)
+       evictedPods, err := ProcessNamespacePods(clientset, testNamespace, 
&FilterOptions{})
+       if err != nil {
+               t.Errorf("Unexpected error: %v", err)
+       }
+
+       expectedEvictedPods := []string{"pod-2", "pod-6"}
+
+       if len(evictedPods) != len(expectedEvictedPods) {
+               t.Errorf("Expected %d evicted pods, got %d", 
len(expectedEvictedPods), len(evictedPods))
+       }
+
+       for i, pod := range evictedPods {
+               if pod != expectedEvictedPods[i] {
+                       t.Errorf("Expected evicted pod %s, got %s", 
expectedEvictedPods[i], pod)
+               }
+       }
+}
+
+func TestGetUnusedPodsStructured(t *testing.T) {
+       clientset := createTestPods(t)
+
+       includeExcludeLists := IncludeExcludeLists{
+               IncludeListStr: "",
+               ExcludeListStr: "",
+       }
+
+       opts := Opts{
+               WebhookURL:    "",
+               Channel:       "",
+               Token:         "",
+               DeleteFlag:    false,
+               NoInteractive: true,
+       }
+
+       output, err := GetUnusedPods(includeExcludeLists, &FilterOptions{}, 
clientset, "json", opts)
+       if err != nil {
+               t.Fatalf("Error calling GetUnusedPodsStructured: %v", err)
+       }
+
+       expectedOutput := map[string]map[string][]string{
+               testNamespace: {
+                       "Pods": {"pod-2", "pod-6"},
+               },
+       }
+
+       var actualOutput map[string]map[string][]string
+       if err := json.Unmarshal([]byte(output), &actualOutput); err != nil {
+               t.Fatalf("Error unmarshaling actual output: %v", err)
+       }
+
+       if !reflect.DeepEqual(expectedOutput, actualOutput) {
+               t.Errorf("Expected output does not match actual output")
+               t.Errorf("Expected: %v", expectedOutput)
+               t.Errorf("Actual: %v", actualOutput)
+       }
+}
+
+func init() {
+       scheme.Scheme = runtime.NewScheme()
+       _ = corev1.AddToScheme(scheme.Scheme)
+}

++++++ kor.obsinfo ++++++
--- /var/tmp/diff_new_pack.ORjqk5/_old  2023-12-11 21:50:42.767886785 +0100
+++ /var/tmp/diff_new_pack.ORjqk5/_new  2023-12-11 21:50:42.771886934 +0100
@@ -1,5 +1,5 @@
 name: kor
-version: 0.3.1
-mtime: 1701283959
-commit: a459be1a0dfcf5d96ab0ed8c86ec8dc2d675de39
+version: 0.3.2
+mtime: 1702155853
+commit: d5ad46865819f405591a7c37f34b631f8d756c89
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/kor/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.kor.new.25432/vendor.tar.gz differ: char 5, line 1

Reply via email to