Update go dependencies

This commit is contained in:
Manuel de Brito Fontes 2018-05-26 11:27:53 -04:00 committed by Manuel Alejandro de Brito Fontes
parent 15ffb51394
commit bb4d483837
No known key found for this signature in database
GPG key ID: 786136016A8BA02A
1621 changed files with 86368 additions and 284392 deletions

View file

@ -1,491 +0,0 @@
/*
Copyright 2015 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 helper
import (
"reflect"
"testing"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/kubernetes/pkg/apis/core"
)
func TestSemantic(t *testing.T) {
table := []struct {
a, b interface{}
shouldEqual bool
}{
{resource.MustParse("0"), resource.Quantity{}, true},
{resource.Quantity{}, resource.MustParse("0"), true},
{resource.Quantity{}, resource.MustParse("1m"), false},
{
resource.NewQuantity(5, resource.BinarySI),
resource.NewQuantity(5, resource.DecimalSI),
true,
},
{resource.MustParse("2m"), resource.MustParse("1m"), false},
}
for index, item := range table {
if e, a := item.shouldEqual, Semantic.DeepEqual(item.a, item.b); e != a {
t.Errorf("case[%d], expected %v, got %v.", index, e, a)
}
}
}
func TestIsStandardResource(t *testing.T) {
testCases := []struct {
input string
output bool
}{
{"cpu", true},
{"memory", true},
{"disk", false},
{"blah", false},
{"x.y.z", false},
{"hugepages-2Mi", true},
{"requests.hugepages-2Mi", true},
}
for i, tc := range testCases {
if IsStandardResourceName(tc.input) != tc.output {
t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
}
}
}
func TestIsStandardContainerResource(t *testing.T) {
testCases := []struct {
input string
output bool
}{
{"cpu", true},
{"memory", true},
{"disk", false},
{"hugepages-2Mi", true},
}
for i, tc := range testCases {
if IsStandardContainerResourceName(tc.input) != tc.output {
t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
}
}
}
func TestAddToNodeAddresses(t *testing.T) {
testCases := []struct {
existing []core.NodeAddress
toAdd []core.NodeAddress
expected []core.NodeAddress
}{
{
existing: []core.NodeAddress{},
toAdd: []core.NodeAddress{},
expected: []core.NodeAddress{},
},
{
existing: []core.NodeAddress{},
toAdd: []core.NodeAddress{
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
{Type: core.NodeHostName, Address: "localhost"},
},
expected: []core.NodeAddress{
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
{Type: core.NodeHostName, Address: "localhost"},
},
},
{
existing: []core.NodeAddress{},
toAdd: []core.NodeAddress{
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
},
expected: []core.NodeAddress{
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
},
},
{
existing: []core.NodeAddress{
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
{Type: core.NodeInternalIP, Address: "10.1.1.1"},
},
toAdd: []core.NodeAddress{
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
{Type: core.NodeHostName, Address: "localhost"},
},
expected: []core.NodeAddress{
{Type: core.NodeExternalIP, Address: "1.1.1.1"},
{Type: core.NodeInternalIP, Address: "10.1.1.1"},
{Type: core.NodeHostName, Address: "localhost"},
},
},
}
for i, tc := range testCases {
AddToNodeAddresses(&tc.existing, tc.toAdd...)
if !Semantic.DeepEqual(tc.expected, tc.existing) {
t.Errorf("case[%d], expected: %v, got: %v", i, tc.expected, tc.existing)
}
}
}
func TestGetAccessModesFromString(t *testing.T) {
modes := GetAccessModesFromString("ROX")
if !containsAccessMode(modes, core.ReadOnlyMany) {
t.Errorf("Expected mode %s, but got %+v", core.ReadOnlyMany, modes)
}
modes = GetAccessModesFromString("ROX,RWX")
if !containsAccessMode(modes, core.ReadOnlyMany) {
t.Errorf("Expected mode %s, but got %+v", core.ReadOnlyMany, modes)
}
if !containsAccessMode(modes, core.ReadWriteMany) {
t.Errorf("Expected mode %s, but got %+v", core.ReadWriteMany, modes)
}
modes = GetAccessModesFromString("RWO,ROX,RWX")
if !containsAccessMode(modes, core.ReadOnlyMany) {
t.Errorf("Expected mode %s, but got %+v", core.ReadOnlyMany, modes)
}
if !containsAccessMode(modes, core.ReadWriteMany) {
t.Errorf("Expected mode %s, but got %+v", core.ReadWriteMany, modes)
}
}
func TestRemoveDuplicateAccessModes(t *testing.T) {
modes := []core.PersistentVolumeAccessMode{
core.ReadWriteOnce, core.ReadOnlyMany, core.ReadOnlyMany, core.ReadOnlyMany,
}
modes = removeDuplicateAccessModes(modes)
if len(modes) != 2 {
t.Errorf("Expected 2 distinct modes in set but found %v", len(modes))
}
}
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
matchExpressions := []core.NodeSelectorRequirement{{
Key: "foo",
Operator: core.NodeSelectorOpIn,
Values: []string{"bar", "baz"},
}}
mustParse := func(s string) labels.Selector {
out, e := labels.Parse(s)
if e != nil {
panic(e)
}
return out
}
tc := []struct {
in []core.NodeSelectorRequirement
out labels.Selector
expectErr bool
}{
{in: nil, out: labels.Nothing()},
{in: []core.NodeSelectorRequirement{}, out: labels.Nothing()},
{
in: matchExpressions,
out: mustParse("foo in (baz,bar)"),
},
{
in: []core.NodeSelectorRequirement{{
Key: "foo",
Operator: core.NodeSelectorOpExists,
Values: []string{"bar", "baz"},
}},
expectErr: true,
},
{
in: []core.NodeSelectorRequirement{{
Key: "foo",
Operator: core.NodeSelectorOpGt,
Values: []string{"1"},
}},
out: mustParse("foo>1"),
},
{
in: []core.NodeSelectorRequirement{{
Key: "bar",
Operator: core.NodeSelectorOpLt,
Values: []string{"7"},
}},
out: mustParse("bar<7"),
},
}
for i, tc := range tc {
out, err := NodeSelectorRequirementsAsSelector(tc.in)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
if !reflect.DeepEqual(out, tc.out) {
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
}
}
}
func TestSysctlsFromPodAnnotation(t *testing.T) {
type Test struct {
annotation string
expectValue []core.Sysctl
expectErr bool
}
for i, test := range []Test{
{
annotation: "",
expectValue: nil,
},
{
annotation: "foo.bar",
expectErr: true,
},
{
annotation: "=123",
expectErr: true,
},
{
annotation: "foo.bar=",
expectValue: []core.Sysctl{{Name: "foo.bar", Value: ""}},
},
{
annotation: "foo.bar=42",
expectValue: []core.Sysctl{{Name: "foo.bar", Value: "42"}},
},
{
annotation: "foo.bar=42,",
expectErr: true,
},
{
annotation: "foo.bar=42,abc.def=1",
expectValue: []core.Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}},
},
} {
sysctls, err := SysctlsFromPodAnnotation(test.annotation)
if test.expectErr && err == nil {
t.Errorf("[%v]expected error but got none", i)
} else if !test.expectErr && err != nil {
t.Errorf("[%v]did not expect error but got: %v", i, err)
} else if !reflect.DeepEqual(sysctls, test.expectValue) {
t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls)
}
}
}
// TODO: remove when alpha support for topology constraints is removed
func TestGetNodeAffinityFromAnnotations(t *testing.T) {
testCases := []struct {
annotations map[string]string
expectErr bool
}{
{
annotations: nil,
expectErr: false,
},
{
annotations: map[string]string{},
expectErr: false,
},
{
annotations: map[string]string{
core.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}`,
},
expectErr: false,
},
{
annotations: map[string]string{
core.AlphaStorageNodeAffinityAnnotation: `[{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}]`,
},
expectErr: true,
},
{
annotations: map[string]string{
core.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms":
"matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
}
}`,
},
expectErr: true,
},
}
for i, tc := range testCases {
_, err := GetStorageNodeAffinityFromAnnotation(tc.annotations)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
}
}
func TestIsHugePageResourceName(t *testing.T) {
testCases := []struct {
name core.ResourceName
result bool
}{
{
name: core.ResourceName("hugepages-2Mi"),
result: true,
},
{
name: core.ResourceName("hugepages-1Gi"),
result: true,
},
{
name: core.ResourceName("cpu"),
result: false,
},
{
name: core.ResourceName("memory"),
result: false,
},
}
for _, testCase := range testCases {
if testCase.result != IsHugePageResourceName(testCase.name) {
t.Errorf("resource: %v expected result: %v", testCase.name, testCase.result)
}
}
}
func TestHugePageResourceName(t *testing.T) {
testCases := []struct {
pageSize resource.Quantity
name core.ResourceName
}{
{
pageSize: resource.MustParse("2Mi"),
name: core.ResourceName("hugepages-2Mi"),
},
{
pageSize: resource.MustParse("1Gi"),
name: core.ResourceName("hugepages-1Gi"),
},
{
// verify we do not regress our canonical representation
pageSize: *resource.NewQuantity(int64(2097152), resource.BinarySI),
name: core.ResourceName("hugepages-2Mi"),
},
}
for _, testCase := range testCases {
if result := HugePageResourceName(testCase.pageSize); result != testCase.name {
t.Errorf("pageSize: %v, expected: %v, but got: %v", testCase.pageSize.String(), testCase.name, result.String())
}
}
}
func TestHugePageSizeFromResourceName(t *testing.T) {
testCases := []struct {
name core.ResourceName
expectErr bool
pageSize resource.Quantity
}{
{
name: core.ResourceName("hugepages-2Mi"),
pageSize: resource.MustParse("2Mi"),
expectErr: false,
},
{
name: core.ResourceName("hugepages-1Gi"),
pageSize: resource.MustParse("1Gi"),
expectErr: false,
},
{
name: core.ResourceName("hugepages-bad"),
expectErr: true,
},
}
for _, testCase := range testCases {
value, err := HugePageSizeFromResourceName(testCase.name)
if testCase.expectErr && err == nil {
t.Errorf("Expected an error for %v", testCase.name)
} else if !testCase.expectErr && err != nil {
t.Errorf("Unexpected error for %v, got %v", testCase.name, err)
} else if testCase.pageSize.Value() != value.Value() {
t.Errorf("Unexpected pageSize for resource %v got %v", testCase.name, value.String())
}
}
}
func TestIsOvercommitAllowed(t *testing.T) {
testCases := []struct {
name core.ResourceName
allowed bool
}{
{
name: core.ResourceCPU,
allowed: true,
},
{
name: core.ResourceMemory,
allowed: true,
},
{
name: core.ResourceNvidiaGPU,
allowed: false,
},
{
name: HugePageResourceName(resource.MustParse("2Mi")),
allowed: false,
},
}
for _, testCase := range testCases {
if testCase.allowed != IsOvercommitAllowed(testCase.name) {
t.Errorf("Unexpected result for %v", testCase.name)
}
}
}

View file

@ -1,140 +0,0 @@
/*
Copyright 2014 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 install
import (
"encoding/json"
"reflect"
"testing"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api/legacyscheme"
internal "k8s.io/kubernetes/pkg/apis/core"
)
func TestResourceVersioner(t *testing.T) {
g, err := legacyscheme.Registry.Group(v1.GroupName)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
intf, err := g.DefaultInterfacesFor(v1.SchemeGroupVersion)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
accessor := intf.MetadataAccessor
pod := internal.Pod{ObjectMeta: metav1.ObjectMeta{ResourceVersion: "10"}}
version, err := accessor.ResourceVersion(&pod)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if version != "10" {
t.Errorf("unexpected version %v", version)
}
podList := internal.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "10"}}
version, err = accessor.ResourceVersion(&podList)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if version != "10" {
t.Errorf("unexpected version %v", version)
}
}
func TestCodec(t *testing.T) {
pod := internal.Pod{}
// We do want to use package registered rather than testapi here, because we
// want to test if the package install and package registered work as expected.
data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersion), &pod)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
other := internal.Pod{}
if err := json.Unmarshal(data, &other); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if other.APIVersion != legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersion.Version || other.Kind != "Pod" {
t.Errorf("unexpected unmarshalled object %#v", other)
}
}
func TestInterfacesFor(t *testing.T) {
if _, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).InterfacesFor(internal.SchemeGroupVersion); err == nil {
t.Fatalf("unexpected non-error: %v", err)
}
for i, version := range legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersions {
if vi, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).InterfacesFor(version); err != nil || vi == nil {
t.Fatalf("%d: unexpected result: %v", i, err)
}
}
}
func TestRESTMapper(t *testing.T) {
gv := schema.GroupVersion{Group: "", Version: "v1"}
rcGVK := gv.WithKind("ReplicationController")
podTemplateGVK := gv.WithKind("PodTemplate")
if gvk, err := legacyscheme.Registry.RESTMapper().KindFor(internal.SchemeGroupVersion.WithResource("replicationcontrollers")); err != nil || gvk != rcGVK {
t.Errorf("unexpected version mapping: %v %v", gvk, err)
}
if m, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(podTemplateGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != podTemplateGVK || m.Resource != "podtemplates" {
t.Errorf("unexpected version mapping: %#v %v", m, err)
}
for _, version := range legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersions {
mapping, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(rcGVK.GroupKind(), version.Version)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if mapping.Resource != "replicationControllers" && mapping.Resource != "replicationcontrollers" {
t.Errorf("incorrect resource name: %#v", mapping)
}
if mapping.GroupVersionKind.GroupVersion() != version {
t.Errorf("incorrect version: %v", mapping)
}
interfaces, _ := legacyscheme.Registry.GroupOrDie(internal.GroupName).InterfacesFor(version)
if mapping.ObjectConvertor != interfaces.ObjectConvertor {
t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces)
}
rc := &internal.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
name, err := mapping.MetadataAccessor.Name(rc)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if name != "foo" {
t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor)
}
}
}
func TestUnversioned(t *testing.T) {
for _, obj := range []runtime.Object{
&metav1.Status{},
} {
if unversioned, ok := legacyscheme.Scheme.IsUnversioned(obj); !unversioned || !ok {
t.Errorf("%v is expected to be unversioned", reflect.TypeOf(obj))
}
}
}

View file

@ -1,87 +0,0 @@
/*
Copyright 2017 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 pods
import (
"testing"
)
func TestConvertDownwardAPIFieldLabel(t *testing.T) {
testCases := []struct {
version string
label string
value string
expectedErr bool
expectedLabel string
expectedValue string
}{
{
version: "v2",
label: "metadata.name",
value: "test-pod",
expectedErr: true,
},
{
version: "v1",
label: "invalid-label",
value: "value",
expectedErr: true,
},
{
version: "v1",
label: "metadata.name",
value: "test-pod",
expectedLabel: "metadata.name",
expectedValue: "test-pod",
},
{
version: "v1",
label: "metadata.annotations",
value: "myValue",
expectedLabel: "metadata.annotations",
expectedValue: "myValue",
},
{
version: "v1",
label: "metadata.annotations['myKey']",
value: "myValue",
expectedLabel: "metadata.annotations['myKey']",
expectedValue: "myValue",
},
{
version: "v1",
label: "spec.host",
value: "127.0.0.1",
expectedLabel: "spec.nodeName",
expectedValue: "127.0.0.1",
},
}
for _, tc := range testCases {
label, value, err := ConvertDownwardAPIFieldLabel(tc.version, tc.label, tc.value)
if err != nil {
if tc.expectedErr {
continue
}
t.Errorf("ConvertDownwardAPIFieldLabel(%s, %s, %s) failed: %s",
tc.version, tc.label, tc.value, err)
}
if tc.expectedLabel != label || tc.expectedValue != value {
t.Errorf("ConvertDownwardAPIFieldLabel(%s, %s, %s) = (%s, %s, nil), expected (%s, %s, nil)",
tc.version, tc.label, tc.value, label, value, tc.expectedLabel, tc.expectedValue)
}
}
}

View file

@ -1,120 +0,0 @@
/*
Copyright 2017 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 core
import "testing"
func TestTaintToString(t *testing.T) {
testCases := []struct {
taint *Taint
expectedString string
}{
{
taint: &Taint{
Key: "foo",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
expectedString: "foo=bar:NoSchedule",
},
{
taint: &Taint{
Key: "foo",
Effect: TaintEffectNoSchedule,
},
expectedString: "foo:NoSchedule",
},
}
for i, tc := range testCases {
if tc.expectedString != tc.taint.ToString() {
t.Errorf("[%v] expected taint %v converted to %s, got %s", i, tc.taint, tc.expectedString, tc.taint.ToString())
}
}
}
func TestMatchTaint(t *testing.T) {
testCases := []struct {
description string
taint *Taint
taintToMatch Taint
expectMatch bool
}{
{
description: "two taints with the same key,value,effect should match",
taint: &Taint{
Key: "foo",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
taintToMatch: Taint{
Key: "foo",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
expectMatch: true,
},
{
description: "two taints with the same key,effect but different value should match",
taint: &Taint{
Key: "foo",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
taintToMatch: Taint{
Key: "foo",
Value: "different-value",
Effect: TaintEffectNoSchedule,
},
expectMatch: true,
},
{
description: "two taints with the different key cannot match",
taint: &Taint{
Key: "foo",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
taintToMatch: Taint{
Key: "different-key",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
expectMatch: false,
},
{
description: "two taints with the different effect cannot match",
taint: &Taint{
Key: "foo",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
taintToMatch: Taint{
Key: "foo",
Value: "bar",
Effect: TaintEffectPreferNoSchedule,
},
expectMatch: false,
},
}
for _, tc := range testCases {
if tc.expectMatch != tc.taint.MatchTaint(tc.taintToMatch) {
t.Errorf("[%s] expect taint %s match taint %s", tc.description, tc.taint.ToString(), tc.taintToMatch.ToString())
}
}
}

View file

@ -1,136 +0,0 @@
/*
Copyright 2017 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 core
import "testing"
func TestMatchToleration(t *testing.T) {
tolerationSeconds := int64(5)
tolerationToMatchSeconds := int64(3)
testCases := []struct {
description string
toleration *Toleration
tolerationToMatch *Toleration
expectMatch bool
}{
{
description: "two taints with the same key,operator,value,effect should match",
toleration: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
tolerationToMatch: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
expectMatch: true,
},
{
description: "two taints with the different key cannot match",
toleration: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
tolerationToMatch: &Toleration{
Key: "different-key",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
expectMatch: false,
},
{
description: "two taints with the different operator cannot match",
toleration: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
tolerationToMatch: &Toleration{
Key: "foo",
Operator: "different-operator",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
expectMatch: false,
},
{
description: "two taints with the different value cannot match",
toleration: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
tolerationToMatch: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "different-value",
Effect: TaintEffectNoSchedule,
},
expectMatch: false,
},
{
description: "two taints with the different effect cannot match",
toleration: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
},
tolerationToMatch: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectPreferNoSchedule,
},
expectMatch: false,
},
{
description: "two taints with the different tolerationSeconds should match",
toleration: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
TolerationSeconds: &tolerationSeconds,
},
tolerationToMatch: &Toleration{
Key: "foo",
Operator: "Exists",
Value: "bar",
Effect: TaintEffectNoSchedule,
TolerationSeconds: &tolerationToMatchSeconds,
},
expectMatch: true,
},
}
for _, tc := range testCases {
if actual := tc.toleration.MatchToleration(tc.tolerationToMatch); actual != tc.expectMatch {
t.Errorf("[%s] expect: %v , got: %v", tc.description, tc.expectMatch, !tc.expectMatch)
}
}
}

View file

@ -1711,6 +1711,12 @@ type VolumeMount struct {
type MountPropagationMode string
const (
// MountPropagationNone means that the volume in a container will
// not receive new mounts from the host or other containers, and filesystems
// mounted inside the container won't be propagated to the host or other
// containers.
// Note that this mode corresponds to "private" in Linux terminology.
MountPropagationNone MountPropagationMode = "None"
// MountPropagationHostToContainer means that the volume in a container will
// receive new mounts from the host or other containers, but filesystems
// mounted inside the container won't be propagated to the host or other

View file

@ -1,348 +0,0 @@
/*
Copyright 2015 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 v1_test
import (
"encoding/json"
"math/rand"
"net/url"
"reflect"
"testing"
"time"
"k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/core"
corefuzzer "k8s.io/kubernetes/pkg/apis/core/fuzzer"
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/apis/extensions"
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
// enforce that all types are installed
_ "k8s.io/kubernetes/pkg/api/testapi"
)
func TestPodLogOptions(t *testing.T) {
sinceSeconds := int64(1)
sinceTime := metav1.NewTime(time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC).Local())
tailLines := int64(2)
limitBytes := int64(3)
versionedLogOptions := &v1.PodLogOptions{
Container: "mycontainer",
Follow: true,
Previous: true,
SinceSeconds: &sinceSeconds,
SinceTime: &sinceTime,
Timestamps: true,
TailLines: &tailLines,
LimitBytes: &limitBytes,
}
unversionedLogOptions := &core.PodLogOptions{
Container: "mycontainer",
Follow: true,
Previous: true,
SinceSeconds: &sinceSeconds,
SinceTime: &sinceTime,
Timestamps: true,
TailLines: &tailLines,
LimitBytes: &limitBytes,
}
expectedParameters := url.Values{
"container": {"mycontainer"},
"follow": {"true"},
"previous": {"true"},
"sinceSeconds": {"1"},
"sinceTime": {"2000-01-01T12:34:56Z"},
"timestamps": {"true"},
"tailLines": {"2"},
"limitBytes": {"3"},
}
codec := runtime.NewParameterCodec(legacyscheme.Scheme)
// unversioned -> query params
{
actualParameters, err := codec.EncodeParameters(unversionedLogOptions, v1.SchemeGroupVersion)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(actualParameters, expectedParameters) {
t.Fatalf("Expected\n%#v\ngot\n%#v", expectedParameters, actualParameters)
}
}
// versioned -> query params
{
actualParameters, err := codec.EncodeParameters(versionedLogOptions, v1.SchemeGroupVersion)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(actualParameters, expectedParameters) {
t.Fatalf("Expected\n%#v\ngot\n%#v", expectedParameters, actualParameters)
}
}
// query params -> versioned
{
convertedLogOptions := &v1.PodLogOptions{}
err := codec.DecodeParameters(expectedParameters, v1.SchemeGroupVersion, convertedLogOptions)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(convertedLogOptions, versionedLogOptions) {
t.Fatalf("Unexpected deserialization:\n%s", diff.ObjectGoPrintSideBySide(versionedLogOptions, convertedLogOptions))
}
}
// query params -> unversioned
{
convertedLogOptions := &core.PodLogOptions{}
err := codec.DecodeParameters(expectedParameters, v1.SchemeGroupVersion, convertedLogOptions)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(convertedLogOptions, unversionedLogOptions) {
t.Fatalf("Unexpected deserialization:\n%s", diff.ObjectGoPrintSideBySide(unversionedLogOptions, convertedLogOptions))
}
}
}
// TestPodSpecConversion tests that v1.ServiceAccount is an alias for
// ServiceAccountName.
func TestPodSpecConversion(t *testing.T) {
name, other := "foo", "bar"
// Test internal -> v1. Should have both alias (DeprecatedServiceAccount)
// and new field (ServiceAccountName).
i := &core.PodSpec{
ServiceAccountName: name,
}
v := v1.PodSpec{}
if err := legacyscheme.Scheme.Convert(i, &v, nil); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.ServiceAccountName != name {
t.Fatalf("want v1.ServiceAccountName %q, got %q", name, v.ServiceAccountName)
}
if v.DeprecatedServiceAccount != name {
t.Fatalf("want v1.DeprecatedServiceAccount %q, got %q", name, v.DeprecatedServiceAccount)
}
// Test v1 -> internal. Either DeprecatedServiceAccount, ServiceAccountName,
// or both should translate to ServiceAccountName. ServiceAccountName wins
// if both are set.
testCases := []*v1.PodSpec{
// New
{ServiceAccountName: name},
// Alias
{DeprecatedServiceAccount: name},
// Both: same
{ServiceAccountName: name, DeprecatedServiceAccount: name},
// Both: different
{ServiceAccountName: name, DeprecatedServiceAccount: other},
}
for k, v := range testCases {
got := core.PodSpec{}
err := legacyscheme.Scheme.Convert(v, &got, nil)
if err != nil {
t.Fatalf("unexpected error for case %d: %v", k, err)
}
if got.ServiceAccountName != name {
t.Fatalf("want core.ServiceAccountName %q, got %q", name, got.ServiceAccountName)
}
}
}
func TestResourceListConversion(t *testing.T) {
bigMilliQuantity := resource.NewQuantity(resource.MaxMilliValue, resource.DecimalSI)
bigMilliQuantity.Add(resource.MustParse("12345m"))
tests := []struct {
input v1.ResourceList
expected core.ResourceList
}{
{ // No changes necessary.
input: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("30M"),
v1.ResourceCPU: resource.MustParse("100m"),
v1.ResourceStorage: resource.MustParse("1G"),
},
expected: core.ResourceList{
core.ResourceMemory: resource.MustParse("30M"),
core.ResourceCPU: resource.MustParse("100m"),
core.ResourceStorage: resource.MustParse("1G"),
},
},
{ // Nano-scale values should be rounded up to milli-scale.
input: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("3.000023m"),
v1.ResourceMemory: resource.MustParse("500.000050m"),
},
expected: core.ResourceList{
core.ResourceCPU: resource.MustParse("4m"),
core.ResourceMemory: resource.MustParse("501m"),
},
},
{ // Large values should still be accurate.
input: v1.ResourceList{
v1.ResourceCPU: *bigMilliQuantity.Copy(),
v1.ResourceStorage: *bigMilliQuantity.Copy(),
},
expected: core.ResourceList{
core.ResourceCPU: *bigMilliQuantity.Copy(),
core.ResourceStorage: *bigMilliQuantity.Copy(),
},
},
}
for i, test := range tests {
output := core.ResourceList{}
// defaulting is a separate step from conversion that is applied when reading from the API or from etcd.
// perform that step explicitly.
corev1.SetDefaults_ResourceList(&test.input)
err := legacyscheme.Scheme.Convert(&test.input, &output, nil)
if err != nil {
t.Fatalf("unexpected error for case %d: %v", i, err)
}
if !apiequality.Semantic.DeepEqual(test.expected, output) {
t.Errorf("unexpected conversion for case %d: Expected\n%+v;\nGot\n%+v", i, test.expected, output)
}
}
}
func TestReplicationControllerConversion(t *testing.T) {
// If we start with a RC, we should always have round-trip fidelity.
inputs := []*v1.ReplicationController{
{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: v1.ReplicationControllerSpec{
Replicas: utilpointer.Int32Ptr(1),
MinReadySeconds: 32,
Selector: map[string]string{"foo": "bar", "bar": "foo"},
Template: &v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"foo": "bar", "bar": "foo"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "container",
Image: "image",
},
},
},
},
},
Status: v1.ReplicationControllerStatus{
Replicas: 1,
FullyLabeledReplicas: 2,
ReadyReplicas: 3,
AvailableReplicas: 4,
ObservedGeneration: 5,
Conditions: []v1.ReplicationControllerCondition{
{
Type: v1.ReplicationControllerReplicaFailure,
Status: v1.ConditionTrue,
LastTransitionTime: metav1.NewTime(time.Unix(123456789, 0)),
Reason: "Reason",
Message: "Message",
},
},
},
},
}
// Add some fuzzed RCs.
apiObjectFuzzer := fuzzer.FuzzerFor(fuzzer.MergeFuzzerFuncs(metafuzzer.Funcs, corefuzzer.Funcs), rand.NewSource(152), legacyscheme.Codecs)
for i := 0; i < 100; i++ {
rc := &v1.ReplicationController{}
apiObjectFuzzer.Fuzz(rc)
// Sometimes the fuzzer decides to leave Spec.Template nil.
// We can't support that because Spec.Template is not a pointer in RS,
// so it will round-trip as non-nil but empty.
if rc.Spec.Template == nil {
rc.Spec.Template = &v1.PodTemplateSpec{}
}
// Sometimes the fuzzer decides to insert an empty label key.
// This doesn't round-trip properly because it's invalid.
if rc.Spec.Selector != nil {
delete(rc.Spec.Selector, "")
}
inputs = append(inputs, rc)
}
// Round-trip the input RCs before converting to RS.
for i := range inputs {
inputs[i] = roundTrip(t, inputs[i]).(*v1.ReplicationController)
}
for _, in := range inputs {
rs := &extensions.ReplicaSet{}
// Use in.DeepCopy() to avoid sharing pointers with `in`.
if err := corev1.Convert_v1_ReplicationController_to_extensions_ReplicaSet(in.DeepCopy(), rs, nil); err != nil {
t.Errorf("can't convert RC to RS: %v", err)
continue
}
// Round-trip RS before converting back to RC.
rs = roundTripRS(t, rs)
out := &v1.ReplicationController{}
if err := corev1.Convert_extensions_ReplicaSet_to_v1_ReplicationController(rs, out, nil); err != nil {
t.Errorf("can't convert RS to RC: %v", err)
continue
}
if !apiequality.Semantic.DeepEqual(in, out) {
instr, _ := json.MarshalIndent(in, "", " ")
outstr, _ := json.MarshalIndent(out, "", " ")
t.Errorf("RC-RS conversion round-trip failed:\nin:\n%s\nout:\n%s", instr, outstr)
}
}
}
func roundTripRS(t *testing.T, rs *extensions.ReplicaSet) *extensions.ReplicaSet {
codec := legacyscheme.Codecs.LegacyCodec(extensionsv1beta1.SchemeGroupVersion)
data, err := runtime.Encode(codec, rs)
if err != nil {
t.Errorf("%v\n %#v", err, rs)
return nil
}
obj2, err := runtime.Decode(codec, data)
if err != nil {
t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), rs)
return nil
}
obj3 := &extensions.ReplicaSet{}
err = legacyscheme.Scheme.Convert(obj2, obj3, nil)
if err != nil {
t.Errorf("%v\nSource: %#v", err, obj2)
return nil
}
return obj3
}

File diff suppressed because it is too large Load diff

View file

@ -1,655 +0,0 @@
/*
Copyright 2015 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 helper
import (
"fmt"
"reflect"
"testing"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
func TestIsDefaultNamespaceResource(t *testing.T) {
testCases := []struct {
resourceName v1.ResourceName
expectVal bool
}{
{
resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
expectVal: true,
},
{
resourceName: "kubernetes.io/resource-foo",
expectVal: true,
},
{
resourceName: "foo",
expectVal: true,
},
{
resourceName: "a/b",
expectVal: false,
},
{
resourceName: "",
expectVal: true,
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
t.Parallel()
v := IsDefaultNamespaceResource(tc.resourceName)
if v != tc.expectVal {
t.Errorf("Got %v but expected %v", v, tc.expectVal)
}
})
}
}
func TestHugePageSizeFromResourceName(t *testing.T) {
expected100m, _ := resource.ParseQuantity("100m")
testCases := []struct {
resourceName v1.ResourceName
expectVal resource.Quantity
expectErr bool
}{
{
resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
expectVal: resource.Quantity{},
expectErr: true,
},
{
resourceName: "hugepages-",
expectVal: resource.Quantity{},
expectErr: true,
},
{
resourceName: "hugepages-100m",
expectVal: expected100m,
expectErr: false,
},
{
resourceName: "",
expectVal: resource.Quantity{},
expectErr: true,
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
t.Parallel()
v, err := HugePageSizeFromResourceName(tc.resourceName)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
if v != tc.expectVal {
t.Errorf("Got %v but expected %v", v, tc.expectVal)
}
})
}
}
func TestIsOvercommitAllowed(t *testing.T) {
testCases := []struct {
resourceName v1.ResourceName
expectVal bool
}{
{
resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
expectVal: true,
},
{
resourceName: "kubernetes.io/resource-foo",
expectVal: true,
},
{
resourceName: "alpha.kubernetes.io/nvidia-gpu",
expectVal: false,
},
{
resourceName: "hugepages-100m",
expectVal: false,
},
{
resourceName: "",
expectVal: true,
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
t.Parallel()
v := IsOvercommitAllowed(tc.resourceName)
if v != tc.expectVal {
t.Errorf("Got %v but expected %v", v, tc.expectVal)
}
})
}
}
func TestAddToNodeAddresses(t *testing.T) {
testCases := []struct {
existing []v1.NodeAddress
toAdd []v1.NodeAddress
expected []v1.NodeAddress
}{
{
existing: []v1.NodeAddress{},
toAdd: []v1.NodeAddress{},
expected: []v1.NodeAddress{},
},
{
existing: []v1.NodeAddress{},
toAdd: []v1.NodeAddress{
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
{Type: v1.NodeHostName, Address: "localhost"},
},
expected: []v1.NodeAddress{
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
{Type: v1.NodeHostName, Address: "localhost"},
},
},
{
existing: []v1.NodeAddress{},
toAdd: []v1.NodeAddress{
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
},
expected: []v1.NodeAddress{
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
},
},
{
existing: []v1.NodeAddress{
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
},
toAdd: []v1.NodeAddress{
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
{Type: v1.NodeHostName, Address: "localhost"},
},
expected: []v1.NodeAddress{
{Type: v1.NodeExternalIP, Address: "1.1.1.1"},
{Type: v1.NodeInternalIP, Address: "10.1.1.1"},
{Type: v1.NodeHostName, Address: "localhost"},
},
},
}
for i, tc := range testCases {
AddToNodeAddresses(&tc.existing, tc.toAdd...)
if !apiequality.Semantic.DeepEqual(tc.expected, tc.existing) {
t.Errorf("case[%d], expected: %v, got: %v", i, tc.expected, tc.existing)
}
}
}
func TestGetAccessModesFromString(t *testing.T) {
modes := GetAccessModesFromString("ROX")
if !containsAccessMode(modes, v1.ReadOnlyMany) {
t.Errorf("Expected mode %s, but got %+v", v1.ReadOnlyMany, modes)
}
modes = GetAccessModesFromString("ROX,RWX")
if !containsAccessMode(modes, v1.ReadOnlyMany) {
t.Errorf("Expected mode %s, but got %+v", v1.ReadOnlyMany, modes)
}
if !containsAccessMode(modes, v1.ReadWriteMany) {
t.Errorf("Expected mode %s, but got %+v", v1.ReadWriteMany, modes)
}
modes = GetAccessModesFromString("RWO,ROX,RWX")
if !containsAccessMode(modes, v1.ReadOnlyMany) {
t.Errorf("Expected mode %s, but got %+v", v1.ReadOnlyMany, modes)
}
if !containsAccessMode(modes, v1.ReadWriteMany) {
t.Errorf("Expected mode %s, but got %+v", v1.ReadWriteMany, modes)
}
}
func TestRemoveDuplicateAccessModes(t *testing.T) {
modes := []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce, v1.ReadOnlyMany, v1.ReadOnlyMany, v1.ReadOnlyMany,
}
modes = removeDuplicateAccessModes(modes)
if len(modes) != 2 {
t.Errorf("Expected 2 distinct modes in set but found %v", len(modes))
}
}
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
matchExpressions := []v1.NodeSelectorRequirement{{
Key: "foo",
Operator: v1.NodeSelectorOpIn,
Values: []string{"bar", "baz"},
}}
mustParse := func(s string) labels.Selector {
out, e := labels.Parse(s)
if e != nil {
panic(e)
}
return out
}
tc := []struct {
in []v1.NodeSelectorRequirement
out labels.Selector
expectErr bool
}{
{in: nil, out: labels.Nothing()},
{in: []v1.NodeSelectorRequirement{}, out: labels.Nothing()},
{
in: matchExpressions,
out: mustParse("foo in (baz,bar)"),
},
{
in: []v1.NodeSelectorRequirement{{
Key: "foo",
Operator: v1.NodeSelectorOpExists,
Values: []string{"bar", "baz"},
}},
expectErr: true,
},
{
in: []v1.NodeSelectorRequirement{{
Key: "foo",
Operator: v1.NodeSelectorOpGt,
Values: []string{"1"},
}},
out: mustParse("foo>1"),
},
{
in: []v1.NodeSelectorRequirement{{
Key: "bar",
Operator: v1.NodeSelectorOpLt,
Values: []string{"7"},
}},
out: mustParse("bar<7"),
},
}
for i, tc := range tc {
out, err := NodeSelectorRequirementsAsSelector(tc.in)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
if !reflect.DeepEqual(out, tc.out) {
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
}
}
}
func TestTolerationsTolerateTaintsWithFilter(t *testing.T) {
testCases := []struct {
description string
tolerations []v1.Toleration
taints []v1.Taint
applyFilter taintsFilterFunc
expectTolerated bool
}{
{
description: "empty tolerations tolerate empty taints",
tolerations: []v1.Toleration{},
taints: []v1.Taint{},
applyFilter: func(t *v1.Taint) bool { return true },
expectTolerated: true,
},
{
description: "non-empty tolerations tolerate empty taints",
tolerations: []v1.Toleration{
{
Key: "foo",
Operator: "Exists",
Effect: v1.TaintEffectNoSchedule,
},
},
taints: []v1.Taint{},
applyFilter: func(t *v1.Taint) bool { return true },
expectTolerated: true,
},
{
description: "tolerations match all taints, expect tolerated",
tolerations: []v1.Toleration{
{
Key: "foo",
Operator: "Exists",
Effect: v1.TaintEffectNoSchedule,
},
},
taints: []v1.Taint{
{
Key: "foo",
Effect: v1.TaintEffectNoSchedule,
},
},
applyFilter: func(t *v1.Taint) bool { return true },
expectTolerated: true,
},
{
description: "tolerations don't match taints, but no taints apply to the filter, expect tolerated",
tolerations: []v1.Toleration{
{
Key: "foo",
Operator: "Exists",
Effect: v1.TaintEffectNoSchedule,
},
},
taints: []v1.Taint{
{
Key: "bar",
Effect: v1.TaintEffectNoSchedule,
},
},
applyFilter: func(t *v1.Taint) bool { return false },
expectTolerated: true,
},
{
description: "no filterFunc indicated, means all taints apply to the filter, tolerations don't match taints, expect untolerated",
tolerations: []v1.Toleration{
{
Key: "foo",
Operator: "Exists",
Effect: v1.TaintEffectNoSchedule,
},
},
taints: []v1.Taint{
{
Key: "bar",
Effect: v1.TaintEffectNoSchedule,
},
},
applyFilter: nil,
expectTolerated: false,
},
{
description: "tolerations match taints, expect tolerated",
tolerations: []v1.Toleration{
{
Key: "foo",
Operator: "Exists",
Effect: v1.TaintEffectNoExecute,
},
},
taints: []v1.Taint{
{
Key: "foo",
Effect: v1.TaintEffectNoExecute,
},
{
Key: "bar",
Effect: v1.TaintEffectNoSchedule,
},
},
applyFilter: func(t *v1.Taint) bool { return t.Effect == v1.TaintEffectNoExecute },
expectTolerated: true,
},
}
for _, tc := range testCases {
if tc.expectTolerated != TolerationsTolerateTaintsWithFilter(tc.tolerations, tc.taints, tc.applyFilter) {
filteredTaints := []v1.Taint{}
for _, taint := range tc.taints {
if tc.applyFilter != nil && !tc.applyFilter(&taint) {
continue
}
filteredTaints = append(filteredTaints, taint)
}
t.Errorf("[%s] expect tolerations %+v tolerate filtered taints %+v in taints %+v", tc.description, tc.tolerations, filteredTaints, tc.taints)
}
}
}
func TestGetAvoidPodsFromNode(t *testing.T) {
controllerFlag := true
testCases := []struct {
node *v1.Node
expectValue v1.AvoidPods
expectErr bool
}{
{
node: &v1.Node{},
expectValue: v1.AvoidPods{},
expectErr: false,
},
{
node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
v1.PreferAvoidPodsAnnotationKey: `
{
"preferAvoidPods": [
{
"podSignature": {
"podController": {
"apiVersion": "v1",
"kind": "ReplicationController",
"name": "foo",
"uid": "abcdef123456",
"controller": true
}
},
"reason": "some reason",
"message": "some message"
}
]
}`,
},
},
},
expectValue: v1.AvoidPods{
PreferAvoidPods: []v1.PreferAvoidPodsEntry{
{
PodSignature: v1.PodSignature{
PodController: &metav1.OwnerReference{
APIVersion: "v1",
Kind: "ReplicationController",
Name: "foo",
UID: "abcdef123456",
Controller: &controllerFlag,
},
},
Reason: "some reason",
Message: "some message",
},
},
},
expectErr: false,
},
{
node: &v1.Node{
// Missing end symbol of "podController" and "podSignature"
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
v1.PreferAvoidPodsAnnotationKey: `
{
"preferAvoidPods": [
{
"podSignature": {
"podController": {
"kind": "ReplicationController",
"apiVersion": "v1"
"reason": "some reason",
"message": "some message"
}
]
}`,
},
},
},
expectValue: v1.AvoidPods{},
expectErr: true,
},
}
for i, tc := range testCases {
v, err := GetAvoidPodsFromNodeAnnotations(tc.node.Annotations)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
if !reflect.DeepEqual(tc.expectValue, v) {
t.Errorf("[%v]expect value %v but got %v with %v", i, tc.expectValue, v, v.PreferAvoidPods[0].PodSignature.PodController.Controller)
}
}
}
func TestSysctlsFromPodAnnotation(t *testing.T) {
type Test struct {
annotation string
expectValue []v1.Sysctl
expectErr bool
}
for i, test := range []Test{
{
annotation: "",
expectValue: nil,
},
{
annotation: "foo.bar",
expectErr: true,
},
{
annotation: "=123",
expectErr: true,
},
{
annotation: "foo.bar=",
expectValue: []v1.Sysctl{{Name: "foo.bar", Value: ""}},
},
{
annotation: "foo.bar=42",
expectValue: []v1.Sysctl{{Name: "foo.bar", Value: "42"}},
},
{
annotation: "foo.bar=42,",
expectErr: true,
},
{
annotation: "foo.bar=42,abc.def=1",
expectValue: []v1.Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}},
},
} {
sysctls, err := SysctlsFromPodAnnotation(test.annotation)
if test.expectErr && err == nil {
t.Errorf("[%v]expected error but got none", i)
} else if !test.expectErr && err != nil {
t.Errorf("[%v]did not expect error but got: %v", i, err)
} else if !reflect.DeepEqual(sysctls, test.expectValue) {
t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls)
}
}
}
// TODO: remove when alpha support for topology constraints is removed
func TestGetNodeAffinityFromAnnotations(t *testing.T) {
testCases := []struct {
annotations map[string]string
expectErr bool
}{
{
annotations: nil,
expectErr: false,
},
{
annotations: map[string]string{},
expectErr: false,
},
{
annotations: map[string]string{
v1.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}`,
},
expectErr: false,
},
{
annotations: map[string]string{
v1.AlphaStorageNodeAffinityAnnotation: `[{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}]`,
},
expectErr: true,
},
{
annotations: map[string]string{
v1.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms":
"matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
}
}`,
},
expectErr: true,
},
}
for i, tc := range testCases {
_, err := GetStorageNodeAffinityFromAnnotation(tc.annotations)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
}
}

View file

@ -1,392 +0,0 @@
/*
Copyright 2014 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 (
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/apis/core"
)
func TestValidateEvent(t *testing.T) {
table := []struct {
*core.Event
valid bool
}{
{
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
Namespace: "foo",
},
InvolvedObject: core.ObjectReference{
Namespace: "bar",
Kind: "Pod",
},
},
false,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test2",
Namespace: "aoeu-_-aoeu",
},
InvolvedObject: core.ObjectReference{
Namespace: "aoeu-_-aoeu",
Kind: "Pod",
},
},
false,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test3",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
},
true,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test4",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Namespace",
},
},
true,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test5",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "extensions/v1beta1",
Kind: "NoKind",
Namespace: metav1.NamespaceDefault,
},
},
true,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test6",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "extensions/v1beta1",
Kind: "Job",
Namespace: "foo",
},
},
false,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test7",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "extensions/v1beta1",
Kind: "Job",
Namespace: metav1.NamespaceDefault,
},
},
true,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test8",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "other/v1beta1",
Kind: "Job",
Namespace: "foo",
},
},
false,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test9",
Namespace: "foo",
},
InvolvedObject: core.ObjectReference{
APIVersion: "other/v1beta1",
Kind: "Job",
Namespace: "foo",
},
},
true,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test10",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "extensions",
Kind: "Job",
Namespace: "foo",
},
},
false,
}, {
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test11",
Namespace: "foo",
},
InvolvedObject: core.ObjectReference{
// must register in v1beta1 to be true
APIVersion: "extensions/v1beta1",
Kind: "Job",
Namespace: "foo",
},
},
true,
},
{
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test12",
Namespace: "foo",
},
InvolvedObject: core.ObjectReference{
APIVersion: "other/v1beta1",
Kind: "FooBar",
Namespace: "bar",
},
},
false,
},
{
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test13",
Namespace: "",
},
InvolvedObject: core.ObjectReference{
APIVersion: "other/v1beta1",
Kind: "FooBar",
Namespace: "bar",
},
},
false,
},
{
&core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test14",
Namespace: "foo",
},
InvolvedObject: core.ObjectReference{
APIVersion: "other/v1beta1",
Kind: "FooBar",
Namespace: "",
},
},
false,
},
}
for _, item := range table {
if e, a := item.valid, len(ValidateEvent(item.Event)) == 0; e != a {
t.Errorf("%v: expected %v, got %v: %v", item.Event.Name, e, a, ValidateEvent(item.Event))
}
}
}
func TestValidateNewEvent(t *testing.T) {
someTime := metav1.MicroTime{Time: time.Unix(1505828956, 0)}
table := []struct {
*core.Event
valid bool
msg string
}{
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceDefault,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
},
valid: false,
msg: "Old Event with EventTime should trigger new validation and fail",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Action: "Do",
Reason: "Because",
},
valid: true,
msg: "Valid new Event",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "my-contr@ller",
ReportingInstance: "node-xyz",
Action: "Do",
Reason: "Because",
},
valid: false,
msg: "not qualified reportingController",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
Action: "Do",
Reason: "Because",
},
valid: false,
msg: "too long reporting instance",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Action: "Do",
},
valid: false,
msg: "missing reason",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: metav1.NamespaceSystem,
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Reason: "Because",
},
valid: false,
msg: "missing action",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Reason: "Because",
},
valid: false,
msg: "missing namespace",
},
{
Event: &core.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
InvolvedObject: core.ObjectReference{
APIVersion: "v1",
Kind: "Node",
},
EventTime: someTime,
ReportingController: "k8s.io/my-controller",
ReportingInstance: "node-xyz",
Action: "Do",
Reason: "Because",
Message: `zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz`,
},
valid: false,
msg: "too long message",
},
}
for _, item := range table {
if e, a := item.valid, len(ValidateEvent(item.Event)) == 0; e != a {
t.Errorf("%v: expected %v, got %v: %v", item.msg, e, a, ValidateEvent(item.Event))
}
}
}

View file

@ -1140,7 +1140,7 @@ func validateMountPropagation(mountPropagation *core.MountPropagationMode, conta
return allErrs
}
supportedMountPropagations := sets.NewString(string(core.MountPropagationBidirectional), string(core.MountPropagationHostToContainer))
supportedMountPropagations := sets.NewString(string(core.MountPropagationBidirectional), string(core.MountPropagationHostToContainer), string(core.MountPropagationNone))
if !supportedMountPropagations.Has(string(*mountPropagation)) {
allErrs = append(allErrs, field.NotSupported(fldPath, *mountPropagation, supportedMountPropagations.List()))
}
@ -1383,9 +1383,6 @@ func validateLocalVolumeSource(ls *core.LocalVolumeSource, fldPath *field.Path)
return allErrs
}
if !path.IsAbs(ls.Path) {
allErrs = append(allErrs, field.Invalid(fldPath, ls.Path, "must be an absolute path"))
}
allErrs = append(allErrs, validatePathNoBacksteps(ls.Path, fldPath.Child("path"))...)
return allErrs
}
@ -3017,9 +3014,6 @@ func ValidateNodeSelectorRequirement(rq core.NodeSelectorRequirement, fldPath *f
func ValidateNodeSelectorTerm(term core.NodeSelectorTerm, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(term.MatchExpressions) == 0 {
return append(allErrs, field.Required(fldPath.Child("matchExpressions"), "must have at least one node selector requirement"))
}
for j, req := range term.MatchExpressions {
allErrs = append(allErrs, ValidateNodeSelectorRequirement(req, fldPath.Child("matchExpressions").Index(j))...)
}

File diff suppressed because it is too large Load diff

View file

@ -1,62 +0,0 @@
/*
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 extensions
import (
"reflect"
"testing"
)
func TestPodAnnotationsFromSysctls(t *testing.T) {
type Test struct {
sysctls []string
expectedValue string
}
for _, test := range []Test{
{sysctls: []string{"a.b"}, expectedValue: "a.b"},
{sysctls: []string{"a.b", "c.d"}, expectedValue: "a.b,c.d"},
{sysctls: []string{"a.b", "a.b"}, expectedValue: "a.b,a.b"},
{sysctls: []string{}, expectedValue: ""},
{sysctls: nil, expectedValue: ""},
} {
a := PodAnnotationsFromSysctls(test.sysctls)
if a != test.expectedValue {
t.Errorf("wrong value for %v: got=%q wanted=%q", test.sysctls, a, test.expectedValue)
}
}
}
func TestSysctlsFromPodSecurityPolicyAnnotation(t *testing.T) {
type Test struct {
expectedValue []string
annotation string
}
for _, test := range []Test{
{annotation: "a.b", expectedValue: []string{"a.b"}},
{annotation: "a.b,c.d", expectedValue: []string{"a.b", "c.d"}},
{annotation: "a.b,a.b", expectedValue: []string{"a.b", "a.b"}},
{annotation: "", expectedValue: []string{}},
} {
sysctls, err := SysctlsFromPodSecurityPolicyAnnotation(test.annotation)
if err != nil {
t.Errorf("error for %q: %v", test.annotation, err)
}
if !reflect.DeepEqual(sysctls, test.expectedValue) {
t.Errorf("wrong value for %q: got=%v wanted=%v", test.annotation, sysctls, test.expectedValue)
}
}
}