Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for viewing completed/inactive CronJob jobs #3103

Merged
merged 5 commits into from
Jun 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/app/backend/resource/cronjob/detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type CronJobDetail struct {
ConcurrencyPolicy string `json:"concurrencyPolicy"`
StartingDeadLineSeconds *int64 `json:"startingDeadlineSeconds"`
ActiveJobs job.JobList `json:"activeJobs"`
InactiveJobs job.JobList `json:"inactiveJobs"`
Events common.EventList `json:"events"`

// Extends list item structure.
Expand All @@ -54,23 +55,26 @@ func GetCronJobDetail(client k8sClient.Interface, dsQuery *dataselect.DataSelect
return nil, criticalError
}

inactiveJobs, err := GetCronJobCompletedJobs(client, metricClient, dsQuery, namespace, name)

events, err := GetCronJobEvents(client, dsQuery, namespace, name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}

cj := toCronJobDetail(rawObject, *activeJobs, *events, nonCriticalErrors)
cj := toCronJobDetail(rawObject, *activeJobs, *inactiveJobs, *events, nonCriticalErrors)
return &cj, nil
}

func toCronJobDetail(cj *batch2.CronJob, activeJobs job.JobList, events common.EventList,
func toCronJobDetail(cj *batch2.CronJob, activeJobs job.JobList, inactiveJobs job.JobList, events common.EventList,
nonCriticalErrors []error) CronJobDetail {
return CronJobDetail{
CronJob: toCronJob(cj),
ConcurrencyPolicy: string(cj.Spec.ConcurrencyPolicy),
StartingDeadLineSeconds: cj.Spec.StartingDeadlineSeconds,
ActiveJobs: activeJobs,
InactiveJobs: inactiveJobs,
Events: events,
Errors: nonCriticalErrors,
}
Expand Down
7 changes: 6 additions & 1 deletion src/app/backend/resource/cronjob/detail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestGetJobDetail(t *testing.T) {
{
namespace,
name,
[]string{"get", "get", "list", "list", "list", "list"},
[]string{"get", "get", "list", "list", "list", "get", "list", "list", "list", "list"},
&batch.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Expand All @@ -65,6 +65,11 @@ func TestGetJobDetail(t *testing.T) {
CumulativeMetrics: make([]metricapi.Metric, 0),
Errors: make([]error, 0),
},
InactiveJobs: job.JobList{
Jobs: make([]job.Job, 0),
CumulativeMetrics: make([]metricapi.Metric, 0),
Errors: make([]error, 0),
},
Events: *event.EmptyEventList,
Errors: []error{},
},
Expand Down
72 changes: 62 additions & 10 deletions src/app/backend/resource/cronjob/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/job"
batch "k8s.io/api/batch/v1"
"k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
client "k8s.io/client-go/kubernetes"
Expand Down Expand Up @@ -72,23 +71,76 @@ func GetCronJobJobs(client client.Interface, metricClient metricapi.MetricClient
return emptyJobList, criticalError
}

jobs.Items = filterJobsByOwnerReferences(cronJob.Status.Active, jobs.Items)
jobs.Items = filterJobsByOwnerUID(cronJob.UID, jobs.Items)
jobs.Items = filterJobsByState(true, jobs.Items)

return job.ToJobList(jobs.Items, pods.Items, events.Items, nonCriticalErrors, dsQuery, metricClient), nil
}

func filterJobsByOwnerReferences(refs []v1.ObjectReference, jobs []batch.Job) (matchingJobs []batch.Job) {
m := make(map[types.UID]batch.Job, 0)
for _, j := range jobs {
m[j.UID] = j // Map job to their UIDs to enable quick access.
// GetCronJobJobs returns list of jobs owned by cron job.
func GetCronJobCompletedJobs(client client.Interface, metricClient metricapi.MetricClient,
dsQuery *dataselect.DataSelectQuery, namespace, name string) (*job.JobList, error) {
var err error

cronJob, err := client.BatchV1beta1().CronJobs(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return emptyJobList, err
}

channels := &common.ResourceChannels{
JobList: common.GetJobListChannel(client, common.NewSameNamespaceQuery(namespace), 1),
PodList: common.GetPodListChannel(client, common.NewSameNamespaceQuery(namespace), 1),
EventList: common.GetEventListChannel(client, common.NewSameNamespaceQuery(namespace), 1),
}

jobs := <-channels.JobList.List
err = <-channels.JobList.Error
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return emptyJobList, nil
}

pods := <-channels.PodList.List
err = <-channels.PodList.Error
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return emptyJobList, criticalError
}

events := <-channels.EventList.List
err = <-channels.EventList.Error
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return emptyJobList, criticalError
}

for _, ref := range refs {
matchedJob, hasMatch := m[ref.UID]
if hasMatch {
matchingJobs = append(matchingJobs, matchedJob)
jobs.Items = filterJobsByOwnerUID(cronJob.UID, jobs.Items)
jobs.Items = filterJobsByState(false, jobs.Items)

return job.ToJobList(jobs.Items, pods.Items, events.Items, nonCriticalErrors, dsQuery, metricClient), nil
}

func filterJobsByOwnerUID(UID types.UID, jobs []batch.Job) (matchingJobs []batch.Job) {
for _, j := range jobs {
for _, i := range j.OwnerReferences {
if i.UID == UID {
matchingJobs = append(matchingJobs, j)
break
}
}
}
return
}

func filterJobsByState(active bool, jobs []batch.Job) (matchingJobs []batch.Job) {
for _, j := range jobs {
if active && j.Status.Active > 0 {
matchingJobs = append(matchingJobs, j)
} else if !active && j.Status.Active == 0 {
matchingJobs = append(matchingJobs, j)
} else {
//sup
}
}
return
}
12 changes: 12 additions & 0 deletions src/app/frontend/cronjob/detail/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,17 @@
</kd-content>
</kd-content-card>

<kd-content-card>
<kd-content>
<kd-job-card-list job-list="ctrl.cronJobDetail.inactiveJobs"
job-list-resource="ctrl.jobListResource">
<kd-header>[[Inactive Jobs|Inactive Jobs card title, displayed on Cron Job details page.]]</kd-header>
<kd-empty-list-text>
[[There are currently no inactive Jobs managed by this Cron Job.|]]
</kd-empty-list-text>
</kd-job-card-list>
</kd-content>
</kd-content-card>

<kd-event-card-list event-list="::ctrl.cronJobDetail.events"
event-list-resource="::ctrl.eventsResource"></kd-event-card-list>