mirror of https://github.com/k3s-io/k3s
Move internal types of job from pkg/apis/extensions to pkg/apis/batch
parent
c5df0bf23e
commit
a3b4447305
|
@ -32,7 +32,7 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
test = flag.BoolP("test", "t", false, "set this flag to generate the client code for the testdata")
|
test = flag.BoolP("test", "t", false, "set this flag to generate the client code for the testdata")
|
||||||
inputVersions = flag.StringSlice("input", []string{"api/", "extensions/"}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions\"")
|
inputVersions = flag.StringSlice("input", []string{"api/", "extensions/", "batch/"}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions/,batch/\"")
|
||||||
clientsetName = flag.StringP("clientset-name", "n", "internalclientset", "the name of the generated clientset package.")
|
clientsetName = flag.StringP("clientset-name", "n", "internalclientset", "the name of the generated clientset package.")
|
||||||
clientsetPath = flag.String("clientset-path", "k8s.io/kubernetes/pkg/client/clientset_generated/", "the generated clientset will be output to <clientset-path>/<clientset-name>. Default to \"k8s.io/kubernetes/pkg/client/clientset_generated/\"")
|
clientsetPath = flag.String("clientset-path", "k8s.io/kubernetes/pkg/client/clientset_generated/", "the generated clientset will be output to <clientset-path>/<clientset-name>. Default to \"k8s.io/kubernetes/pkg/client/clientset_generated/\"")
|
||||||
clientsetOnly = flag.Bool("clientset-only", false, "when set, client-gen only generates the clientset shell, without generating the individual typed clients")
|
clientsetOnly = flag.Bool("clientset-only", false, "when set, client-gen only generates the clientset shell, without generating the individual typed clients")
|
||||||
|
|
|
@ -60,6 +60,7 @@ func DefaultNameSystem() string {
|
||||||
var fallbackPackages = []string{
|
var fallbackPackages = []string{
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned",
|
"k8s.io/kubernetes/pkg/api/unversioned",
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions",
|
"k8s.io/kubernetes/pkg/apis/extensions",
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch",
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInternalTypeFor(context *generator.Context, t *types.Type) (*types.Type, bool) {
|
func getInternalTypeFor(context *generator.Context, t *types.Type) (*types.Type, bool) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
expvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation"
|
expvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation"
|
||||||
"k8s.io/kubernetes/pkg/capabilities"
|
"k8s.io/kubernetes/pkg/capabilities"
|
||||||
|
@ -109,7 +110,7 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
|
||||||
t.Namespace = api.NamespaceDefault
|
t.Namespace = api.NamespaceDefault
|
||||||
}
|
}
|
||||||
errors = expvalidation.ValidateDeployment(t)
|
errors = expvalidation.ValidateDeployment(t)
|
||||||
case *extensions.Job:
|
case *batch.Job:
|
||||||
if t.Namespace == "" {
|
if t.Namespace == "" {
|
||||||
t.Namespace = api.NamespaceDefault
|
t.Namespace = api.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
@ -237,7 +238,7 @@ func TestExampleObjectSchemas(t *testing.T) {
|
||||||
"../docs/user-guide": {
|
"../docs/user-guide": {
|
||||||
"multi-pod": nil,
|
"multi-pod": nil,
|
||||||
"pod": &api.Pod{},
|
"pod": &api.Pod{},
|
||||||
"job": &extensions.Job{},
|
"job": &batch.Job{},
|
||||||
"ingress": &extensions.Ingress{},
|
"ingress": &extensions.Ingress{},
|
||||||
"nginx-deployment": &extensions.Deployment{},
|
"nginx-deployment": &extensions.Deployment{},
|
||||||
"new-nginx-deployment": &extensions.Deployment{},
|
"new-nginx-deployment": &extensions.Deployment{},
|
||||||
|
@ -405,12 +406,12 @@ func TestExampleObjectSchemas(t *testing.T) {
|
||||||
"javaweb-2": &api.Pod{},
|
"javaweb-2": &api.Pod{},
|
||||||
},
|
},
|
||||||
"../examples/job/work-queue-1": {
|
"../examples/job/work-queue-1": {
|
||||||
"job": &extensions.Job{},
|
"job": &batch.Job{},
|
||||||
},
|
},
|
||||||
"../examples/job/work-queue-2": {
|
"../examples/job/work-queue-2": {
|
||||||
"redis-pod": &api.Pod{},
|
"redis-pod": &api.Pod{},
|
||||||
"redis-service": &api.Service{},
|
"redis-service": &api.Service{},
|
||||||
"job": &extensions.Job{},
|
"job": &batch.Job{},
|
||||||
},
|
},
|
||||||
"../examples/azure_file": {
|
"../examples/azure_file": {
|
||||||
"azure": &api.Pod{},
|
"azure": &api.Pod{},
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
@ -156,7 +157,7 @@ func FuzzerFor(t *testing.T, version unversioned.GroupVersion, src rand.Source)
|
||||||
j.RollingUpdate = &rollingUpdate
|
j.RollingUpdate = &rollingUpdate
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func(j *extensions.JobSpec, c fuzz.Continue) {
|
func(j *batch.JobSpec, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||||
completions := int(c.Rand.Int31())
|
completions := int(c.Rand.Int31())
|
||||||
parallelism := int(c.Rand.Int31())
|
parallelism := int(c.Rand.Int31())
|
||||||
|
|
|
@ -19,7 +19,6 @@ package batch
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -47,8 +46,11 @@ func AddToScheme(scheme *runtime.Scheme) {
|
||||||
// Adds the list of known types to api.Scheme.
|
// Adds the list of known types to api.Scheme.
|
||||||
func addKnownTypes(scheme *runtime.Scheme) {
|
func addKnownTypes(scheme *runtime.Scheme) {
|
||||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||||
&extensions.Job{},
|
&Job{},
|
||||||
&extensions.JobList{},
|
&JobList{},
|
||||||
&api.ListOptions{},
|
&api.ListOptions{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (obj *Job) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
|
func (obj *JobList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package batch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
)
|
||||||
|
|
||||||
|
// +genclient=true
|
||||||
|
|
||||||
|
// Job represents the configuration of a single job.
|
||||||
|
type Job struct {
|
||||||
|
unversioned.TypeMeta `json:",inline"`
|
||||||
|
// Standard object's metadata.
|
||||||
|
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||||
|
api.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
// Spec is a structure defining the expected behavior of a job.
|
||||||
|
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
||||||
|
Spec JobSpec `json:"spec,omitempty"`
|
||||||
|
|
||||||
|
// Status is a structure describing current status of a job.
|
||||||
|
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
||||||
|
Status JobStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// JobList is a collection of jobs.
|
||||||
|
type JobList struct {
|
||||||
|
unversioned.TypeMeta `json:",inline"`
|
||||||
|
// Standard list metadata
|
||||||
|
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||||
|
unversioned.ListMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
// Items is the list of Job.
|
||||||
|
Items []Job `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// JobSpec describes how the job execution will look like.
|
||||||
|
type JobSpec struct {
|
||||||
|
|
||||||
|
// Parallelism specifies the maximum desired number of pods the job should
|
||||||
|
// run at any given time. The actual number of pods running in steady state will
|
||||||
|
// be less than this number when ((.spec.completions - .status.successful) < .spec.parallelism),
|
||||||
|
// i.e. when the work left to do is less than max parallelism.
|
||||||
|
Parallelism *int `json:"parallelism,omitempty"`
|
||||||
|
|
||||||
|
// Completions specifies the desired number of successfully finished pods the
|
||||||
|
// job should be run with. Setting to nil means that the success of any
|
||||||
|
// pod signals the success of all pods, and allows parallelism to have any positive
|
||||||
|
// value. Setting to 1 means that parallelism is limited to 1 and the success of that
|
||||||
|
// pod signals the success of the job.
|
||||||
|
Completions *int `json:"completions,omitempty"`
|
||||||
|
|
||||||
|
// Optional duration in seconds relative to the startTime that the job may be active
|
||||||
|
// before the system tries to terminate it; value must be positive integer
|
||||||
|
ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"`
|
||||||
|
|
||||||
|
// Selector is a label query over pods that should match the pod count.
|
||||||
|
// Normally, the system sets this field for you.
|
||||||
|
Selector *unversioned.LabelSelector `json:"selector,omitempty"`
|
||||||
|
|
||||||
|
// ManualSelector controls generation of pod labels and pod selectors.
|
||||||
|
// Leave `manualSelector` unset unless you are certain what you are doing.
|
||||||
|
// When false or unset, the system pick labels unique to this job
|
||||||
|
// and appends those labels to the pod template. When true,
|
||||||
|
// the user is responsible for picking unique labels and specifying
|
||||||
|
// the selector. Failure to pick a unique label may cause this
|
||||||
|
// and other jobs to not function correctly. However, You may see
|
||||||
|
// `manualSelector=true` in jobs that were created with the old `extensions/v1beta1`
|
||||||
|
// API.
|
||||||
|
ManualSelector *bool `json:"manualSelector,omitempty"`
|
||||||
|
|
||||||
|
// Template is the object that describes the pod that will be created when
|
||||||
|
// executing a job.
|
||||||
|
Template api.PodTemplateSpec `json:"template"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// JobStatus represents the current state of a Job.
|
||||||
|
type JobStatus struct {
|
||||||
|
|
||||||
|
// Conditions represent the latest available observations of an object's current state.
|
||||||
|
Conditions []JobCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// StartTime represents time when the job was acknowledged by the Job Manager.
|
||||||
|
// It is not guaranteed to be set in happens-before order across separate operations.
|
||||||
|
// It is represented in RFC3339 form and is in UTC.
|
||||||
|
StartTime *unversioned.Time `json:"startTime,omitempty"`
|
||||||
|
|
||||||
|
// CompletionTime represents time when the job was completed. It is not guaranteed to
|
||||||
|
// be set in happens-before order across separate operations.
|
||||||
|
// It is represented in RFC3339 form and is in UTC.
|
||||||
|
CompletionTime *unversioned.Time `json:"completionTime,omitempty"`
|
||||||
|
|
||||||
|
// Active is the number of actively running pods.
|
||||||
|
Active int `json:"active,omitempty"`
|
||||||
|
|
||||||
|
// Succeeded is the number of pods which reached Phase Succeeded.
|
||||||
|
Succeeded int `json:"succeeded,omitempty"`
|
||||||
|
|
||||||
|
// Failed is the number of pods which reached Phase Failed.
|
||||||
|
Failed int `json:"failed,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobConditionType string
|
||||||
|
|
||||||
|
// These are valid conditions of a job.
|
||||||
|
const (
|
||||||
|
// JobComplete means the job has completed its execution.
|
||||||
|
JobComplete JobConditionType = "Complete"
|
||||||
|
// JobFailed means the job has failed its execution.
|
||||||
|
JobFailed JobConditionType = "Failed"
|
||||||
|
)
|
||||||
|
|
||||||
|
// JobCondition describes current state of a job.
|
||||||
|
type JobCondition struct {
|
||||||
|
// Type of job condition, Complete or Failed.
|
||||||
|
Type JobConditionType `json:"type"`
|
||||||
|
// Status of the condition, one of True, False, Unknown.
|
||||||
|
Status api.ConditionStatus `json:"status"`
|
||||||
|
// Last time the condition was checked.
|
||||||
|
LastProbeTime unversioned.Time `json:"lastProbeTime,omitempty"`
|
||||||
|
// Last time the condition transit from one status to another.
|
||||||
|
LastTransitionTime unversioned.Time `json:"lastTransitionTime,omitempty"`
|
||||||
|
// (brief) reason for the condition's last transition.
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
|
// Human readable message indicating details about last transition.
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
|
@ -18,14 +18,22 @@ package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
|
"k8s.io/kubernetes/pkg/conversion"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addConversionFuncs(scheme *runtime.Scheme) {
|
func addConversionFuncs(scheme *runtime.Scheme) {
|
||||||
// Add non-generated conversion functions
|
// Add non-generated conversion functions
|
||||||
err := scheme.AddConversionFuncs()
|
err := scheme.AddConversionFuncs(
|
||||||
|
Convert_batch_JobSpec_To_v1_JobSpec,
|
||||||
|
Convert_v1_JobSpec_To_batch_JobSpec,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If one of the conversion functions is malformed, detect it immediately.
|
// If one of the conversion functions is malformed, detect it immediately.
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -45,3 +53,91 @@ func addConversionFuncs(scheme *runtime.Scheme) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Convert_batch_JobSpec_To_v1_JobSpec(in *batch.JobSpec, out *JobSpec, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*batch.JobSpec))(in)
|
||||||
|
}
|
||||||
|
if in.Parallelism != nil {
|
||||||
|
out.Parallelism = new(int32)
|
||||||
|
*out.Parallelism = int32(*in.Parallelism)
|
||||||
|
} else {
|
||||||
|
out.Parallelism = nil
|
||||||
|
}
|
||||||
|
if in.Completions != nil {
|
||||||
|
out.Completions = new(int32)
|
||||||
|
*out.Completions = int32(*in.Completions)
|
||||||
|
} else {
|
||||||
|
out.Completions = nil
|
||||||
|
}
|
||||||
|
if in.ActiveDeadlineSeconds != nil {
|
||||||
|
out.ActiveDeadlineSeconds = new(int64)
|
||||||
|
*out.ActiveDeadlineSeconds = *in.ActiveDeadlineSeconds
|
||||||
|
} else {
|
||||||
|
out.ActiveDeadlineSeconds = nil
|
||||||
|
}
|
||||||
|
// unable to generate simple pointer conversion for unversioned.LabelSelector -> v1.LabelSelector
|
||||||
|
if in.Selector != nil {
|
||||||
|
out.Selector = new(LabelSelector)
|
||||||
|
if err := Convert_unversioned_LabelSelector_To_v1_LabelSelector(in.Selector, out.Selector, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Selector = nil
|
||||||
|
}
|
||||||
|
if in.ManualSelector != nil {
|
||||||
|
out.ManualSelector = new(bool)
|
||||||
|
*out.ManualSelector = *in.ManualSelector
|
||||||
|
} else {
|
||||||
|
out.ManualSelector = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := v1.Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, &out.Template, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Convert_v1_JobSpec_To_batch_JobSpec(in *JobSpec, out *batch.JobSpec, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*JobSpec))(in)
|
||||||
|
}
|
||||||
|
if in.Parallelism != nil {
|
||||||
|
out.Parallelism = new(int)
|
||||||
|
*out.Parallelism = int(*in.Parallelism)
|
||||||
|
} else {
|
||||||
|
out.Parallelism = nil
|
||||||
|
}
|
||||||
|
if in.Completions != nil {
|
||||||
|
out.Completions = new(int)
|
||||||
|
*out.Completions = int(*in.Completions)
|
||||||
|
} else {
|
||||||
|
out.Completions = nil
|
||||||
|
}
|
||||||
|
if in.ActiveDeadlineSeconds != nil {
|
||||||
|
out.ActiveDeadlineSeconds = new(int64)
|
||||||
|
*out.ActiveDeadlineSeconds = *in.ActiveDeadlineSeconds
|
||||||
|
} else {
|
||||||
|
out.ActiveDeadlineSeconds = nil
|
||||||
|
}
|
||||||
|
// unable to generate simple pointer conversion for v1.LabelSelector -> unversioned.LabelSelector
|
||||||
|
if in.Selector != nil {
|
||||||
|
out.Selector = new(unversioned.LabelSelector)
|
||||||
|
if err := Convert_v1_LabelSelector_To_unversioned_LabelSelector(in.Selector, out.Selector, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Selector = nil
|
||||||
|
}
|
||||||
|
if in.ManualSelector != nil {
|
||||||
|
out.ManualSelector = new(bool)
|
||||||
|
*out.ManualSelector = *in.ManualSelector
|
||||||
|
} else {
|
||||||
|
out.ManualSelector = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := v1.Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(&in.Template, &out.Template, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
unversionedvalidation "k8s.io/kubernetes/pkg/api/unversioned/validation"
|
||||||
|
apivalidation "k8s.io/kubernetes/pkg/api/validation"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: generalize for other controller objects that will follow the same pattern, such as ReplicaSet and DaemonSet, and
|
||||||
|
// move to new location. Replace batch.Job with an interface.
|
||||||
|
//
|
||||||
|
// ValidateGeneratedSelector validates that the generated selector on a controller object match the controller object
|
||||||
|
// metadata, and the labels on the pod template are as generated.
|
||||||
|
func ValidateGeneratedSelector(obj *batch.Job) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if obj.Spec.ManualSelector != nil && *obj.Spec.ManualSelector {
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.Spec.Selector == nil {
|
||||||
|
return allErrs // This case should already have been checked in caller. No need for more errors.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If somehow uid was unset then we would get "controller-uid=" as the selector
|
||||||
|
// which is bad.
|
||||||
|
if obj.ObjectMeta.UID == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(field.NewPath("metadata").Child("uid"), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If somehow uid was unset then we would get "controller-uid=" as the selector
|
||||||
|
// which is bad.
|
||||||
|
if obj.ObjectMeta.UID == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(field.NewPath("metadata").Child("uid"), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If selector generation was requested, then expected labels must be
|
||||||
|
// present on pod template, and much match job's uid and name. The
|
||||||
|
// generated (not-manual) selectors/labels ensure no overlap with other
|
||||||
|
// controllers. The manual mode allows orphaning, adoption,
|
||||||
|
// backward-compatibility, and experimentation with new
|
||||||
|
// labeling/selection schemes. Automatic selector generation should
|
||||||
|
// have placed certain labels on the pod, but this could have failed if
|
||||||
|
// the user added coflicting labels. Validate that the expected
|
||||||
|
// generated ones are there.
|
||||||
|
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateHasLabel(obj.Spec.Template.ObjectMeta, field.NewPath("spec").Child("template").Child("metadata"), "controller-uid", string(obj.UID))...)
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateHasLabel(obj.Spec.Template.ObjectMeta, field.NewPath("spec").Child("template").Child("metadata"), "job-name", string(obj.Name))...)
|
||||||
|
expectedLabels := make(map[string]string)
|
||||||
|
expectedLabels["controller-uid"] = string(obj.UID)
|
||||||
|
expectedLabels["job-name"] = string(obj.Name)
|
||||||
|
// Whether manually or automatically generated, the selector of the job must match the pods it will produce.
|
||||||
|
if selector, err := unversioned.LabelSelectorAsSelector(obj.Spec.Selector); err == nil {
|
||||||
|
if !selector.Matches(labels.Set(expectedLabels)) {
|
||||||
|
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("selector"), obj.Spec.Selector, "`selector` not auto-generated"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateJob(job *batch.Job) field.ErrorList {
|
||||||
|
// Jobs and rcs have the same name validation
|
||||||
|
allErrs := apivalidation.ValidateObjectMeta(&job.ObjectMeta, true, apivalidation.ValidateReplicationControllerName, field.NewPath("metadata"))
|
||||||
|
allErrs = append(allErrs, ValidateGeneratedSelector(job)...)
|
||||||
|
allErrs = append(allErrs, ValidateJobSpec(&job.Spec, field.NewPath("spec"))...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateJobSpec(spec *batch.JobSpec, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
|
if spec.Parallelism != nil {
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Parallelism), fldPath.Child("parallelism"))...)
|
||||||
|
}
|
||||||
|
if spec.Completions != nil {
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Completions), fldPath.Child("completions"))...)
|
||||||
|
}
|
||||||
|
if spec.ActiveDeadlineSeconds != nil {
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.ActiveDeadlineSeconds), fldPath.Child("activeDeadlineSeconds"))...)
|
||||||
|
}
|
||||||
|
if spec.Selector == nil {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
|
||||||
|
} else {
|
||||||
|
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whether manually or automatically generated, the selector of the job must match the pods it will produce.
|
||||||
|
if selector, err := unversioned.LabelSelectorAsSelector(spec.Selector); err == nil {
|
||||||
|
labels := labels.Set(spec.Template.Labels)
|
||||||
|
if !selector.Matches(labels) {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...)
|
||||||
|
if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure &&
|
||||||
|
spec.Template.Spec.RestartPolicy != api.RestartPolicyNever {
|
||||||
|
allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"),
|
||||||
|
spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)}))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateJobStatus(status *batch.JobStatus, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Active), fldPath.Child("active"))...)
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Succeeded), fldPath.Child("succeeded"))...)
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Failed), fldPath.Child("failed"))...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateJobUpdate(job, oldJob *batch.Job) field.ErrorList {
|
||||||
|
allErrs := apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta, field.NewPath("metadata"))
|
||||||
|
allErrs = append(allErrs, ValidateJobSpecUpdate(job.Spec, oldJob.Spec, field.NewPath("spec"))...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateJobUpdateStatus(job, oldJob *batch.Job) field.ErrorList {
|
||||||
|
allErrs := apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta, field.NewPath("metadata"))
|
||||||
|
allErrs = append(allErrs, ValidateJobStatusUpdate(job.Status, oldJob.Status)...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateJobSpecUpdate(spec, oldSpec batch.JobSpec, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
allErrs = append(allErrs, ValidateJobSpec(&spec, fldPath)...)
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Completions, oldSpec.Completions, fldPath.Child("completions"))...)
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Selector, oldSpec.Selector, fldPath.Child("selector"))...)
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Template, oldSpec.Template, fldPath.Child("template"))...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateJobStatusUpdate(status, oldStatus batch.JobStatus) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
allErrs = append(allErrs, ValidateJobStatus(&status, field.NewPath("status"))...)
|
||||||
|
return allErrs
|
||||||
|
}
|
|
@ -0,0 +1,297 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
|
"k8s.io/kubernetes/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateJob(t *testing.T) {
|
||||||
|
validManualSelector := &unversioned.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{"a": "b"},
|
||||||
|
}
|
||||||
|
validGeneratedSelector := &unversioned.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{"controller-uid": "1a2b3c", "job-name": "myjob"},
|
||||||
|
}
|
||||||
|
validPodTemplateSpecForManual := api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: validManualSelector.MatchLabels,
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicyOnFailure,
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
validPodTemplateSpecForGenerated := api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: validGeneratedSelector.MatchLabels,
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicyOnFailure,
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
successCases := map[string]batch.Job{
|
||||||
|
"manual selector": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Selector: validManualSelector,
|
||||||
|
ManualSelector: newBool(true),
|
||||||
|
Template: validPodTemplateSpecForManual,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"generated selector": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Selector: validGeneratedSelector,
|
||||||
|
ManualSelector: newBool(false),
|
||||||
|
Template: validPodTemplateSpecForGenerated,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for k, v := range successCases {
|
||||||
|
if errs := ValidateJob(&v); len(errs) != 0 {
|
||||||
|
t.Errorf("expected success for %s: %v", k, errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
negative := -1
|
||||||
|
negative64 := int64(-1)
|
||||||
|
errorCases := map[string]batch.Job{
|
||||||
|
"spec.parallelism:must be greater than or equal to 0": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Parallelism: &negative,
|
||||||
|
ManualSelector: newBool(true),
|
||||||
|
Template: validPodTemplateSpecForGenerated,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec.completions:must be greater than or equal to 0": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Completions: &negative,
|
||||||
|
Selector: validManualSelector,
|
||||||
|
ManualSelector: newBool(true),
|
||||||
|
Template: validPodTemplateSpecForGenerated,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec.activeDeadlineSeconds:must be greater than or equal to 0": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
ActiveDeadlineSeconds: &negative64,
|
||||||
|
Selector: validManualSelector,
|
||||||
|
ManualSelector: newBool(true),
|
||||||
|
Template: validPodTemplateSpecForGenerated,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec.selector:Required value": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Template: validPodTemplateSpecForGenerated,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec.template.metadata.labels: Invalid value: {\"y\":\"z\"}: `selector` does not match template `labels`": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Selector: validManualSelector,
|
||||||
|
ManualSelector: newBool(true),
|
||||||
|
Template: api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: map[string]string{"y": "z"},
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicyOnFailure,
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec.template.metadata.labels: Invalid value: {\"controller-uid\":\"4d5e6f\"}: `selector` does not match template `labels`": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Selector: validManualSelector,
|
||||||
|
ManualSelector: newBool(true),
|
||||||
|
Template: api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: map[string]string{"controller-uid": "4d5e6f"},
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicyOnFailure,
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec.template.spec.restartPolicy: Unsupported value": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "myjob",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
UID: types.UID("1a2b3c"),
|
||||||
|
},
|
||||||
|
Spec: batch.JobSpec{
|
||||||
|
Selector: validManualSelector,
|
||||||
|
ManualSelector: newBool(true),
|
||||||
|
Template: api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: validManualSelector.MatchLabels,
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range errorCases {
|
||||||
|
errs := ValidateJob(&v)
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Errorf("expected failure for %s", k)
|
||||||
|
} else {
|
||||||
|
s := strings.Split(k, ":")
|
||||||
|
err := errs[0]
|
||||||
|
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
|
||||||
|
t.Errorf("unexpected error: %v, expected: %s", err, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateJobUpdateStatus(t *testing.T) {
|
||||||
|
type testcase struct {
|
||||||
|
old batch.Job
|
||||||
|
update batch.Job
|
||||||
|
}
|
||||||
|
|
||||||
|
successCases := []testcase{
|
||||||
|
{
|
||||||
|
old: batch.Job{
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
|
Status: batch.JobStatus{
|
||||||
|
Active: 1,
|
||||||
|
Succeeded: 2,
|
||||||
|
Failed: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: batch.Job{
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
|
Status: batch.JobStatus{
|
||||||
|
Active: 1,
|
||||||
|
Succeeded: 1,
|
||||||
|
Failed: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, successCase := range successCases {
|
||||||
|
successCase.old.ObjectMeta.ResourceVersion = "1"
|
||||||
|
successCase.update.ObjectMeta.ResourceVersion = "1"
|
||||||
|
if errs := ValidateJobUpdateStatus(&successCase.update, &successCase.old); len(errs) != 0 {
|
||||||
|
t.Errorf("expected success: %v", errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCases := map[string]testcase{
|
||||||
|
"[status.active: Invalid value: -1: must be greater than or equal to 0, status.succeeded: Invalid value: -2: must be greater than or equal to 0]": {
|
||||||
|
old: batch.Job{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "abc",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
ResourceVersion: "10",
|
||||||
|
},
|
||||||
|
Status: batch.JobStatus{
|
||||||
|
Active: 1,
|
||||||
|
Succeeded: 2,
|
||||||
|
Failed: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: batch.Job{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "abc",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
ResourceVersion: "10",
|
||||||
|
},
|
||||||
|
Status: batch.JobStatus{
|
||||||
|
Active: -1,
|
||||||
|
Succeeded: -2,
|
||||||
|
Failed: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testName, errorCase := range errorCases {
|
||||||
|
errs := ValidateJobUpdateStatus(&errorCase.update, &errorCase.old)
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Errorf("expected failure: %s", testName)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if errs.ToAggregate().Error() != testName {
|
||||||
|
t.Errorf("expected '%s' got '%s'", errs.ToAggregate().Error(), testName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBool(val bool) *bool {
|
||||||
|
p := new(bool)
|
||||||
|
*p = val
|
||||||
|
return p
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ package extensions
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,8 +53,8 @@ func addKnownTypes(scheme *runtime.Scheme) {
|
||||||
&DeploymentRollback{},
|
&DeploymentRollback{},
|
||||||
&HorizontalPodAutoscaler{},
|
&HorizontalPodAutoscaler{},
|
||||||
&HorizontalPodAutoscalerList{},
|
&HorizontalPodAutoscalerList{},
|
||||||
&Job{},
|
&batch.Job{},
|
||||||
&JobList{},
|
&batch.JobList{},
|
||||||
&ReplicationControllerDummy{},
|
&ReplicationControllerDummy{},
|
||||||
&Scale{},
|
&Scale{},
|
||||||
&ThirdPartyResource{},
|
&ThirdPartyResource{},
|
||||||
|
@ -78,8 +79,6 @@ func (obj *DeploymentList) GetObjectKind() unversioned.ObjectKind {
|
||||||
func (obj *DeploymentRollback) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
func (obj *DeploymentRollback) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
func (obj *HorizontalPodAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
func (obj *HorizontalPodAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
func (obj *HorizontalPodAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
func (obj *HorizontalPodAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
func (obj *Job) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
|
||||||
func (obj *JobList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
|
||||||
func (obj *ReplicationControllerDummy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
func (obj *ReplicationControllerDummy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
func (obj *ThirdPartyResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
func (obj *ThirdPartyResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||||
|
|
|
@ -496,127 +496,6 @@ type ThirdPartyResourceDataList struct {
|
||||||
|
|
||||||
// +genclient=true
|
// +genclient=true
|
||||||
|
|
||||||
// Job represents the configuration of a single job.
|
|
||||||
type Job struct {
|
|
||||||
unversioned.TypeMeta `json:",inline"`
|
|
||||||
// Standard object's metadata.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
|
||||||
api.ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
// Spec is a structure defining the expected behavior of a job.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
|
||||||
Spec JobSpec `json:"spec,omitempty"`
|
|
||||||
|
|
||||||
// Status is a structure describing current status of a job.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
|
||||||
Status JobStatus `json:"status,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// JobList is a collection of jobs.
|
|
||||||
type JobList struct {
|
|
||||||
unversioned.TypeMeta `json:",inline"`
|
|
||||||
// Standard list metadata
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
|
||||||
unversioned.ListMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
// Items is the list of Job.
|
|
||||||
Items []Job `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// JobSpec describes how the job execution will look like.
|
|
||||||
type JobSpec struct {
|
|
||||||
|
|
||||||
// Parallelism specifies the maximum desired number of pods the job should
|
|
||||||
// run at any given time. The actual number of pods running in steady state will
|
|
||||||
// be less than this number when ((.spec.completions - .status.successful) < .spec.parallelism),
|
|
||||||
// i.e. when the work left to do is less than max parallelism.
|
|
||||||
Parallelism *int `json:"parallelism,omitempty"`
|
|
||||||
|
|
||||||
// Completions specifies the desired number of successfully finished pods the
|
|
||||||
// job should be run with. Setting to nil means that the success of any
|
|
||||||
// pod signals the success of all pods, and allows parallelism to have any positive
|
|
||||||
// value. Setting to 1 means that parallelism is limited to 1 and the success of that
|
|
||||||
// pod signals the success of the job.
|
|
||||||
Completions *int `json:"completions,omitempty"`
|
|
||||||
|
|
||||||
// Optional duration in seconds relative to the startTime that the job may be active
|
|
||||||
// before the system tries to terminate it; value must be positive integer
|
|
||||||
ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"`
|
|
||||||
|
|
||||||
// Selector is a label query over pods that should match the pod count.
|
|
||||||
// Normally, the system sets this field for you.
|
|
||||||
Selector *unversioned.LabelSelector `json:"selector,omitempty"`
|
|
||||||
|
|
||||||
// ManualSelector controls generation of pod labels and pod selectors.
|
|
||||||
// Leave `manualSelector` unset unless you are certain what you are doing.
|
|
||||||
// When false or unset, the system pick labels unique to this job
|
|
||||||
// and appends those labels to the pod template. When true,
|
|
||||||
// the user is responsible for picking unique labels and specifying
|
|
||||||
// the selector. Failure to pick a unique label may cause this
|
|
||||||
// and other jobs to not function correctly. However, You may see
|
|
||||||
// `manualSelector=true` in jobs that were created with the old `extensions/v1beta1`
|
|
||||||
// API.
|
|
||||||
ManualSelector *bool `json:"manualSelector,omitempty"`
|
|
||||||
|
|
||||||
// Template is the object that describes the pod that will be created when
|
|
||||||
// executing a job.
|
|
||||||
Template api.PodTemplateSpec `json:"template"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// JobStatus represents the current state of a Job.
|
|
||||||
type JobStatus struct {
|
|
||||||
|
|
||||||
// Conditions represent the latest available observations of an object's current state.
|
|
||||||
Conditions []JobCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
|
||||||
|
|
||||||
// StartTime represents time when the job was acknowledged by the Job Manager.
|
|
||||||
// It is not guaranteed to be set in happens-before order across separate operations.
|
|
||||||
// It is represented in RFC3339 form and is in UTC.
|
|
||||||
StartTime *unversioned.Time `json:"startTime,omitempty"`
|
|
||||||
|
|
||||||
// CompletionTime represents time when the job was completed. It is not guaranteed to
|
|
||||||
// be set in happens-before order across separate operations.
|
|
||||||
// It is represented in RFC3339 form and is in UTC.
|
|
||||||
CompletionTime *unversioned.Time `json:"completionTime,omitempty"`
|
|
||||||
|
|
||||||
// Active is the number of actively running pods.
|
|
||||||
Active int `json:"active,omitempty"`
|
|
||||||
|
|
||||||
// Succeeded is the number of pods which reached Phase Succeeded.
|
|
||||||
Succeeded int `json:"succeeded,omitempty"`
|
|
||||||
|
|
||||||
// Failed is the number of pods which reached Phase Failed.
|
|
||||||
Failed int `json:"failed,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JobConditionType string
|
|
||||||
|
|
||||||
// These are valid conditions of a job.
|
|
||||||
const (
|
|
||||||
// JobComplete means the job has completed its execution.
|
|
||||||
JobComplete JobConditionType = "Complete"
|
|
||||||
// JobFailed means the job has failed its execution.
|
|
||||||
JobFailed JobConditionType = "Failed"
|
|
||||||
)
|
|
||||||
|
|
||||||
// JobCondition describes current state of a job.
|
|
||||||
type JobCondition struct {
|
|
||||||
// Type of job condition, Complete or Failed.
|
|
||||||
Type JobConditionType `json:"type"`
|
|
||||||
// Status of the condition, one of True, False, Unknown.
|
|
||||||
Status api.ConditionStatus `json:"status"`
|
|
||||||
// Last time the condition was checked.
|
|
||||||
LastProbeTime unversioned.Time `json:"lastProbeTime,omitempty"`
|
|
||||||
// Last time the condition transit from one status to another.
|
|
||||||
LastTransitionTime unversioned.Time `json:"lastTransitionTime,omitempty"`
|
|
||||||
// (brief) reason for the condition's last transition.
|
|
||||||
Reason string `json:"reason,omitempty"`
|
|
||||||
// Human readable message indicating details about last transition.
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// +genclient=true
|
|
||||||
|
|
||||||
// Ingress is a collection of rules that allow inbound connections to reach the
|
// Ingress is a collection of rules that allow inbound connections to reach the
|
||||||
// endpoints defined by a backend. An Ingress can be configured to give services
|
// endpoints defined by a backend. An Ingress can be configured to give services
|
||||||
// externally-reachable urls, load balance traffic, terminate SSL, offer name
|
// externally-reachable urls, load balance traffic, terminate SSL, offer name
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/conversion"
|
"k8s.io/kubernetes/pkg/conversion"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
@ -42,8 +43,9 @@ func addConversionFuncs(scheme *runtime.Scheme) {
|
||||||
Convert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment,
|
Convert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment,
|
||||||
Convert_extensions_ReplicaSetSpec_To_v1beta1_ReplicaSetSpec,
|
Convert_extensions_ReplicaSetSpec_To_v1beta1_ReplicaSetSpec,
|
||||||
Convert_v1beta1_ReplicaSetSpec_To_extensions_ReplicaSetSpec,
|
Convert_v1beta1_ReplicaSetSpec_To_extensions_ReplicaSetSpec,
|
||||||
Convert_extensions_JobSpec_To_v1beta1_JobSpec,
|
// batch
|
||||||
Convert_v1beta1_JobSpec_To_extensions_JobSpec,
|
Convert_batch_JobSpec_To_v1beta1_JobSpec,
|
||||||
|
Convert_v1beta1_JobSpec_To_batch_JobSpec,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If one of the conversion functions is malformed, detect it immediately.
|
// If one of the conversion functions is malformed, detect it immediately.
|
||||||
|
@ -312,9 +314,9 @@ func Convert_v1beta1_ReplicaSetSpec_To_extensions_ReplicaSetSpec(in *ReplicaSetS
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Convert_extensions_JobSpec_To_v1beta1_JobSpec(in *extensions.JobSpec, out *JobSpec, s conversion.Scope) error {
|
func Convert_batch_JobSpec_To_v1beta1_JobSpec(in *batch.JobSpec, out *JobSpec, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*extensions.JobSpec))(in)
|
defaulting.(func(*batch.JobSpec))(in)
|
||||||
}
|
}
|
||||||
if in.Parallelism != nil {
|
if in.Parallelism != nil {
|
||||||
out.Parallelism = new(int32)
|
out.Parallelism = new(int32)
|
||||||
|
@ -364,7 +366,7 @@ func Convert_extensions_JobSpec_To_v1beta1_JobSpec(in *extensions.JobSpec, out *
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Convert_v1beta1_JobSpec_To_extensions_JobSpec(in *JobSpec, out *extensions.JobSpec, s conversion.Scope) error {
|
func Convert_v1beta1_JobSpec_To_batch_JobSpec(in *JobSpec, out *batch.JobSpec, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*JobSpec))(in)
|
defaulting.(func(*JobSpec))(in)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
versioned "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
versioned "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ func TestJobSpecConversion(t *testing.T) {
|
||||||
|
|
||||||
// Test internal -> v1beta1.
|
// Test internal -> v1beta1.
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
i := &extensions.JobSpec{
|
i := &batch.JobSpec{
|
||||||
ManualSelector: test.in,
|
ManualSelector: test.in,
|
||||||
}
|
}
|
||||||
v := versioned.JobSpec{}
|
v := versioned.JobSpec{}
|
||||||
|
@ -72,7 +72,7 @@ func TestJobSpecConversion(t *testing.T) {
|
||||||
i := &versioned.JobSpec{
|
i := &versioned.JobSpec{
|
||||||
AutoSelector: test.in,
|
AutoSelector: test.in,
|
||||||
}
|
}
|
||||||
e := extensions.JobSpec{}
|
e := batch.JobSpec{}
|
||||||
if err := api.Scheme.Convert(i, &e); err != nil {
|
if err := api.Scheme.Convert(i, &e); err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,136 +382,6 @@ func ValidateThirdPartyResourceData(obj *extensions.ThirdPartyResourceData) fiel
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: generalize for other controller objects that will follow the same pattern, such as ReplicaSet and DaemonSet, and
|
|
||||||
// move to new location. Replace extensions.Job with an interface.
|
|
||||||
//
|
|
||||||
// ValidateGeneratedSelector validates that the generated selector on a controller object match the controller object
|
|
||||||
// metadata, and the labels on the pod template are as generated.
|
|
||||||
func ValidateGeneratedSelector(obj *extensions.Job) field.ErrorList {
|
|
||||||
allErrs := field.ErrorList{}
|
|
||||||
if obj.Spec.ManualSelector != nil && *obj.Spec.ManualSelector {
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj.Spec.Selector == nil {
|
|
||||||
return allErrs // This case should already have been checked in caller. No need for more errors.
|
|
||||||
}
|
|
||||||
|
|
||||||
// If somehow uid was unset then we would get "controller-uid=" as the selector
|
|
||||||
// which is bad.
|
|
||||||
if obj.ObjectMeta.UID == "" {
|
|
||||||
allErrs = append(allErrs, field.Required(field.NewPath("metadata").Child("uid"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If somehow uid was unset then we would get "controller-uid=" as the selector
|
|
||||||
// which is bad.
|
|
||||||
if obj.ObjectMeta.UID == "" {
|
|
||||||
allErrs = append(allErrs, field.Required(field.NewPath("metadata").Child("uid"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If selector generation was requested, then expected labels must be
|
|
||||||
// present on pod template, and much match job's uid and name. The
|
|
||||||
// generated (not-manual) selectors/labels ensure no overlap with other
|
|
||||||
// controllers. The manual mode allows orphaning, adoption,
|
|
||||||
// backward-compatibility, and experimentation with new
|
|
||||||
// labeling/selection schemes. Automatic selector generation should
|
|
||||||
// have placed certain labels on the pod, but this could have failed if
|
|
||||||
// the user added coflicting labels. Validate that the expected
|
|
||||||
// generated ones are there.
|
|
||||||
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateHasLabel(obj.Spec.Template.ObjectMeta, field.NewPath("spec").Child("template").Child("metadata"), "controller-uid", string(obj.UID))...)
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateHasLabel(obj.Spec.Template.ObjectMeta, field.NewPath("spec").Child("template").Child("metadata"), "job-name", string(obj.Name))...)
|
|
||||||
expectedLabels := make(map[string]string)
|
|
||||||
expectedLabels["controller-uid"] = string(obj.UID)
|
|
||||||
expectedLabels["job-name"] = string(obj.Name)
|
|
||||||
// Whether manually or automatically generated, the selector of the job must match the pods it will produce.
|
|
||||||
if selector, err := unversioned.LabelSelectorAsSelector(obj.Spec.Selector); err == nil {
|
|
||||||
if !selector.Matches(labels.Set(expectedLabels)) {
|
|
||||||
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("selector"), obj.Spec.Selector, "`selector` not auto-generated"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateJob(job *extensions.Job) field.ErrorList {
|
|
||||||
// Jobs and rcs have the same name validation
|
|
||||||
allErrs := apivalidation.ValidateObjectMeta(&job.ObjectMeta, true, apivalidation.ValidateReplicationControllerName, field.NewPath("metadata"))
|
|
||||||
allErrs = append(allErrs, ValidateGeneratedSelector(job)...)
|
|
||||||
allErrs = append(allErrs, ValidateJobSpec(&job.Spec, field.NewPath("spec"))...)
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateJobSpec(spec *extensions.JobSpec, fldPath *field.Path) field.ErrorList {
|
|
||||||
allErrs := field.ErrorList{}
|
|
||||||
|
|
||||||
if spec.Parallelism != nil {
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Parallelism), fldPath.Child("parallelism"))...)
|
|
||||||
}
|
|
||||||
if spec.Completions != nil {
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Completions), fldPath.Child("completions"))...)
|
|
||||||
}
|
|
||||||
if spec.ActiveDeadlineSeconds != nil {
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.ActiveDeadlineSeconds), fldPath.Child("activeDeadlineSeconds"))...)
|
|
||||||
}
|
|
||||||
if spec.Selector == nil {
|
|
||||||
allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
|
|
||||||
} else {
|
|
||||||
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whether manually or automatically generated, the selector of the job must match the pods it will produce.
|
|
||||||
if selector, err := unversioned.LabelSelectorAsSelector(spec.Selector); err == nil {
|
|
||||||
labels := labels.Set(spec.Template.Labels)
|
|
||||||
if !selector.Matches(labels) {
|
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...)
|
|
||||||
if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure &&
|
|
||||||
spec.Template.Spec.RestartPolicy != api.RestartPolicyNever {
|
|
||||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"),
|
|
||||||
spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)}))
|
|
||||||
}
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateJobStatus(status *extensions.JobStatus, fldPath *field.Path) field.ErrorList {
|
|
||||||
allErrs := field.ErrorList{}
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Active), fldPath.Child("active"))...)
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Succeeded), fldPath.Child("succeeded"))...)
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Failed), fldPath.Child("failed"))...)
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateJobUpdate(job, oldJob *extensions.Job) field.ErrorList {
|
|
||||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta, field.NewPath("metadata"))
|
|
||||||
allErrs = append(allErrs, ValidateJobSpecUpdate(job.Spec, oldJob.Spec, field.NewPath("spec"))...)
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateJobUpdateStatus(job, oldJob *extensions.Job) field.ErrorList {
|
|
||||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta, field.NewPath("metadata"))
|
|
||||||
allErrs = append(allErrs, ValidateJobStatusUpdate(job.Status, oldJob.Status)...)
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateJobSpecUpdate(spec, oldSpec extensions.JobSpec, fldPath *field.Path) field.ErrorList {
|
|
||||||
allErrs := field.ErrorList{}
|
|
||||||
allErrs = append(allErrs, ValidateJobSpec(&spec, fldPath)...)
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Completions, oldSpec.Completions, fldPath.Child("completions"))...)
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Selector, oldSpec.Selector, fldPath.Child("selector"))...)
|
|
||||||
allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Template, oldSpec.Template, fldPath.Child("template"))...)
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateJobStatusUpdate(status, oldStatus extensions.JobStatus) field.ErrorList {
|
|
||||||
allErrs := field.ErrorList{}
|
|
||||||
allErrs = append(allErrs, ValidateJobStatus(&status, field.NewPath("status"))...)
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateIngress tests if required fields in the Ingress are set.
|
// ValidateIngress tests if required fields in the Ingress are set.
|
||||||
func ValidateIngress(ingress *extensions.Ingress) field.ErrorList {
|
func ValidateIngress(ingress *extensions.Ingress) field.ErrorList {
|
||||||
allErrs := apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName, field.NewPath("metadata"))
|
allErrs := apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName, field.NewPath("metadata"))
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/controller/podautoscaler"
|
"k8s.io/kubernetes/pkg/controller/podautoscaler"
|
||||||
"k8s.io/kubernetes/pkg/types"
|
|
||||||
"k8s.io/kubernetes/pkg/util/intstr"
|
"k8s.io/kubernetes/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -989,270 +988,6 @@ func TestValidateDeploymentRollback(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateJob(t *testing.T) {
|
|
||||||
validManualSelector := &unversioned.LabelSelector{
|
|
||||||
MatchLabels: map[string]string{"a": "b"},
|
|
||||||
}
|
|
||||||
validGeneratedSelector := &unversioned.LabelSelector{
|
|
||||||
MatchLabels: map[string]string{"controller-uid": "1a2b3c", "job-name": "myjob"},
|
|
||||||
}
|
|
||||||
validPodTemplateSpecForManual := api.PodTemplateSpec{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Labels: validManualSelector.MatchLabels,
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
RestartPolicy: api.RestartPolicyOnFailure,
|
|
||||||
DNSPolicy: api.DNSClusterFirst,
|
|
||||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
validPodTemplateSpecForGenerated := api.PodTemplateSpec{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Labels: validGeneratedSelector.MatchLabels,
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
RestartPolicy: api.RestartPolicyOnFailure,
|
|
||||||
DNSPolicy: api.DNSClusterFirst,
|
|
||||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
successCases := map[string]extensions.Job{
|
|
||||||
"manual selector": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Selector: validManualSelector,
|
|
||||||
ManualSelector: newBool(true),
|
|
||||||
Template: validPodTemplateSpecForManual,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"generated selector": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Selector: validGeneratedSelector,
|
|
||||||
ManualSelector: newBool(false),
|
|
||||||
Template: validPodTemplateSpecForGenerated,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for k, v := range successCases {
|
|
||||||
if errs := ValidateJob(&v); len(errs) != 0 {
|
|
||||||
t.Errorf("expected success for %s: %v", k, errs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
negative := -1
|
|
||||||
negative64 := int64(-1)
|
|
||||||
errorCases := map[string]extensions.Job{
|
|
||||||
"spec.parallelism:must be greater than or equal to 0": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Parallelism: &negative,
|
|
||||||
ManualSelector: newBool(true),
|
|
||||||
Template: validPodTemplateSpecForGenerated,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec.completions:must be greater than or equal to 0": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Completions: &negative,
|
|
||||||
Selector: validManualSelector,
|
|
||||||
ManualSelector: newBool(true),
|
|
||||||
Template: validPodTemplateSpecForGenerated,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec.activeDeadlineSeconds:must be greater than or equal to 0": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
ActiveDeadlineSeconds: &negative64,
|
|
||||||
Selector: validManualSelector,
|
|
||||||
ManualSelector: newBool(true),
|
|
||||||
Template: validPodTemplateSpecForGenerated,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec.selector:Required value": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Template: validPodTemplateSpecForGenerated,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec.template.metadata.labels: Invalid value: {\"y\":\"z\"}: `selector` does not match template `labels`": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Selector: validManualSelector,
|
|
||||||
ManualSelector: newBool(true),
|
|
||||||
Template: api.PodTemplateSpec{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Labels: map[string]string{"y": "z"},
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
RestartPolicy: api.RestartPolicyOnFailure,
|
|
||||||
DNSPolicy: api.DNSClusterFirst,
|
|
||||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec.template.metadata.labels: Invalid value: {\"controller-uid\":\"4d5e6f\"}: `selector` does not match template `labels`": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Selector: validManualSelector,
|
|
||||||
ManualSelector: newBool(true),
|
|
||||||
Template: api.PodTemplateSpec{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Labels: map[string]string{"controller-uid": "4d5e6f"},
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
RestartPolicy: api.RestartPolicyOnFailure,
|
|
||||||
DNSPolicy: api.DNSClusterFirst,
|
|
||||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec.template.spec.restartPolicy: Unsupported value": {
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "myjob",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
UID: types.UID("1a2b3c"),
|
|
||||||
},
|
|
||||||
Spec: extensions.JobSpec{
|
|
||||||
Selector: validManualSelector,
|
|
||||||
ManualSelector: newBool(true),
|
|
||||||
Template: api.PodTemplateSpec{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Labels: validManualSelector.MatchLabels,
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
RestartPolicy: api.RestartPolicyAlways,
|
|
||||||
DNSPolicy: api.DNSClusterFirst,
|
|
||||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range errorCases {
|
|
||||||
errs := ValidateJob(&v)
|
|
||||||
if len(errs) == 0 {
|
|
||||||
t.Errorf("expected failure for %s", k)
|
|
||||||
} else {
|
|
||||||
s := strings.Split(k, ":")
|
|
||||||
err := errs[0]
|
|
||||||
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
|
|
||||||
t.Errorf("unexpected error: %v, expected: %s", err, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateJobUpdateStatus(t *testing.T) {
|
|
||||||
type testcase struct {
|
|
||||||
old extensions.Job
|
|
||||||
update extensions.Job
|
|
||||||
}
|
|
||||||
|
|
||||||
successCases := []testcase{
|
|
||||||
{
|
|
||||||
old: extensions.Job{
|
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
|
||||||
Status: extensions.JobStatus{
|
|
||||||
Active: 1,
|
|
||||||
Succeeded: 2,
|
|
||||||
Failed: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: extensions.Job{
|
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
|
||||||
Status: extensions.JobStatus{
|
|
||||||
Active: 1,
|
|
||||||
Succeeded: 1,
|
|
||||||
Failed: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, successCase := range successCases {
|
|
||||||
successCase.old.ObjectMeta.ResourceVersion = "1"
|
|
||||||
successCase.update.ObjectMeta.ResourceVersion = "1"
|
|
||||||
if errs := ValidateJobUpdateStatus(&successCase.update, &successCase.old); len(errs) != 0 {
|
|
||||||
t.Errorf("expected success: %v", errs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errorCases := map[string]testcase{
|
|
||||||
"[status.active: Invalid value: -1: must be greater than or equal to 0, status.succeeded: Invalid value: -2: must be greater than or equal to 0]": {
|
|
||||||
old: extensions.Job{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "abc",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
ResourceVersion: "10",
|
|
||||||
},
|
|
||||||
Status: extensions.JobStatus{
|
|
||||||
Active: 1,
|
|
||||||
Succeeded: 2,
|
|
||||||
Failed: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: extensions.Job{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "abc",
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
ResourceVersion: "10",
|
|
||||||
},
|
|
||||||
Status: extensions.JobStatus{
|
|
||||||
Active: -1,
|
|
||||||
Succeeded: -2,
|
|
||||||
Failed: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for testName, errorCase := range errorCases {
|
|
||||||
errs := ValidateJobUpdateStatus(&errorCase.update, &errorCase.old)
|
|
||||||
if len(errs) == 0 {
|
|
||||||
t.Errorf("expected failure: %s", testName)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if errs.ToAggregate().Error() != testName {
|
|
||||||
t.Errorf("expected '%s' got '%s'", errs.ToAggregate().Error(), testName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ingressRules map[string]string
|
type ingressRules map[string]string
|
||||||
|
|
||||||
func TestValidateIngress(t *testing.T) {
|
func TestValidateIngress(t *testing.T) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
)
|
)
|
||||||
|
@ -474,7 +475,7 @@ type StoreToJobLister struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exists checks if the given job exists in the store.
|
// Exists checks if the given job exists in the store.
|
||||||
func (s *StoreToJobLister) Exists(job *extensions.Job) (bool, error) {
|
func (s *StoreToJobLister) Exists(job *batch.Job) (bool, error) {
|
||||||
_, exists, err := s.Store.Get(job)
|
_, exists, err := s.Store.Get(job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -483,17 +484,17 @@ func (s *StoreToJobLister) Exists(job *extensions.Job) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// StoreToJobLister lists all jobs in the store.
|
// StoreToJobLister lists all jobs in the store.
|
||||||
func (s *StoreToJobLister) List() (jobs extensions.JobList, err error) {
|
func (s *StoreToJobLister) List() (jobs batch.JobList, err error) {
|
||||||
for _, c := range s.Store.List() {
|
for _, c := range s.Store.List() {
|
||||||
jobs.Items = append(jobs.Items, *(c.(*extensions.Job)))
|
jobs.Items = append(jobs.Items, *(c.(*batch.Job)))
|
||||||
}
|
}
|
||||||
return jobs, nil
|
return jobs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPodJobs returns a list of jobs managing a pod. Returns an error only if no matching jobs are found.
|
// GetPodJobs returns a list of jobs managing a pod. Returns an error only if no matching jobs are found.
|
||||||
func (s *StoreToJobLister) GetPodJobs(pod *api.Pod) (jobs []extensions.Job, err error) {
|
func (s *StoreToJobLister) GetPodJobs(pod *api.Pod) (jobs []batch.Job, err error) {
|
||||||
var selector labels.Selector
|
var selector labels.Selector
|
||||||
var job extensions.Job
|
var job batch.Job
|
||||||
|
|
||||||
if len(pod.Labels) == 0 {
|
if len(pod.Labels) == 0 {
|
||||||
err = fmt.Errorf("no jobs found for pod %v because it has no labels", pod.Name)
|
err = fmt.Errorf("no jobs found for pod %v because it has no labels", pod.Name)
|
||||||
|
@ -501,7 +502,7 @@ func (s *StoreToJobLister) GetPodJobs(pod *api.Pod) (jobs []extensions.Job, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range s.Store.List() {
|
for _, m := range s.Store.List() {
|
||||||
job = *m.(*extensions.Job)
|
job = *m.(*batch.Job)
|
||||||
if job.Namespace != pod.Namespace {
|
if job.Namespace != pod.Namespace {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
|
@ -476,18 +477,18 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
store := NewStore(MetaNamespaceKeyFunc)
|
store := NewStore(MetaNamespaceKeyFunc)
|
||||||
lister := StoreToJobLister{store}
|
lister := StoreToJobLister{store}
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
inJobs []*extensions.Job
|
inJobs []*batch.Job
|
||||||
list func() ([]extensions.Job, error)
|
list func() ([]batch.Job, error)
|
||||||
outJobNames sets.String
|
outJobNames sets.String
|
||||||
expectErr bool
|
expectErr bool
|
||||||
msg string
|
msg string
|
||||||
}{
|
}{
|
||||||
// Basic listing
|
// Basic listing
|
||||||
{
|
{
|
||||||
inJobs: []*extensions.Job{
|
inJobs: []*batch.Job{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||||
},
|
},
|
||||||
list: func() ([]extensions.Job, error) {
|
list: func() ([]batch.Job, error) {
|
||||||
list, err := lister.List()
|
list, err := lister.List()
|
||||||
return list.Items, err
|
return list.Items, err
|
||||||
},
|
},
|
||||||
|
@ -496,12 +497,12 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
},
|
},
|
||||||
// Listing multiple jobs
|
// Listing multiple jobs
|
||||||
{
|
{
|
||||||
inJobs: []*extensions.Job{
|
inJobs: []*batch.Job{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "complex"}},
|
{ObjectMeta: api.ObjectMeta{Name: "complex"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "complex2"}},
|
{ObjectMeta: api.ObjectMeta{Name: "complex2"}},
|
||||||
},
|
},
|
||||||
list: func() ([]extensions.Job, error) {
|
list: func() ([]batch.Job, error) {
|
||||||
list, err := lister.List()
|
list, err := lister.List()
|
||||||
return list.Items, err
|
return list.Items, err
|
||||||
},
|
},
|
||||||
|
@ -510,17 +511,17 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
},
|
},
|
||||||
// No pod labels
|
// No pod labels
|
||||||
{
|
{
|
||||||
inJobs: []*extensions.Job{
|
inJobs: []*batch.Job{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "baz"},
|
MatchLabels: map[string]string{"foo": "baz"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
list: func() ([]extensions.Job, error) {
|
list: func() ([]batch.Job, error) {
|
||||||
pod := &api.Pod{
|
pod := &api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "pod", Namespace: "ns"},
|
ObjectMeta: api.ObjectMeta{Name: "pod", Namespace: "ns"},
|
||||||
}
|
}
|
||||||
|
@ -532,12 +533,12 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
},
|
},
|
||||||
// No Job selectors
|
// No Job selectors
|
||||||
{
|
{
|
||||||
inJobs: []*extensions.Job{
|
inJobs: []*batch.Job{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
list: func() ([]extensions.Job, error) {
|
list: func() ([]batch.Job, error) {
|
||||||
pod := &api.Pod{
|
pod := &api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "pod",
|
Name: "pod",
|
||||||
|
@ -553,10 +554,10 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
},
|
},
|
||||||
// Matching labels to selectors and namespace
|
// Matching labels to selectors and namespace
|
||||||
{
|
{
|
||||||
inJobs: []*extensions.Job{
|
inJobs: []*batch.Job{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "bar"},
|
MatchLabels: map[string]string{"foo": "bar"},
|
||||||
},
|
},
|
||||||
|
@ -564,14 +565,14 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "bar"},
|
MatchLabels: map[string]string{"foo": "bar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
list: func() ([]extensions.Job, error) {
|
list: func() ([]batch.Job, error) {
|
||||||
pod := &api.Pod{
|
pod := &api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "pod",
|
Name: "pod",
|
||||||
|
@ -586,10 +587,10 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
},
|
},
|
||||||
// Matching labels to selectors and namespace, error case
|
// Matching labels to selectors and namespace, error case
|
||||||
{
|
{
|
||||||
inJobs: []*extensions.Job{
|
inJobs: []*batch.Job{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "foo"},
|
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "foo"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "bar"},
|
MatchLabels: map[string]string{"foo": "bar"},
|
||||||
},
|
},
|
||||||
|
@ -597,14 +598,14 @@ func TestStoreToJobLister(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "bar"},
|
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "bar"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "bar"},
|
MatchLabels: map[string]string{"foo": "bar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
list: func() ([]extensions.Job, error) {
|
list: func() ([]batch.Job, error) {
|
||||||
pod := &api.Pod{
|
pod := &api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "pod",
|
Name: "pod",
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/util/wait"
|
"k8s.io/kubernetes/pkg/util/wait"
|
||||||
"k8s.io/kubernetes/pkg/watch"
|
"k8s.io/kubernetes/pkg/watch"
|
||||||
|
@ -129,7 +130,7 @@ func ReplicaSetHasDesiredReplicas(c ExtensionsInterface, replicaSet *extensions.
|
||||||
|
|
||||||
// JobHasDesiredParallelism returns a condition that will be true if the desired parallelism count
|
// JobHasDesiredParallelism returns a condition that will be true if the desired parallelism count
|
||||||
// for a job equals the current active counts or is less by an appropriate successful/unsuccessful count.
|
// for a job equals the current active counts or is less by an appropriate successful/unsuccessful count.
|
||||||
func JobHasDesiredParallelism(c ExtensionsInterface, job *extensions.Job) wait.ConditionFunc {
|
func JobHasDesiredParallelism(c BatchInterface, job *batch.Job) wait.ConditionFunc {
|
||||||
|
|
||||||
return func() (bool, error) {
|
return func() (bool, error) {
|
||||||
job, err := c.Jobs(job.Namespace).Get(job.Name)
|
job, err := c.Jobs(job.Namespace).Get(job.Name)
|
||||||
|
|
|
@ -18,7 +18,7 @@ package unversioned
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/watch"
|
"k8s.io/kubernetes/pkg/watch"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,13 +29,13 @@ type JobsNamespacer interface {
|
||||||
|
|
||||||
// JobInterface exposes methods to work on Job resources.
|
// JobInterface exposes methods to work on Job resources.
|
||||||
type JobInterface interface {
|
type JobInterface interface {
|
||||||
List(opts api.ListOptions) (*extensions.JobList, error)
|
List(opts api.ListOptions) (*batch.JobList, error)
|
||||||
Get(name string) (*extensions.Job, error)
|
Get(name string) (*batch.Job, error)
|
||||||
Create(job *extensions.Job) (*extensions.Job, error)
|
Create(job *batch.Job) (*batch.Job, error)
|
||||||
Update(job *extensions.Job) (*extensions.Job, error)
|
Update(job *batch.Job) (*batch.Job, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *api.DeleteOptions) error
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts api.ListOptions) (watch.Interface, error)
|
||||||
UpdateStatus(job *extensions.Job) (*extensions.Job, error)
|
UpdateStatus(job *batch.Job) (*batch.Job, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// jobs implements JobsNamespacer interface
|
// jobs implements JobsNamespacer interface
|
||||||
|
@ -53,29 +53,29 @@ func newJobs(c *ExtensionsClient, namespace string) *jobs {
|
||||||
var _ JobInterface = &jobs{}
|
var _ JobInterface = &jobs{}
|
||||||
|
|
||||||
// List returns a list of jobs that match the label and field selectors.
|
// List returns a list of jobs that match the label and field selectors.
|
||||||
func (c *jobs) List(opts api.ListOptions) (result *extensions.JobList, err error) {
|
func (c *jobs) List(opts api.ListOptions) (result *batch.JobList, err error) {
|
||||||
result = &extensions.JobList{}
|
result = &batch.JobList{}
|
||||||
err = c.r.Get().Namespace(c.ns).Resource("jobs").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
err = c.r.Get().Namespace(c.ns).Resource("jobs").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns information about a particular job.
|
// Get returns information about a particular job.
|
||||||
func (c *jobs) Get(name string) (result *extensions.Job, err error) {
|
func (c *jobs) Get(name string) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Get().Namespace(c.ns).Resource("jobs").Name(name).Do().Into(result)
|
err = c.r.Get().Namespace(c.ns).Resource("jobs").Name(name).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates a new job.
|
// Create creates a new job.
|
||||||
func (c *jobs) Create(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *jobs) Create(job *batch.Job) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Post().Namespace(c.ns).Resource("jobs").Body(job).Do().Into(result)
|
err = c.r.Post().Namespace(c.ns).Resource("jobs").Body(job).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update updates an existing job.
|
// Update updates an existing job.
|
||||||
func (c *jobs) Update(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *jobs) Update(job *batch.Job) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).Body(job).Do().Into(result)
|
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).Body(job).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,8 @@ func (c *jobs) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStatus takes the name of the job and the new status. Returns the server's representation of the job, and an error, if it occurs.
|
// UpdateStatus takes the name of the job and the new status. Returns the server's representation of the job, and an error, if it occurs.
|
||||||
func (c *jobs) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *jobs) UpdateStatus(job *batch.Job) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
|
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -117,29 +117,29 @@ func newJobsV1(c *BatchClient, namespace string) *jobsV1 {
|
||||||
var _ JobInterface = &jobsV1{}
|
var _ JobInterface = &jobsV1{}
|
||||||
|
|
||||||
// List returns a list of jobs that match the label and field selectors.
|
// List returns a list of jobs that match the label and field selectors.
|
||||||
func (c *jobsV1) List(opts api.ListOptions) (result *extensions.JobList, err error) {
|
func (c *jobsV1) List(opts api.ListOptions) (result *batch.JobList, err error) {
|
||||||
result = &extensions.JobList{}
|
result = &batch.JobList{}
|
||||||
err = c.r.Get().Namespace(c.ns).Resource("jobs").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
err = c.r.Get().Namespace(c.ns).Resource("jobs").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns information about a particular job.
|
// Get returns information about a particular job.
|
||||||
func (c *jobsV1) Get(name string) (result *extensions.Job, err error) {
|
func (c *jobsV1) Get(name string) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Get().Namespace(c.ns).Resource("jobs").Name(name).Do().Into(result)
|
err = c.r.Get().Namespace(c.ns).Resource("jobs").Name(name).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates a new job.
|
// Create creates a new job.
|
||||||
func (c *jobsV1) Create(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *jobsV1) Create(job *batch.Job) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Post().Namespace(c.ns).Resource("jobs").Body(job).Do().Into(result)
|
err = c.r.Post().Namespace(c.ns).Resource("jobs").Body(job).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update updates an existing job.
|
// Update updates an existing job.
|
||||||
func (c *jobsV1) Update(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *jobsV1) Update(job *batch.Job) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).Body(job).Do().Into(result)
|
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).Body(job).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -160,8 +160,8 @@ func (c *jobsV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStatus takes the name of the job and the new status. Returns the server's representation of the job, and an error, if it occurs.
|
// UpdateStatus takes the name of the job and the new status. Returns the server's representation of the job, and an error, if it occurs.
|
||||||
func (c *jobsV1) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *jobsV1) UpdateStatus(job *batch.Job) (result *batch.Job, err error) {
|
||||||
result = &extensions.Job{}
|
result = &batch.Job{}
|
||||||
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
|
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,8 @@ func testListJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||||
Path: group.ResourcePath(getJobsResourceName(), ns, ""),
|
Path: group.ResourcePath(getJobsResourceName(), ns, ""),
|
||||||
},
|
},
|
||||||
Response: simple.Response{StatusCode: 200,
|
Response: simple.Response{StatusCode: 200,
|
||||||
Body: &extensions.JobList{
|
Body: &batch.JobList{
|
||||||
Items: []extensions.Job{
|
Items: []batch.Job{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
|
@ -61,7 +61,7 @@ func testListJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||||
"name": "baz",
|
"name": "baz",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Template: api.PodTemplateSpec{},
|
Template: api.PodTemplateSpec{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -90,7 +90,7 @@ func testGetJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||||
},
|
},
|
||||||
Response: simple.Response{
|
Response: simple.Response{
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
Body: &extensions.Job{
|
Body: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
|
@ -98,7 +98,7 @@ func testGetJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||||
"name": "baz",
|
"name": "baz",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Template: api.PodTemplateSpec{},
|
Template: api.PodTemplateSpec{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -117,7 +117,7 @@ func TestGetJob(t *testing.T) {
|
||||||
|
|
||||||
func testUpdateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
func testUpdateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||||
ns := api.NamespaceDefault
|
ns := api.NamespaceDefault
|
||||||
requestJob := &extensions.Job{
|
requestJob := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
|
@ -132,7 +132,7 @@ func testUpdateJob(t *testing.T, group testapi.TestGroup, resourceGroup string)
|
||||||
},
|
},
|
||||||
Response: simple.Response{
|
Response: simple.Response{
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
Body: &extensions.Job{
|
Body: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
|
@ -140,7 +140,7 @@ func testUpdateJob(t *testing.T, group testapi.TestGroup, resourceGroup string)
|
||||||
"name": "baz",
|
"name": "baz",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Template: api.PodTemplateSpec{},
|
Template: api.PodTemplateSpec{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -159,7 +159,7 @@ func TestUpdateJob(t *testing.T) {
|
||||||
|
|
||||||
func testUpdateJobStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
func testUpdateJobStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||||
ns := api.NamespaceDefault
|
ns := api.NamespaceDefault
|
||||||
requestJob := &extensions.Job{
|
requestJob := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
|
@ -174,7 +174,7 @@ func testUpdateJobStatus(t *testing.T, group testapi.TestGroup, resourceGroup st
|
||||||
},
|
},
|
||||||
Response: simple.Response{
|
Response: simple.Response{
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
Body: &extensions.Job{
|
Body: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
|
@ -182,10 +182,10 @@ func testUpdateJobStatus(t *testing.T, group testapi.TestGroup, resourceGroup st
|
||||||
"name": "baz",
|
"name": "baz",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Template: api.PodTemplateSpec{},
|
Template: api.PodTemplateSpec{},
|
||||||
},
|
},
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Active: 1,
|
Active: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -225,7 +225,7 @@ func TestDeleteJob(t *testing.T) {
|
||||||
|
|
||||||
func testCreateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
func testCreateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||||
ns := api.NamespaceDefault
|
ns := api.NamespaceDefault
|
||||||
requestJob := &extensions.Job{
|
requestJob := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
|
@ -240,7 +240,7 @@ func testCreateJob(t *testing.T, group testapi.TestGroup, resourceGroup string)
|
||||||
},
|
},
|
||||||
Response: simple.Response{
|
Response: simple.Response{
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
Body: &extensions.Job{
|
Body: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
|
@ -248,7 +248,7 @@ func testCreateJob(t *testing.T, group testapi.TestGroup, resourceGroup string)
|
||||||
"name": "baz",
|
"name": "baz",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Template: api.PodTemplateSpec{},
|
Template: api.PodTemplateSpec{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,7 +18,7 @@ package testclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/watch"
|
"k8s.io/kubernetes/pkg/watch"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,44 +29,44 @@ type FakeJobs struct {
|
||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobs) Get(name string) (*extensions.Job, error) {
|
func (c *FakeJobs) Get(name string) (*batch.Job, error) {
|
||||||
obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &extensions.Job{})
|
obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &batch.Job{})
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobs) List(opts api.ListOptions) (*extensions.JobList, error) {
|
func (c *FakeJobs) List(opts api.ListOptions) (*batch.JobList, error) {
|
||||||
obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &extensions.JobList{})
|
obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &batch.JobList{})
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.JobList), err
|
return obj.(*batch.JobList), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobs) Create(job *extensions.Job) (*extensions.Job, error) {
|
func (c *FakeJobs) Create(job *batch.Job) (*batch.Job, error) {
|
||||||
obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job)
|
obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job)
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobs) Update(job *extensions.Job) (*extensions.Job, error) {
|
func (c *FakeJobs) Update(job *batch.Job) (*batch.Job, error) {
|
||||||
obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job)
|
obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job)
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobs) Delete(name string, options *api.DeleteOptions) error {
|
func (c *FakeJobs) Delete(name string, options *api.DeleteOptions) error {
|
||||||
_, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &extensions.Job{})
|
_, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &batch.Job{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,13 +74,13 @@ func (c *FakeJobs) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||||
return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts))
|
return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobs) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *FakeJobs) UpdateStatus(job *batch.Job) (result *batch.Job, err error) {
|
||||||
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job)
|
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job)
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default
|
// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default
|
||||||
|
@ -92,44 +92,44 @@ type FakeJobsV1 struct {
|
||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobsV1) Get(name string) (*extensions.Job, error) {
|
func (c *FakeJobsV1) Get(name string) (*batch.Job, error) {
|
||||||
obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &extensions.Job{})
|
obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &batch.Job{})
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobsV1) List(opts api.ListOptions) (*extensions.JobList, error) {
|
func (c *FakeJobsV1) List(opts api.ListOptions) (*batch.JobList, error) {
|
||||||
obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &extensions.JobList{})
|
obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &batch.JobList{})
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.JobList), err
|
return obj.(*batch.JobList), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobsV1) Create(job *extensions.Job) (*extensions.Job, error) {
|
func (c *FakeJobsV1) Create(job *batch.Job) (*batch.Job, error) {
|
||||||
obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job)
|
obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job)
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobsV1) Update(job *extensions.Job) (*extensions.Job, error) {
|
func (c *FakeJobsV1) Update(job *batch.Job) (*batch.Job, error) {
|
||||||
obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job)
|
obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job)
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobsV1) Delete(name string, options *api.DeleteOptions) error {
|
func (c *FakeJobsV1) Delete(name string, options *api.DeleteOptions) error {
|
||||||
_, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &extensions.Job{})
|
_, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &batch.Job{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,11 +137,11 @@ func (c *FakeJobsV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||||
return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts))
|
return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakeJobsV1) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
|
func (c *FakeJobsV1) UpdateStatus(job *batch.Job) (result *batch.Job, err error) {
|
||||||
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job)
|
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job)
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*extensions.Job), err
|
return obj.(*batch.Job), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/client/cache"
|
"k8s.io/kubernetes/pkg/client/cache"
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned"
|
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned"
|
||||||
|
@ -53,7 +53,7 @@ type JobController struct {
|
||||||
internalPodInformer framework.SharedInformer
|
internalPodInformer framework.SharedInformer
|
||||||
|
|
||||||
// To allow injection of updateJobStatus for testing.
|
// To allow injection of updateJobStatus for testing.
|
||||||
updateHandler func(job *extensions.Job) error
|
updateHandler func(job *batch.Job) error
|
||||||
syncHandler func(jobKey string) error
|
syncHandler func(jobKey string) error
|
||||||
// podStoreSynced returns true if the pod store has been synced at least once.
|
// podStoreSynced returns true if the pod store has been synced at least once.
|
||||||
// Added as a member to the struct to allow injection for testing.
|
// Added as a member to the struct to allow injection for testing.
|
||||||
|
@ -96,19 +96,19 @@ func NewJobController(podInformer framework.SharedInformer, kubeClient clientset
|
||||||
jm.jobStore.Store, jm.jobController = framework.NewInformer(
|
jm.jobStore.Store, jm.jobController = framework.NewInformer(
|
||||||
&cache.ListWatch{
|
&cache.ListWatch{
|
||||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||||
return jm.kubeClient.Extensions().Jobs(api.NamespaceAll).List(options)
|
return jm.kubeClient.Batch().Jobs(api.NamespaceAll).List(options)
|
||||||
},
|
},
|
||||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||||
return jm.kubeClient.Extensions().Jobs(api.NamespaceAll).Watch(options)
|
return jm.kubeClient.Batch().Jobs(api.NamespaceAll).Watch(options)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&extensions.Job{},
|
&batch.Job{},
|
||||||
// TODO: Can we have much longer period here?
|
// TODO: Can we have much longer period here?
|
||||||
replicationcontroller.FullControllerResyncPeriod,
|
replicationcontroller.FullControllerResyncPeriod,
|
||||||
framework.ResourceEventHandlerFuncs{
|
framework.ResourceEventHandlerFuncs{
|
||||||
AddFunc: jm.enqueueController,
|
AddFunc: jm.enqueueController,
|
||||||
UpdateFunc: func(old, cur interface{}) {
|
UpdateFunc: func(old, cur interface{}) {
|
||||||
if job := cur.(*extensions.Job); !isJobFinished(job) {
|
if job := cur.(*batch.Job); !isJobFinished(job) {
|
||||||
jm.enqueueController(job)
|
jm.enqueueController(job)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -155,7 +155,7 @@ func (jm *JobController) Run(workers int, stopCh <-chan struct{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPodJob returns the job managing the given pod.
|
// getPodJob returns the job managing the given pod.
|
||||||
func (jm *JobController) getPodJob(pod *api.Pod) *extensions.Job {
|
func (jm *JobController) getPodJob(pod *api.Pod) *batch.Job {
|
||||||
jobs, err := jm.jobStore.GetPodJobs(pod)
|
jobs, err := jm.jobStore.GetPodJobs(pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(4).Infof("No jobs found for pod %v, job controller will avoid syncing", pod.Name)
|
glog.V(4).Infof("No jobs found for pod %v, job controller will avoid syncing", pod.Name)
|
||||||
|
@ -251,7 +251,7 @@ func (jm *JobController) deletePod(obj interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// obj could be an *extensions.Job, or a DeletionFinalStateUnknown marker item.
|
// obj could be an *batch.Job, or a DeletionFinalStateUnknown marker item.
|
||||||
func (jm *JobController) enqueueController(obj interface{}) {
|
func (jm *JobController) enqueueController(obj interface{}) {
|
||||||
key, err := controller.KeyFunc(obj)
|
key, err := controller.KeyFunc(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -314,7 +314,7 @@ func (jm *JobController) syncJob(key string) error {
|
||||||
jm.queue.Add(key)
|
jm.queue.Add(key)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
job := *obj.(*extensions.Job)
|
job := *obj.(*batch.Job)
|
||||||
|
|
||||||
// Check the expectations of the job before counting active pods, otherwise a new pod can sneak in
|
// Check the expectations of the job before counting active pods, otherwise a new pod can sneak in
|
||||||
// and update the expectations after we've retrieved active pods from the store. If a new pod enters
|
// and update the expectations after we've retrieved active pods from the store. If a new pod enters
|
||||||
|
@ -366,7 +366,7 @@ func (jm *JobController) syncJob(key string) error {
|
||||||
// update status values accordingly
|
// update status values accordingly
|
||||||
failed += active
|
failed += active
|
||||||
active = 0
|
active = 0
|
||||||
job.Status.Conditions = append(job.Status.Conditions, newCondition(extensions.JobFailed, "DeadlineExceeded", "Job was active longer than specified deadline"))
|
job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobFailed, "DeadlineExceeded", "Job was active longer than specified deadline"))
|
||||||
jm.recorder.Event(&job, api.EventTypeNormal, "DeadlineExceeded", "Job was active longer than specified deadline")
|
jm.recorder.Event(&job, api.EventTypeNormal, "DeadlineExceeded", "Job was active longer than specified deadline")
|
||||||
} else {
|
} else {
|
||||||
if jobNeedsSync {
|
if jobNeedsSync {
|
||||||
|
@ -400,7 +400,7 @@ func (jm *JobController) syncJob(key string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if complete {
|
if complete {
|
||||||
job.Status.Conditions = append(job.Status.Conditions, newCondition(extensions.JobComplete, "", ""))
|
job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobComplete, "", ""))
|
||||||
now := unversioned.Now()
|
now := unversioned.Now()
|
||||||
job.Status.CompletionTime = &now
|
job.Status.CompletionTime = &now
|
||||||
}
|
}
|
||||||
|
@ -421,7 +421,7 @@ func (jm *JobController) syncJob(key string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pastActiveDeadline checks if job has ActiveDeadlineSeconds field set and if it is exceeded.
|
// pastActiveDeadline checks if job has ActiveDeadlineSeconds field set and if it is exceeded.
|
||||||
func pastActiveDeadline(job *extensions.Job) bool {
|
func pastActiveDeadline(job *batch.Job) bool {
|
||||||
if job.Spec.ActiveDeadlineSeconds == nil || job.Status.StartTime == nil {
|
if job.Spec.ActiveDeadlineSeconds == nil || job.Status.StartTime == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -432,8 +432,8 @@ func pastActiveDeadline(job *extensions.Job) bool {
|
||||||
return duration >= allowedDuration
|
return duration >= allowedDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCondition(conditionType extensions.JobConditionType, reason, message string) extensions.JobCondition {
|
func newCondition(conditionType batch.JobConditionType, reason, message string) batch.JobCondition {
|
||||||
return extensions.JobCondition{
|
return batch.JobCondition{
|
||||||
Type: conditionType,
|
Type: conditionType,
|
||||||
Status: api.ConditionTrue,
|
Status: api.ConditionTrue,
|
||||||
LastProbeTime: unversioned.Now(),
|
LastProbeTime: unversioned.Now(),
|
||||||
|
@ -452,7 +452,7 @@ func getStatus(pods []api.Pod) (succeeded, failed int) {
|
||||||
|
|
||||||
// manageJob is the core method responsible for managing the number of running
|
// manageJob is the core method responsible for managing the number of running
|
||||||
// pods according to what is specified in the job.Spec.
|
// pods according to what is specified in the job.Spec.
|
||||||
func (jm *JobController) manageJob(activePods []*api.Pod, succeeded int, job *extensions.Job) int {
|
func (jm *JobController) manageJob(activePods []*api.Pod, succeeded int, job *batch.Job) int {
|
||||||
var activeLock sync.Mutex
|
var activeLock sync.Mutex
|
||||||
active := len(activePods)
|
active := len(activePods)
|
||||||
parallelism := *job.Spec.Parallelism
|
parallelism := *job.Spec.Parallelism
|
||||||
|
@ -538,8 +538,8 @@ func (jm *JobController) manageJob(activePods []*api.Pod, succeeded int, job *ex
|
||||||
return active
|
return active
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jm *JobController) updateJobStatus(job *extensions.Job) error {
|
func (jm *JobController) updateJobStatus(job *batch.Job) error {
|
||||||
_, err := jm.kubeClient.Extensions().Jobs(job.Namespace).UpdateStatus(job)
|
_, err := jm.kubeClient.Batch().Jobs(job.Namespace).UpdateStatus(job)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,9 +554,9 @@ func filterPods(pods []api.Pod, phase api.PodPhase) int {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func isJobFinished(j *extensions.Job) bool {
|
func isJobFinished(j *batch.Job) bool {
|
||||||
for _, c := range j.Status.Conditions {
|
for _, c := range j.Status.Conditions {
|
||||||
if (c.Type == extensions.JobComplete || c.Type == extensions.JobFailed) && c.Status == api.ConditionTrue {
|
if (c.Type == batch.JobComplete || c.Type == batch.JobFailed) && c.Status == api.ConditionTrue {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -564,7 +564,7 @@ func isJobFinished(j *extensions.Job) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker.
|
// byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker.
|
||||||
type byCreationTimestamp []extensions.Job
|
type byCreationTimestamp []batch.Job
|
||||||
|
|
||||||
func (o byCreationTimestamp) Len() int { return len(o) }
|
func (o byCreationTimestamp) Len() int { return len(o) }
|
||||||
func (o byCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
func (o byCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||||
"k8s.io/kubernetes/pkg/client/restclient"
|
"k8s.io/kubernetes/pkg/client/restclient"
|
||||||
|
@ -37,13 +37,13 @@ import (
|
||||||
|
|
||||||
var alwaysReady = func() bool { return true }
|
var alwaysReady = func() bool { return true }
|
||||||
|
|
||||||
func newJob(parallelism, completions int) *extensions.Job {
|
func newJob(parallelism, completions int) *batch.Job {
|
||||||
j := &extensions.Job{
|
j := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: api.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "bar"},
|
MatchLabels: map[string]string{"foo": "bar"},
|
||||||
},
|
},
|
||||||
|
@ -76,7 +76,7 @@ func newJob(parallelism, completions int) *extensions.Job {
|
||||||
return j
|
return j
|
||||||
}
|
}
|
||||||
|
|
||||||
func getKey(job *extensions.Job, t *testing.T) string {
|
func getKey(job *batch.Job, t *testing.T) string {
|
||||||
if key, err := controller.KeyFunc(job); err != nil {
|
if key, err := controller.KeyFunc(job); err != nil {
|
||||||
t.Errorf("Unexpected error getting key for job %v: %v", job.Name, err)
|
t.Errorf("Unexpected error getting key for job %v: %v", job.Name, err)
|
||||||
return ""
|
return ""
|
||||||
|
@ -86,7 +86,7 @@ func getKey(job *extensions.Job, t *testing.T) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create count pods with the given phase for the given job
|
// create count pods with the given phase for the given job
|
||||||
func newPodList(count int, status api.PodPhase, job *extensions.Job) []api.Pod {
|
func newPodList(count int, status api.PodPhase, job *batch.Job) []api.Pod {
|
||||||
pods := []api.Pod{}
|
pods := []api.Pod{}
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
newPod := api.Pod{
|
newPod := api.Pod{
|
||||||
|
@ -211,8 +211,8 @@ func TestControllerSyncJob(t *testing.T) {
|
||||||
fakePodControl := controller.FakePodControl{Err: tc.podControllerError}
|
fakePodControl := controller.FakePodControl{Err: tc.podControllerError}
|
||||||
manager.podControl = &fakePodControl
|
manager.podControl = &fakePodControl
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
var actual *extensions.Job
|
var actual *batch.Job
|
||||||
manager.updateHandler = func(job *extensions.Job) error {
|
manager.updateHandler = func(job *batch.Job) error {
|
||||||
actual = job
|
actual = job
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ func TestControllerSyncJob(t *testing.T) {
|
||||||
t.Errorf("%s: .status.startTime was not set", name)
|
t.Errorf("%s: .status.startTime was not set", name)
|
||||||
}
|
}
|
||||||
// validate conditions
|
// validate conditions
|
||||||
if tc.expectedComplete && !getCondition(actual, extensions.JobComplete) {
|
if tc.expectedComplete && !getCondition(actual, batch.JobComplete) {
|
||||||
t.Errorf("%s: expected completion condition. Got %#v", name, actual.Status.Conditions)
|
t.Errorf("%s: expected completion condition. Got %#v", name, actual.Status.Conditions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,8 +306,8 @@ func TestSyncJobPastDeadline(t *testing.T) {
|
||||||
fakePodControl := controller.FakePodControl{}
|
fakePodControl := controller.FakePodControl{}
|
||||||
manager.podControl = &fakePodControl
|
manager.podControl = &fakePodControl
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
var actual *extensions.Job
|
var actual *batch.Job
|
||||||
manager.updateHandler = func(job *extensions.Job) error {
|
manager.updateHandler = func(job *batch.Job) error {
|
||||||
actual = job
|
actual = job
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -355,13 +355,13 @@ func TestSyncJobPastDeadline(t *testing.T) {
|
||||||
t.Errorf("%s: .status.startTime was not set", name)
|
t.Errorf("%s: .status.startTime was not set", name)
|
||||||
}
|
}
|
||||||
// validate conditions
|
// validate conditions
|
||||||
if !getCondition(actual, extensions.JobFailed) {
|
if !getCondition(actual, batch.JobFailed) {
|
||||||
t.Errorf("%s: expected fail condition. Got %#v", name, actual.Status.Conditions)
|
t.Errorf("%s: expected fail condition. Got %#v", name, actual.Status.Conditions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCondition(job *extensions.Job, condition extensions.JobConditionType) bool {
|
func getCondition(job *batch.Job, condition batch.JobConditionType) bool {
|
||||||
for _, v := range job.Status.Conditions {
|
for _, v := range job.Status.Conditions {
|
||||||
if v.Type == condition && v.Status == api.ConditionTrue {
|
if v.Type == condition && v.Status == api.ConditionTrue {
|
||||||
return true
|
return true
|
||||||
|
@ -376,8 +376,8 @@ func TestSyncPastDeadlineJobFinished(t *testing.T) {
|
||||||
fakePodControl := controller.FakePodControl{}
|
fakePodControl := controller.FakePodControl{}
|
||||||
manager.podControl = &fakePodControl
|
manager.podControl = &fakePodControl
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
var actual *extensions.Job
|
var actual *batch.Job
|
||||||
manager.updateHandler = func(job *extensions.Job) error {
|
manager.updateHandler = func(job *batch.Job) error {
|
||||||
actual = job
|
actual = job
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,7 @@ func TestSyncPastDeadlineJobFinished(t *testing.T) {
|
||||||
job.Spec.ActiveDeadlineSeconds = &activeDeadlineSeconds
|
job.Spec.ActiveDeadlineSeconds = &activeDeadlineSeconds
|
||||||
start := unversioned.Unix(unversioned.Now().Time.Unix()-15, 0)
|
start := unversioned.Unix(unversioned.Now().Time.Unix()-15, 0)
|
||||||
job.Status.StartTime = &start
|
job.Status.StartTime = &start
|
||||||
job.Status.Conditions = append(job.Status.Conditions, newCondition(extensions.JobFailed, "DeadlineExceeded", "Job was active longer than specified deadline"))
|
job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobFailed, "DeadlineExceeded", "Job was active longer than specified deadline"))
|
||||||
manager.jobStore.Store.Add(job)
|
manager.jobStore.Store.Add(job)
|
||||||
err := manager.syncJob(getKey(job, t))
|
err := manager.syncJob(getKey(job, t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -412,7 +412,7 @@ func TestSyncJobComplete(t *testing.T) {
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
|
|
||||||
job := newJob(1, 1)
|
job := newJob(1, 1)
|
||||||
job.Status.Conditions = append(job.Status.Conditions, newCondition(extensions.JobComplete, "", ""))
|
job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobComplete, "", ""))
|
||||||
manager.jobStore.Store.Add(job)
|
manager.jobStore.Store.Add(job)
|
||||||
err := manager.syncJob(getKey(job, t))
|
err := manager.syncJob(getKey(job, t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -422,7 +422,7 @@ func TestSyncJobComplete(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error when trying to get job from the store: %v", err)
|
t.Fatalf("Unexpected error when trying to get job from the store: %v", err)
|
||||||
}
|
}
|
||||||
actual := uncastJob.(*extensions.Job)
|
actual := uncastJob.(*batch.Job)
|
||||||
// Verify that after syncing a complete job, the conditions are the same.
|
// Verify that after syncing a complete job, the conditions are the same.
|
||||||
if got, expected := len(actual.Status.Conditions), 1; got != expected {
|
if got, expected := len(actual.Status.Conditions), 1; got != expected {
|
||||||
t.Fatalf("Unexpected job status conditions amount; expected %d, got %d", expected, got)
|
t.Fatalf("Unexpected job status conditions amount; expected %d, got %d", expected, got)
|
||||||
|
@ -435,7 +435,7 @@ func TestSyncJobDeleted(t *testing.T) {
|
||||||
fakePodControl := controller.FakePodControl{}
|
fakePodControl := controller.FakePodControl{}
|
||||||
manager.podControl = &fakePodControl
|
manager.podControl = &fakePodControl
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
manager.updateHandler = func(job *extensions.Job) error { return nil }
|
manager.updateHandler = func(job *batch.Job) error { return nil }
|
||||||
job := newJob(2, 2)
|
job := newJob(2, 2)
|
||||||
err := manager.syncJob(getKey(job, t))
|
err := manager.syncJob(getKey(job, t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -455,7 +455,7 @@ func TestSyncJobUpdateRequeue(t *testing.T) {
|
||||||
fakePodControl := controller.FakePodControl{}
|
fakePodControl := controller.FakePodControl{}
|
||||||
manager.podControl = &fakePodControl
|
manager.podControl = &fakePodControl
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
manager.updateHandler = func(job *extensions.Job) error { return fmt.Errorf("Fake error") }
|
manager.updateHandler = func(job *batch.Job) error { return fmt.Errorf("Fake error") }
|
||||||
job := newJob(2, 2)
|
job := newJob(2, 2)
|
||||||
manager.jobStore.Store.Add(job)
|
manager.jobStore.Store.Add(job)
|
||||||
err := manager.syncJob(getKey(job, t))
|
err := manager.syncJob(getKey(job, t))
|
||||||
|
@ -475,14 +475,14 @@ func TestJobPodLookup(t *testing.T) {
|
||||||
manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc)
|
manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc)
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
job *extensions.Job
|
job *batch.Job
|
||||||
pod *api.Pod
|
pod *api.Pod
|
||||||
|
|
||||||
expectedName string
|
expectedName string
|
||||||
}{
|
}{
|
||||||
// pods without labels don't match any job
|
// pods without labels don't match any job
|
||||||
{
|
{
|
||||||
job: &extensions.Job{
|
job: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "basic"},
|
ObjectMeta: api.ObjectMeta{Name: "basic"},
|
||||||
},
|
},
|
||||||
pod: &api.Pod{
|
pod: &api.Pod{
|
||||||
|
@ -492,9 +492,9 @@ func TestJobPodLookup(t *testing.T) {
|
||||||
},
|
},
|
||||||
// matching labels, different namespace
|
// matching labels, different namespace
|
||||||
{
|
{
|
||||||
job: &extensions.Job{
|
job: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "bar"},
|
MatchLabels: map[string]string{"foo": "bar"},
|
||||||
},
|
},
|
||||||
|
@ -511,9 +511,9 @@ func TestJobPodLookup(t *testing.T) {
|
||||||
},
|
},
|
||||||
// matching ns and labels returns
|
// matching ns and labels returns
|
||||||
{
|
{
|
||||||
job: &extensions.Job{
|
job: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchExpressions: []unversioned.LabelSelectorRequirement{
|
MatchExpressions: []unversioned.LabelSelectorRequirement{
|
||||||
{
|
{
|
||||||
|
@ -566,7 +566,7 @@ func TestSyncJobExpectations(t *testing.T) {
|
||||||
fakePodControl := controller.FakePodControl{}
|
fakePodControl := controller.FakePodControl{}
|
||||||
manager.podControl = &fakePodControl
|
manager.podControl = &fakePodControl
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
manager.updateHandler = func(job *extensions.Job) error { return nil }
|
manager.updateHandler = func(job *batch.Job) error { return nil }
|
||||||
|
|
||||||
job := newJob(2, 2)
|
job := newJob(2, 2)
|
||||||
manager.jobStore.Store.Add(job)
|
manager.jobStore.Store.Add(job)
|
||||||
|
@ -602,7 +602,7 @@ func TestWatchJobs(t *testing.T) {
|
||||||
manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc)
|
manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc)
|
||||||
manager.podStoreSynced = alwaysReady
|
manager.podStoreSynced = alwaysReady
|
||||||
|
|
||||||
var testJob extensions.Job
|
var testJob batch.Job
|
||||||
received := make(chan struct{})
|
received := make(chan struct{})
|
||||||
|
|
||||||
// The update sent through the fakeWatcher should make its way into the workqueue,
|
// The update sent through the fakeWatcher should make its way into the workqueue,
|
||||||
|
@ -613,7 +613,7 @@ func TestWatchJobs(t *testing.T) {
|
||||||
if !exists || err != nil {
|
if !exists || err != nil {
|
||||||
t.Errorf("Expected to find job under key %v", key)
|
t.Errorf("Expected to find job under key %v", key)
|
||||||
}
|
}
|
||||||
job, ok := obj.(*extensions.Job)
|
job, ok := obj.(*batch.Job)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("unexpected type: %v %#v", reflect.TypeOf(obj), obj)
|
t.Fatalf("unexpected type: %v %#v", reflect.TypeOf(obj), obj)
|
||||||
}
|
}
|
||||||
|
@ -637,10 +637,10 @@ func TestWatchJobs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsJobFinished(t *testing.T) {
|
func TestIsJobFinished(t *testing.T) {
|
||||||
job := &extensions.Job{
|
job := &batch.Job{
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Conditions: []extensions.JobCondition{{
|
Conditions: []batch.JobCondition{{
|
||||||
Type: extensions.JobComplete,
|
Type: batch.JobComplete,
|
||||||
Status: api.ConditionTrue,
|
Status: api.ConditionTrue,
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
@ -681,7 +681,7 @@ func TestWatchPods(t *testing.T) {
|
||||||
close(received)
|
close(received)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
job, ok := obj.(*extensions.Job)
|
job, ok := obj.(*batch.Job)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("unexpected type: %v %#v", reflect.TypeOf(obj), obj)
|
t.Errorf("unexpected type: %v %#v", reflect.TypeOf(obj), obj)
|
||||||
close(received)
|
close(received)
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/client/restclient"
|
"k8s.io/kubernetes/pkg/client/restclient"
|
||||||
"k8s.io/kubernetes/pkg/client/unversioned/fake"
|
"k8s.io/kubernetes/pkg/client/unversioned/fake"
|
||||||
|
@ -262,14 +263,14 @@ func TestDrain(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
job := extensions.Job{
|
job := batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "job",
|
Name: "job",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
CreationTimestamp: unversioned.Time{Time: time.Now()},
|
CreationTimestamp: unversioned.Time{Time: time.Now()},
|
||||||
SelfLink: "/apis/extensions/v1beta1/namespaces/default/jobs/job",
|
SelfLink: "/apis/extensions/v1beta1/namespaces/default/jobs/job",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{MatchLabels: labels},
|
Selector: &unversioned.LabelSelector{MatchLabels: labels},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -665,7 +665,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||||
}
|
}
|
||||||
pod, _, err := GetFirstPod(client, t.Namespace, selector)
|
pod, _, err := GetFirstPod(client, t.Namespace, selector)
|
||||||
return pod, err
|
return pod, err
|
||||||
case *extensions.Job:
|
case *batch.Job:
|
||||||
selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector)
|
selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid label selector: %v", err)
|
return nil, fmt.Errorf("invalid label selector: %v", err)
|
||||||
|
|
|
@ -1089,7 +1089,7 @@ func (d *JobDescriber) Describe(namespace, name string) (string, error) {
|
||||||
return describeJob(job, events)
|
return describeJob(job, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
func describeJob(job *extensions.Job, events *api.EventList) (string, error) {
|
func describeJob(job *batch.Job, events *api.EventList) (string, error) {
|
||||||
return tabbedString(func(out io.Writer) error {
|
return tabbedString(func(out io.Writer) error {
|
||||||
fmt.Fprintf(out, "Name:\t%s\n", job.Name)
|
fmt.Fprintf(out, "Name:\t%s\n", job.Name)
|
||||||
fmt.Fprintf(out, "Namespace:\t%s\n", job.Namespace)
|
fmt.Fprintf(out, "Namespace:\t%s\n", job.Namespace)
|
||||||
|
|
|
@ -36,6 +36,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/meta"
|
"k8s.io/kubernetes/pkg/api/meta"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/apps"
|
"k8s.io/kubernetes/pkg/apis/apps"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
@ -795,7 +796,7 @@ func printReplicaSetList(list *extensions.ReplicaSetList, w io.Writer, options P
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printJob(job *extensions.Job, w io.Writer, options PrintOptions) error {
|
func printJob(job *batch.Job, w io.Writer, options PrintOptions) error {
|
||||||
name := job.Name
|
name := job.Name
|
||||||
namespace := job.Namespace
|
namespace := job.Namespace
|
||||||
containers := job.Spec.Template.Spec.Containers
|
containers := job.Spec.Template.Spec.Containers
|
||||||
|
@ -848,7 +849,7 @@ func printJob(job *extensions.Job, w io.Writer, options PrintOptions) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printJobList(list *extensions.JobList, w io.Writer, options PrintOptions) error {
|
func printJobList(list *batch.JobList, w io.Writer, options PrintOptions) error {
|
||||||
for _, job := range list.Items {
|
for _, job := range list.Items {
|
||||||
if err := printJob(&job, w, options); err != nil {
|
if err := printJob(&job, w, options); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1784,7 +1785,7 @@ func formatWideHeaders(wide bool, t reflect.Type) []string {
|
||||||
if t.String() == "*api.ReplicationController" || t.String() == "*api.ReplicationControllerList" {
|
if t.String() == "*api.ReplicationController" || t.String() == "*api.ReplicationControllerList" {
|
||||||
return []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"}
|
return []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"}
|
||||||
}
|
}
|
||||||
if t.String() == "*extensions.Job" || t.String() == "*extensions.JobList" {
|
if t.String() == "*batch.Job" || t.String() == "*batch.JobList" {
|
||||||
return []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"}
|
return []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"}
|
||||||
}
|
}
|
||||||
if t.String() == "*api.Service" || t.String() == "*api.ServiceList" {
|
if t.String() == "*api.Service" || t.String() == "*api.ServiceList" {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
kubectltesting "k8s.io/kubernetes/pkg/kubectl/testing"
|
kubectltesting "k8s.io/kubernetes/pkg/kubectl/testing"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
@ -1343,34 +1344,34 @@ func TestPrintDaemonSet(t *testing.T) {
|
||||||
func TestPrintJob(t *testing.T) {
|
func TestPrintJob(t *testing.T) {
|
||||||
completions := 2
|
completions := 2
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
job extensions.Job
|
job batch.Job
|
||||||
expect string
|
expect string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
extensions.Job{
|
batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "job1",
|
Name: "job1",
|
||||||
CreationTimestamp: unversioned.Time{Time: time.Now().Add(1.9e9)},
|
CreationTimestamp: unversioned.Time{Time: time.Now().Add(1.9e9)},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Completions: &completions,
|
Completions: &completions,
|
||||||
},
|
},
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Succeeded: 1,
|
Succeeded: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"job1\t2\t1\t0s\n",
|
"job1\t2\t1\t0s\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
extensions.Job{
|
batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "job2",
|
Name: "job2",
|
||||||
CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)},
|
CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Completions: nil,
|
Completions: nil,
|
||||||
},
|
},
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Succeeded: 0,
|
Succeeded: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
|
batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
@ -280,12 +281,12 @@ func (JobV1Beta1) Generate(genericParams map[string]interface{}) (runtime.Object
|
||||||
}
|
}
|
||||||
podSpec.RestartPolicy = restartPolicy
|
podSpec.RestartPolicy = restartPolicy
|
||||||
|
|
||||||
job := extensions.Job{
|
job := batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: labels,
|
MatchLabels: labels,
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -721,7 +722,7 @@ func TestGenerateDeployment(t *testing.T) {
|
||||||
func TestGenerateJob(t *testing.T) {
|
func TestGenerateJob(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
params map[string]interface{}
|
params map[string]interface{}
|
||||||
expected *extensions.Job
|
expected *batch.Job
|
||||||
expectErr bool
|
expectErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -740,12 +741,12 @@ func TestGenerateJob(t *testing.T) {
|
||||||
"limits": "cpu=400m,memory=200Mi",
|
"limits": "cpu=400m,memory=200Mi",
|
||||||
"restart": "OnFailure",
|
"restart": "OnFailure",
|
||||||
},
|
},
|
||||||
expected: &extensions.Job{
|
expected: &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{"foo": "bar", "baz": "blah"},
|
Labels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"foo": "bar", "baz": "blah"},
|
MatchLabels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||||
},
|
},
|
||||||
|
@ -807,8 +808,8 @@ func TestGenerateJob(t *testing.T) {
|
||||||
if test.expectErr && err != nil {
|
if test.expectErr && err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(obj.(*extensions.Job), test.expected) {
|
if !reflect.DeepEqual(obj.(*batch.Job), test.expected) {
|
||||||
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*extensions.Job))
|
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*batch.Job))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func ScalerFor(kind unversioned.GroupKind, c client.Interface) (Scaler, error) {
|
||||||
case extensions.Kind("ReplicaSet"):
|
case extensions.Kind("ReplicaSet"):
|
||||||
return &ReplicaSetScaler{c.Extensions()}, nil
|
return &ReplicaSetScaler{c.Extensions()}, nil
|
||||||
case extensions.Kind("Job"), batch.Kind("Job"):
|
case extensions.Kind("Job"), batch.Kind("Job"):
|
||||||
return &JobScaler{c.Extensions()}, nil // Either kind of job can be scaled with Extensions interface.
|
return &JobScaler{c.Batch()}, nil // Either kind of job can be scaled with Batch interface.
|
||||||
case extensions.Kind("Deployment"):
|
case extensions.Kind("Deployment"):
|
||||||
return &DeploymentScaler{c.Extensions()}, nil
|
return &DeploymentScaler{c.Extensions()}, nil
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ func (scaler *ReplicaSetScaler) Scale(namespace, name string, newSize uint, prec
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateJob ensures that the preconditions match. Returns nil if they are valid, an error otherwise.
|
// ValidateJob ensures that the preconditions match. Returns nil if they are valid, an error otherwise.
|
||||||
func (precondition *ScalePrecondition) ValidateJob(job *extensions.Job) error {
|
func (precondition *ScalePrecondition) ValidateJob(job *batch.Job) error {
|
||||||
if precondition.Size != -1 && job.Spec.Parallelism == nil {
|
if precondition.Size != -1 && job.Spec.Parallelism == nil {
|
||||||
return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), "nil"}
|
return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), "nil"}
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,7 @@ func (precondition *ScalePrecondition) ValidateJob(job *extensions.Job) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type JobScaler struct {
|
type JobScaler struct {
|
||||||
c client.ExtensionsInterface
|
c client.BatchInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScaleSimple is responsible for updating job's parallelism.
|
// ScaleSimple is responsible for updating job's parallelism.
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
kerrors "k8s.io/kubernetes/pkg/api/errors"
|
kerrors "k8s.io/kubernetes/pkg/api/errors"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
|
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
|
||||||
|
@ -252,17 +253,17 @@ type ErrorJobs struct {
|
||||||
invalid bool
|
invalid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ErrorJobs) Update(job *extensions.Job) (*extensions.Job, error) {
|
func (c *ErrorJobs) Update(job *batch.Job) (*batch.Job, error) {
|
||||||
if c.invalid {
|
if c.invalid {
|
||||||
return nil, kerrors.NewInvalid(extensions.Kind(job.Kind), job.Name, nil)
|
return nil, kerrors.NewInvalid(batch.Kind(job.Kind), job.Name, nil)
|
||||||
}
|
}
|
||||||
return nil, errors.New("Job update failure")
|
return nil, errors.New("Job update failure")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ErrorJobs) Get(name string) (*extensions.Job, error) {
|
func (c *ErrorJobs) Get(name string) (*batch.Job, error) {
|
||||||
zero := 0
|
zero := 0
|
||||||
return &extensions.Job{
|
return &batch.Job{
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &zero,
|
Parallelism: &zero,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -316,7 +317,7 @@ func TestJobScale(t *testing.T) {
|
||||||
if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "jobs" || action.GetName() != name {
|
if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "jobs" || action.GetName() != name {
|
||||||
t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
|
t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
|
||||||
}
|
}
|
||||||
if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "jobs" || *action.GetObject().(*extensions.Job).Spec.Parallelism != int(count) {
|
if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "jobs" || *action.GetObject().(*batch.Job).Spec.Parallelism != int(count) {
|
||||||
t.Errorf("unexpected action %v, expected update-job with parallelism = %d", actions[1], count)
|
t.Errorf("unexpected action %v, expected update-job with parallelism = %d", actions[1], count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,8 +343,8 @@ func TestJobScaleInvalid(t *testing.T) {
|
||||||
|
|
||||||
func TestJobScaleFailsPreconditions(t *testing.T) {
|
func TestJobScaleFailsPreconditions(t *testing.T) {
|
||||||
ten := 10
|
ten := 10
|
||||||
fake := testclient.NewSimpleFake(&extensions.Job{
|
fake := testclient.NewSimpleFake(&batch.Job{
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &ten,
|
Parallelism: &ten,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -366,7 +367,7 @@ func TestValidateJob(t *testing.T) {
|
||||||
zero, ten, twenty := 0, 10, 20
|
zero, ten, twenty := 0, 10, 20
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
preconditions ScalePrecondition
|
preconditions ScalePrecondition
|
||||||
job extensions.Job
|
job batch.Job
|
||||||
expectError bool
|
expectError bool
|
||||||
test string
|
test string
|
||||||
}{
|
}{
|
||||||
|
@ -377,11 +378,11 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{-1, ""},
|
preconditions: ScalePrecondition{-1, ""},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "foo",
|
ResourceVersion: "foo",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &ten,
|
Parallelism: &ten,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -390,11 +391,11 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{0, ""},
|
preconditions: ScalePrecondition{0, ""},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "foo",
|
ResourceVersion: "foo",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &zero,
|
Parallelism: &zero,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -403,11 +404,11 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{-1, "foo"},
|
preconditions: ScalePrecondition{-1, "foo"},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "foo",
|
ResourceVersion: "foo",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &ten,
|
Parallelism: &ten,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -416,11 +417,11 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{10, "foo"},
|
preconditions: ScalePrecondition{10, "foo"},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "foo",
|
ResourceVersion: "foo",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &ten,
|
Parallelism: &ten,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -429,11 +430,11 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{10, "foo"},
|
preconditions: ScalePrecondition{10, "foo"},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "foo",
|
ResourceVersion: "foo",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &twenty,
|
Parallelism: &twenty,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -442,7 +443,7 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{10, "foo"},
|
preconditions: ScalePrecondition{10, "foo"},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "foo",
|
ResourceVersion: "foo",
|
||||||
},
|
},
|
||||||
|
@ -452,11 +453,11 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{10, "foo"},
|
preconditions: ScalePrecondition{10, "foo"},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "bar",
|
ResourceVersion: "bar",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &ten,
|
Parallelism: &ten,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -465,11 +466,11 @@ func TestValidateJob(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preconditions: ScalePrecondition{10, "foo"},
|
preconditions: ScalePrecondition{10, "foo"},
|
||||||
job: extensions.Job{
|
job: batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
ResourceVersion: "bar",
|
ResourceVersion: "bar",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &twenty,
|
Parallelism: &twenty,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -314,9 +314,9 @@ func (reaper *DaemonSetReaper) Stop(namespace, name string, timeout time.Duratio
|
||||||
}
|
}
|
||||||
|
|
||||||
func (reaper *JobReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *api.DeleteOptions) error {
|
func (reaper *JobReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *api.DeleteOptions) error {
|
||||||
jobs := reaper.Extensions().Jobs(namespace)
|
jobs := reaper.Batch().Jobs(namespace)
|
||||||
pods := reaper.Pods(namespace)
|
pods := reaper.Pods(namespace)
|
||||||
scaler, err := ScalerFor(extensions.Kind("Job"), *reaper)
|
scaler, err := ScalerFor(batch.Kind("Job"), *reaper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
|
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
|
||||||
|
@ -388,26 +389,26 @@ func TestJobStop(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "OnlyOneJob",
|
Name: "OnlyOneJob",
|
||||||
Objs: []runtime.Object{
|
Objs: []runtime.Object{
|
||||||
&extensions.Job{ // GET
|
&batch.Job{ // GET
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &zero,
|
Parallelism: &zero,
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"k1": "v1"},
|
MatchLabels: map[string]string{"k1": "v1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&extensions.JobList{ // LIST
|
&batch.JobList{ // LIST
|
||||||
Items: []extensions.Job{
|
Items: []batch.Job{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &zero,
|
Parallelism: &zero,
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"k1": "v1"},
|
MatchLabels: map[string]string{"k1": "v1"},
|
||||||
|
@ -424,26 +425,26 @@ func TestJobStop(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "JobWithDeadPods",
|
Name: "JobWithDeadPods",
|
||||||
Objs: []runtime.Object{
|
Objs: []runtime.Object{
|
||||||
&extensions.Job{ // GET
|
&batch.Job{ // GET
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &zero,
|
Parallelism: &zero,
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"k1": "v1"},
|
MatchLabels: map[string]string{"k1": "v1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&extensions.JobList{ // LIST
|
&batch.JobList{ // LIST
|
||||||
Items: []extensions.Job{
|
Items: []batch.Job{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: &zero,
|
Parallelism: &zero,
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
MatchLabels: map[string]string{"k1": "v1"},
|
MatchLabels: map[string]string{"k1": "v1"},
|
||||||
|
|
|
@ -18,7 +18,7 @@ package etcd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
"k8s.io/kubernetes/pkg/registry/cachesize"
|
||||||
|
@ -37,12 +37,12 @@ type REST struct {
|
||||||
func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||||
prefix := "/jobs"
|
prefix := "/jobs"
|
||||||
|
|
||||||
newListFunc := func() runtime.Object { return &extensions.JobList{} }
|
newListFunc := func() runtime.Object { return &batch.JobList{} }
|
||||||
storageInterface := opts.Decorator(
|
storageInterface := opts.Decorator(
|
||||||
opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.Jobs), &extensions.Job{}, prefix, job.Strategy, newListFunc)
|
opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.Jobs), &batch.Job{}, prefix, job.Strategy, newListFunc)
|
||||||
|
|
||||||
store := &etcdgeneric.Etcd{
|
store := &etcdgeneric.Etcd{
|
||||||
NewFunc: func() runtime.Object { return &extensions.Job{} },
|
NewFunc: func() runtime.Object { return &batch.Job{} },
|
||||||
|
|
||||||
// NewListFunc returns an object capable of storing results of an etcd list.
|
// NewListFunc returns an object capable of storing results of an etcd list.
|
||||||
NewListFunc: newListFunc,
|
NewListFunc: newListFunc,
|
||||||
|
@ -58,13 +58,13 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||||
},
|
},
|
||||||
// Retrieve the name field of a job
|
// Retrieve the name field of a job
|
||||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||||
return obj.(*extensions.Job).Name, nil
|
return obj.(*batch.Job).Name, nil
|
||||||
},
|
},
|
||||||
// Used to match objects based on labels/fields for list and watch
|
// Used to match objects based on labels/fields for list and watch
|
||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return job.MatchJob(label, field)
|
return job.MatchJob(label, field)
|
||||||
},
|
},
|
||||||
QualifiedResource: extensions.Resource("jobs"),
|
QualifiedResource: batch.Resource("jobs"),
|
||||||
DeleteCollectionWorkers: opts.DeleteCollectionWorkers,
|
DeleteCollectionWorkers: opts.DeleteCollectionWorkers,
|
||||||
|
|
||||||
// Used to validate job creation
|
// Used to validate job creation
|
||||||
|
@ -89,7 +89,7 @@ type StatusREST struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StatusREST) New() runtime.Object {
|
func (r *StatusREST) New() runtime.Object {
|
||||||
return &extensions.Job{}
|
return &batch.Job{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update alters the status subset of an object.
|
// Update alters the status subset of an object.
|
||||||
|
|
|
@ -21,9 +21,8 @@ import (
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
// Ensure that extensions/v1beta1 package is initialized.
|
|
||||||
_ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
|
||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic"
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
|
@ -39,15 +38,15 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer)
|
||||||
return jobStorage, statusStorage, server
|
return jobStorage, statusStorage, server
|
||||||
}
|
}
|
||||||
|
|
||||||
func validNewJob() *extensions.Job {
|
func validNewJob() *batch.Job {
|
||||||
completions := 1
|
completions := 1
|
||||||
parallelism := 1
|
parallelism := 1
|
||||||
return &extensions.Job{
|
return &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Completions: &completions,
|
Completions: &completions,
|
||||||
Parallelism: ¶llelism,
|
Parallelism: ¶llelism,
|
||||||
Selector: &unversioned.LabelSelector{
|
Selector: &unversioned.LabelSelector{
|
||||||
|
@ -84,8 +83,8 @@ func TestCreate(t *testing.T) {
|
||||||
// valid
|
// valid
|
||||||
validJob,
|
validJob,
|
||||||
// invalid (empty selector)
|
// invalid (empty selector)
|
||||||
&extensions.Job{
|
&batch.Job{
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Completions: validJob.Spec.Completions,
|
Completions: validJob.Spec.Completions,
|
||||||
Selector: &unversioned.LabelSelector{},
|
Selector: &unversioned.LabelSelector{},
|
||||||
Template: validJob.Spec.Template,
|
Template: validJob.Spec.Template,
|
||||||
|
@ -104,18 +103,18 @@ func TestUpdate(t *testing.T) {
|
||||||
validNewJob(),
|
validNewJob(),
|
||||||
// updateFunc
|
// updateFunc
|
||||||
func(obj runtime.Object) runtime.Object {
|
func(obj runtime.Object) runtime.Object {
|
||||||
object := obj.(*extensions.Job)
|
object := obj.(*batch.Job)
|
||||||
object.Spec.Parallelism = &two
|
object.Spec.Parallelism = &two
|
||||||
return object
|
return object
|
||||||
},
|
},
|
||||||
// invalid updateFunc
|
// invalid updateFunc
|
||||||
func(obj runtime.Object) runtime.Object {
|
func(obj runtime.Object) runtime.Object {
|
||||||
object := obj.(*extensions.Job)
|
object := obj.(*batch.Job)
|
||||||
object.Spec.Selector = &unversioned.LabelSelector{}
|
object.Spec.Selector = &unversioned.LabelSelector{}
|
||||||
return object
|
return object
|
||||||
},
|
},
|
||||||
func(obj runtime.Object) runtime.Object {
|
func(obj runtime.Object) runtime.Object {
|
||||||
object := obj.(*extensions.Job)
|
object := obj.(*batch.Job)
|
||||||
object.Spec.Completions = &two
|
object.Spec.Completions = &two
|
||||||
return object
|
return object
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,8 +22,8 @@ import (
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions/validation"
|
"k8s.io/kubernetes/pkg/apis/batch/validation"
|
||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic"
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
|
@ -47,20 +47,20 @@ func (jobStrategy) NamespaceScoped() bool {
|
||||||
|
|
||||||
// PrepareForCreate clears the status of a job before creation.
|
// PrepareForCreate clears the status of a job before creation.
|
||||||
func (jobStrategy) PrepareForCreate(obj runtime.Object) {
|
func (jobStrategy) PrepareForCreate(obj runtime.Object) {
|
||||||
job := obj.(*extensions.Job)
|
job := obj.(*batch.Job)
|
||||||
job.Status = extensions.JobStatus{}
|
job.Status = batch.JobStatus{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||||
func (jobStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
func (jobStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
newJob := obj.(*extensions.Job)
|
newJob := obj.(*batch.Job)
|
||||||
oldJob := old.(*extensions.Job)
|
oldJob := old.(*batch.Job)
|
||||||
newJob.Status = oldJob.Status
|
newJob.Status = oldJob.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates a new job.
|
// Validate validates a new job.
|
||||||
func (jobStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList {
|
func (jobStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList {
|
||||||
job := obj.(*extensions.Job)
|
job := obj.(*batch.Job)
|
||||||
// TODO: move UID generation earlier and do this in defaulting logic?
|
// TODO: move UID generation earlier and do this in defaulting logic?
|
||||||
if job.Spec.ManualSelector == nil || *job.Spec.ManualSelector == false {
|
if job.Spec.ManualSelector == nil || *job.Spec.ManualSelector == false {
|
||||||
generateSelector(job)
|
generateSelector(job)
|
||||||
|
@ -71,7 +71,7 @@ func (jobStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList
|
||||||
// generateSelector adds a selector to a job and labels to its template
|
// generateSelector adds a selector to a job and labels to its template
|
||||||
// which can be used to uniquely identify the pods created by that job,
|
// which can be used to uniquely identify the pods created by that job,
|
||||||
// if the user has requested this behavior.
|
// if the user has requested this behavior.
|
||||||
func generateSelector(obj *extensions.Job) {
|
func generateSelector(obj *batch.Job) {
|
||||||
if obj.Spec.Template.Labels == nil {
|
if obj.Spec.Template.Labels == nil {
|
||||||
obj.Spec.Template.Labels = make(map[string]string)
|
obj.Spec.Template.Labels = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
@ -133,8 +133,8 @@ func (jobStrategy) AllowCreateOnUpdate() bool {
|
||||||
|
|
||||||
// ValidateUpdate is the default update validation for an end user.
|
// ValidateUpdate is the default update validation for an end user.
|
||||||
func (jobStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
func (jobStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
||||||
validationErrorList := validation.ValidateJob(obj.(*extensions.Job))
|
validationErrorList := validation.ValidateJob(obj.(*batch.Job))
|
||||||
updateErrorList := validation.ValidateJobUpdate(obj.(*extensions.Job), old.(*extensions.Job))
|
updateErrorList := validation.ValidateJobUpdate(obj.(*batch.Job), old.(*batch.Job))
|
||||||
return append(validationErrorList, updateErrorList...)
|
return append(validationErrorList, updateErrorList...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,17 +145,17 @@ type jobStatusStrategy struct {
|
||||||
var StatusStrategy = jobStatusStrategy{Strategy}
|
var StatusStrategy = jobStatusStrategy{Strategy}
|
||||||
|
|
||||||
func (jobStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
func (jobStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
newJob := obj.(*extensions.Job)
|
newJob := obj.(*batch.Job)
|
||||||
oldJob := old.(*extensions.Job)
|
oldJob := old.(*batch.Job)
|
||||||
newJob.Spec = oldJob.Spec
|
newJob.Spec = oldJob.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jobStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
func (jobStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
||||||
return validation.ValidateJobUpdateStatus(obj.(*extensions.Job), old.(*extensions.Job))
|
return validation.ValidateJobUpdateStatus(obj.(*batch.Job), old.(*batch.Job))
|
||||||
}
|
}
|
||||||
|
|
||||||
// JobSelectableFields returns a field set that represents the object for matching purposes.
|
// JobSelectableFields returns a field set that represents the object for matching purposes.
|
||||||
func JobToSelectableFields(job *extensions.Job) fields.Set {
|
func JobToSelectableFields(job *batch.Job) fields.Set {
|
||||||
objectMetaFieldsSet := generic.ObjectMetaFieldsSet(job.ObjectMeta, true)
|
objectMetaFieldsSet := generic.ObjectMetaFieldsSet(job.ObjectMeta, true)
|
||||||
specificFieldsSet := fields.Set{
|
specificFieldsSet := fields.Set{
|
||||||
"status.successful": strconv.Itoa(job.Status.Succeeded),
|
"status.successful": strconv.Itoa(job.Status.Succeeded),
|
||||||
|
@ -171,7 +171,7 @@ func MatchJob(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
Label: label,
|
Label: label,
|
||||||
Field: field,
|
Field: field,
|
||||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
job, ok := obj.(*extensions.Job)
|
job, ok := obj.(*batch.Job)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil, fmt.Errorf("Given object is not a job.")
|
return nil, nil, fmt.Errorf("Given object is not a job.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/types"
|
"k8s.io/kubernetes/pkg/types"
|
||||||
)
|
)
|
||||||
|
@ -57,17 +57,17 @@ func TestJobStrategy(t *testing.T) {
|
||||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
job := &extensions.Job{
|
job := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "myjob",
|
Name: "myjob",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: api.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: validPodTemplateSpec,
|
Template: validPodTemplateSpec,
|
||||||
ManualSelector: newBool(true),
|
ManualSelector: newBool(true),
|
||||||
},
|
},
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Active: 11,
|
Active: 11,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -81,12 +81,12 @@ func TestJobStrategy(t *testing.T) {
|
||||||
t.Errorf("Unexpected error validating %v", errs)
|
t.Errorf("Unexpected error validating %v", errs)
|
||||||
}
|
}
|
||||||
parallelism := 10
|
parallelism := 10
|
||||||
updatedJob := &extensions.Job{
|
updatedJob := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "4"},
|
ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "4"},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: ¶llelism,
|
Parallelism: ¶llelism,
|
||||||
},
|
},
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Active: 11,
|
Active: 11,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -114,13 +114,13 @@ func TestJobStrategyWithGeneration(t *testing.T) {
|
||||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
job := &extensions.Job{
|
job := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "myjob2",
|
Name: "myjob2",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: api.NamespaceDefault,
|
||||||
UID: theUID,
|
UID: theUID,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: nil,
|
Selector: nil,
|
||||||
Template: validPodTemplateSpec,
|
Template: validPodTemplateSpec,
|
||||||
},
|
},
|
||||||
|
@ -175,33 +175,33 @@ func TestJobStatusStrategy(t *testing.T) {
|
||||||
}
|
}
|
||||||
oldParallelism := 10
|
oldParallelism := 10
|
||||||
newParallelism := 11
|
newParallelism := 11
|
||||||
oldJob := &extensions.Job{
|
oldJob := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "myjob",
|
Name: "myjob",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: api.NamespaceDefault,
|
||||||
ResourceVersion: "10",
|
ResourceVersion: "10",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: validPodTemplateSpec,
|
Template: validPodTemplateSpec,
|
||||||
Parallelism: &oldParallelism,
|
Parallelism: &oldParallelism,
|
||||||
},
|
},
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Active: 11,
|
Active: 11,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
newJob := &extensions.Job{
|
newJob := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "myjob",
|
Name: "myjob",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: api.NamespaceDefault,
|
||||||
ResourceVersion: "9",
|
ResourceVersion: "9",
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: validPodTemplateSpec,
|
Template: validPodTemplateSpec,
|
||||||
Parallelism: &newParallelism,
|
Parallelism: &newParallelism,
|
||||||
},
|
},
|
||||||
Status: extensions.JobStatus{
|
Status: batch.JobStatus{
|
||||||
Active: 12,
|
Active: 12,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ func TestSelectableFieldLabelConversions(t *testing.T) {
|
||||||
apitesting.TestSelectableFieldLabelConversionsOfKind(t,
|
apitesting.TestSelectableFieldLabelConversionsOfKind(t,
|
||||||
testapi.Extensions.GroupVersion().String(),
|
testapi.Extensions.GroupVersion().String(),
|
||||||
"Job",
|
"Job",
|
||||||
labels.Set(JobToSelectableFields(&extensions.Job{})),
|
labels.Set(JobToSelectableFields(&batch.Job{})),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
@ -128,7 +128,7 @@ var _ = framework.KubeDescribe("V1Job", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("scale job up")
|
By("scale job up")
|
||||||
scaler, err := kubectl.ScalerFor(extensions.Kind("Job"), f.Client)
|
scaler, err := kubectl.ScalerFor(batch.Kind("Job"), f.Client)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
||||||
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
||||||
|
@ -153,7 +153,7 @@ var _ = framework.KubeDescribe("V1Job", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("scale job down")
|
By("scale job down")
|
||||||
scaler, err := kubectl.ScalerFor(extensions.Kind("Job"), f.Client)
|
scaler, err := kubectl.ScalerFor(batch.Kind("Job"), f.Client)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
||||||
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
||||||
|
@ -176,7 +176,7 @@ var _ = framework.KubeDescribe("V1Job", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("delete a job")
|
By("delete a job")
|
||||||
reaper, err := kubectl.ReaperFor(extensions.Kind("Job"), f.Client)
|
reaper, err := kubectl.ReaperFor(batch.Kind("Job"), f.Client)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
timeout := 1 * time.Minute
|
timeout := 1 * time.Minute
|
||||||
err = reaper.Stop(f.Namespace.Name, job.Name, timeout, api.NewDeleteOptions(0))
|
err = reaper.Stop(f.Namespace.Name, job.Name, timeout, api.NewDeleteOptions(0))
|
||||||
|
@ -203,12 +203,12 @@ var _ = framework.KubeDescribe("V1Job", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// newTestV1Job returns a job which does one of several testing behaviors.
|
// newTestV1Job returns a job which does one of several testing behaviors.
|
||||||
func newTestV1Job(behavior, name string, rPol api.RestartPolicy, parallelism, completions int) *extensions.Job {
|
func newTestV1Job(behavior, name string, rPol api.RestartPolicy, parallelism, completions int) *batch.Job {
|
||||||
job := &extensions.Job{
|
job := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: ¶llelism,
|
Parallelism: ¶llelism,
|
||||||
Completions: &completions,
|
Completions: &completions,
|
||||||
Template: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
|
@ -264,7 +264,7 @@ func newTestV1Job(behavior, name string, rPol api.RestartPolicy, parallelism, co
|
||||||
return job
|
return job
|
||||||
}
|
}
|
||||||
|
|
||||||
func createV1Job(c *client.Client, ns string, job *extensions.Job) (*extensions.Job, error) {
|
func createV1Job(c *client.Client, ns string, job *batch.Job) (*batch.Job, error) {
|
||||||
return c.Batch().Jobs(ns).Create(job)
|
return c.Batch().Jobs(ns).Create(job)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ func waitForV1JobFail(c *client.Client, ns, jobName string) error {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
for _, c := range curr.Status.Conditions {
|
for _, c := range curr.Status.Conditions {
|
||||||
if c.Type == extensions.JobFailed && c.Status == api.ConditionTrue {
|
if c.Type == batch.JobFailed && c.Status == api.ConditionTrue {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
@ -124,7 +124,7 @@ var _ = framework.KubeDescribe("Job", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("scale job up")
|
By("scale job up")
|
||||||
scaler, err := kubectl.ScalerFor(extensions.Kind("Job"), f.Client)
|
scaler, err := kubectl.ScalerFor(batch.Kind("Job"), f.Client)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
||||||
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
||||||
|
@ -149,7 +149,7 @@ var _ = framework.KubeDescribe("Job", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("scale job down")
|
By("scale job down")
|
||||||
scaler, err := kubectl.ScalerFor(extensions.Kind("Job"), f.Client)
|
scaler, err := kubectl.ScalerFor(batch.Kind("Job"), f.Client)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
waitForScale := kubectl.NewRetryParams(5*time.Second, 1*time.Minute)
|
||||||
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
waitForReplicas := kubectl.NewRetryParams(5*time.Second, 5*time.Minute)
|
||||||
|
@ -172,7 +172,7 @@ var _ = framework.KubeDescribe("Job", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("delete a job")
|
By("delete a job")
|
||||||
reaper, err := kubectl.ReaperFor(extensions.Kind("Job"), f.Client)
|
reaper, err := kubectl.ReaperFor(batch.Kind("Job"), f.Client)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
timeout := 1 * time.Minute
|
timeout := 1 * time.Minute
|
||||||
err = reaper.Stop(f.Namespace.Name, job.Name, timeout, api.NewDeleteOptions(0))
|
err = reaper.Stop(f.Namespace.Name, job.Name, timeout, api.NewDeleteOptions(0))
|
||||||
|
@ -199,12 +199,12 @@ var _ = framework.KubeDescribe("Job", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// newTestJob returns a job which does one of several testing behaviors.
|
// newTestJob returns a job which does one of several testing behaviors.
|
||||||
func newTestJob(behavior, name string, rPol api.RestartPolicy, parallelism, completions int) *extensions.Job {
|
func newTestJob(behavior, name string, rPol api.RestartPolicy, parallelism, completions int) *batch.Job {
|
||||||
job := &extensions.Job{
|
job := &batch.Job{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
Spec: extensions.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Parallelism: ¶llelism,
|
Parallelism: ¶llelism,
|
||||||
Completions: &completions,
|
Completions: &completions,
|
||||||
ManualSelector: newBool(true),
|
ManualSelector: newBool(true),
|
||||||
|
@ -261,7 +261,7 @@ func newTestJob(behavior, name string, rPol api.RestartPolicy, parallelism, comp
|
||||||
return job
|
return job
|
||||||
}
|
}
|
||||||
|
|
||||||
func createJob(c *client.Client, ns string, job *extensions.Job) (*extensions.Job, error) {
|
func createJob(c *client.Client, ns string, job *batch.Job) (*batch.Job, error) {
|
||||||
return c.Extensions().Jobs(ns).Create(job)
|
return c.Extensions().Jobs(ns).Create(job)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ func waitForJobFail(c *client.Client, ns, jobName string) error {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
for _, c := range curr.Status.Conditions {
|
for _, c := range curr.Status.Conditions {
|
||||||
if c.Type == extensions.JobFailed && c.Status == api.ConditionTrue {
|
if c.Type == batch.JobFailed && c.Status == api.ConditionTrue {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue