diff --git a/pkg/kubectl/polymorphichelpers/BUILD b/pkg/kubectl/polymorphichelpers/BUILD index 09459b60f2b..9771a8b7cd4 100644 --- a/pkg/kubectl/polymorphichelpers/BUILD +++ b/pkg/kubectl/polymorphichelpers/BUILD @@ -56,10 +56,16 @@ go_library( go_test( name = "go_default_test", srcs = [ + "canbeautoscaled_test.go", "canbeexposed_test.go", "helpers_test.go", "logsforobject_test.go", + "mapbasedselectorforobject_test.go", + "objectpauser_test.go", + "objectresumer_test.go", "portsforobject_test.go", + "protocolsforobject_test.go", + "updatepodspec_test.go", ], embed = [":go_default_library"], deps = [ @@ -69,14 +75,20 @@ go_test( "//pkg/apis/extensions:go_default_library", "//pkg/client/clientset_generated/internalclientset/fake:go_default_library", "//pkg/controller:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", + "//staging/src/k8s.io/api/apps/v1beta1:go_default_library", + "//staging/src/k8s.io/api/apps/v1beta2:go_default_library", + "//staging/src/k8s.io/api/batch/v1:go_default_library", + "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", + "//staging/src/k8s.io/api/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", ], diff --git a/pkg/kubectl/polymorphichelpers/canbeautoscaled_test.go b/pkg/kubectl/polymorphichelpers/canbeautoscaled_test.go new file mode 100644 index 00000000000..c2f0e8a027c --- /dev/null +++ b/pkg/kubectl/polymorphichelpers/canbeautoscaled_test.go @@ -0,0 +1,50 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" + api "k8s.io/kubernetes/pkg/apis/core" +) + +func TestCanBeAutoscaled(t *testing.T) { + tests := []struct { + kind schema.GroupKind + expectErr bool + }{ + { + kind: api.Kind("ReplicationController"), + expectErr: false, + }, + { + kind: api.Kind("Node"), + expectErr: true, + }, + } + + for _, test := range tests { + err := canBeAutoscaled(test.kind) + if test.expectErr && err == nil { + t.Error("unexpected non-error") + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + } + } +} diff --git a/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject_test.go b/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject_test.go new file mode 100644 index 00000000000..59bf5dec444 --- /dev/null +++ b/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject_test.go @@ -0,0 +1,142 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func TestMapBasedSelectorForObject(t *testing.T) { + tests := []struct { + object runtime.Object + expectSelector string + expectErr bool + }{ + { + object: &api.ReplicationController{ + Spec: api.ReplicationControllerSpec{ + Selector: map[string]string{ + "foo": "bar", + }, + }, + }, + expectSelector: "foo=bar", + }, + { + object: &api.Pod{}, + expectErr: true, + }, + { + object: &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "foo": "bar", + }, + }, + }, + expectSelector: "foo=bar", + }, + { + object: &api.Service{ + Spec: api.ServiceSpec{ + Selector: map[string]string{ + "foo": "bar", + }, + }, + }, + expectSelector: "foo=bar", + }, + { + object: &api.Service{}, + expectErr: true, + }, + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + expectSelector: "foo=bar", + }, + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "foo", + }, + }, + }, + }, + }, + expectErr: true, + }, + { + object: &extensions.ReplicaSet{ + Spec: extensions.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + expectSelector: "foo=bar", + }, + { + object: &extensions.ReplicaSet{ + Spec: extensions.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "foo", + }, + }, + }, + }, + }, + expectErr: true, + }, + { + object: &api.Node{}, + expectErr: true, + }, + } + + for _, test := range tests { + actual, err := mapBasedSelectorForObject(test.object) + if test.expectErr && err == nil { + t.Error("unexpected non-error") + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + } + if actual != test.expectSelector { + t.Errorf("expected selector %q, but got %q", test.expectSelector, actual) + } + } +} diff --git a/pkg/kubectl/polymorphichelpers/objectpauser_test.go b/pkg/kubectl/polymorphichelpers/objectpauser_test.go new file mode 100644 index 00000000000..9ce0dbb3046 --- /dev/null +++ b/pkg/kubectl/polymorphichelpers/objectpauser_test.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "bytes" + "testing" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func TestDefaultObjectPauser(t *testing.T) { + tests := []struct { + object runtime.Object + expect []byte + expectErr bool + }{ + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Paused: false, + }, + }, + expect: []byte(`paused":true`), + expectErr: false, + }, + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Paused: true, + }, + }, + expectErr: true, + }, + { + object: &extensions.ReplicaSet{}, + expectErr: true, + }, + } + + for _, test := range tests { + actual, err := defaultObjectPauser(test.object) + if test.expectErr { + if err == nil { + t.Error("unexpected non-error") + } + continue + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + continue + } + if !bytes.Contains(actual, test.expect) { + t.Errorf("expected %s, but got %s", test.expect, actual) + } + } +} diff --git a/pkg/kubectl/polymorphichelpers/objectresumer_test.go b/pkg/kubectl/polymorphichelpers/objectresumer_test.go new file mode 100644 index 00000000000..6488f335f92 --- /dev/null +++ b/pkg/kubectl/polymorphichelpers/objectresumer_test.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "bytes" + "testing" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func TestDefaultObjectResumer(t *testing.T) { + tests := []struct { + object runtime.Object + notHave []byte + expectErr bool + }{ + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Paused: true, + }, + }, + notHave: []byte(`paused":true`), + expectErr: false, + }, + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Paused: false, + }, + }, + expectErr: true, + }, + { + object: &extensions.ReplicaSet{}, + expectErr: true, + }, + } + + for _, test := range tests { + actual, err := defaultObjectResumer(test.object) + if test.expectErr { + if err == nil { + t.Error("unexpected non-error") + } + continue + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + continue + } + if bytes.Contains(actual, test.notHave) { + t.Errorf("expected to not have %s, but got %s", test.notHave, actual) + } + } +} diff --git a/pkg/kubectl/polymorphichelpers/portsforobject_test.go b/pkg/kubectl/polymorphichelpers/portsforobject_test.go index 3bd05b1f803..b1ebb6fe4aa 100644 --- a/pkg/kubectl/polymorphichelpers/portsforobject_test.go +++ b/pkg/kubectl/polymorphichelpers/portsforobject_test.go @@ -19,36 +19,122 @@ package polymorphichelpers import ( "testing" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/sets" + "reflect" + + "k8s.io/apimachinery/pkg/runtime" api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" ) func TestPortsForObject(t *testing.T) { - pod := &api.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Ports: []api.ContainerPort{ + tests := []struct { + object runtime.Object + expectErr bool + }{ + { + object: &api.Pod{ + Spec: api.PodSpec{ + Containers: []api.Container{ { - ContainerPort: 101, + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + }, + }, }, }, }, }, }, + { + object: &api.Service{ + Spec: api.ServiceSpec{ + Ports: []api.ServicePort{ + { + Port: 101, + }, + }, + }, + }, + }, + { + object: &api.ReplicationController{ + Spec: api.ReplicationControllerSpec{ + Template: &api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Template: api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + object: &extensions.ReplicaSet{ + Spec: extensions.ReplicaSetSpec{ + Template: api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + object: &api.Node{}, + expectErr: true, + }, } + expectedPorts := []string{"101"} - expected := sets.NewString("101") - ports, err := portsForObject(pod) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - got := sets.NewString(ports...) - - if !expected.Equal(got) { - t.Fatalf("Ports mismatch! Expected %v, got %v", expected, got) + for _, test := range tests { + actual, err := portsForObject(test.object) + if test.expectErr { + if err == nil { + t.Error("unexpected non-error") + } + continue + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + continue + } + if !reflect.DeepEqual(actual, expectedPorts) { + t.Errorf("expected ports %v, but got %v", expectedPorts, actual) + } } } diff --git a/pkg/kubectl/polymorphichelpers/protocolsforobject_test.go b/pkg/kubectl/polymorphichelpers/protocolsforobject_test.go new file mode 100644 index 00000000000..76c00bdcdbb --- /dev/null +++ b/pkg/kubectl/polymorphichelpers/protocolsforobject_test.go @@ -0,0 +1,145 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "testing" + + "reflect" + + "k8s.io/apimachinery/pkg/runtime" + api "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/kubernetes/pkg/apis/extensions" +) + +func TestProtocolsForObject(t *testing.T) { + tests := []struct { + object runtime.Object + expectErr bool + }{ + { + object: &api.Pod{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + Protocol: "tcp", + }, + }, + }, + }, + }, + }, + }, + { + object: &api.Service{ + Spec: api.ServiceSpec{ + Ports: []api.ServicePort{ + { + Port: 101, + Protocol: "tcp", + }, + }, + }, + }, + }, + { + object: &api.ReplicationController{ + Spec: api.ReplicationControllerSpec{ + Template: &api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + Protocol: "tcp", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + object: &extensions.Deployment{ + Spec: extensions.DeploymentSpec{ + Template: api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + Protocol: "tcp", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + object: &extensions.ReplicaSet{ + Spec: extensions.ReplicaSetSpec{ + Template: api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Ports: []api.ContainerPort{ + { + ContainerPort: 101, + Protocol: "tcp", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + object: &api.Node{}, + expectErr: true, + }, + } + expectedPorts := map[string]string{"101": "tcp"} + + for _, test := range tests { + actual, err := protocolsForObject(test.object) + if test.expectErr { + if err == nil { + t.Error("unexpected non-error") + } + continue + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + continue + } + if !reflect.DeepEqual(actual, expectedPorts) { + t.Errorf("expected ports %v, but got %v", expectedPorts, actual) + } + } +} diff --git a/pkg/kubectl/polymorphichelpers/updatepodspec_test.go b/pkg/kubectl/polymorphichelpers/updatepodspec_test.go new file mode 100644 index 00000000000..abf98faeddd --- /dev/null +++ b/pkg/kubectl/polymorphichelpers/updatepodspec_test.go @@ -0,0 +1,131 @@ +/* +Copyright 2018 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 polymorphichelpers + +import ( + "testing" + + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1beta2 "k8s.io/api/apps/v1beta2" + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + "k8s.io/api/core/v1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestUpdatePodSpecForObject(t *testing.T) { + tests := []struct { + object runtime.Object + expect bool + expectErr bool + }{ + { + object: &v1.Pod{}, + expect: true, + }, + { + object: &v1.ReplicationController{}, + expect: true, + }, + { + object: &extensionsv1beta1.Deployment{}, + expect: true, + }, + { + object: &appsv1beta1.Deployment{}, + expect: true, + }, + { + object: &appsv1beta2.Deployment{}, + expect: true, + }, + { + object: &appsv1.Deployment{}, + expect: true, + }, + { + object: &extensionsv1beta1.DaemonSet{}, + expect: true, + }, { + object: &appsv1beta2.DaemonSet{}, + expect: true, + }, + { + object: &appsv1.DaemonSet{}, + expect: true, + }, + { + object: &extensionsv1beta1.ReplicaSet{}, + expect: true, + }, + { + object: &appsv1beta2.ReplicaSet{}, + expect: true, + }, + { + object: &appsv1.ReplicaSet{}, + expect: true, + }, + { + object: &appsv1beta1.StatefulSet{}, + expect: true, + }, + { + object: &appsv1beta2.StatefulSet{}, + expect: true, + }, + { + object: &appsv1.StatefulSet{}, + expect: true, + }, + { + object: &batchv1.Job{}, + expect: true, + }, + { + object: &batchv1beta1.CronJob{}, + expect: true, + }, + { + object: &batchv2alpha1.CronJob{}, + expect: true, + }, + { + object: &v1.Node{}, + expect: false, + expectErr: true, + }, + } + + for _, test := range tests { + actual, err := updatePodSpecForObject(test.object, func(*v1.PodSpec) error { + return nil + }) + if test.expectErr && err == nil { + t.Error("unexpected non-error") + } + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + } + if actual != test.expect { + t.Errorf("expected %v, but got %v", test.expect, actual) + } + } +}