mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 08:17:26 +00:00
Merge pull request #130697 from thockin/fix_replication_controller_validation_tests
Fix validation test for ReplicationController
This commit is contained in:
commit
a38d4e53e1
@ -16606,435 +16606,267 @@ func TestValidateReplicationControllerStatusUpdate(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateReplicationControllerUpdate(t *testing.T) {
|
// Helper function for RC tests.
|
||||||
validSelector := map[string]string{"a": "b"}
|
func mkValidReplicationController(tweaks ...func(rc *core.ReplicationController)) core.ReplicationController {
|
||||||
validPodTemplate := core.PodTemplate{
|
rc := core.ReplicationController{
|
||||||
Template: core.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
Spec: podtest.MakePodSpec(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
readWriteVolumePodTemplate := core.PodTemplate{
|
|
||||||
Template: core.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
Spec: podtest.MakePodSpec(
|
|
||||||
podtest.SetVolumes(core.Volume{Name: "gcepd", VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
|
||||||
invalidPodTemplate := core.PodTemplate{
|
|
||||||
Template: core.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: invalidSelector,
|
|
||||||
},
|
|
||||||
Spec: podtest.MakePodSpec(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
type rcUpdateTest struct {
|
|
||||||
old core.ReplicationController
|
|
||||||
update core.ReplicationController
|
|
||||||
}
|
|
||||||
successCases := []rcUpdateTest{{
|
|
||||||
old: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: 3,
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
old: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: 1,
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &readWriteVolumePodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, successCase := range successCases {
|
|
||||||
successCase.old.ObjectMeta.ResourceVersion = "1"
|
|
||||||
successCase.update.ObjectMeta.ResourceVersion = "1"
|
|
||||||
if errs := ValidateReplicationControllerUpdate(&successCase.update, &successCase.old, PodValidationOptions{}); len(errs) != 0 {
|
|
||||||
t.Errorf("expected success: %v", errs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errorCases := map[string]rcUpdateTest{
|
|
||||||
"more than one read/write": {
|
|
||||||
old: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: 2,
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &readWriteVolumePodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid selector": {
|
|
||||||
old: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: 2,
|
|
||||||
Selector: invalidSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid pod": {
|
|
||||||
old: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: 2,
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &invalidPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"negative replicas": {
|
|
||||||
old: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: -1,
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for testName, errorCase := range errorCases {
|
|
||||||
if errs := ValidateReplicationControllerUpdate(&errorCase.update, &errorCase.old, PodValidationOptions{}); len(errs) == 0 {
|
|
||||||
t.Errorf("expected failure: %s", testName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateReplicationController(t *testing.T) {
|
|
||||||
validSelector := map[string]string{"a": "b"}
|
|
||||||
validPodTemplate := core.PodTemplate{
|
|
||||||
Template: core.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
Spec: podtest.MakePodSpec(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
readWriteVolumePodTemplate := core.PodTemplate{
|
|
||||||
Template: core.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
Spec: podtest.MakePodSpec(
|
|
||||||
podtest.SetVolumes(core.Volume{Name: "gcepd", VolumeSource: core.VolumeSource{GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
hostnetPodTemplate := core.PodTemplate{
|
|
||||||
Template: core.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
Spec: podtest.MakePodSpec(
|
|
||||||
podtest.SetSecurityContext(&core.PodSecurityContext{
|
|
||||||
HostNetwork: true,
|
|
||||||
}),
|
|
||||||
podtest.SetContainers(podtest.MakeContainer("abc", podtest.SetContainerPorts(
|
|
||||||
core.ContainerPort{
|
|
||||||
ContainerPort: 12345,
|
|
||||||
Protocol: core.ProtocolTCP,
|
|
||||||
}))),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
|
||||||
invalidPodTemplate := core.PodTemplate{
|
|
||||||
Template: core.PodTemplateSpec{
|
|
||||||
Spec: podtest.MakePodSpec(),
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: invalidSelector,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
successCases := []core.ReplicationController{{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
Spec: core.ReplicationControllerSpec{
|
||||||
Replicas: 1,
|
Replicas: 1,
|
||||||
Selector: validSelector,
|
Selector: map[string]string{"a": "b"},
|
||||||
Template: &readWriteVolumePodTemplate.Template,
|
Template: &core.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{"a": "b"},
|
||||||
|
},
|
||||||
|
Spec: podtest.MakePodSpec(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
for _, tweak := range tweaks {
|
||||||
|
tweak(&rc)
|
||||||
|
}
|
||||||
|
return rc
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateReplicationControllerUpdate(t *testing.T) {
|
||||||
|
successCases := []struct {
|
||||||
|
old core.ReplicationController
|
||||||
|
update core.ReplicationController
|
||||||
|
}{{
|
||||||
|
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
|
update: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Replicas = 0
|
||||||
|
}),
|
||||||
}, {
|
}, {
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "hostnet", Namespace: metav1.NamespaceDefault},
|
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
Spec: core.ReplicationControllerSpec{
|
update: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
Replicas: 1,
|
rc.Spec.Replicas = 3
|
||||||
Selector: validSelector,
|
}),
|
||||||
Template: &hostnetPodTemplate.Template,
|
}, {
|
||||||
},
|
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
|
update: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Replicas = 2
|
||||||
|
rc.Spec.Template.Spec = podtest.MakePodSpec(
|
||||||
|
podtest.SetVolumes(
|
||||||
|
core.Volume{
|
||||||
|
Name: "gcepd",
|
||||||
|
VolumeSource: core.VolumeSource{
|
||||||
|
GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{
|
||||||
|
PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}),
|
||||||
}}
|
}}
|
||||||
for _, successCase := range successCases {
|
for _, tc := range successCases {
|
||||||
if errs := ValidateReplicationController(&successCase, PodValidationOptions{}); len(errs) != 0 {
|
tc.old.ObjectMeta.ResourceVersion = "1"
|
||||||
|
tc.update.ObjectMeta.ResourceVersion = "1"
|
||||||
|
if errs := ValidateReplicationControllerUpdate(&tc.update, &tc.old, PodValidationOptions{}); len(errs) != 0 {
|
||||||
t.Errorf("expected success: %v", errs)
|
t.Errorf("expected success: %v", errs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errorCases := map[string]struct {
|
errorCases := map[string]struct {
|
||||||
rc core.ReplicationController
|
old core.ReplicationController
|
||||||
expectedOrigin []string
|
update core.ReplicationController
|
||||||
|
expectedErrs field.ErrorList
|
||||||
}{
|
}{
|
||||||
"zero-length ID": {
|
"unmatched selector": {
|
||||||
rc: core.ReplicationController{
|
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "", Namespace: metav1.NamespaceDefault},
|
update: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
Spec: core.ReplicationControllerSpec{
|
rc.Spec.Selector["another"] = "value"
|
||||||
Selector: validSelector,
|
}),
|
||||||
Template: &validPodTemplate.Template,
|
expectedErrs: field.ErrorList{
|
||||||
},
|
field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"missing-namespace": {
|
"invalid selector": {
|
||||||
rc: core.ReplicationController{
|
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc-123"},
|
update: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
Spec: core.ReplicationControllerSpec{
|
invalid := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
||||||
Selector: validSelector,
|
rc.Spec.Template.Labels = invalid
|
||||||
Template: &validPodTemplate.Template,
|
rc.Spec.Selector = invalid
|
||||||
},
|
}),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Invalid(field.NewPath("spec.template.labels"), nil, "").WithOrigin("labelKey"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"empty selector": {
|
"invalid pod": {
|
||||||
rc: core.ReplicationController{
|
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
update: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
Spec: core.ReplicationControllerSpec{
|
rc.Spec.Template = nil
|
||||||
Template: &validPodTemplate.Template,
|
}),
|
||||||
},
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Required(field.NewPath("spec.template"), ""),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"selector_doesnt_match": {
|
"negative replicas": {
|
||||||
rc: core.ReplicationController{
|
old: mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
update: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
Spec: core.ReplicationControllerSpec{
|
rc.Spec.Replicas = -1
|
||||||
Selector: map[string]string{"foo": "bar"},
|
}),
|
||||||
Template: &validPodTemplate.Template,
|
expectedErrs: field.ErrorList{
|
||||||
},
|
field.Invalid(field.NewPath("spec.replicas"), nil, "").WithOrigin("minimum"),
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid manifest": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"read-write persistent disk with > 1 pod": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc"},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: 2,
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &readWriteVolumePodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"negative_replicas": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: -1,
|
|
||||||
Selector: validSelector,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedOrigin: []string{
|
|
||||||
"minimum",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid_label": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "abc-123",
|
|
||||||
Namespace: metav1.NamespaceDefault,
|
|
||||||
Labels: map[string]string{
|
|
||||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid_label 2": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "abc-123",
|
|
||||||
Namespace: metav1.NamespaceDefault,
|
|
||||||
Labels: map[string]string{
|
|
||||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Template: &invalidPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid_annotation": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "abc-123",
|
|
||||||
Namespace: metav1.NamespaceDefault,
|
|
||||||
Annotations: map[string]string{
|
|
||||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &validPodTemplate.Template,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid restart policy 1": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "abc-123",
|
|
||||||
Namespace: metav1.NamespaceDefault,
|
|
||||||
},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &core.PodTemplateSpec{
|
|
||||||
Spec: podtest.MakePodSpec(podtest.SetRestartPolicy(core.RestartPolicyOnFailure)),
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"invalid restart policy 2": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "abc-123",
|
|
||||||
Namespace: metav1.NamespaceDefault,
|
|
||||||
},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &core.PodTemplateSpec{
|
|
||||||
Spec: podtest.MakePodSpec(podtest.SetRestartPolicy(core.RestartPolicyNever)),
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"template may not contain ephemeral containers": {
|
|
||||||
rc: core.ReplicationController{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
|
|
||||||
Spec: core.ReplicationControllerSpec{
|
|
||||||
Replicas: 1,
|
|
||||||
Selector: validSelector,
|
|
||||||
Template: &core.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: validSelector,
|
|
||||||
},
|
|
||||||
Spec: podtest.MakePodSpec(
|
|
||||||
podtest.SetEphemeralContainers(core.EphemeralContainer{EphemeralContainerCommon: core.EphemeralContainerCommon{Name: "debug", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, tc := range errorCases {
|
||||||
errs := ValidateReplicationController(&v.rc, PodValidationOptions{})
|
t.Run(k, func(t *testing.T) {
|
||||||
if len(errs) == 0 {
|
tc.old.ObjectMeta.ResourceVersion = "1"
|
||||||
t.Errorf("expected failure for %s", k)
|
tc.update.ObjectMeta.ResourceVersion = "1"
|
||||||
|
errs := ValidateReplicationControllerUpdate(&tc.update, &tc.old, PodValidationOptions{})
|
||||||
|
matcher := fldtest.ErrorMatcher{}.ByType().ByField().ByOrigin().ByDetailSubstring()
|
||||||
|
matcher.Test(t, tc.expectedErrs, errs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateReplicationController(t *testing.T) {
|
||||||
|
successCases := []core.ReplicationController{
|
||||||
|
mkValidReplicationController(func(rc *core.ReplicationController) {}),
|
||||||
|
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Name = "abc-123" }),
|
||||||
|
mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Replicas = 2
|
||||||
|
rc.Spec.Template.Spec = podtest.MakePodSpec(
|
||||||
|
podtest.SetVolumes(
|
||||||
|
core.Volume{
|
||||||
|
Name: "gcepd",
|
||||||
|
VolumeSource: core.VolumeSource{
|
||||||
|
GCEPersistentDisk: &core.GCEPersistentDiskVolumeSource{
|
||||||
|
PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}),
|
||||||
|
mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Template.Spec = podtest.MakePodSpec(
|
||||||
|
podtest.SetSecurityContext(&core.PodSecurityContext{HostNetwork: true}),
|
||||||
|
podtest.SetContainers(podtest.MakeContainer("abc",
|
||||||
|
podtest.SetContainerPorts(core.ContainerPort{
|
||||||
|
ContainerPort: 12345, Protocol: core.ProtocolTCP,
|
||||||
|
}))),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 0 }),
|
||||||
|
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 1 }),
|
||||||
|
mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = 100 }),
|
||||||
|
}
|
||||||
|
for _, tc := range successCases {
|
||||||
|
if errs := ValidateReplicationController(&tc, PodValidationOptions{}); len(errs) != 0 {
|
||||||
|
t.Errorf("expected success: %v", errs)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
expectedOrigins := sets.NewString(v.expectedOrigin...)
|
errorCases := map[string]struct {
|
||||||
|
input core.ReplicationController
|
||||||
for i := range errs {
|
expectedErrs field.ErrorList
|
||||||
field := errs[i].Field
|
}{
|
||||||
if !strings.HasPrefix(field, "spec.template.") &&
|
"missing name": {
|
||||||
field != "metadata.name" &&
|
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Name = "" }),
|
||||||
field != "metadata.namespace" &&
|
expectedErrs: field.ErrorList{
|
||||||
field != "spec.selector" &&
|
field.Required(field.NewPath("metadata.name"), ""),
|
||||||
field != "spec.template" &&
|
},
|
||||||
field != "GCEPersistentDisk.ReadOnly" &&
|
},
|
||||||
field != "spec.replicas" &&
|
"missing namespace": {
|
||||||
field != "spec.template.labels" &&
|
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Namespace = "" }),
|
||||||
field != "metadata.annotations" &&
|
expectedErrs: field.ErrorList{
|
||||||
field != "metadata.labels" &&
|
field.Required(field.NewPath("metadata.namespace"), ""),
|
||||||
field != "status.replicas" {
|
},
|
||||||
t.Errorf("%s: missing prefix for: %v", k, errs[i])
|
},
|
||||||
}
|
"empty selector": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Selector = nil }),
|
||||||
if len(v.expectedOrigin) > 0 && errs[i].Origin != "" {
|
expectedErrs: field.ErrorList{
|
||||||
if !expectedOrigins.Has(errs[i].Origin) {
|
field.Required(field.NewPath("spec.selector"), ""),
|
||||||
t.Errorf("%s: unexpected origin for: %v, expected one of %v", k, errs[i].Origin, v.expectedOrigin)
|
},
|
||||||
|
},
|
||||||
|
"selector doesnt match": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Selector = map[string]string{"foo": "bar"} }),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid manifest": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Template = nil }),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Required(field.NewPath("spec.template"), ""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"negative replicas": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) { rc.Spec.Replicas = -1 }),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Invalid(field.NewPath("spec.replicas"), nil, "").WithOrigin("minimum"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid label": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Labels = map[string]string{
|
||||||
|
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||||
}
|
}
|
||||||
expectedOrigins.Delete(errs[i].Origin)
|
}),
|
||||||
}
|
expectedErrs: field.ErrorList{
|
||||||
}
|
field.Invalid(field.NewPath("metadata.labels"), nil, "").WithOrigin("labelKey"),
|
||||||
if len(expectedOrigins) > 0 {
|
},
|
||||||
t.Errorf("%s: missing errors with origin: %v", k, expectedOrigins.List())
|
},
|
||||||
}
|
"invalid label 2": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Template.Labels = map[string]string{
|
||||||
|
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Invalid(field.NewPath("spec.template.metadata.labels"), nil, "does not match template"),
|
||||||
|
field.Invalid(field.NewPath("spec.template.labels"), nil, "").WithOrigin("labelKey"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid annotation": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Annotations = map[string]string{
|
||||||
|
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Invalid(field.NewPath("metadata.annotations"), nil, "name part must consist of"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid restart policy 1": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Template.Spec.RestartPolicy = core.RestartPolicyOnFailure
|
||||||
|
}),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.NotSupported[core.RestartPolicy](field.NewPath("spec.template.spec.restartPolicy"), nil, nil),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid restart policy 2": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Template.Spec.RestartPolicy = core.RestartPolicyNever
|
||||||
|
}),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.NotSupported[core.RestartPolicy](field.NewPath("spec.template.spec.restartPolicy"), nil, nil),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"template may not contain ephemeral containers": {
|
||||||
|
input: mkValidReplicationController(func(rc *core.ReplicationController) {
|
||||||
|
rc.Spec.Template.Spec = podtest.MakePodSpec(
|
||||||
|
podtest.SetEphemeralContainers(
|
||||||
|
core.EphemeralContainer{
|
||||||
|
EphemeralContainerCommon: core.EphemeralContainerCommon{
|
||||||
|
Name: "debug",
|
||||||
|
Image: "image",
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
|
TerminationMessagePolicy: "File",
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}),
|
||||||
|
expectedErrs: field.ErrorList{
|
||||||
|
field.Forbidden(field.NewPath("spec.template.spec.ephemeralContainers"), "not allowed in pod template"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for k, tc := range errorCases {
|
||||||
|
t.Run(k, func(t *testing.T) {
|
||||||
|
errs := ValidateReplicationController(&tc.input, PodValidationOptions{})
|
||||||
|
matcher := fldtest.ErrorMatcher{}.ByType().ByField().ByOrigin().ByDetailSubstring()
|
||||||
|
matcher.Test(t, tc.expectedErrs, errs)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user