Merge pull request #26106 from soltysh/scheduledjob_validation

Automatic merge from submit-queue

ScheduledJob validation

@erictune while playing earlier today I've noticed `suspend` isn't a pointer which requires it to be set. Additionally the validation for job selectors is too strict in that it requires the selector to match produced pods, which doesn't make sense for SJ, I've changed it to being forbidden to set entirely.

[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/.github/PULL_REQUEST_TEMPLATE.md?pixel)]()
This commit is contained in:
k8s-merge-robot 2016-05-30 09:05:01 -07:00
commit dff1ed1497
11 changed files with 236 additions and 214 deletions

View File

@ -246,7 +246,13 @@ func DeepCopy_batch_ScheduledJobSpec(in ScheduledJobSpec, out *ScheduledJobSpec,
out.StartingDeadlineSeconds = nil out.StartingDeadlineSeconds = nil
} }
out.ConcurrencyPolicy = in.ConcurrencyPolicy out.ConcurrencyPolicy = in.ConcurrencyPolicy
out.Suspend = in.Suspend if in.Suspend != nil {
in, out := in.Suspend, &out.Suspend
*out = new(bool)
**out = *in
} else {
out.Suspend = nil
}
if err := DeepCopy_batch_JobTemplateSpec(in.JobTemplate, &out.JobTemplate, c); err != nil { if err := DeepCopy_batch_JobTemplateSpec(in.JobTemplate, &out.JobTemplate, c); err != nil {
return err return err
} }

View File

@ -3602,33 +3602,43 @@ func (x *ScheduledJobSpec) CodecEncodeSelf(e *codec1978.Encoder) {
} }
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234) z.EncSendContainerState(codecSelfer_containerArrayElem1234)
yym15 := z.EncBinary() if x.Suspend == nil {
_ = yym15 r.EncodeNil()
if false {
} else { } else {
r.EncodeBool(bool(x.Suspend)) yy15 := *x.Suspend
yym16 := z.EncBinary()
_ = yym16
if false {
} else {
r.EncodeBool(bool(yy15))
}
} }
} else { } else {
z.EncSendContainerState(codecSelfer_containerMapKey1234) z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("suspend")) r.EncodeString(codecSelferC_UTF81234, string("suspend"))
z.EncSendContainerState(codecSelfer_containerMapValue1234) z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym16 := z.EncBinary() if x.Suspend == nil {
_ = yym16 r.EncodeNil()
if false {
} else { } else {
r.EncodeBool(bool(x.Suspend)) yy17 := *x.Suspend
yym18 := z.EncBinary()
_ = yym18
if false {
} else {
r.EncodeBool(bool(yy17))
}
} }
} }
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234) z.EncSendContainerState(codecSelfer_containerArrayElem1234)
yy18 := &x.JobTemplate yy20 := &x.JobTemplate
yy18.CodecEncodeSelf(e) yy20.CodecEncodeSelf(e)
} else { } else {
z.EncSendContainerState(codecSelfer_containerMapKey1234) z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("jobTemplate")) r.EncodeString(codecSelferC_UTF81234, string("jobTemplate"))
z.EncSendContainerState(codecSelfer_containerMapValue1234) z.EncSendContainerState(codecSelfer_containerMapValue1234)
yy20 := &x.JobTemplate yy22 := &x.JobTemplate
yy20.CodecEncodeSelf(e) yy22.CodecEncodeSelf(e)
} }
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234) z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
@ -3721,16 +3731,26 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
} }
case "suspend": case "suspend":
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Suspend = false if x.Suspend != nil {
x.Suspend = nil
}
} else { } else {
x.Suspend = bool(r.DecodeBool()) if x.Suspend == nil {
x.Suspend = new(bool)
}
yym9 := z.DecBinary()
_ = yym9
if false {
} else {
*((*bool)(x.Suspend)) = r.DecodeBool()
}
} }
case "jobTemplate": case "jobTemplate":
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.JobTemplate = JobTemplateSpec{} x.JobTemplate = JobTemplateSpec{}
} else { } else {
yyv9 := &x.JobTemplate yyv10 := &x.JobTemplate
yyv9.CodecDecodeSelf(d) yyv10.CodecDecodeSelf(d)
} }
default: default:
z.DecStructFieldNotFound(-1, yys3) z.DecStructFieldNotFound(-1, yys3)
@ -3743,16 +3763,16 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d) z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r _, _, _ = h, z, r
var yyj10 int var yyj11 int
var yyb10 bool var yyb11 bool
var yyhl10 bool = l >= 0 var yyhl11 bool = l >= 0
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3762,13 +3782,13 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
} else { } else {
x.Schedule = string(r.DecodeString()) x.Schedule = string(r.DecodeString())
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3781,20 +3801,20 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if x.StartingDeadlineSeconds == nil { if x.StartingDeadlineSeconds == nil {
x.StartingDeadlineSeconds = new(int64) x.StartingDeadlineSeconds = new(int64)
} }
yym13 := z.DecBinary() yym14 := z.DecBinary()
_ = yym13 _ = yym14
if false { if false {
} else { } else {
*((*int64)(x.StartingDeadlineSeconds)) = int64(r.DecodeInt(64)) *((*int64)(x.StartingDeadlineSeconds)) = int64(r.DecodeInt(64))
} }
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3804,29 +3824,39 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
} else { } else {
x.ConcurrencyPolicy = ConcurrencyPolicy(r.DecodeString()) x.ConcurrencyPolicy = ConcurrencyPolicy(r.DecodeString())
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Suspend = false if x.Suspend != nil {
x.Suspend = nil
}
} else { } else {
x.Suspend = bool(r.DecodeBool()) if x.Suspend == nil {
x.Suspend = new(bool)
}
yym17 := z.DecBinary()
_ = yym17
if false {
} else {
*((*bool)(x.Suspend)) = r.DecodeBool()
}
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3834,21 +3864,21 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.JobTemplate = JobTemplateSpec{} x.JobTemplate = JobTemplateSpec{}
} else { } else {
yyv16 := &x.JobTemplate yyv18 := &x.JobTemplate
yyv16.CodecDecodeSelf(d) yyv18.CodecDecodeSelf(d)
} }
for { for {
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
break break
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj10-1, "") z.DecStructFieldNotFound(yyj11-1, "")
} }
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} }

View File

@ -209,7 +209,7 @@ type ScheduledJobSpec struct {
// Suspend flag tells the controller to suspend subsequent executions, it does // Suspend flag tells the controller to suspend subsequent executions, it does
// not apply to already started executions. Defaults to false. // not apply to already started executions. Defaults to false.
Suspend bool `json:"suspend"` Suspend *bool `json:"suspend"`
// JobTemplate is the object that describes the job that will be created when // JobTemplate is the object that describes the job that will be created when
// executing a ScheduledJob. // executing a ScheduledJob.

View File

@ -286,7 +286,13 @@ func DeepCopy_v2alpha1_ScheduledJobSpec(in ScheduledJobSpec, out *ScheduledJobSp
out.StartingDeadlineSeconds = nil out.StartingDeadlineSeconds = nil
} }
out.ConcurrencyPolicy = in.ConcurrencyPolicy out.ConcurrencyPolicy = in.ConcurrencyPolicy
out.Suspend = in.Suspend if in.Suspend != nil {
in, out := in.Suspend, &out.Suspend
*out = new(bool)
**out = *in
} else {
out.Suspend = nil
}
if err := DeepCopy_v2alpha1_JobTemplateSpec(in.JobTemplate, &out.JobTemplate, c); err != nil { if err := DeepCopy_v2alpha1_JobTemplateSpec(in.JobTemplate, &out.JobTemplate, c); err != nil {
return err return err
} }

View File

@ -636,14 +636,16 @@ func (m *ScheduledJobSpec) MarshalTo(data []byte) (int, error) {
i++ i++
i = encodeVarintGenerated(data, i, uint64(len(m.ConcurrencyPolicy))) i = encodeVarintGenerated(data, i, uint64(len(m.ConcurrencyPolicy)))
i += copy(data[i:], m.ConcurrencyPolicy) i += copy(data[i:], m.ConcurrencyPolicy)
data[i] = 0x20 if m.Suspend != nil {
i++ data[i] = 0x20
if m.Suspend { i++
data[i] = 1 if *m.Suspend {
} else { data[i] = 1
data[i] = 0 } else {
data[i] = 0
}
i++
} }
i++
data[i] = 0x2a data[i] = 0x2a
i++ i++
i = encodeVarintGenerated(data, i, uint64(m.JobTemplate.Size())) i = encodeVarintGenerated(data, i, uint64(m.JobTemplate.Size()))
@ -905,7 +907,9 @@ func (m *ScheduledJobSpec) Size() (n int) {
} }
l = len(m.ConcurrencyPolicy) l = len(m.ConcurrencyPolicy)
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
n += 2 if m.Suspend != nil {
n += 2
}
l = m.JobTemplate.Size() l = m.JobTemplate.Size()
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
return n return n
@ -2741,7 +2745,8 @@ func (m *ScheduledJobSpec) Unmarshal(data []byte) error {
break break
} }
} }
m.Suspend = bool(v != 0) b := bool(v != 0)
m.Suspend = &b
case 5: case 5:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field JobTemplate", wireType) return fmt.Errorf("proto: wrong wireType = %d for field JobTemplate", wireType)

View File

@ -24,7 +24,6 @@ package k8s.io.kubernetes.pkg.apis.batch.v2alpha1;
import "k8s.io/kubernetes/pkg/api/resource/generated.proto"; import "k8s.io/kubernetes/pkg/api/resource/generated.proto";
import "k8s.io/kubernetes/pkg/api/unversioned/generated.proto"; import "k8s.io/kubernetes/pkg/api/unversioned/generated.proto";
import "k8s.io/kubernetes/pkg/api/v1/generated.proto"; import "k8s.io/kubernetes/pkg/api/v1/generated.proto";
import "k8s.io/kubernetes/pkg/runtime/generated.proto";
import "k8s.io/kubernetes/pkg/util/intstr/generated.proto"; import "k8s.io/kubernetes/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated". // Package-wide variables from generator "generated".

View File

@ -3578,33 +3578,43 @@ func (x *ScheduledJobSpec) CodecEncodeSelf(e *codec1978.Encoder) {
} }
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234) z.EncSendContainerState(codecSelfer_containerArrayElem1234)
yym15 := z.EncBinary() if x.Suspend == nil {
_ = yym15 r.EncodeNil()
if false {
} else { } else {
r.EncodeBool(bool(x.Suspend)) yy15 := *x.Suspend
yym16 := z.EncBinary()
_ = yym16
if false {
} else {
r.EncodeBool(bool(yy15))
}
} }
} else { } else {
z.EncSendContainerState(codecSelfer_containerMapKey1234) z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("suspend")) r.EncodeString(codecSelferC_UTF81234, string("suspend"))
z.EncSendContainerState(codecSelfer_containerMapValue1234) z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym16 := z.EncBinary() if x.Suspend == nil {
_ = yym16 r.EncodeNil()
if false {
} else { } else {
r.EncodeBool(bool(x.Suspend)) yy17 := *x.Suspend
yym18 := z.EncBinary()
_ = yym18
if false {
} else {
r.EncodeBool(bool(yy17))
}
} }
} }
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234) z.EncSendContainerState(codecSelfer_containerArrayElem1234)
yy18 := &x.JobTemplate yy20 := &x.JobTemplate
yy18.CodecEncodeSelf(e) yy20.CodecEncodeSelf(e)
} else { } else {
z.EncSendContainerState(codecSelfer_containerMapKey1234) z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("jobTemplate")) r.EncodeString(codecSelferC_UTF81234, string("jobTemplate"))
z.EncSendContainerState(codecSelfer_containerMapValue1234) z.EncSendContainerState(codecSelfer_containerMapValue1234)
yy20 := &x.JobTemplate yy22 := &x.JobTemplate
yy20.CodecEncodeSelf(e) yy22.CodecEncodeSelf(e)
} }
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234) z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
@ -3697,16 +3707,26 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
} }
case "suspend": case "suspend":
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Suspend = false if x.Suspend != nil {
x.Suspend = nil
}
} else { } else {
x.Suspend = bool(r.DecodeBool()) if x.Suspend == nil {
x.Suspend = new(bool)
}
yym9 := z.DecBinary()
_ = yym9
if false {
} else {
*((*bool)(x.Suspend)) = r.DecodeBool()
}
} }
case "jobTemplate": case "jobTemplate":
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.JobTemplate = JobTemplateSpec{} x.JobTemplate = JobTemplateSpec{}
} else { } else {
yyv9 := &x.JobTemplate yyv10 := &x.JobTemplate
yyv9.CodecDecodeSelf(d) yyv10.CodecDecodeSelf(d)
} }
default: default:
z.DecStructFieldNotFound(-1, yys3) z.DecStructFieldNotFound(-1, yys3)
@ -3719,16 +3739,16 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d) z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r _, _, _ = h, z, r
var yyj10 int var yyj11 int
var yyb10 bool var yyb11 bool
var yyhl10 bool = l >= 0 var yyhl11 bool = l >= 0
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3738,13 +3758,13 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
} else { } else {
x.Schedule = string(r.DecodeString()) x.Schedule = string(r.DecodeString())
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3757,20 +3777,20 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if x.StartingDeadlineSeconds == nil { if x.StartingDeadlineSeconds == nil {
x.StartingDeadlineSeconds = new(int64) x.StartingDeadlineSeconds = new(int64)
} }
yym13 := z.DecBinary() yym14 := z.DecBinary()
_ = yym13 _ = yym14
if false { if false {
} else { } else {
*((*int64)(x.StartingDeadlineSeconds)) = int64(r.DecodeInt(64)) *((*int64)(x.StartingDeadlineSeconds)) = int64(r.DecodeInt(64))
} }
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3780,29 +3800,39 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
} else { } else {
x.ConcurrencyPolicy = ConcurrencyPolicy(r.DecodeString()) x.ConcurrencyPolicy = ConcurrencyPolicy(r.DecodeString())
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Suspend = false if x.Suspend != nil {
x.Suspend = nil
}
} else { } else {
x.Suspend = bool(r.DecodeBool()) if x.Suspend == nil {
x.Suspend = new(bool)
}
yym17 := z.DecBinary()
_ = yym17
if false {
} else {
*((*bool)(x.Suspend)) = r.DecodeBool()
}
} }
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -3810,21 +3840,21 @@ func (x *ScheduledJobSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.JobTemplate = JobTemplateSpec{} x.JobTemplate = JobTemplateSpec{}
} else { } else {
yyv16 := &x.JobTemplate yyv18 := &x.JobTemplate
yyv16.CodecDecodeSelf(d) yyv18.CodecDecodeSelf(d)
} }
for { for {
yyj10++ yyj11++
if yyhl10 { if yyhl11 {
yyb10 = yyj10 > l yyb11 = yyj11 > l
} else { } else {
yyb10 = r.CheckBreak() yyb11 = r.CheckBreak()
} }
if yyb10 { if yyb11 {
break break
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj10-1, "") z.DecStructFieldNotFound(yyj11-1, "")
} }
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} }

View File

@ -211,7 +211,7 @@ type ScheduledJobSpec struct {
// Suspend flag tells the controller to suspend subsequent executions, it does // Suspend flag tells the controller to suspend subsequent executions, it does
// not apply to already started executions. Defaults to false. // not apply to already started executions. Defaults to false.
Suspend bool `json:"suspend" protobuf:"varint,4,opt,name=suspend"` Suspend *bool `json:"suspend" protobuf:"varint,4,opt,name=suspend"`
// JobTemplate is the object that describes the job that will be created when // JobTemplate is the object that describes the job that will be created when
// executing a ScheduledJob. // executing a ScheduledJob.

View File

@ -89,17 +89,8 @@ func ValidateJob(job *batch.Job) field.ErrorList {
} }
func ValidateJobSpec(spec *batch.JobSpec, fldPath *field.Path) field.ErrorList { func ValidateJobSpec(spec *batch.JobSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{} allErrs := validateJobSpec(spec, fldPath)
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 { if spec.Selector == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("selector"), "")) allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
} else { } else {
@ -113,6 +104,21 @@ func ValidateJobSpec(spec *batch.JobSpec, fldPath *field.Path) field.ErrorList {
allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`")) allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`"))
} }
} }
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"))...)
}
allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...) allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...)
if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure &&
@ -215,7 +221,14 @@ func ValidateJobTemplate(job *batch.JobTemplate) field.ErrorList {
} }
func ValidateJobTemplateSpec(spec *batch.JobTemplateSpec, fldPath *field.Path) field.ErrorList { func ValidateJobTemplateSpec(spec *batch.JobTemplateSpec, fldPath *field.Path) field.ErrorList {
// this method should be identical to ValidateJob allErrs := validateJobSpec(&spec.Spec, fldPath.Child("spec"))
allErrs := ValidateJobSpec(&spec.Spec, fldPath.Child("spec"))
// jobtemplate will always have the selector automatically generated
if spec.Spec.Selector != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("spec", "selector"), spec.Spec.Selector, "`selector` will be auto-generated"))
}
if spec.Spec.ManualSelector != nil && *spec.Spec.ManualSelector {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("spec", "manualSelector"), spec.Spec.ManualSelector, []string{"nil", "false"}))
}
return allErrs return allErrs
} }

View File

@ -306,8 +306,8 @@ func TestValidateJobUpdateStatus(t *testing.T) {
func TestValidateScheduledJob(t *testing.T) { func TestValidateScheduledJob(t *testing.T) {
validManualSelector := getValidManualSelector() validManualSelector := getValidManualSelector()
validGeneratedSelector := getValidGeneratedSelector() validPodTemplateSpec := getValidPodTemplateSpecForGenerated(getValidGeneratedSelector())
validPodTemplateSpec := getValidPodTemplateSpecForGenerated(validGeneratedSelector) validPodTemplateSpec.Labels = map[string]string{}
successCases := map[string]batch.ScheduledJob{ successCases := map[string]batch.ScheduledJob{
"basic scheduled job": { "basic scheduled job": {
@ -321,7 +321,6 @@ func TestValidateScheduledJob(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validGeneratedSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
@ -349,7 +348,6 @@ func TestValidateScheduledJob(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validGeneratedSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
@ -366,7 +364,6 @@ func TestValidateScheduledJob(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validGeneratedSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
@ -384,7 +381,6 @@ func TestValidateScheduledJob(t *testing.T) {
StartingDeadlineSeconds: &negative64, StartingDeadlineSeconds: &negative64,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validGeneratedSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
@ -400,7 +396,6 @@ func TestValidateScheduledJob(t *testing.T) {
Schedule: "* * * * * ?", Schedule: "* * * * * ?",
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validGeneratedSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
@ -417,7 +412,6 @@ func TestValidateScheduledJob(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validGeneratedSelector,
Parallelism: &negative, Parallelism: &negative,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
@ -437,7 +431,6 @@ func TestValidateScheduledJob(t *testing.T) {
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Completions: &negative, Completions: &negative,
Selector: validGeneratedSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
@ -455,13 +448,12 @@ func TestValidateScheduledJob(t *testing.T) {
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
ActiveDeadlineSeconds: &negative64, ActiveDeadlineSeconds: &negative64,
Selector: validGeneratedSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
}, },
}, },
"spec.jobTemplate.spec.selector:Required value": { "spec.jobTemplate.spec.selector: Invalid value: {\"matchLabels\":{\"a\":\"b\"}}: `selector` will be auto-generated": {
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "myscheduledjob", Name: "myscheduledjob",
Namespace: api.NamespaceDefault, Namespace: api.NamespaceDefault,
@ -472,12 +464,13 @@ func TestValidateScheduledJob(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validManualSelector,
Template: validPodTemplateSpec, Template: validPodTemplateSpec,
}, },
}, },
}, },
}, },
"spec.jobTemplate.spec.template.metadata.labels: Invalid value: {\"y\":\"z\"}: `selector` does not match template `labels`": { "spec.jobTemplate.spec.manualSelector: Unsupported value": {
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "myscheduledjob", Name: "myscheduledjob",
Namespace: api.NamespaceDefault, Namespace: api.NamespaceDefault,
@ -488,45 +481,8 @@ func TestValidateScheduledJob(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validManualSelector,
ManualSelector: newBool(true), ManualSelector: newBool(true),
Template: api.PodTemplateSpec{ Template: validPodTemplateSpec,
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.jobTemplate.spec.template.metadata.labels: Invalid value: {\"controller-uid\":\"4d5e6f\"}: `selector` does not match template `labels`": {
ObjectMeta: api.ObjectMeta{
Name: "myscheduledjob",
Namespace: api.NamespaceDefault,
UID: types.UID("1a2b3c"),
},
Spec: batch.ScheduledJobSpec{
Schedule: "* * * * * ?",
ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{
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"}},
},
},
}, },
}, },
}, },
@ -542,12 +498,7 @@ func TestValidateScheduledJob(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validManualSelector,
ManualSelector: newBool(true),
Template: api.PodTemplateSpec{ Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: validManualSelector.MatchLabels,
},
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicyAlways, RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,

View File

@ -41,13 +41,7 @@ func TestScheduledJobStrategy(t *testing.T) {
t.Errorf("ScheduledJob should not allow create on update") t.Errorf("ScheduledJob should not allow create on update")
} }
validSelector := &unversioned.LabelSelector{
MatchLabels: map[string]string{"a": "b"},
}
validPodTemplateSpec := api.PodTemplateSpec{ validPodTemplateSpec := api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: validSelector.MatchLabels,
},
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicyOnFailure, RestartPolicy: api.RestartPolicyOnFailure,
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
@ -64,9 +58,7 @@ func TestScheduledJobStrategy(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validSelector, Template: validPodTemplateSpec,
Template: validPodTemplateSpec,
ManualSelector: newBool(true),
}, },
}, },
}, },
@ -110,13 +102,7 @@ func TestScheduledJobStatusStrategy(t *testing.T) {
if StatusStrategy.AllowCreateOnUpdate() { if StatusStrategy.AllowCreateOnUpdate() {
t.Errorf("ScheduledJob should not allow create on update") t.Errorf("ScheduledJob should not allow create on update")
} }
validSelector := &unversioned.LabelSelector{
MatchLabels: map[string]string{"a": "b"},
}
validPodTemplateSpec := api.PodTemplateSpec{ validPodTemplateSpec := api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: validSelector.MatchLabels,
},
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicyOnFailure, RestartPolicy: api.RestartPolicyOnFailure,
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
@ -135,9 +121,7 @@ func TestScheduledJobStatusStrategy(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validSelector, Template: validPodTemplateSpec,
Template: validPodTemplateSpec,
ManualSelector: newBool(true),
}, },
}, },
}, },
@ -154,9 +138,7 @@ func TestScheduledJobStatusStrategy(t *testing.T) {
ConcurrencyPolicy: batch.AllowConcurrent, ConcurrencyPolicy: batch.AllowConcurrent,
JobTemplate: batch.JobTemplateSpec{ JobTemplate: batch.JobTemplateSpec{
Spec: batch.JobSpec{ Spec: batch.JobSpec{
Selector: validSelector, Template: validPodTemplateSpec,
Template: validPodTemplateSpec,
ManualSelector: newBool(true),
}, },
}, },
}, },