8
8
"k8s.io/client-go/kubernetes"
9
9
"k8s.io/client-go/pkg/api/v1"
10
10
"k8s.io/client-go/tools/cache"
11
+ "k8s.io/apimachinery/pkg/version"
11
12
"log"
12
13
"reflect"
13
14
"strconv"
@@ -41,7 +42,14 @@ func NewPodController(kclient *kubernetes.Clientset, opts map[string]string) *Po
41
42
42
43
keepSuccessHours , _ := strconv .Atoi (opts ["keepSuccessHours" ])
43
44
keepFailedHours , _ := strconv .Atoi (opts ["keepFailedHours" ])
45
+ keepPendingHours , _ := strconv .Atoi (opts ["keepPendingHours" ])
44
46
dryRun , _ := strconv .ParseBool (opts ["dryRun" ])
47
+ version , err := kclient .ServerVersion ()
48
+
49
+ if err != nil {
50
+ log .Fatalf ("Failed to retrieve server version %v" , err )
51
+ }
52
+
45
53
// Create informer for watching Namespaces
46
54
podInformer := cache .NewSharedIndexInformer (
47
55
& cache.ListWatch {
@@ -59,11 +67,11 @@ func NewPodController(kclient *kubernetes.Clientset, opts map[string]string) *Po
59
67
)
60
68
podInformer .AddEventHandler (cache.ResourceEventHandlerFuncs {
61
69
AddFunc : func (cur interface {}) {
62
- podWatcher .doTheMagic (cur , keepSuccessHours , keepFailedHours , dryRun )
70
+ podWatcher .doTheMagic (cur , keepSuccessHours , keepFailedHours , keepPendingHours , dryRun , * version )
63
71
},
64
72
UpdateFunc : func (old , cur interface {}) {
65
73
if ! reflect .DeepEqual (old , cur ) {
66
- podWatcher .doTheMagic (cur , keepSuccessHours , keepFailedHours , dryRun )
74
+ podWatcher .doTheMagic (cur , keepSuccessHours , keepFailedHours , keepPendingHours , dryRun , * version )
67
75
}
68
76
},
69
77
})
@@ -90,12 +98,13 @@ func (c *PodController) Run(stopCh <-chan struct{}, wg *sync.WaitGroup) {
90
98
<- stopCh
91
99
}
92
100
93
- func (c * PodController ) doTheMagic (cur interface {}, keepSuccessHours int , keepFailedHours int , dryRun bool ) {
101
+ func (c * PodController ) doTheMagic (cur interface {}, keepSuccessHours int , keepFailedHours int , keepPendingHours int , dryRun bool , version version.Info ) {
102
+
94
103
podObj := cur .(* v1.Pod )
95
- // handle jobs only
96
- var createdMeta CreatedByAnnotation
97
- json . Unmarshal ([] byte ( podObj . ObjectMeta . Annotations [ "kubernetes.io/created-by" ]), & createdMeta )
98
- if createdMeta . Reference . Kind != "Job" {
104
+ parentJobName := c . getParentJobName ( podObj , version )
105
+ // if we couldn't find a prent job name, ignore this pod
106
+ if parentJobName == "" {
107
+ log . Printf ( "Pod %s was not created by a job, ignoring." , podObj . Name )
99
108
return
100
109
}
101
110
@@ -104,11 +113,15 @@ func (c *PodController) doTheMagic(cur interface{}, keepSuccessHours int, keepFa
104
113
switch podObj .Status .Phase {
105
114
case v1 .PodSucceeded :
106
115
if keepSuccessHours == 0 || (keepSuccessHours > 0 && executionTimeHours > float32 (keepSuccessHours )) {
107
- c .deleteObjects (podObj , createdMeta , dryRun )
116
+ c .deleteObjects (podObj , parentJobName , dryRun )
108
117
}
109
118
case v1 .PodFailed :
110
119
if keepFailedHours == 0 || (keepFailedHours > 0 && executionTimeHours > float32 (keepFailedHours )) {
111
- c .deleteObjects (podObj , createdMeta , dryRun )
120
+ c .deleteObjects (podObj , parentJobName , dryRun )
121
+ }
122
+ case v1 .PodPending :
123
+ if keepPendingHours > 0 && executionTimeHours > float32 (keepPendingHours ) {
124
+ c .deleteObjects (podObj , parentJobName , dryRun )
112
125
}
113
126
default :
114
127
return
@@ -132,7 +145,7 @@ func (c *PodController) getExecutionTimeHours(podObj *v1.Pod) (executionTimeHour
132
145
return
133
146
}
134
147
135
- func (c * PodController ) deleteObjects (podObj * v1.Pod , createdMeta CreatedByAnnotation , dryRun bool ) {
148
+ func (c * PodController ) deleteObjects (podObj * v1.Pod , parentJobName string , dryRun bool ) {
136
149
// Delete Pod
137
150
if ! dryRun {
138
151
log .Printf ("Deleting pod '%s'" , podObj .Name )
@@ -143,12 +156,39 @@ func (c *PodController) deleteObjects(podObj *v1.Pod, createdMeta CreatedByAnnot
143
156
}
144
157
// Delete Job itself
145
158
if ! dryRun {
146
- log .Printf ("Deleting job '%s'" , createdMeta . Reference . Name )
159
+ log .Printf ("Deleting job '%s'" , parentJobName )
147
160
var jo metav1.DeleteOptions
148
- c .kclient .BatchV1Client .Jobs (createdMeta . Reference . Namespace ).Delete (createdMeta . Reference . Name , & jo )
161
+ c .kclient .BatchV1Client .Jobs (podObj . Namespace ).Delete (parentJobName , & jo )
149
162
} else {
150
- log .Printf ("Job '%s' would have been deleted" , createdMeta . Reference . Name )
163
+ log .Printf ("Job '%s' would have been deleted" , parentJobName )
151
164
}
152
165
return
153
-
154
166
}
167
+
168
+
169
+ func (c * PodController ) getParentJobName (podObj * v1.Pod , version version.Info ) (parentJobName string ) {
170
+
171
+ oldVersion := false
172
+
173
+ major ,_ := strconv .Atoi (version .Major )
174
+ minor ,_ := strconv .Atoi (version .Minor )
175
+ if major < 2 && minor < 8 {
176
+ oldVersion = true
177
+ }
178
+
179
+ if oldVersion {
180
+ var createdMeta CreatedByAnnotation
181
+ json .Unmarshal ([]byte (podObj .ObjectMeta .Annotations ["kubernetes.io/created-by" ]), & createdMeta )
182
+ if createdMeta .Reference .Kind == "Job" {
183
+ parentJobName = createdMeta .Reference .Name
184
+ }
185
+ }else {
186
+ // Going all over the owners, looking for a job, usually there is only one owner
187
+ for _ , ow := range podObj .OwnerReferences {
188
+ if ow .Kind == "Job" {
189
+ parentJobName = ow .Name
190
+ }
191
+ }
192
+ }
193
+ return
194
+ }
0 commit comments