123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- /*
- Copyright 2016 The Kubernetes Authors.
- 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/apps"
- )
- func TestValidatePetSet(t *testing.T) {
- validLabels := map[string]string{"a": "b"}
- validPodTemplate := api.PodTemplate{
- Template: api.PodTemplateSpec{
- ObjectMeta: api.ObjectMeta{
- Labels: validLabels,
- },
- Spec: api.PodSpec{
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
- },
- },
- }
- invalidLabels := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
- invalidPodTemplate := api.PodTemplate{
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- },
- ObjectMeta: api.ObjectMeta{
- Labels: invalidLabels,
- },
- },
- }
- successCases := []apps.PetSet{
- {
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- {
- ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- }
- for _, successCase := range successCases {
- if errs := ValidatePetSet(&successCase); len(errs) != 0 {
- t.Errorf("expected success: %v", errs)
- }
- }
- errorCases := map[string]apps.PetSet{
- "zero-length ID": {
- ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- "missing-namespace": {
- ObjectMeta: api.ObjectMeta{Name: "abc-123"},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- "empty selector": {
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Template: validPodTemplate.Template,
- },
- },
- "selector_doesnt_match": {
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
- Template: validPodTemplate.Template,
- },
- },
- "invalid manifest": {
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- },
- },
- "negative_replicas": {
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Replicas: -1,
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- },
- },
- "invalid_label": {
- ObjectMeta: api.ObjectMeta{
- Name: "abc-123",
- Namespace: api.NamespaceDefault,
- Labels: map[string]string{
- "NoUppercaseOrSpecialCharsLike=Equals": "bar",
- },
- },
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- "invalid_label 2": {
- ObjectMeta: api.ObjectMeta{
- Name: "abc-123",
- Namespace: api.NamespaceDefault,
- Labels: map[string]string{
- "NoUppercaseOrSpecialCharsLike=Equals": "bar",
- },
- },
- Spec: apps.PetSetSpec{
- Template: invalidPodTemplate.Template,
- },
- },
- "invalid_annotation": {
- ObjectMeta: api.ObjectMeta{
- Name: "abc-123",
- Namespace: api.NamespaceDefault,
- Annotations: map[string]string{
- "NoUppercaseOrSpecialCharsLike=Equals": "bar",
- },
- },
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- "invalid restart policy 1": {
- ObjectMeta: api.ObjectMeta{
- Name: "abc-123",
- Namespace: api.NamespaceDefault,
- },
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- RestartPolicy: api.RestartPolicyOnFailure,
- DNSPolicy: api.DNSClusterFirst,
- Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
- },
- ObjectMeta: api.ObjectMeta{
- Labels: validLabels,
- },
- },
- },
- },
- "invalid restart policy 2": {
- ObjectMeta: api.ObjectMeta{
- Name: "abc-123",
- Namespace: api.NamespaceDefault,
- },
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- RestartPolicy: api.RestartPolicyNever,
- DNSPolicy: api.DNSClusterFirst,
- Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
- },
- ObjectMeta: api.ObjectMeta{
- Labels: validLabels,
- },
- },
- },
- },
- }
- for k, v := range errorCases {
- errs := ValidatePetSet(&v)
- if len(errs) == 0 {
- t.Errorf("expected failure for %s", k)
- }
- for i := range errs {
- field := errs[i].Field
- if !strings.HasPrefix(field, "spec.template.") &&
- field != "metadata.name" &&
- field != "metadata.namespace" &&
- field != "spec.selector" &&
- field != "spec.template" &&
- field != "GCEPersistentDisk.ReadOnly" &&
- field != "spec.replicas" &&
- field != "spec.template.labels" &&
- field != "metadata.annotations" &&
- field != "metadata.labels" &&
- field != "status.replicas" {
- t.Errorf("%s: missing prefix for: %v", k, errs[i])
- }
- }
- }
- }
- func TestValidatePetSetUpdate(t *testing.T) {
- validLabels := map[string]string{"a": "b"}
- validPodTemplate := api.PodTemplate{
- Template: api.PodTemplateSpec{
- ObjectMeta: api.ObjectMeta{
- Labels: validLabels,
- },
- Spec: api.PodSpec{
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
- },
- },
- }
- readWriteVolumePodTemplate := api.PodTemplate{
- Template: api.PodTemplateSpec{
- ObjectMeta: api.ObjectMeta{
- Labels: validLabels,
- },
- Spec: api.PodSpec{
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
- Volumes: []api.Volume{{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}},
- },
- },
- }
- invalidLabels := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
- invalidPodTemplate := api.PodTemplate{
- Template: api.PodTemplateSpec{
- Spec: api.PodSpec{
- RestartPolicy: api.RestartPolicyAlways,
- DNSPolicy: api.DNSClusterFirst,
- },
- ObjectMeta: api.ObjectMeta{
- Labels: invalidLabels,
- },
- },
- }
- type psUpdateTest struct {
- old apps.PetSet
- update apps.PetSet
- }
- successCases := []psUpdateTest{
- {
- old: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- update: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Replicas: 3,
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- },
- }
- for _, successCase := range successCases {
- successCase.old.ObjectMeta.ResourceVersion = "1"
- successCase.update.ObjectMeta.ResourceVersion = "1"
- if errs := ValidatePetSetUpdate(&successCase.update, &successCase.old); len(errs) != 0 {
- t.Errorf("expected success: %v", errs)
- }
- }
- errorCases := map[string]psUpdateTest{
- "more than one read/write": {
- old: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- update: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Replicas: 2,
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: readWriteVolumePodTemplate.Template,
- },
- },
- },
- "updates to a field other than spec.Replicas": {
- old: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- update: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Replicas: 1,
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: readWriteVolumePodTemplate.Template,
- },
- },
- },
- "invalid selector": {
- old: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- update: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Replicas: 2,
- Selector: &unversioned.LabelSelector{MatchLabels: invalidLabels},
- Template: validPodTemplate.Template,
- },
- },
- },
- "invalid pod": {
- old: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- update: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Replicas: 2,
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: invalidPodTemplate.Template,
- },
- },
- },
- "negative replicas": {
- old: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- update: apps.PetSet{
- ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
- Spec: apps.PetSetSpec{
- Replicas: -1,
- Selector: &unversioned.LabelSelector{MatchLabels: validLabels},
- Template: validPodTemplate.Template,
- },
- },
- },
- }
- for testName, errorCase := range errorCases {
- if errs := ValidatePetSetUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 {
- t.Errorf("expected failure: %s", testName)
- }
- }
- }
|