/
cronjob.go
executable file
·117 lines (106 loc) · 3.5 KB
/
cronjob.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package kubernetes
import (
"fmt"
"time"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"github.com/weaveworks/scope/report"
)
// These constants are keys used in node metadata
const (
Schedule = report.KubernetesSchedule
Suspended = report.KubernetesSuspended
LastScheduled = report.KubernetesLastScheduled
ActiveJobs = report.KubernetesActiveJobs
)
// CronJob represents a Kubernetes cron job
type CronJob interface {
Meta
Selectors() ([]labels.Selector, error)
GetNode(probeID string) report.Node
}
type cronJob struct {
*batchv1beta1.CronJob
Meta
jobs []*batchv1.Job
}
// NewCronJob creates a new cron job. jobs should be all jobs, which will be filtered
// for those matching this cron job.
func NewCronJob(cji interface{}, jobs map[types.UID]*batchv1.Job) CronJob {
switch cj := cji.(type) {
case *batchv2alpha1.CronJob:
return newCronJob(upgradeCronJob(cj), jobs)
case *batchv1beta1.CronJob:
return newCronJob(cj, jobs)
default:
panic(fmt.Sprintf("interface conversion: interface{} is %T, not *batchv2alpha1.CronJob or *batchv1beta1.CronJob", cj))
}
}
func newCronJob(cj *batchv1beta1.CronJob, jobs map[types.UID]*batchv1.Job) CronJob {
myJobs := []*batchv1.Job{}
for _, o := range cj.Status.Active {
if j, ok := jobs[o.UID]; ok {
myJobs = append(myJobs, j)
}
}
return &cronJob{
CronJob: cj,
Meta: meta{cj.ObjectMeta},
jobs: myJobs,
}
}
func (cj *cronJob) Selectors() ([]labels.Selector, error) {
selectors := []labels.Selector{}
for _, j := range cj.jobs {
selector, err := metav1.LabelSelectorAsSelector(j.Spec.Selector)
if err != nil {
return nil, err
}
selectors = append(selectors, selector)
}
return selectors, nil
}
func (cj *cronJob) GetNode(probeID string) report.Node {
latest := map[string]string{
NodeType: "CronJob",
Schedule: cj.Spec.Schedule,
Suspended: fmt.Sprint(cj.Spec.Suspend != nil && *cj.Spec.Suspend), // nil -> false
ActiveJobs: fmt.Sprint(len(cj.jobs)),
report.ControlProbeID: probeID,
}
if cj.Status.LastScheduleTime != nil {
latest[LastScheduled] = cj.Status.LastScheduleTime.Format(time.RFC3339Nano)
}
return cj.MetaNode(report.MakeCronJobNodeID(cj.UID())).
WithLatests(latest).
WithLatestActiveControls(Describe)
}
func upgradeCronJob(legacy *batchv2alpha1.CronJob) *batchv1beta1.CronJob {
jobTemplate := batchv1beta1.JobTemplateSpec{
ObjectMeta: legacy.Spec.JobTemplate.ObjectMeta,
Spec: legacy.Spec.JobTemplate.Spec,
}
spec := batchv1beta1.CronJobSpec{
Schedule: legacy.Spec.Schedule,
StartingDeadlineSeconds: legacy.Spec.StartingDeadlineSeconds,
ConcurrencyPolicy: batchv1beta1.ConcurrencyPolicy(legacy.Spec.ConcurrencyPolicy),
Suspend: legacy.Spec.Suspend,
JobTemplate: jobTemplate,
SuccessfulJobsHistoryLimit: legacy.Spec.SuccessfulJobsHistoryLimit,
FailedJobsHistoryLimit: legacy.Spec.FailedJobsHistoryLimit,
}
status := batchv1beta1.CronJobStatus{
Active: legacy.Status.Active,
LastScheduleTime: legacy.Status.LastScheduleTime,
}
return &batchv1beta1.CronJob{
TypeMeta: legacy.TypeMeta,
ObjectMeta: legacy.ObjectMeta,
Spec: spec,
Status: status,
}
}