From 3fcae205687be8e65cf3fce43d77d4cf9cb534f3 Mon Sep 17 00:00:00 2001 From: nwendling Date: Thu, 30 Apr 2015 11:24:15 +0200 Subject: [PATCH 1/2] job controller proposal document added --- docs/proposals/job_controller.md | 226 +++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 docs/proposals/job_controller.md diff --git a/docs/proposals/job_controller.md b/docs/proposals/job_controller.md new file mode 100644 index 000000000000..4c92012d5b25 --- /dev/null +++ b/docs/proposals/job_controller.md @@ -0,0 +1,226 @@ +**Abstract** + +First basic implementation proposal for a Job controller. Several exiting issues were already created regarding that particular subject: + + Distributed CRON jobs in k8s #2156 + Job Controller #1624 + +Several features also already exist that could be used by external tools to trigger batch execution on one pod within k8 cluster. + + Create a standalone pod (not linked to any existing replication controllers) + Execute a new process within a given container from a running pod. + +**Motivation** + +The main goal is to provide a new pod controller type, called Job, with the following characteristics: + +* Be able to start of one or several pods tracked as a single entity representing a one execution of this job. Final job execution status will reflect the completion status of all pods started for this run. + +* Ability to trigger a new job execution either on demand (triggered through server API by an external agent or by another k8 subsystem), or periodically based on a time-based schedule defined in job specification part (using ISO8601 syntax notation). + +* Be able to restart a limited number of time failing containers of pods created by one job execution (using "Restart on failure" logic extended by a maximal restart count). + +* Be able to limit the execution time of pods created by this job. + +* Be able to provide status information about pending and current job executions, along with a (limited) history of previous job runs (containing start/stop times with completion exit code) + +* (Future evolution) Trigger jobs based on success/failure of others. + + +**Job basic definition** + +The new Job object json definition for a basic implementation will have the following content: +``` +{ + "apiVersion": "v1beta3", + "kind": "Job", + "metadata" : { + "name": "myJob" + "labels" : { + "name": "myJob" + } + } + "spec": { + "schedule": { + "timeSpec": "R5/T01:00:00/PT01", + "skipOutdated": true + "blockOnFailure": false + }, + "allowConcurrentRun": false, + "maxRestart": 2, + "execTimeout": 100, + "PodCount": 1, + "selector": { "name": "myjob"}, + "template": { + "metadata" : { + "name": "myJobPodTemplate" + "labels" : { + "name": "myJobPodTemplate" + } + } + "spec": { + "restartPolicy": "OnFailure" + "containers": [{ + "name": "job-container", + "image": "app/job", + ... + }] + } + } + } +} +``` +**Fields definition:** + +Compared to replication controller, replica count is replaced by the PodCount field (number of Pods started simultaneously for a single job execution run). +All other fields are characteritic of this new controller type: + +* "maxRestart": (default to 1) maximal number of times a failing container is allowed to be restarted. +* "execTimeout": (not restricted by default) maximal duration a container within a pod started by the Job controller is allowed to run. Reaching this limit leads to the container to be killed. +* "PodCount": (default to 1) number of pods started by a single run of the Job. +* "allowConcurrentRun": (default to true) dictates if concurrent runs of this Job are allowed or not. + +* "schedule": (optional) sub structure defining scheduling details + * "timeSpec": describes the job schedule, expressed (using the ISO 8601) with a 3 parts dash separated string: "R[n]/[start date]/[duration]" + The first part gives the number of repetitions of the job (omitting this number means infinite repetitions) + The second part gives the starting time of the scheduling period. + The third part is the duration between successive runs of the scheduled pod(s). + * "suspendOnFailure": dictated if job schedule should be suspended in case of failure of the last completed job run. + * "skipOutdated": dictates if pending scheduled job runs should be discarded in favour of the latest one. This covers the case of a job having suspended its execution after a failed run, with several schedule points reached in the meantime (or the case of a long lasting run with concurrent execution disable). Instead of stacking pending executions, only the latest one is kept (and intermediate pending runs discarded). + +**Implementation details** + +Job objects are stored in a dedicated registry directory key (separated from the directory key used for replication controllers). + +Similarly to replication controllers, a dedicated manager takes care of all jobs existing in the system, performing the following tasks: + +* Executes a loop on the full list of defined jobs, calling on each a defined synchronization call-back, each execution loop being spaced by a configuration defined time interval (with default value of 5 seconds). +* Performs a (recursive) watch of the registry directory key containing jobs definition. For each job newly defined or updated in the system, the same synchronization routine is invoked. + +This job manager provides a way for each job defined with schedule information to setup a dedicated timer for next schedule time. This allows a better accuracy of start execution time for pods launched by jobs and remove dependency on the interval value set for the synchronization loop. + +The maximal restart count and maximal execution time for pods containers started by a job will be enforced at kubelet level, using dedicated resource limits added by the job in pod's containers definition. Two new resource types ("execution time" and "execution count") are introduced, that are used to add in the container's resources limits the figures defined in job specification and taken into account by the kubelet module (container is killed if the execution time is reached and restarted in case of failure exit up to this maximal count). + +In order to precisely track job pods, 2 specific labels are pushed in created pod metadata: +* the job name ("jobName") +* A tag ("jobTag", either a generated UID, or simply the schedule date of this job execution) allowing to group all pods started started for a given job execution. + +Along with labels, specific environment variables are also dynamically added in created pods definition: the number of pods started for this job execution and for each one its index number in the started pods list. + +Job has the responsibility to advertise job run completion status (success or failure) through events, to perform the necessary clean-up in pods registry, to provide a detailed status of active job runs and the completion status of previous completed runs up to a given amount of history). +Collecting the standard output/error of pod's containers is not covered by this design (a common solution for containers started by any controller is needed). + +**API types definition:** + +The following API objects can be introduced: + +``` +type JobScheduleSpec struct { + + // TimeSpec contains the schedule in ISO8601 format. + TimeSpec string `json:"timeSpec"` + + // SkipOutdated specifies that if AllowConcurrent is false, only the latest pending job + // that is waiting for the currently executing one to complete must be started (default: true) + SkipOutdated bool `json:"skipOutdated"` + + // BlockOnFailure suspends scheduling of next job runs after a failed one + BlockOnFailure bool `json:"blockOnFailure"` +} + +type JobSpec struct { + + // JobScheduleSpec contains scheduling related infos + JobScheduleSpec ScheduleSpec `json:"scheduleSpec"` + + // AllowConcurrent specified whether concurrent jobs may be started + // (covers the case where new job schedule time is reached, while + // other previously started jobs are still running) + AllowConcurrent bool `json:"allowConcurrent"` + + // ExecTimeout specifies the max amount of time a job is allowed to run (in seconds). + ExecTimeout int `json:"execTimeout"` + + // MaxRestart specifies the max number of restarts for a failing scheduled pod. + MaxRestart int `json:"maxRestart"` + + // PodCount specifies the numbe of pods to start for each job run + PodCount int `json:"podCount"` + + // Pod selector for that controller + Selector map[string]string `json:"selector"` + + // Reference to stand alone PodTemplate + TemplateRef *ObjectReference `json:"templateRef,omitempty"` + + // Embedded pod template + Template *PodTemplateSpec `json:"template,omitempty"` +} + +type JobExecStatus string +const ( + JobExecPending JobExecStatus = "pending" + JobExecRunning JobExecStatus = "running" + JobExecCompleted JobExecStatus = "completed" +) + +type JobExecution struct { + // CreatedAt gives job creation time + CreatedAt util.Time + + // StartedAt gives job starting time + StartedAt util.Time + + // CompletedAt + CompletedAt util.Time + + // Success gives job completion result + Success bool + + // JobExecStatus + Status JobExecStatus + + // Tag is added in labels of pod(s) created for this job execution. It allows + // job object to safely group/track all pods started for one given job execution. + Tag util.UID +} + +// JobStatus represents the current state of Job +type JobStatus struct { + // PendingExecutions are the job runs pending for execution + PendingExecutions []JobExecution `json:"pendingExecutions"` + + // CurrentExecutions are the job run currently executing + // (With pods scheduled in the kubernetes cluster) + RunningExecutions []JobExecution `json:"runningExecutions"` + + // PreviousRunStates tracks previously scheduled jobs (up to a limited amount) + CompletedExecution []JobExecution `json:"completedExecution"` + + // ScheduleCount tracks the count of run for this job + ScheduleCount int `json:"scheduleCount"` +} + +// Job represents the configuration of a job controller. +type Job struct { + TypeMeta `json:",inline"` + ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired behavior of this job controller. + Spec JobSpec `json:"spec,omitempty"` + + // Status is the current status of this job controller. + Status JobStatus `json:"status,omitempty"` +} + +// JobList is a collection of job controllers. +type JobList struct { + TypeMeta `json:",inline"` + ListMeta `json:"metadata,omitempty"` + + Items []Job `json:"items"` +} +``` + +JobExecution structure is defined to contain all informations for pending, running and completed job executions. The Job status structure holds objects of this type in three separated ordered lists (one by execution status). The "pending" execution list is used as a way to stack executions for job preventing concurrent runs, and also to trigger execution for job defined without time based scheduling. A new API server entry point is introduced to allow this on-demand job execution. Changes in this pending list is detected by the watch process in controller-manager module and the job instance called back takes the appropriate action (in the common case, creates pods and move this job execution in the running list) + From 53371233c2a27070204f305c93912512db99a540 Mon Sep 17 00:00:00 2001 From: Maciej Szulik Date: Tue, 14 Jul 2015 16:15:12 +0200 Subject: [PATCH 2/2] Job controller proposal --- docs/proposals/job.md | 151 +++++++++++++++++++++ docs/proposals/job_controller.md | 226 ------------------------------- docs/proposals/scheduledjob.md | 113 ++++++++++++++++ 3 files changed, 264 insertions(+), 226 deletions(-) create mode 100644 docs/proposals/job.md delete mode 100644 docs/proposals/job_controller.md create mode 100644 docs/proposals/scheduledjob.md diff --git a/docs/proposals/job.md b/docs/proposals/job.md new file mode 100644 index 000000000000..704efa1c6dc8 --- /dev/null +++ b/docs/proposals/job.md @@ -0,0 +1,151 @@ +# Job Controller + +## Abstract +A proposal for implementing a new controller - Job controller - which will be responsible +for managing pod(s) that require to run-once to a completion, in contrast to what +ReplicationController currently offers. + +Several existing issues and PRs were already created regarding that particular subject: +* Job Controller [#1624](https://github.com/GoogleCloudPlatform/kubernetes/issues/1624) +* New Job resource [#7380](https://github.com/GoogleCloudPlatform/kubernetes/pull/7380) + + +## Use Cases +1. Be able to start of one or several pods tracked as a single entity. +1. Be able to implement basic batch oriented tasks. +1. Be able to get the job status. +1. Be able to limit the execution time for a job. +1. Be able to specify the number of instances performing a task. +1. Be able to specify triggers on job’s success/failure. + + +## Motivation +Jobs are needed for executing multi-pod computation to completion; a good example +here would be the ability to implement a MapReduce or Hadoop style workload. +Additionally this new controller should take over pod management logic we currently +have in certain OpenShift controllers, namely build controller. + + +## Implementation +Job controller is similar to replication controller in that they manage pods. +This implies they will follow the same controller framework that replication +controllers already defined. The biggest difference between `Job` and +`ReplicationController` objects is the purpose; `ReplicationController` +ensures that a specified number of Pods are running at any one time, whereas +`Job` is responsible for keeping the desired number of Pods to a completion of +a task. This will be represented by the `RestartPolicy` which is required to +always take value of `RestartPolicyNever` or `RestartOnFailure`. + + +The new `Job` object will have the following content: + +```go +// Job represents the configuration of a single job. +type Job struct { + TypeMeta + ObjectMeta + + // Spec is a structure defining the expected behavior of a job. + Spec JobSpec + + // Status is a structure describing current status of a job. + Status JobStatus +} + +// JobList is a collection of jobs. +type JobList struct { + TypeMeta + ListMeta + + Items []Job +} +``` + +`JobSpec` structure is defined to contain all the information how the actual job execution +will look like. + +```go +// JobSpec describes how the job execution will look like. +type JobSpec struct { + + // TaskCount specifies the desired number of pods the job should be run with. + TaskCount int + + // Optional duration in seconds relative to the StartTime that the job may be active + // before the system actively tries to terminate it; value must be positive integer + ActiveDeadlineSeconds *int64 + + // Selector is a label query over pods that should match the pod count. + Selector map[string]string + + // Spec is the object that describes the pod that will be created when + // executing a job. + Spec PodSpec +} +``` + +`JobStatus` structure is defined to contain informations about pods executing +specified job. The structure holds information about pods currently executing +the job. + +```go +// JobStatus represents the current state of a Job. +type JobStatus struct { + // Executions holds a detailed information about each of the pods running a job. + Executions []JobExec + + // Completions is the number of pods successfully completed their job. + Completions int + +} + +// JobExec represents the current state of a single execution of a Job. +type JobExec struct { + // CreationTime represents time when the job execution was created + CreationTime util.Time + + // StartTime represents time when the job execution was started + StartTime util.Time + + // CompletionTime represents time when the job execution was completed + CompletionTime util.Time + + // Phase represents the point in the job execution lifecycle. + Phase JobExecPhase + + // Tag is added in labels of pod(s) created for this job execution. It allows + // job object to safely group/track all pods started for one given job execution. + Tag util.UID +} + +// JobExecPhase represents job execution phase at given point in time. +type JobExecPhase string + +// These are valid JobExec phases. +const ( + // JobExecPending means the pod has been accepted by the system but one or more + // pods has not been started. + JobExecPending JobExecPhase = "Pending" + // JobExecRunning means that all pods have been started. + JobExecRunning JobExecPhase = "Running" + // JobExecComplete means that all pods have terminated with an exit code of 0. + JobExecComplete JobExecPhase = "Complete" + // JobExecFailed means that all pods have terminated and at least one of + // them terminated with non-zero exit code. + JobExecFailed JobExecPhase = "Failed" +) +``` + +## Events +Job controller will be emitting the following events: +* JobStart +* JobFinish + +## Future evolution +Below are the possible future extensions to the Job controller: +* Be able to create a chain of jobs dependent one on another. + +## Discussion points: +* triggers +* replacing build controller (others?) +* diff --git a/docs/proposals/job_controller.md b/docs/proposals/job_controller.md deleted file mode 100644 index 4c92012d5b25..000000000000 --- a/docs/proposals/job_controller.md +++ /dev/null @@ -1,226 +0,0 @@ -**Abstract** - -First basic implementation proposal for a Job controller. Several exiting issues were already created regarding that particular subject: - - Distributed CRON jobs in k8s #2156 - Job Controller #1624 - -Several features also already exist that could be used by external tools to trigger batch execution on one pod within k8 cluster. - - Create a standalone pod (not linked to any existing replication controllers) - Execute a new process within a given container from a running pod. - -**Motivation** - -The main goal is to provide a new pod controller type, called Job, with the following characteristics: - -* Be able to start of one or several pods tracked as a single entity representing a one execution of this job. Final job execution status will reflect the completion status of all pods started for this run. - -* Ability to trigger a new job execution either on demand (triggered through server API by an external agent or by another k8 subsystem), or periodically based on a time-based schedule defined in job specification part (using ISO8601 syntax notation). - -* Be able to restart a limited number of time failing containers of pods created by one job execution (using "Restart on failure" logic extended by a maximal restart count). - -* Be able to limit the execution time of pods created by this job. - -* Be able to provide status information about pending and current job executions, along with a (limited) history of previous job runs (containing start/stop times with completion exit code) - -* (Future evolution) Trigger jobs based on success/failure of others. - - -**Job basic definition** - -The new Job object json definition for a basic implementation will have the following content: -``` -{ - "apiVersion": "v1beta3", - "kind": "Job", - "metadata" : { - "name": "myJob" - "labels" : { - "name": "myJob" - } - } - "spec": { - "schedule": { - "timeSpec": "R5/T01:00:00/PT01", - "skipOutdated": true - "blockOnFailure": false - }, - "allowConcurrentRun": false, - "maxRestart": 2, - "execTimeout": 100, - "PodCount": 1, - "selector": { "name": "myjob"}, - "template": { - "metadata" : { - "name": "myJobPodTemplate" - "labels" : { - "name": "myJobPodTemplate" - } - } - "spec": { - "restartPolicy": "OnFailure" - "containers": [{ - "name": "job-container", - "image": "app/job", - ... - }] - } - } - } -} -``` -**Fields definition:** - -Compared to replication controller, replica count is replaced by the PodCount field (number of Pods started simultaneously for a single job execution run). -All other fields are characteritic of this new controller type: - -* "maxRestart": (default to 1) maximal number of times a failing container is allowed to be restarted. -* "execTimeout": (not restricted by default) maximal duration a container within a pod started by the Job controller is allowed to run. Reaching this limit leads to the container to be killed. -* "PodCount": (default to 1) number of pods started by a single run of the Job. -* "allowConcurrentRun": (default to true) dictates if concurrent runs of this Job are allowed or not. - -* "schedule": (optional) sub structure defining scheduling details - * "timeSpec": describes the job schedule, expressed (using the ISO 8601) with a 3 parts dash separated string: "R[n]/[start date]/[duration]" - The first part gives the number of repetitions of the job (omitting this number means infinite repetitions) - The second part gives the starting time of the scheduling period. - The third part is the duration between successive runs of the scheduled pod(s). - * "suspendOnFailure": dictated if job schedule should be suspended in case of failure of the last completed job run. - * "skipOutdated": dictates if pending scheduled job runs should be discarded in favour of the latest one. This covers the case of a job having suspended its execution after a failed run, with several schedule points reached in the meantime (or the case of a long lasting run with concurrent execution disable). Instead of stacking pending executions, only the latest one is kept (and intermediate pending runs discarded). - -**Implementation details** - -Job objects are stored in a dedicated registry directory key (separated from the directory key used for replication controllers). - -Similarly to replication controllers, a dedicated manager takes care of all jobs existing in the system, performing the following tasks: - -* Executes a loop on the full list of defined jobs, calling on each a defined synchronization call-back, each execution loop being spaced by a configuration defined time interval (with default value of 5 seconds). -* Performs a (recursive) watch of the registry directory key containing jobs definition. For each job newly defined or updated in the system, the same synchronization routine is invoked. - -This job manager provides a way for each job defined with schedule information to setup a dedicated timer for next schedule time. This allows a better accuracy of start execution time for pods launched by jobs and remove dependency on the interval value set for the synchronization loop. - -The maximal restart count and maximal execution time for pods containers started by a job will be enforced at kubelet level, using dedicated resource limits added by the job in pod's containers definition. Two new resource types ("execution time" and "execution count") are introduced, that are used to add in the container's resources limits the figures defined in job specification and taken into account by the kubelet module (container is killed if the execution time is reached and restarted in case of failure exit up to this maximal count). - -In order to precisely track job pods, 2 specific labels are pushed in created pod metadata: -* the job name ("jobName") -* A tag ("jobTag", either a generated UID, or simply the schedule date of this job execution) allowing to group all pods started started for a given job execution. - -Along with labels, specific environment variables are also dynamically added in created pods definition: the number of pods started for this job execution and for each one its index number in the started pods list. - -Job has the responsibility to advertise job run completion status (success or failure) through events, to perform the necessary clean-up in pods registry, to provide a detailed status of active job runs and the completion status of previous completed runs up to a given amount of history). -Collecting the standard output/error of pod's containers is not covered by this design (a common solution for containers started by any controller is needed). - -**API types definition:** - -The following API objects can be introduced: - -``` -type JobScheduleSpec struct { - - // TimeSpec contains the schedule in ISO8601 format. - TimeSpec string `json:"timeSpec"` - - // SkipOutdated specifies that if AllowConcurrent is false, only the latest pending job - // that is waiting for the currently executing one to complete must be started (default: true) - SkipOutdated bool `json:"skipOutdated"` - - // BlockOnFailure suspends scheduling of next job runs after a failed one - BlockOnFailure bool `json:"blockOnFailure"` -} - -type JobSpec struct { - - // JobScheduleSpec contains scheduling related infos - JobScheduleSpec ScheduleSpec `json:"scheduleSpec"` - - // AllowConcurrent specified whether concurrent jobs may be started - // (covers the case where new job schedule time is reached, while - // other previously started jobs are still running) - AllowConcurrent bool `json:"allowConcurrent"` - - // ExecTimeout specifies the max amount of time a job is allowed to run (in seconds). - ExecTimeout int `json:"execTimeout"` - - // MaxRestart specifies the max number of restarts for a failing scheduled pod. - MaxRestart int `json:"maxRestart"` - - // PodCount specifies the numbe of pods to start for each job run - PodCount int `json:"podCount"` - - // Pod selector for that controller - Selector map[string]string `json:"selector"` - - // Reference to stand alone PodTemplate - TemplateRef *ObjectReference `json:"templateRef,omitempty"` - - // Embedded pod template - Template *PodTemplateSpec `json:"template,omitempty"` -} - -type JobExecStatus string -const ( - JobExecPending JobExecStatus = "pending" - JobExecRunning JobExecStatus = "running" - JobExecCompleted JobExecStatus = "completed" -) - -type JobExecution struct { - // CreatedAt gives job creation time - CreatedAt util.Time - - // StartedAt gives job starting time - StartedAt util.Time - - // CompletedAt - CompletedAt util.Time - - // Success gives job completion result - Success bool - - // JobExecStatus - Status JobExecStatus - - // Tag is added in labels of pod(s) created for this job execution. It allows - // job object to safely group/track all pods started for one given job execution. - Tag util.UID -} - -// JobStatus represents the current state of Job -type JobStatus struct { - // PendingExecutions are the job runs pending for execution - PendingExecutions []JobExecution `json:"pendingExecutions"` - - // CurrentExecutions are the job run currently executing - // (With pods scheduled in the kubernetes cluster) - RunningExecutions []JobExecution `json:"runningExecutions"` - - // PreviousRunStates tracks previously scheduled jobs (up to a limited amount) - CompletedExecution []JobExecution `json:"completedExecution"` - - // ScheduleCount tracks the count of run for this job - ScheduleCount int `json:"scheduleCount"` -} - -// Job represents the configuration of a job controller. -type Job struct { - TypeMeta `json:",inline"` - ObjectMeta `json:"metadata,omitempty"` - - // Spec defines the desired behavior of this job controller. - Spec JobSpec `json:"spec,omitempty"` - - // Status is the current status of this job controller. - Status JobStatus `json:"status,omitempty"` -} - -// JobList is a collection of job controllers. -type JobList struct { - TypeMeta `json:",inline"` - ListMeta `json:"metadata,omitempty"` - - Items []Job `json:"items"` -} -``` - -JobExecution structure is defined to contain all informations for pending, running and completed job executions. The Job status structure holds objects of this type in three separated ordered lists (one by execution status). The "pending" execution list is used as a way to stack executions for job preventing concurrent runs, and also to trigger execution for job defined without time based scheduling. A new API server entry point is introduced to allow this on-demand job execution. Changes in this pending list is detected by the watch process in controller-manager module and the job instance called back takes the appropriate action (in the common case, creates pods and move this job execution in the running list) - diff --git a/docs/proposals/scheduledjob.md b/docs/proposals/scheduledjob.md new file mode 100644 index 000000000000..eef28c482c82 --- /dev/null +++ b/docs/proposals/scheduledjob.md @@ -0,0 +1,113 @@ +# ScheduledJob Controller + +## Abstract +A proposal for implementing a new controller - ScheduledJob controller - which +will be responsible for managing time based jobs, namely: +* once at a specified point in time, +* repeatedly at a specified point in time. + +There is already an upstream discussion regarding that particular subject: +* Distributed CRON jobs [#2156](https://github.com/GoogleCloudPlatform/kubernetes/issues/2156) + +There are also similar solutions available already: +* [Mesos Chronos](https://github.com/mesos/chronos) +* [Quartz](http://quartz-scheduler.org/) + + +## Use Cases +1. Be able to schedule a job execution at a given point in time. +1. Be able to create a repetitive job, eg. database backup, sending emails. + + +## Motivation +ScheduledJobs are needed for performing all time related actions, namely backups, +report generation and alike. Each of these tasks should be allowed to perform +repeatedly (once a day/month, etc.) or once at a given point in time. + + +## Implementation +ScheduledJob controller relies heavily on the [Job Controller API](https://github.com/openshift/origin/blob/master/docs/proposals/job.md) +for running actual jobs, on top of which it adds information regarding the date +and time part according to ISO8601 format. + +The new `ScheduledJob` object will have the following content: + +```go +// ScheduledJob represents the configuration of a single scheduled job. +type ScheduledJob struct { + TypeMeta + ObjectMeta + + // Spec is a structure defining the expected behavior of a job, including the schedule. + Spec ScheduledJobSpec + + // Status is a structure describing current status of a job. + Status ScheduledJobStatus +} + +// ScheduledJobList is a collection of scheduled jobs. +type ScheduledJobList struct { + TypeMeta + ListMeta + + Items []ScheduledJob +} +``` + +`ScheduledJobSpec` structure is defined to contain all the information how the actual +job execution will look like, including the `JobSpec` from [Job Controller API](https://github.com/openshift/origin/blob/master/docs/proposals/job.md) +and the schedule in ISO8601 format. + +```go +// ScheduledJobSpec describes how the job execution will look like and when it will actually run. +type ScheduledJobSpec struct { + + // Spec is a structure defining the expected behavior of a job. + Spec JobSpec + + // Schedule contains the schedule in ISO8601 format, eg. + // - 2015-07-21T14:00:00Z - represents date and time in UTC + // - R/2015-07-21T14:00:00Z/P1D - represents endlessly repeating interval (1 day), starting from given date + Schedule string + + // SkipOutdated specifies that if AllowConcurrent is false, only the newest job + // will be started (default: true), ignoring executions that missed their schedule. + SkipOutdated bool + + // BlockOnFailure suspends scheduling of next job runs after a failed one. + BlockOnFailure bool + + // AllowConcurrent specified whether concurrent jobs may be started. + AllowConcurrent bool +} +``` + +`ScheduledJobStatus` structure is defined to contain some information for scheduled +job executions (up to a limited amount). The structure holds objects in three lists: +* "Pending" list is used as a way to stack executions for job preventing concurrent +runs, and also to trigger an execution for a job defined without time based scheduling; +* "Running" list contains all actually running jobs with detailed information; +* "Failed" list contains information about recently failed jobs. + +```go +// ScheduledJobStatus represents the current state of a Job. +type ScheduledJobStatus struct { + // PendingExecutions are the job runs pending for execution + PendingExecutions []JobStatus + + // CurrentExecutions are the job run currently executing + RunningExecutions []JobStatus + + // CompletedExecutions tracks previously scheduled jobs (up to a limited amount) + CompletedExecutions []JobStatus + + // FailedExecutions tracks previously failed jobs + FailedExecutions []JobStatus + + // ScheduleCount tracks the amount of successful executions for this job + CompletedCount int + + // FailedCount tracks the amount of failures for this job + FailedCount int +} +```