Update go dependencies
This commit is contained in:
parent
15ffb51394
commit
bb4d483837
1621 changed files with 86368 additions and 284392 deletions
95
vendor/k8s.io/kubernetes/pkg/kubelet/active_deadline_test.go
generated
vendored
95
vendor/k8s.io/kubernetes/pkg/kubelet/active_deadline_test.go
generated
vendored
|
|
@ -1,95 +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 kubelet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/tools/record"
|
||||
)
|
||||
|
||||
// mockPodStatusProvider returns the status on the specified pod
|
||||
type mockPodStatusProvider struct {
|
||||
pods []*v1.Pod
|
||||
}
|
||||
|
||||
// GetPodStatus returns the status on the associated pod with matching uid (if found)
|
||||
func (m *mockPodStatusProvider) GetPodStatus(uid types.UID) (v1.PodStatus, bool) {
|
||||
for _, pod := range m.pods {
|
||||
if pod.UID == uid {
|
||||
return pod.Status, true
|
||||
}
|
||||
}
|
||||
return v1.PodStatus{}, false
|
||||
}
|
||||
|
||||
// TestActiveDeadlineHandler verifies the active deadline handler functions as expected.
|
||||
func TestActiveDeadlineHandler(t *testing.T) {
|
||||
pods := newTestPods(4)
|
||||
fakeClock := clock.NewFakeClock(time.Now())
|
||||
podStatusProvider := &mockPodStatusProvider{pods: pods}
|
||||
fakeRecorder := &record.FakeRecorder{}
|
||||
handler, err := newActiveDeadlineHandler(podStatusProvider, fakeRecorder, fakeClock)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
now := metav1.Now()
|
||||
startTime := metav1.NewTime(now.Time.Add(-1 * time.Minute))
|
||||
|
||||
// this pod has exceeded its active deadline
|
||||
exceededActiveDeadlineSeconds := int64(30)
|
||||
pods[0].Status.StartTime = &startTime
|
||||
pods[0].Spec.ActiveDeadlineSeconds = &exceededActiveDeadlineSeconds
|
||||
|
||||
// this pod has not exceeded its active deadline
|
||||
notYetActiveDeadlineSeconds := int64(120)
|
||||
pods[1].Status.StartTime = &startTime
|
||||
pods[1].Spec.ActiveDeadlineSeconds = ¬YetActiveDeadlineSeconds
|
||||
|
||||
// this pod has no deadline
|
||||
pods[2].Status.StartTime = &startTime
|
||||
pods[2].Spec.ActiveDeadlineSeconds = nil
|
||||
|
||||
testCases := []struct {
|
||||
pod *v1.Pod
|
||||
expected bool
|
||||
}{{pods[0], true}, {pods[1], false}, {pods[2], false}, {pods[3], false}}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
if actual := handler.ShouldSync(testCase.pod); actual != testCase.expected {
|
||||
t.Errorf("[%d] ShouldSync expected %#v, got %#v", i, testCase.expected, actual)
|
||||
}
|
||||
actual := handler.ShouldEvict(testCase.pod)
|
||||
if actual.Evict != testCase.expected {
|
||||
t.Errorf("[%d] ShouldEvict.Evict expected %#v, got %#v", i, testCase.expected, actual.Evict)
|
||||
}
|
||||
if testCase.expected {
|
||||
if actual.Reason != reason {
|
||||
t.Errorf("[%d] ShouldEvict.Reason expected %#v, got %#v", i, message, actual.Reason)
|
||||
}
|
||||
if actual.Message != message {
|
||||
t.Errorf("[%d] ShouldEvict.Message expected %#v, got %#v", i, message, actual.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
210
vendor/k8s.io/kubernetes/pkg/kubelet/container/cache_test.go
generated
vendored
210
vendor/k8s.io/kubernetes/pkg/kubelet/container/cache_test.go
generated
vendored
|
|
@ -1,210 +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 container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
func newTestCache() *cache {
|
||||
c := NewCache()
|
||||
return c.(*cache)
|
||||
}
|
||||
|
||||
func TestCacheNotInitialized(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
// If the global timestamp is not set, always return nil.
|
||||
d := cache.getIfNewerThan(types.UID("1234"), time.Time{})
|
||||
assert.True(t, d == nil, "should return nil since cache is not initialized")
|
||||
}
|
||||
|
||||
func getTestPodIDAndStatus(numContainers int) (types.UID, *PodStatus) {
|
||||
id := types.UID(strconv.FormatInt(time.Now().UnixNano(), 10))
|
||||
name := fmt.Sprintf("cache-foo-%s", string(id))
|
||||
namespace := "ns"
|
||||
var status *PodStatus
|
||||
if numContainers > 0 {
|
||||
status = &PodStatus{ID: id, Name: name, Namespace: namespace}
|
||||
} else {
|
||||
status = &PodStatus{ID: id}
|
||||
}
|
||||
for i := 0; i < numContainers; i++ {
|
||||
status.ContainerStatuses = append(status.ContainerStatuses, &ContainerStatus{Name: string(i)})
|
||||
}
|
||||
return id, status
|
||||
}
|
||||
|
||||
func TestGetIfNewerThanWhenPodExists(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
timestamp := time.Now()
|
||||
|
||||
cases := []struct {
|
||||
cacheTime time.Time
|
||||
modified time.Time
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
// Both the global cache timestamp and the modified time are newer
|
||||
// than the timestamp.
|
||||
cacheTime: timestamp.Add(time.Second),
|
||||
modified: timestamp,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
// Global cache timestamp is newer, but the pod entry modified
|
||||
// time is older than the given timestamp. This means that the
|
||||
// entry is up-to-date even though it hasn't changed for a while.
|
||||
cacheTime: timestamp.Add(time.Second),
|
||||
modified: timestamp.Add(-time.Second * 10),
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
// Global cache timestamp is older, but the pod entry modified
|
||||
// time is newer than the given timestamp. This means that the
|
||||
// entry is up-to-date but the rest of the cache are still being
|
||||
// updated.
|
||||
cacheTime: timestamp.Add(-time.Second),
|
||||
modified: timestamp.Add(time.Second * 3),
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
// Both the global cache timestamp and the modified time are older
|
||||
// than the given timestamp.
|
||||
cacheTime: timestamp.Add(-time.Second),
|
||||
modified: timestamp.Add(-time.Second),
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for i, c := range cases {
|
||||
podID, status := getTestPodIDAndStatus(2)
|
||||
cache.UpdateTime(c.cacheTime)
|
||||
cache.Set(podID, status, nil, c.modified)
|
||||
d := cache.getIfNewerThan(podID, timestamp)
|
||||
assert.Equal(t, c.expected, d != nil, "test[%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPodNewerThanWhenPodDoesNotExist(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
cacheTime := time.Now()
|
||||
cache.UpdateTime(cacheTime)
|
||||
podID := types.UID("1234")
|
||||
|
||||
cases := []struct {
|
||||
timestamp time.Time
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
timestamp: cacheTime.Add(-time.Second),
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
timestamp: cacheTime.Add(time.Second),
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for i, c := range cases {
|
||||
d := cache.getIfNewerThan(podID, c.timestamp)
|
||||
assert.Equal(t, c.expected, d != nil, "test[%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheSetAndGet(t *testing.T) {
|
||||
cache := NewCache()
|
||||
cases := []struct {
|
||||
numContainers int
|
||||
error error
|
||||
}{
|
||||
{numContainers: 3, error: nil},
|
||||
{numContainers: 2, error: fmt.Errorf("unable to get status")},
|
||||
{numContainers: 0, error: nil},
|
||||
}
|
||||
for i, c := range cases {
|
||||
podID, status := getTestPodIDAndStatus(c.numContainers)
|
||||
cache.Set(podID, status, c.error, time.Time{})
|
||||
// Read back the status and error stored in cache and make sure they
|
||||
// match the original ones.
|
||||
actualStatus, actualErr := cache.Get(podID)
|
||||
assert.Equal(t, status, actualStatus, "test[%d]", i)
|
||||
assert.Equal(t, c.error, actualErr, "test[%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheGetPodDoesNotExist(t *testing.T) {
|
||||
cache := NewCache()
|
||||
podID, status := getTestPodIDAndStatus(0)
|
||||
// If the pod does not exist in cache, cache should return an status
|
||||
// object with id filled.
|
||||
actualStatus, actualErr := cache.Get(podID)
|
||||
assert.Equal(t, status, actualStatus)
|
||||
assert.Equal(t, nil, actualErr)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
cache := &cache{pods: map[types.UID]*data{}}
|
||||
// Write a new pod status into the cache.
|
||||
podID, status := getTestPodIDAndStatus(3)
|
||||
cache.Set(podID, status, nil, time.Time{})
|
||||
actualStatus, actualErr := cache.Get(podID)
|
||||
assert.Equal(t, status, actualStatus)
|
||||
assert.Equal(t, nil, actualErr)
|
||||
// Delete the pod from cache, and verify that we get an empty status.
|
||||
cache.Delete(podID)
|
||||
expectedStatus := &PodStatus{ID: podID}
|
||||
actualStatus, actualErr = cache.Get(podID)
|
||||
assert.Equal(t, expectedStatus, actualStatus)
|
||||
assert.Equal(t, nil, actualErr)
|
||||
}
|
||||
|
||||
func verifyNotification(t *testing.T, ch chan *data, expectNotification bool) {
|
||||
if expectNotification {
|
||||
assert.True(t, len(ch) > 0, "Did not receive notification")
|
||||
} else {
|
||||
assert.True(t, len(ch) < 1, "Should not have triggered the notification")
|
||||
}
|
||||
// Drain the channel.
|
||||
for i := 0; i < len(ch); i++ {
|
||||
<-ch
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterNotification(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
cacheTime := time.Now()
|
||||
cache.UpdateTime(cacheTime)
|
||||
|
||||
podID, status := getTestPodIDAndStatus(1)
|
||||
ch := cache.subscribe(podID, cacheTime.Add(time.Second))
|
||||
verifyNotification(t, ch, false)
|
||||
cache.Set(podID, status, nil, cacheTime.Add(time.Second))
|
||||
// The Set operation should've triggered the notification.
|
||||
verifyNotification(t, ch, true)
|
||||
|
||||
podID, _ = getTestPodIDAndStatus(1)
|
||||
|
||||
ch = cache.subscribe(podID, cacheTime.Add(time.Second))
|
||||
verifyNotification(t, ch, false)
|
||||
cache.UpdateTime(cacheTime.Add(time.Second * 2))
|
||||
// The advance of cache timestamp should've triggered the notification.
|
||||
verifyNotification(t, ch, true)
|
||||
}
|
||||
322
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go
generated
vendored
322
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go
generated
vendored
|
|
@ -1,322 +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 container
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestEnvVarsToMap(t *testing.T) {
|
||||
vars := []EnvVar{
|
||||
{
|
||||
Name: "foo",
|
||||
Value: "bar",
|
||||
},
|
||||
{
|
||||
Name: "zoo",
|
||||
Value: "baz",
|
||||
},
|
||||
}
|
||||
|
||||
varMap := EnvVarsToMap(vars)
|
||||
|
||||
if e, a := len(vars), len(varMap); e != a {
|
||||
t.Errorf("Unexpected map length; expected: %d, got %d", e, a)
|
||||
}
|
||||
|
||||
if a := varMap["foo"]; a != "bar" {
|
||||
t.Errorf("Unexpected value of key 'foo': %v", a)
|
||||
}
|
||||
|
||||
if a := varMap["zoo"]; a != "baz" {
|
||||
t.Errorf("Unexpected value of key 'zoo': %v", a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandCommandAndArgs(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
container *v1.Container
|
||||
envs []EnvVar
|
||||
expectedCommand []string
|
||||
expectedArgs []string
|
||||
}{
|
||||
{
|
||||
name: "none",
|
||||
container: &v1.Container{},
|
||||
},
|
||||
{
|
||||
name: "command expanded",
|
||||
container: &v1.Container{
|
||||
Command: []string{"foo", "$(VAR_TEST)", "$(VAR_TEST2)"},
|
||||
},
|
||||
envs: []EnvVar{
|
||||
{
|
||||
Name: "VAR_TEST",
|
||||
Value: "zoo",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST2",
|
||||
Value: "boo",
|
||||
},
|
||||
},
|
||||
expectedCommand: []string{"foo", "zoo", "boo"},
|
||||
},
|
||||
{
|
||||
name: "args expanded",
|
||||
container: &v1.Container{
|
||||
Args: []string{"zap", "$(VAR_TEST)", "$(VAR_TEST2)"},
|
||||
},
|
||||
envs: []EnvVar{
|
||||
{
|
||||
Name: "VAR_TEST",
|
||||
Value: "hap",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST2",
|
||||
Value: "trap",
|
||||
},
|
||||
},
|
||||
expectedArgs: []string{"zap", "hap", "trap"},
|
||||
},
|
||||
{
|
||||
name: "both expanded",
|
||||
container: &v1.Container{
|
||||
Command: []string{"$(VAR_TEST2)--$(VAR_TEST)", "foo", "$(VAR_TEST3)"},
|
||||
Args: []string{"foo", "$(VAR_TEST)", "$(VAR_TEST2)"},
|
||||
},
|
||||
envs: []EnvVar{
|
||||
{
|
||||
Name: "VAR_TEST",
|
||||
Value: "zoo",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST2",
|
||||
Value: "boo",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST3",
|
||||
Value: "roo",
|
||||
},
|
||||
},
|
||||
expectedCommand: []string{"boo--zoo", "foo", "roo"},
|
||||
expectedArgs: []string{"foo", "zoo", "boo"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
actualCommand, actualArgs := ExpandContainerCommandAndArgs(tc.container, tc.envs)
|
||||
|
||||
if e, a := tc.expectedCommand, actualCommand; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%v: unexpected command; expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
|
||||
if e, a := tc.expectedArgs, actualArgs; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%v: unexpected args; expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldContainerBeRestarted(t *testing.T) {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: "12345678",
|
||||
Name: "foo",
|
||||
Namespace: "new",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{Name: "no-history"},
|
||||
{Name: "alive"},
|
||||
{Name: "succeed"},
|
||||
{Name: "failed"},
|
||||
{Name: "unknown"},
|
||||
},
|
||||
},
|
||||
}
|
||||
podStatus := &PodStatus{
|
||||
ID: pod.UID,
|
||||
Name: pod.Name,
|
||||
Namespace: pod.Namespace,
|
||||
ContainerStatuses: []*ContainerStatus{
|
||||
{
|
||||
Name: "alive",
|
||||
State: ContainerStateRunning,
|
||||
},
|
||||
{
|
||||
Name: "succeed",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 0,
|
||||
},
|
||||
{
|
||||
Name: "failed",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 1,
|
||||
},
|
||||
{
|
||||
Name: "alive",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 2,
|
||||
},
|
||||
{
|
||||
Name: "unknown",
|
||||
State: ContainerStateUnknown,
|
||||
},
|
||||
{
|
||||
Name: "failed",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
policies := []v1.RestartPolicy{
|
||||
v1.RestartPolicyNever,
|
||||
v1.RestartPolicyOnFailure,
|
||||
v1.RestartPolicyAlways,
|
||||
}
|
||||
expected := map[string][]bool{
|
||||
"no-history": {true, true, true},
|
||||
"alive": {false, false, false},
|
||||
"succeed": {false, false, true},
|
||||
"failed": {false, true, true},
|
||||
"unknown": {true, true, true},
|
||||
}
|
||||
for _, c := range pod.Spec.Containers {
|
||||
for i, policy := range policies {
|
||||
pod.Spec.RestartPolicy = policy
|
||||
e := expected[c.Name][i]
|
||||
r := ShouldContainerBeRestarted(&c, pod, podStatus)
|
||||
if r != e {
|
||||
t.Errorf("Restart for container %q with restart policy %q expected %t, got %t",
|
||||
c.Name, policy, e, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasPrivilegedContainer(t *testing.T) {
|
||||
newBoolPtr := func(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
tests := map[string]struct {
|
||||
securityContext *v1.SecurityContext
|
||||
expected bool
|
||||
}{
|
||||
"nil security context": {
|
||||
securityContext: nil,
|
||||
expected: false,
|
||||
},
|
||||
"nil privileged": {
|
||||
securityContext: &v1.SecurityContext{},
|
||||
expected: false,
|
||||
},
|
||||
"false privileged": {
|
||||
securityContext: &v1.SecurityContext{Privileged: newBoolPtr(false)},
|
||||
expected: false,
|
||||
},
|
||||
"true privileged": {
|
||||
securityContext: &v1.SecurityContext{Privileged: newBoolPtr(true)},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
pod := &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{SecurityContext: v.securityContext},
|
||||
},
|
||||
},
|
||||
}
|
||||
actual := HasPrivilegedContainer(pod)
|
||||
if actual != v.expected {
|
||||
t.Errorf("%s expected %t but got %t", k, v.expected, actual)
|
||||
}
|
||||
}
|
||||
// Test init containers as well.
|
||||
for k, v := range tests {
|
||||
pod := &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
InitContainers: []v1.Container{
|
||||
{SecurityContext: v.securityContext},
|
||||
},
|
||||
},
|
||||
}
|
||||
actual := HasPrivilegedContainer(pod)
|
||||
if actual != v.expected {
|
||||
t.Errorf("%s expected %t but got %t", k, v.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakePortMappings(t *testing.T) {
|
||||
port := func(name string, protocol v1.Protocol, containerPort, hostPort int32, ip string) v1.ContainerPort {
|
||||
return v1.ContainerPort{
|
||||
Name: name,
|
||||
Protocol: protocol,
|
||||
ContainerPort: containerPort,
|
||||
HostPort: hostPort,
|
||||
HostIP: ip,
|
||||
}
|
||||
}
|
||||
portMapping := func(name string, protocol v1.Protocol, containerPort, hostPort int, ip string) PortMapping {
|
||||
return PortMapping{
|
||||
Name: name,
|
||||
Protocol: protocol,
|
||||
ContainerPort: containerPort,
|
||||
HostPort: hostPort,
|
||||
HostIP: ip,
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
container *v1.Container
|
||||
expectedPortMappings []PortMapping
|
||||
}{
|
||||
{
|
||||
&v1.Container{
|
||||
Name: "fooContainer",
|
||||
Ports: []v1.ContainerPort{
|
||||
port("", v1.ProtocolTCP, 80, 8080, "127.0.0.1"),
|
||||
port("", v1.ProtocolTCP, 443, 4343, "192.168.0.1"),
|
||||
port("foo", v1.ProtocolUDP, 555, 5555, ""),
|
||||
// Duplicated, should be ignored.
|
||||
port("foo", v1.ProtocolUDP, 888, 8888, ""),
|
||||
// Duplicated, should be ignored.
|
||||
port("", v1.ProtocolTCP, 80, 8888, ""),
|
||||
},
|
||||
},
|
||||
[]PortMapping{
|
||||
portMapping("fooContainer-TCP:80", v1.ProtocolTCP, 80, 8080, "127.0.0.1"),
|
||||
portMapping("fooContainer-TCP:443", v1.ProtocolTCP, 443, 4343, "192.168.0.1"),
|
||||
portMapping("fooContainer-foo", v1.ProtocolUDP, 555, 5555, ""),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
actual := MakePortMappings(tt.container)
|
||||
assert.Equal(t, tt.expectedPortMappings, actual, "[%d]", i)
|
||||
}
|
||||
}
|
||||
213
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go
generated
vendored
213
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go
generated
vendored
|
|
@ -1,213 +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 container
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
)
|
||||
|
||||
func TestFieldPath(t *testing.T) {
|
||||
pod := &v1.Pod{Spec: v1.PodSpec{Containers: []v1.Container{
|
||||
{Name: "foo"},
|
||||
{Name: "bar"},
|
||||
{Name: ""},
|
||||
{Name: "baz"},
|
||||
}}}
|
||||
table := map[string]struct {
|
||||
pod *v1.Pod
|
||||
container *v1.Container
|
||||
path string
|
||||
success bool
|
||||
}{
|
||||
"basic": {pod, &v1.Container{Name: "foo"}, "spec.containers{foo}", true},
|
||||
"basic2": {pod, &v1.Container{Name: "baz"}, "spec.containers{baz}", true},
|
||||
"emptyName": {pod, &v1.Container{Name: ""}, "spec.containers[2]", true},
|
||||
"basicSamePointer": {pod, &pod.Spec.Containers[0], "spec.containers{foo}", true},
|
||||
"missing": {pod, &v1.Container{Name: "qux"}, "", false},
|
||||
}
|
||||
|
||||
for name, item := range table {
|
||||
res, err := fieldPath(item.pod, item.container)
|
||||
if item.success == false {
|
||||
if err == nil {
|
||||
t.Errorf("%v: unexpected non-error", name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("%v: unexpected error: %v", name, err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.path, res; e != a {
|
||||
t.Errorf("%v: wanted %v, got %v", name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateContainerRef(t *testing.T) {
|
||||
var (
|
||||
okPod = v1.Pod{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
SelfLink: "/api/" + legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() + "/pods/foo",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "by-name",
|
||||
},
|
||||
{},
|
||||
},
|
||||
},
|
||||
}
|
||||
noSelfLinkPod = okPod
|
||||
defaultedSelfLinkPod = okPod
|
||||
)
|
||||
noSelfLinkPod.Kind = ""
|
||||
noSelfLinkPod.APIVersion = ""
|
||||
noSelfLinkPod.ObjectMeta.SelfLink = ""
|
||||
defaultedSelfLinkPod.ObjectMeta.SelfLink = "/api/" + legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() + "/pods/ok"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
pod *v1.Pod
|
||||
container *v1.Container
|
||||
expected *v1.ObjectReference
|
||||
success bool
|
||||
}{
|
||||
{
|
||||
name: "by-name",
|
||||
pod: &okPod,
|
||||
container: &v1.Container{
|
||||
Name: "by-name",
|
||||
},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: ".spec.containers{by-name}",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
name: "no-name",
|
||||
pod: &okPod,
|
||||
container: &v1.Container{},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: ".spec.containers[1]",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
name: "no-selflink",
|
||||
pod: &noSelfLinkPod,
|
||||
container: &v1.Container{},
|
||||
expected: nil,
|
||||
success: false,
|
||||
},
|
||||
{
|
||||
name: "defaulted-selflink",
|
||||
pod: &defaultedSelfLinkPod,
|
||||
container: &v1.Container{
|
||||
Name: "by-name",
|
||||
},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: ".spec.containers{by-name}",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
name: "implicitly-required",
|
||||
pod: &okPod,
|
||||
container: &v1.Container{
|
||||
Name: "net",
|
||||
},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: "implicitly required container net",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
actual, err := GenerateContainerRef(tc.pod, tc.container)
|
||||
if err != nil {
|
||||
if tc.success {
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !tc.success {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.expected.Kind, actual.Kind; e != a {
|
||||
t.Errorf("%v: kind: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.APIVersion, actual.APIVersion; e != a {
|
||||
t.Errorf("%v: apiVersion: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.Name, actual.Name; e != a {
|
||||
t.Errorf("%v: name: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.Namespace, actual.Namespace; e != a {
|
||||
t.Errorf("%v: namespace: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.UID, actual.UID; e != a {
|
||||
t.Errorf("%v: uid: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.ResourceVersion, actual.ResourceVersion; e != a {
|
||||
t.Errorf("%v: kind: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
74
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache_test.go
generated
vendored
74
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache_test.go
generated
vendored
|
|
@ -1,74 +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 container_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
ctest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||
)
|
||||
|
||||
func comparePods(t *testing.T, expected []*ctest.FakePod, actual []*Pod) {
|
||||
if len(expected) != len(actual) {
|
||||
t.Errorf("expected %d pods, got %d instead", len(expected), len(actual))
|
||||
}
|
||||
for i := range expected {
|
||||
if !reflect.DeepEqual(expected[i].Pod, actual[i]) {
|
||||
t.Errorf("expected %#v, got %#v", expected[i].Pod, actual[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPods(t *testing.T) {
|
||||
runtime := &ctest.FakeRuntime{}
|
||||
expected := []*ctest.FakePod{{Pod: &Pod{ID: "1111"}}, {Pod: &Pod{ID: "2222"}}, {Pod: &Pod{ID: "3333"}}}
|
||||
runtime.PodList = expected
|
||||
cache := NewTestRuntimeCache(runtime)
|
||||
actual, err := cache.GetPods()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
comparePods(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestForceUpdateIfOlder(t *testing.T) {
|
||||
runtime := &ctest.FakeRuntime{}
|
||||
cache := NewTestRuntimeCache(runtime)
|
||||
|
||||
// Cache old pods.
|
||||
oldpods := []*ctest.FakePod{{Pod: &Pod{ID: "1111"}}}
|
||||
runtime.PodList = oldpods
|
||||
cache.UpdateCacheWithLock()
|
||||
|
||||
// Update the runtime to new pods.
|
||||
newpods := []*ctest.FakePod{{Pod: &Pod{ID: "1111"}}, {Pod: &Pod{ID: "2222"}}, {Pod: &Pod{ID: "3333"}}}
|
||||
runtime.PodList = newpods
|
||||
|
||||
// An older timestamp should not force an update.
|
||||
cache.ForceUpdateIfOlder(time.Now().Add(-20 * time.Minute))
|
||||
actual := cache.GetCachedPods()
|
||||
comparePods(t, oldpods, actual)
|
||||
|
||||
// A newer timestamp should force an update.
|
||||
cache.ForceUpdateIfOlder(time.Now().Add(20 * time.Second))
|
||||
actual = cache.GetCachedPods()
|
||||
comparePods(t, newpods, actual)
|
||||
}
|
||||
68
vendor/k8s.io/kubernetes/pkg/kubelet/container/sync_result_test.go
generated
vendored
68
vendor/k8s.io/kubernetes/pkg/kubelet/container/sync_result_test.go
generated
vendored
|
|
@ -1,68 +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 container
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPodSyncResult(t *testing.T) {
|
||||
okResults := []*SyncResult{
|
||||
NewSyncResult(StartContainer, "container_0"),
|
||||
NewSyncResult(SetupNetwork, "pod"),
|
||||
}
|
||||
errResults := []*SyncResult{
|
||||
NewSyncResult(KillContainer, "container_1"),
|
||||
NewSyncResult(TeardownNetwork, "pod"),
|
||||
}
|
||||
errResults[0].Fail(errors.New("error_0"), "message_0")
|
||||
errResults[1].Fail(errors.New("error_1"), "message_1")
|
||||
|
||||
// If the PodSyncResult doesn't contain error result, it should not be error
|
||||
result := PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
if result.Error() != nil {
|
||||
t.Errorf("PodSyncResult should not be error: %v", result)
|
||||
}
|
||||
|
||||
// If the PodSyncResult contains error result, it should be error
|
||||
result = PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
result.AddSyncResult(errResults...)
|
||||
if result.Error() == nil {
|
||||
t.Errorf("PodSyncResult should be error: %q", result)
|
||||
}
|
||||
|
||||
// If the PodSyncResult is failed, it should be error
|
||||
result = PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
result.Fail(errors.New("error"))
|
||||
if result.Error() == nil {
|
||||
t.Errorf("PodSyncResult should be error: %q", result)
|
||||
}
|
||||
|
||||
// If the PodSyncResult is added an error PodSyncResult, it should be error
|
||||
errResult := PodSyncResult{}
|
||||
errResult.AddSyncResult(errResults...)
|
||||
result = PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
result.AddPodSyncResult(errResult)
|
||||
if result.Error() == nil {
|
||||
t.Errorf("PodSyncResult should be error: %q", result)
|
||||
}
|
||||
}
|
||||
5
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go
generated
vendored
|
|
@ -237,6 +237,7 @@ type Dependencies struct {
|
|||
DockerClientConfig *dockershim.ClientConfig
|
||||
EventClient v1core.EventsGetter
|
||||
HeartbeatClient v1core.CoreV1Interface
|
||||
OnHeartbeatFailure func()
|
||||
KubeClient clientset.Interface
|
||||
ExternalKubeClient clientset.Interface
|
||||
Mounter mount.Interface
|
||||
|
|
@ -493,6 +494,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
|||
nodeName: nodeName,
|
||||
kubeClient: kubeDeps.KubeClient,
|
||||
heartbeatClient: kubeDeps.HeartbeatClient,
|
||||
onRepeatedHeartbeatFailure: kubeDeps.OnHeartbeatFailure,
|
||||
rootDirectory: rootDirectory,
|
||||
resyncInterval: kubeCfg.SyncFrequency.Duration,
|
||||
sourcesReady: config.NewSourcesReady(kubeDeps.PodConfig.SeenAllSources),
|
||||
|
|
@ -935,6 +937,9 @@ type Kubelet struct {
|
|||
iptClient utilipt.Interface
|
||||
rootDirectory string
|
||||
|
||||
// onRepeatedHeartbeatFailure is called when a heartbeat operation fails more than once. optional.
|
||||
onRepeatedHeartbeatFailure func()
|
||||
|
||||
// podWorkers handle syncing Pods in response to events.
|
||||
podWorkers PodWorkers
|
||||
|
||||
|
|
|
|||
69
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters_test.go
generated
vendored
69
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters_test.go
generated
vendored
|
|
@ -1,69 +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 kubelet
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestKubeletDirs(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kubelet := testKubelet.kubelet
|
||||
root := kubelet.rootDirectory
|
||||
|
||||
var exp, got string
|
||||
|
||||
got = kubelet.getPodsDir()
|
||||
exp = filepath.Join(root, "pods")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPluginsDir()
|
||||
exp = filepath.Join(root, "plugins")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPluginDir("foobar")
|
||||
exp = filepath.Join(root, "plugins/foobar")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPodDir("abc123")
|
||||
exp = filepath.Join(root, "pods/abc123")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPodVolumesDir("abc123")
|
||||
exp = filepath.Join(root, "pods/abc123/volumes")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPodVolumeDir("abc123", "plugin", "foobar")
|
||||
exp = filepath.Join(root, "pods/abc123/volumes/plugin/foobar")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPodPluginsDir("abc123")
|
||||
exp = filepath.Join(root, "pods/abc123/plugins")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPodPluginDir("abc123", "foobar")
|
||||
exp = filepath.Join(root, "pods/abc123/plugins/foobar")
|
||||
assert.Equal(t, exp, got)
|
||||
|
||||
got = kubelet.getPodContainerDir("abc123", "def456")
|
||||
exp = filepath.Join(root, "pods/abc123/containers/def456")
|
||||
assert.Equal(t, exp, got)
|
||||
}
|
||||
206
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network_test.go
generated
vendored
206
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network_test.go
generated
vendored
|
|
@ -1,206 +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 kubelet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNetworkHostGetsPodNotFound(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, true)
|
||||
defer testKubelet.Cleanup()
|
||||
nh := networkHost{testKubelet.kubelet}
|
||||
|
||||
actualPod, _ := nh.GetPodByName("", "")
|
||||
if actualPod != nil {
|
||||
t.Fatalf("Was expected nil, received %v instead", actualPod)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetworkHostGetsKubeClient(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, true)
|
||||
defer testKubelet.Cleanup()
|
||||
nh := networkHost{testKubelet.kubelet}
|
||||
|
||||
if nh.GetKubeClient() != testKubelet.fakeKubeClient {
|
||||
t.Fatalf("NetworkHost client does not match testKubelet's client")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetworkHostGetsRuntime(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, true)
|
||||
defer testKubelet.Cleanup()
|
||||
nh := networkHost{testKubelet.kubelet}
|
||||
|
||||
if nh.GetRuntime() != testKubelet.fakeRuntime {
|
||||
t.Fatalf("NetworkHost runtime does not match testKubelet's runtime")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetworkHostSupportsLegacyFeatures(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, true)
|
||||
defer testKubelet.Cleanup()
|
||||
nh := networkHost{testKubelet.kubelet}
|
||||
|
||||
if nh.SupportsLegacyFeatures() == false {
|
||||
t.Fatalf("SupportsLegacyFeatures should not be false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoOpHostGetsName(t *testing.T) {
|
||||
nh := NoOpLegacyHost{}
|
||||
pod, err := nh.GetPodByName("", "")
|
||||
if pod != nil && err != true {
|
||||
t.Fatalf("noOpLegacyHost getpodbyname expected to be nil and true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoOpHostGetsKubeClient(t *testing.T) {
|
||||
nh := NoOpLegacyHost{}
|
||||
if nh.GetKubeClient() != nil {
|
||||
t.Fatalf("noOpLegacyHost client expected to be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoOpHostGetsRuntime(t *testing.T) {
|
||||
nh := NoOpLegacyHost{}
|
||||
if nh.GetRuntime() != nil {
|
||||
t.Fatalf("noOpLegacyHost runtime expected to be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoOpHostSupportsLegacyFeatures(t *testing.T) {
|
||||
nh := NoOpLegacyHost{}
|
||||
if nh.SupportsLegacyFeatures() != false {
|
||||
t.Fatalf("noOpLegacyHost legacy features expected to be false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeIPParam(t *testing.T) {
|
||||
type test struct {
|
||||
nodeIP string
|
||||
success bool
|
||||
testName string
|
||||
}
|
||||
tests := []test{
|
||||
{
|
||||
nodeIP: "",
|
||||
success: false,
|
||||
testName: "IP not set",
|
||||
},
|
||||
{
|
||||
nodeIP: "127.0.0.1",
|
||||
success: false,
|
||||
testName: "IPv4 loopback address",
|
||||
},
|
||||
{
|
||||
nodeIP: "::1",
|
||||
success: false,
|
||||
testName: "IPv6 loopback address",
|
||||
},
|
||||
{
|
||||
nodeIP: "224.0.0.1",
|
||||
success: false,
|
||||
testName: "multicast IPv4 address",
|
||||
},
|
||||
{
|
||||
nodeIP: "ff00::1",
|
||||
success: false,
|
||||
testName: "multicast IPv6 address",
|
||||
},
|
||||
{
|
||||
nodeIP: "169.254.0.1",
|
||||
success: false,
|
||||
testName: "IPv4 link-local unicast address",
|
||||
},
|
||||
{
|
||||
nodeIP: "fe80::0202:b3ff:fe1e:8329",
|
||||
success: false,
|
||||
testName: "IPv6 link-local unicast address",
|
||||
},
|
||||
{
|
||||
nodeIP: "0.0.0.0",
|
||||
success: false,
|
||||
testName: "Unspecified IPv4 address",
|
||||
},
|
||||
{
|
||||
nodeIP: "::",
|
||||
success: false,
|
||||
testName: "Unspecified IPv6 address",
|
||||
},
|
||||
{
|
||||
nodeIP: "1.2.3.4",
|
||||
success: false,
|
||||
testName: "IPv4 address that doesn't belong to host",
|
||||
},
|
||||
}
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
assert.Error(t, err, fmt.Sprintf(
|
||||
"Unable to obtain a list of the node's unicast interface addresses."))
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
if ip.IsLoopback() || ip.IsLinkLocalUnicast() {
|
||||
break
|
||||
}
|
||||
successTest := test{
|
||||
nodeIP: ip.String(),
|
||||
success: true,
|
||||
testName: fmt.Sprintf("Success test case for address %s", ip.String()),
|
||||
}
|
||||
tests = append(tests, successTest)
|
||||
}
|
||||
for _, test := range tests {
|
||||
err := validateNodeIP(net.ParseIP(test.nodeIP))
|
||||
if test.success {
|
||||
assert.NoError(t, err, "test %s", test.testName)
|
||||
} else {
|
||||
assert.Error(t, err, fmt.Sprintf("test %s", test.testName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIPTablesMark(t *testing.T) {
|
||||
tests := []struct {
|
||||
bit int
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
14,
|
||||
"0x00004000/0x00004000",
|
||||
},
|
||||
{
|
||||
15,
|
||||
"0x00008000/0x00008000",
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
res := getIPTablesMark(tc.bit)
|
||||
assert.Equal(t, tc.expect, res, "input %d", tc.bit)
|
||||
}
|
||||
}
|
||||
3
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go
generated
vendored
|
|
@ -371,6 +371,9 @@ func (kl *Kubelet) syncNodeStatus() {
|
|||
func (kl *Kubelet) updateNodeStatus() error {
|
||||
for i := 0; i < nodeStatusUpdateRetry; i++ {
|
||||
if err := kl.tryUpdateNodeStatus(i); err != nil {
|
||||
if i > 0 && kl.onRepeatedHeartbeatFailure != nil {
|
||||
kl.onRepeatedHeartbeatFailure()
|
||||
}
|
||||
glog.Errorf("Error updating node status, will retry: %v", err)
|
||||
} else {
|
||||
return nil
|
||||
|
|
|
|||
1418
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status_test.go
generated
vendored
1418
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
26
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go
generated
vendored
26
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go
generated
vendored
|
|
@ -110,23 +110,6 @@ func (kl *Kubelet) makeGPUDevices(pod *v1.Pod, container *v1.Container) ([]kubec
|
|||
return devices, nil
|
||||
}
|
||||
|
||||
func makeAbsolutePath(goos, path string) string {
|
||||
if goos != "windows" {
|
||||
return "/" + path
|
||||
}
|
||||
// These are all for windows
|
||||
// If there is a colon, give up.
|
||||
if strings.Contains(path, ":") {
|
||||
return path
|
||||
}
|
||||
// If there is a slash, but no drive, add 'c:'
|
||||
if strings.HasPrefix(path, "/") || strings.HasPrefix(path, "\\") {
|
||||
return "c:" + path
|
||||
}
|
||||
// Otherwise, add 'c:\'
|
||||
return "c:\\" + path
|
||||
}
|
||||
|
||||
// makeBlockVolumes maps the raw block devices specified in the path of the container
|
||||
// Experimental
|
||||
func (kl *Kubelet) makeBlockVolumes(pod *v1.Pod, container *v1.Container, podVolumes kubecontainer.VolumeMap, blkutil volumepathhandler.BlockVolumePathHandler) ([]kubecontainer.DeviceInfo, error) {
|
||||
|
|
@ -239,6 +222,7 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h
|
|||
VolumePath: volumePath,
|
||||
PodDir: podDir,
|
||||
ContainerName: container.Name,
|
||||
ReadOnly: mount.ReadOnly || vol.Mounter.GetAttributes().ReadOnly,
|
||||
})
|
||||
if err != nil {
|
||||
// Don't pass detailed error back to the user because it could give information about host filesystem
|
||||
|
|
@ -255,7 +239,7 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h
|
|||
}
|
||||
}
|
||||
if !filepath.IsAbs(containerPath) {
|
||||
containerPath = makeAbsolutePath(runtime.GOOS, containerPath)
|
||||
containerPath = volumeutil.MakeAbsolutePath(runtime.GOOS, containerPath)
|
||||
}
|
||||
|
||||
propagation, err := translateMountPropagation(mount.MountPropagation)
|
||||
|
|
@ -301,12 +285,14 @@ func translateMountPropagation(mountMode *v1.MountPropagationMode) (runtimeapi.M
|
|||
}
|
||||
switch {
|
||||
case mountMode == nil:
|
||||
// HostToContainer is the default
|
||||
return runtimeapi.MountPropagation_PROPAGATION_HOST_TO_CONTAINER, nil
|
||||
// PRIVATE is the default
|
||||
return runtimeapi.MountPropagation_PROPAGATION_PRIVATE, nil
|
||||
case *mountMode == v1.MountPropagationHostToContainer:
|
||||
return runtimeapi.MountPropagation_PROPAGATION_HOST_TO_CONTAINER, nil
|
||||
case *mountMode == v1.MountPropagationBidirectional:
|
||||
return runtimeapi.MountPropagation_PROPAGATION_BIDIRECTIONAL, nil
|
||||
case *mountMode == v1.MountPropagationNone:
|
||||
return runtimeapi.MountPropagation_PROPAGATION_PRIVATE, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid MountPropagation mode: %q", mountMode)
|
||||
}
|
||||
|
|
|
|||
2551
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go
generated
vendored
2551
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
102
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_windows_test.go
generated
vendored
102
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_windows_test.go
generated
vendored
|
|
@ -1,102 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
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 kubelet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/api/core/v1"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
)
|
||||
|
||||
func TestMakeMountsWindows(t *testing.T) {
|
||||
container := v1.Container{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
MountPath: "c:/etc/hosts",
|
||||
Name: "disk",
|
||||
ReadOnly: false,
|
||||
},
|
||||
{
|
||||
MountPath: "c:/mnt/path3",
|
||||
Name: "disk",
|
||||
ReadOnly: true,
|
||||
},
|
||||
{
|
||||
MountPath: "c:/mnt/path4",
|
||||
Name: "disk4",
|
||||
ReadOnly: false,
|
||||
},
|
||||
{
|
||||
MountPath: "c:/mnt/path5",
|
||||
Name: "disk5",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
podVolumes := kubecontainer.VolumeMap{
|
||||
"disk": kubecontainer.VolumeInfo{Mounter: &stubVolume{path: "c:/mnt/disk"}},
|
||||
"disk4": kubecontainer.VolumeInfo{Mounter: &stubVolume{path: "c:/mnt/host"}},
|
||||
"disk5": kubecontainer.VolumeInfo{Mounter: &stubVolume{path: "c:/var/lib/kubelet/podID/volumes/empty/disk5"}},
|
||||
}
|
||||
|
||||
pod := v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
HostNetwork: true,
|
||||
},
|
||||
}
|
||||
|
||||
fm := &mount.FakeMounter{}
|
||||
mounts, _, _ := makeMounts(&pod, "/pod", &container, "fakepodname", "", "", podVolumes, fm)
|
||||
|
||||
expectedMounts := []kubecontainer.Mount{
|
||||
{
|
||||
Name: "disk",
|
||||
ContainerPath: "c:/etc/hosts",
|
||||
HostPath: "c:/mnt/disk",
|
||||
ReadOnly: false,
|
||||
SELinuxRelabel: false,
|
||||
},
|
||||
{
|
||||
Name: "disk",
|
||||
ContainerPath: "c:/mnt/path3",
|
||||
HostPath: "c:/mnt/disk",
|
||||
ReadOnly: true,
|
||||
SELinuxRelabel: false,
|
||||
},
|
||||
{
|
||||
Name: "disk4",
|
||||
ContainerPath: "c:/mnt/path4",
|
||||
HostPath: "c:/mnt/host",
|
||||
ReadOnly: false,
|
||||
SELinuxRelabel: false,
|
||||
},
|
||||
{
|
||||
Name: "disk5",
|
||||
ContainerPath: "c:/mnt/path5",
|
||||
HostPath: "c:/var/lib/kubelet/podID/volumes/empty/disk5",
|
||||
ReadOnly: false,
|
||||
SELinuxRelabel: false,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expectedMounts, mounts, "mounts of container %+v", container)
|
||||
}
|
||||
111
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_resources_test.go
generated
vendored
111
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_resources_test.go
generated
vendored
|
|
@ -1,111 +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 kubelet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
cadvisorapi "github.com/google/cadvisor/info/v1"
|
||||
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
|
||||
"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"
|
||||
)
|
||||
|
||||
func TestPodResourceLimitsDefaulting(t *testing.T) {
|
||||
cpuCores := resource.MustParse("10")
|
||||
memoryCapacity := resource.MustParse("10Gi")
|
||||
tk := newTestKubelet(t, true)
|
||||
defer tk.Cleanup()
|
||||
tk.fakeCadvisor.On("VersionInfo").Return(&cadvisorapi.VersionInfo{}, nil)
|
||||
tk.fakeCadvisor.On("MachineInfo").Return(&cadvisorapi.MachineInfo{
|
||||
NumCores: int(cpuCores.Value()),
|
||||
MemoryCapacity: uint64(memoryCapacity.Value()),
|
||||
}, nil)
|
||||
tk.fakeCadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{}, nil)
|
||||
tk.fakeCadvisor.On("RootFsInfo").Return(cadvisorapiv2.FsInfo{}, nil)
|
||||
tk.kubelet.nodeInfo = &testNodeInfo{
|
||||
nodes: []*v1.Node{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: string(tk.kubelet.nodeName),
|
||||
},
|
||||
Status: v1.NodeStatus{
|
||||
Allocatable: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("6"),
|
||||
v1.ResourceMemory: resource.MustParse("4Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
cases := []struct {
|
||||
pod *v1.Pod
|
||||
expected *v1.Pod
|
||||
}{
|
||||
{
|
||||
pod: getPod("0", "0"),
|
||||
expected: getPod("6", "4Gi"),
|
||||
},
|
||||
{
|
||||
pod: getPod("1", "0"),
|
||||
expected: getPod("1", "4Gi"),
|
||||
},
|
||||
{
|
||||
pod: getPod("", ""),
|
||||
expected: getPod("6", "4Gi"),
|
||||
},
|
||||
{
|
||||
pod: getPod("0", "1Mi"),
|
||||
expected: getPod("6", "1Mi"),
|
||||
},
|
||||
}
|
||||
as := assert.New(t)
|
||||
for idx, tc := range cases {
|
||||
actual, _, err := tk.kubelet.defaultPodLimitsForDownwardAPI(tc.pod, nil)
|
||||
as.Nil(err, "failed to default pod limits: %v", err)
|
||||
if !apiequality.Semantic.DeepEqual(tc.expected, actual) {
|
||||
as.Fail("test case [%d] failed. Expected: %+v, Got: %+v", idx, tc.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getPod(cpuLimit, memoryLimit string) *v1.Pod {
|
||||
resources := v1.ResourceRequirements{}
|
||||
if cpuLimit != "" || memoryLimit != "" {
|
||||
resources.Limits = make(v1.ResourceList)
|
||||
}
|
||||
if cpuLimit != "" {
|
||||
resources.Limits[v1.ResourceCPU] = resource.MustParse(cpuLimit)
|
||||
}
|
||||
if memoryLimit != "" {
|
||||
resources.Limits[v1.ResourceMemory] = resource.MustParse(memoryLimit)
|
||||
}
|
||||
return &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "foo",
|
||||
Resources: resources,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
2239
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go
generated
vendored
2239
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
470
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_volumes_test.go
generated
vendored
470
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_volumes_test.go
generated
vendored
|
|
@ -1,470 +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 kubelet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
core "k8s.io/client-go/testing"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
func TestListVolumesForPod(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kubelet := testKubelet.kubelet
|
||||
|
||||
pod := podWithUIDNameNsSpec("12345678", "foo", "test", v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "vol2",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
stopCh := runVolumeManager(kubelet)
|
||||
defer close(stopCh)
|
||||
|
||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||
err := kubelet.volumeManager.WaitForAttachAndMount(pod)
|
||||
assert.NoError(t, err)
|
||||
|
||||
podName := util.GetUniquePodName(pod)
|
||||
|
||||
volumesToReturn, volumeExsit := kubelet.ListVolumesForPod(types.UID(podName))
|
||||
assert.True(t, volumeExsit, "expected to find volumes for pod %q", podName)
|
||||
|
||||
outerVolumeSpecName1 := "vol1"
|
||||
assert.NotNil(t, volumesToReturn[outerVolumeSpecName1], "key %s", outerVolumeSpecName1)
|
||||
|
||||
outerVolumeSpecName2 := "vol2"
|
||||
assert.NotNil(t, volumesToReturn[outerVolumeSpecName2], "key %s", outerVolumeSpecName2)
|
||||
|
||||
}
|
||||
|
||||
func TestPodVolumesExist(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kubelet := testKubelet.kubelet
|
||||
|
||||
pods := []*v1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
UID: "pod1uid",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod2",
|
||||
UID: "pod2uid",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol2",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod3",
|
||||
UID: "pod3uid",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol3",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
stopCh := runVolumeManager(kubelet)
|
||||
defer close(stopCh)
|
||||
|
||||
kubelet.podManager.SetPods(pods)
|
||||
for _, pod := range pods {
|
||||
err := kubelet.volumeManager.WaitForAttachAndMount(pod)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
for _, pod := range pods {
|
||||
podVolumesExist := kubelet.podVolumesExist(pod.UID)
|
||||
assert.True(t, podVolumesExist, "pod %q", pod.UID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumeAttachAndMountControllerDisabled(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kubelet := testKubelet.kubelet
|
||||
|
||||
pod := podWithUIDNameNsSpec("12345678", "foo", "test", v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
stopCh := runVolumeManager(kubelet)
|
||||
defer close(stopCh)
|
||||
|
||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||
err := kubelet.volumeManager.WaitForAttachAndMount(pod)
|
||||
assert.NoError(t, err)
|
||||
|
||||
podVolumes := kubelet.volumeManager.GetMountedVolumesForPod(
|
||||
util.GetUniquePodName(pod))
|
||||
|
||||
expectedPodVolumes := []string{"vol1"}
|
||||
assert.Len(t, podVolumes, len(expectedPodVolumes), "Volumes for pod %+v", pod)
|
||||
for _, name := range expectedPodVolumes {
|
||||
assert.Contains(t, podVolumes, name, "Volumes for pod %+v", pod)
|
||||
}
|
||||
assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once")
|
||||
assert.NoError(t, volumetest.VerifyWaitForAttachCallCount(
|
||||
1 /* expectedWaitForAttachCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyAttachCallCount(
|
||||
1 /* expectedAttachCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyMountDeviceCallCount(
|
||||
1 /* expectedMountDeviceCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifySetUpCallCount(
|
||||
1 /* expectedSetUpCallCount */, testKubelet.volumePlugin))
|
||||
}
|
||||
|
||||
func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kubelet := testKubelet.kubelet
|
||||
|
||||
pod := podWithUIDNameNsSpec("12345678", "foo", "test", v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
stopCh := runVolumeManager(kubelet)
|
||||
defer close(stopCh)
|
||||
|
||||
// Add pod
|
||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||
|
||||
// Verify volumes attached
|
||||
err := kubelet.volumeManager.WaitForAttachAndMount(pod)
|
||||
assert.NoError(t, err)
|
||||
|
||||
podVolumes := kubelet.volumeManager.GetMountedVolumesForPod(
|
||||
util.GetUniquePodName(pod))
|
||||
|
||||
expectedPodVolumes := []string{"vol1"}
|
||||
assert.Len(t, podVolumes, len(expectedPodVolumes), "Volumes for pod %+v", pod)
|
||||
for _, name := range expectedPodVolumes {
|
||||
assert.Contains(t, podVolumes, name, "Volumes for pod %+v", pod)
|
||||
}
|
||||
|
||||
assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once")
|
||||
assert.NoError(t, volumetest.VerifyWaitForAttachCallCount(
|
||||
1 /* expectedWaitForAttachCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyAttachCallCount(
|
||||
1 /* expectedAttachCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyMountDeviceCallCount(
|
||||
1 /* expectedMountDeviceCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifySetUpCallCount(
|
||||
1 /* expectedSetUpCallCount */, testKubelet.volumePlugin))
|
||||
|
||||
// Remove pod
|
||||
kubelet.podManager.SetPods([]*v1.Pod{})
|
||||
|
||||
assert.NoError(t, waitForVolumeUnmount(kubelet.volumeManager, pod))
|
||||
|
||||
// Verify volumes unmounted
|
||||
podVolumes = kubelet.volumeManager.GetMountedVolumesForPod(
|
||||
util.GetUniquePodName(pod))
|
||||
|
||||
assert.Len(t, podVolumes, 0,
|
||||
"Expected volumes to be unmounted and detached. But some volumes are still mounted: %#v", podVolumes)
|
||||
|
||||
assert.NoError(t, volumetest.VerifyTearDownCallCount(
|
||||
1 /* expectedTearDownCallCount */, testKubelet.volumePlugin))
|
||||
|
||||
// Verify volumes detached and no longer reported as in use
|
||||
assert.NoError(t, waitForVolumeDetach(v1.UniqueVolumeName("fake/vol1"), kubelet.volumeManager))
|
||||
assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once")
|
||||
assert.NoError(t, volumetest.VerifyDetachCallCount(
|
||||
1 /* expectedDetachCallCount */, testKubelet.volumePlugin))
|
||||
}
|
||||
|
||||
func TestVolumeAttachAndMountControllerEnabled(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kubelet := testKubelet.kubelet
|
||||
kubeClient := testKubelet.fakeKubeClient
|
||||
kubeClient.AddReactor("get", "nodes",
|
||||
func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname},
|
||||
Status: v1.NodeStatus{
|
||||
VolumesAttached: []v1.AttachedVolume{
|
||||
{
|
||||
Name: "fake/vol1",
|
||||
DevicePath: "fake/path",
|
||||
},
|
||||
}},
|
||||
Spec: v1.NodeSpec{ExternalID: testKubeletHostname},
|
||||
}, nil
|
||||
})
|
||||
kubeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, fmt.Errorf("no reaction implemented for %s", action)
|
||||
})
|
||||
|
||||
pod := podWithUIDNameNsSpec("12345678", "foo", "test", v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
stopCh := runVolumeManager(kubelet)
|
||||
defer close(stopCh)
|
||||
|
||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||
|
||||
// Fake node status update
|
||||
go simulateVolumeInUseUpdate(
|
||||
v1.UniqueVolumeName("fake/vol1"),
|
||||
stopCh,
|
||||
kubelet.volumeManager)
|
||||
|
||||
assert.NoError(t, kubelet.volumeManager.WaitForAttachAndMount(pod))
|
||||
|
||||
podVolumes := kubelet.volumeManager.GetMountedVolumesForPod(
|
||||
util.GetUniquePodName(pod))
|
||||
|
||||
expectedPodVolumes := []string{"vol1"}
|
||||
assert.Len(t, podVolumes, len(expectedPodVolumes), "Volumes for pod %+v", pod)
|
||||
for _, name := range expectedPodVolumes {
|
||||
assert.Contains(t, podVolumes, name, "Volumes for pod %+v", pod)
|
||||
}
|
||||
assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once")
|
||||
assert.NoError(t, volumetest.VerifyWaitForAttachCallCount(
|
||||
1 /* expectedWaitForAttachCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyZeroAttachCalls(testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyMountDeviceCallCount(
|
||||
1 /* expectedMountDeviceCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifySetUpCallCount(
|
||||
1 /* expectedSetUpCallCount */, testKubelet.volumePlugin))
|
||||
}
|
||||
|
||||
func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kubelet := testKubelet.kubelet
|
||||
kubeClient := testKubelet.fakeKubeClient
|
||||
kubeClient.AddReactor("get", "nodes",
|
||||
func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname},
|
||||
Status: v1.NodeStatus{
|
||||
VolumesAttached: []v1.AttachedVolume{
|
||||
{
|
||||
Name: "fake/vol1",
|
||||
DevicePath: "fake/path",
|
||||
},
|
||||
}},
|
||||
Spec: v1.NodeSpec{ExternalID: testKubeletHostname},
|
||||
}, nil
|
||||
})
|
||||
kubeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, fmt.Errorf("no reaction implemented for %s", action)
|
||||
})
|
||||
|
||||
pod := podWithUIDNameNsSpec("12345678", "foo", "test", v1.PodSpec{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||
PDName: "fake-device",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
stopCh := runVolumeManager(kubelet)
|
||||
defer close(stopCh)
|
||||
|
||||
// Add pod
|
||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||
|
||||
// Fake node status update
|
||||
go simulateVolumeInUseUpdate(
|
||||
v1.UniqueVolumeName("fake/vol1"),
|
||||
stopCh,
|
||||
kubelet.volumeManager)
|
||||
|
||||
// Verify volumes attached
|
||||
assert.NoError(t, kubelet.volumeManager.WaitForAttachAndMount(pod))
|
||||
|
||||
podVolumes := kubelet.volumeManager.GetMountedVolumesForPod(
|
||||
util.GetUniquePodName(pod))
|
||||
|
||||
expectedPodVolumes := []string{"vol1"}
|
||||
assert.Len(t, podVolumes, len(expectedPodVolumes), "Volumes for pod %+v", pod)
|
||||
for _, name := range expectedPodVolumes {
|
||||
assert.Contains(t, podVolumes, name, "Volumes for pod %+v", pod)
|
||||
}
|
||||
|
||||
assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once")
|
||||
assert.NoError(t, volumetest.VerifyWaitForAttachCallCount(
|
||||
1 /* expectedWaitForAttachCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyZeroAttachCalls(testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifyMountDeviceCallCount(
|
||||
1 /* expectedMountDeviceCallCount */, testKubelet.volumePlugin))
|
||||
assert.NoError(t, volumetest.VerifySetUpCallCount(
|
||||
1 /* expectedSetUpCallCount */, testKubelet.volumePlugin))
|
||||
|
||||
// Remove pod
|
||||
kubelet.podManager.SetPods([]*v1.Pod{})
|
||||
|
||||
assert.NoError(t, waitForVolumeUnmount(kubelet.volumeManager, pod))
|
||||
|
||||
// Verify volumes unmounted
|
||||
podVolumes = kubelet.volumeManager.GetMountedVolumesForPod(
|
||||
util.GetUniquePodName(pod))
|
||||
|
||||
assert.Len(t, podVolumes, 0,
|
||||
"Expected volumes to be unmounted and detached. But some volumes are still mounted: %#v", podVolumes)
|
||||
|
||||
assert.NoError(t, volumetest.VerifyTearDownCallCount(
|
||||
1 /* expectedTearDownCallCount */, testKubelet.volumePlugin))
|
||||
|
||||
// Verify volumes detached and no longer reported as in use
|
||||
assert.NoError(t, waitForVolumeDetach(v1.UniqueVolumeName("fake/vol1"), kubelet.volumeManager))
|
||||
assert.True(t, testKubelet.volumePlugin.GetNewAttacherCallCount() >= 1, "Expected plugin NewAttacher to be called at least once")
|
||||
assert.NoError(t, volumetest.VerifyZeroDetachCallCount(testKubelet.volumePlugin))
|
||||
}
|
||||
|
||||
type stubVolume struct {
|
||||
path string
|
||||
volume.MetricsNil
|
||||
}
|
||||
|
||||
func (f *stubVolume) GetPath() string {
|
||||
return f.path
|
||||
}
|
||||
|
||||
func (f *stubVolume) GetAttributes() volume.Attributes {
|
||||
return volume.Attributes{}
|
||||
}
|
||||
|
||||
func (f *stubVolume) CanMount() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *stubVolume) SetUp(fsGroup *int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *stubVolume) SetUpAt(dir string, fsGroup *int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type stubBlockVolume struct {
|
||||
dirPath string
|
||||
volName string
|
||||
}
|
||||
|
||||
func (f *stubBlockVolume) GetGlobalMapPath(spec *volume.Spec) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (f *stubBlockVolume) GetPodDeviceMapPath() (string, string) {
|
||||
return f.dirPath, f.volName
|
||||
}
|
||||
|
||||
func (f *stubBlockVolume) SetUpDevice() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
func (f *stubBlockVolume) TearDownDevice(mapPath string, devicePath string) error {
|
||||
return nil
|
||||
}
|
||||
38
vendor/k8s.io/kubernetes/pkg/kubelet/oom_watcher_test.go
generated
vendored
38
vendor/k8s.io/kubernetes/pkg/kubelet/oom_watcher_test.go
generated
vendored
|
|
@ -1,38 +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 kubelet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/tools/record"
|
||||
cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
|
||||
)
|
||||
|
||||
func TestBasic(t *testing.T) {
|
||||
fakeRecorder := &record.FakeRecorder{}
|
||||
mockCadvisor := &cadvisortest.Fake{}
|
||||
node := &v1.ObjectReference{}
|
||||
oomWatcher := NewOOMWatcher(mockCadvisor, fakeRecorder)
|
||||
assert.NoError(t, oomWatcher.Start(node))
|
||||
|
||||
// TODO: Improve this test once cadvisor exports events.EventChannel as an interface
|
||||
// and thereby allow using a mock version of cadvisor.
|
||||
}
|
||||
203
vendor/k8s.io/kubernetes/pkg/kubelet/pod_container_deletor_test.go
generated
vendored
203
vendor/k8s.io/kubernetes/pkg/kubelet/pod_container_deletor_test.go
generated
vendored
|
|
@ -1,203 +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 kubelet
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
)
|
||||
|
||||
func TestGetContainersToDeleteInPodWithFilter(t *testing.T) {
|
||||
pod := kubecontainer.PodStatus{
|
||||
ContainerStatuses: []*kubecontainer.ContainerStatus{
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "1"},
|
||||
Name: "foo",
|
||||
CreatedAt: time.Now(),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "2"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "3"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(2 * time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "4"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(3 * time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "5"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(4 * time.Second),
|
||||
State: kubecontainer.ContainerStateRunning,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
containersToKeep int
|
||||
expectedContainersToDelete containerStatusbyCreatedList
|
||||
}{
|
||||
{
|
||||
0,
|
||||
[]*kubecontainer.ContainerStatus{pod.ContainerStatuses[3], pod.ContainerStatuses[2], pod.ContainerStatuses[1]},
|
||||
},
|
||||
{
|
||||
1,
|
||||
[]*kubecontainer.ContainerStatus{pod.ContainerStatuses[2], pod.ContainerStatuses[1]},
|
||||
},
|
||||
{
|
||||
2,
|
||||
[]*kubecontainer.ContainerStatus{pod.ContainerStatuses[1]},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
candidates := getContainersToDeleteInPod("4", &pod, test.containersToKeep)
|
||||
if !reflect.DeepEqual(candidates, test.expectedContainersToDelete) {
|
||||
t.Errorf("expected %v got %v", test.expectedContainersToDelete, candidates)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetContainersToDeleteInPod(t *testing.T) {
|
||||
pod := kubecontainer.PodStatus{
|
||||
ContainerStatuses: []*kubecontainer.ContainerStatus{
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "1"},
|
||||
Name: "foo",
|
||||
CreatedAt: time.Now(),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "2"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "3"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(2 * time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "4"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(3 * time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "5"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(4 * time.Second),
|
||||
State: kubecontainer.ContainerStateRunning,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
containersToKeep int
|
||||
expectedContainersToDelete containerStatusbyCreatedList
|
||||
}{
|
||||
{
|
||||
0,
|
||||
[]*kubecontainer.ContainerStatus{pod.ContainerStatuses[3], pod.ContainerStatuses[2], pod.ContainerStatuses[1], pod.ContainerStatuses[0]},
|
||||
},
|
||||
{
|
||||
1,
|
||||
[]*kubecontainer.ContainerStatus{pod.ContainerStatuses[2], pod.ContainerStatuses[1], pod.ContainerStatuses[0]},
|
||||
},
|
||||
{
|
||||
2,
|
||||
[]*kubecontainer.ContainerStatus{pod.ContainerStatuses[1], pod.ContainerStatuses[0]},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
candidates := getContainersToDeleteInPod("", &pod, test.containersToKeep)
|
||||
if !reflect.DeepEqual(candidates, test.expectedContainersToDelete) {
|
||||
t.Errorf("expected %v got %v", test.expectedContainersToDelete, candidates)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetContainersToDeleteInPodWithNoMatch(t *testing.T) {
|
||||
pod := kubecontainer.PodStatus{
|
||||
ContainerStatuses: []*kubecontainer.ContainerStatus{
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "1"},
|
||||
Name: "foo",
|
||||
CreatedAt: time.Now(),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "2"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "3"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(2 * time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "4"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(3 * time.Second),
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
},
|
||||
{
|
||||
ID: kubecontainer.ContainerID{Type: "test", ID: "5"},
|
||||
Name: "bar",
|
||||
CreatedAt: time.Now().Add(4 * time.Second),
|
||||
State: kubecontainer.ContainerStateRunning,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
filterID string
|
||||
expectedContainersToDelete containerStatusbyCreatedList
|
||||
}{
|
||||
{
|
||||
"abc",
|
||||
[]*kubecontainer.ContainerStatus{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
candidates := getContainersToDeleteInPod(test.filterID, &pod, len(pod.ContainerStatuses))
|
||||
if !reflect.DeepEqual(candidates, test.expectedContainersToDelete) {
|
||||
t.Errorf("expected %v got %v", test.expectedContainersToDelete, candidates)
|
||||
}
|
||||
}
|
||||
}
|
||||
355
vendor/k8s.io/kubernetes/pkg/kubelet/pod_workers_test.go
generated
vendored
355
vendor/k8s.io/kubernetes/pkg/kubelet/pod_workers_test.go
generated
vendored
|
|
@ -1,355 +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 kubelet
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/tools/record"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/queue"
|
||||
)
|
||||
|
||||
// fakePodWorkers runs sync pod function in serial, so we can have
|
||||
// deterministic behaviour in testing.
|
||||
type fakePodWorkers struct {
|
||||
syncPodFn syncPodFnType
|
||||
cache kubecontainer.Cache
|
||||
t TestingInterface
|
||||
}
|
||||
|
||||
func (f *fakePodWorkers) UpdatePod(options *UpdatePodOptions) {
|
||||
status, err := f.cache.Get(options.Pod.UID)
|
||||
if err != nil {
|
||||
f.t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if err := f.syncPodFn(syncPodOptions{
|
||||
mirrorPod: options.MirrorPod,
|
||||
pod: options.Pod,
|
||||
podStatus: status,
|
||||
updateType: options.UpdateType,
|
||||
killPodOptions: options.KillPodOptions,
|
||||
}); err != nil {
|
||||
f.t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fakePodWorkers) ForgetNonExistingPodWorkers(desiredPods map[types.UID]empty) {}
|
||||
|
||||
func (f *fakePodWorkers) ForgetWorker(uid types.UID) {}
|
||||
|
||||
type TestingInterface interface {
|
||||
Errorf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
func newPod(uid, name string) *v1.Pod {
|
||||
return &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: types.UID(uid),
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// syncPodRecord is a record of a sync pod call
|
||||
type syncPodRecord struct {
|
||||
name string
|
||||
updateType kubetypes.SyncPodType
|
||||
}
|
||||
|
||||
func createPodWorkers() (*podWorkers, map[types.UID][]syncPodRecord) {
|
||||
lock := sync.Mutex{}
|
||||
processed := make(map[types.UID][]syncPodRecord)
|
||||
fakeRecorder := &record.FakeRecorder{}
|
||||
fakeRuntime := &containertest.FakeRuntime{}
|
||||
fakeCache := containertest.NewFakeCache(fakeRuntime)
|
||||
podWorkers := newPodWorkers(
|
||||
func(options syncPodOptions) error {
|
||||
func() {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
pod := options.pod
|
||||
processed[pod.UID] = append(processed[pod.UID], syncPodRecord{
|
||||
name: pod.Name,
|
||||
updateType: options.updateType,
|
||||
})
|
||||
}()
|
||||
return nil
|
||||
},
|
||||
fakeRecorder,
|
||||
queue.NewBasicWorkQueue(&clock.RealClock{}),
|
||||
time.Second,
|
||||
time.Second,
|
||||
fakeCache,
|
||||
)
|
||||
return podWorkers, processed
|
||||
}
|
||||
|
||||
func drainWorkers(podWorkers *podWorkers, numPods int) {
|
||||
for {
|
||||
stillWorking := false
|
||||
podWorkers.podLock.Lock()
|
||||
for i := 0; i < numPods; i++ {
|
||||
if podWorkers.isWorking[types.UID(string(i))] {
|
||||
stillWorking = true
|
||||
}
|
||||
}
|
||||
podWorkers.podLock.Unlock()
|
||||
if !stillWorking {
|
||||
break
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePod(t *testing.T) {
|
||||
podWorkers, processed := createPodWorkers()
|
||||
|
||||
numPods := 20
|
||||
for i := 0; i < numPods; i++ {
|
||||
for j := i; j < numPods; j++ {
|
||||
podWorkers.UpdatePod(&UpdatePodOptions{
|
||||
Pod: newPod(string(j), string(i)),
|
||||
UpdateType: kubetypes.SyncPodCreate,
|
||||
})
|
||||
}
|
||||
}
|
||||
drainWorkers(podWorkers, numPods)
|
||||
|
||||
if len(processed) != numPods {
|
||||
t.Errorf("Not all pods processed: %v", len(processed))
|
||||
return
|
||||
}
|
||||
for i := 0; i < numPods; i++ {
|
||||
uid := types.UID(i)
|
||||
if len(processed[uid]) < 1 || len(processed[uid]) > i+1 {
|
||||
t.Errorf("Pod %v processed %v times", i, len(processed[uid]))
|
||||
continue
|
||||
}
|
||||
|
||||
// PodWorker guarantees the first and the last event will be processed
|
||||
first := 0
|
||||
last := len(processed[uid]) - 1
|
||||
if processed[uid][first].name != string(0) {
|
||||
t.Errorf("Pod %v: incorrect order %v, %v", i, first, processed[uid][first])
|
||||
|
||||
}
|
||||
if processed[uid][last].name != string(i) {
|
||||
t.Errorf("Pod %v: incorrect order %v, %v", i, last, processed[uid][last])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePodDoesNotForgetSyncPodKill(t *testing.T) {
|
||||
podWorkers, processed := createPodWorkers()
|
||||
numPods := 20
|
||||
for i := 0; i < numPods; i++ {
|
||||
pod := newPod(string(i), string(i))
|
||||
podWorkers.UpdatePod(&UpdatePodOptions{
|
||||
Pod: pod,
|
||||
UpdateType: kubetypes.SyncPodCreate,
|
||||
})
|
||||
podWorkers.UpdatePod(&UpdatePodOptions{
|
||||
Pod: pod,
|
||||
UpdateType: kubetypes.SyncPodKill,
|
||||
})
|
||||
podWorkers.UpdatePod(&UpdatePodOptions{
|
||||
Pod: pod,
|
||||
UpdateType: kubetypes.SyncPodUpdate,
|
||||
})
|
||||
}
|
||||
drainWorkers(podWorkers, numPods)
|
||||
if len(processed) != numPods {
|
||||
t.Errorf("Not all pods processed: %v", len(processed))
|
||||
return
|
||||
}
|
||||
for i := 0; i < numPods; i++ {
|
||||
uid := types.UID(i)
|
||||
// each pod should be processed two times (create, kill, but not update)
|
||||
syncPodRecords := processed[uid]
|
||||
if len(syncPodRecords) < 2 {
|
||||
t.Errorf("Pod %v processed %v times, but expected at least 2", i, len(syncPodRecords))
|
||||
continue
|
||||
}
|
||||
if syncPodRecords[0].updateType != kubetypes.SyncPodCreate {
|
||||
t.Errorf("Pod %v event was %v, but expected %v", i, syncPodRecords[0].updateType, kubetypes.SyncPodCreate)
|
||||
}
|
||||
if syncPodRecords[1].updateType != kubetypes.SyncPodKill {
|
||||
t.Errorf("Pod %v event was %v, but expected %v", i, syncPodRecords[1].updateType, kubetypes.SyncPodKill)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestForgetNonExistingPodWorkers(t *testing.T) {
|
||||
podWorkers, _ := createPodWorkers()
|
||||
|
||||
numPods := 20
|
||||
for i := 0; i < numPods; i++ {
|
||||
podWorkers.UpdatePod(&UpdatePodOptions{
|
||||
Pod: newPod(string(i), "name"),
|
||||
UpdateType: kubetypes.SyncPodUpdate,
|
||||
})
|
||||
}
|
||||
drainWorkers(podWorkers, numPods)
|
||||
|
||||
if len(podWorkers.podUpdates) != numPods {
|
||||
t.Errorf("Incorrect number of open channels %v", len(podWorkers.podUpdates))
|
||||
}
|
||||
|
||||
desiredPods := map[types.UID]empty{}
|
||||
desiredPods[types.UID(2)] = empty{}
|
||||
desiredPods[types.UID(14)] = empty{}
|
||||
podWorkers.ForgetNonExistingPodWorkers(desiredPods)
|
||||
if len(podWorkers.podUpdates) != 2 {
|
||||
t.Errorf("Incorrect number of open channels %v", len(podWorkers.podUpdates))
|
||||
}
|
||||
if _, exists := podWorkers.podUpdates[types.UID(2)]; !exists {
|
||||
t.Errorf("No updates channel for pod 2")
|
||||
}
|
||||
if _, exists := podWorkers.podUpdates[types.UID(14)]; !exists {
|
||||
t.Errorf("No updates channel for pod 14")
|
||||
}
|
||||
|
||||
podWorkers.ForgetNonExistingPodWorkers(map[types.UID]empty{})
|
||||
if len(podWorkers.podUpdates) != 0 {
|
||||
t.Errorf("Incorrect number of open channels %v", len(podWorkers.podUpdates))
|
||||
}
|
||||
}
|
||||
|
||||
type simpleFakeKubelet struct {
|
||||
pod *v1.Pod
|
||||
mirrorPod *v1.Pod
|
||||
podStatus *kubecontainer.PodStatus
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func (kl *simpleFakeKubelet) syncPod(options syncPodOptions) error {
|
||||
kl.pod, kl.mirrorPod, kl.podStatus = options.pod, options.mirrorPod, options.podStatus
|
||||
return nil
|
||||
}
|
||||
|
||||
func (kl *simpleFakeKubelet) syncPodWithWaitGroup(options syncPodOptions) error {
|
||||
kl.pod, kl.mirrorPod, kl.podStatus = options.pod, options.mirrorPod, options.podStatus
|
||||
kl.wg.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
// byContainerName sort the containers in a running pod by their names.
|
||||
type byContainerName kubecontainer.Pod
|
||||
|
||||
func (b byContainerName) Len() int { return len(b.Containers) }
|
||||
|
||||
func (b byContainerName) Swap(i, j int) {
|
||||
b.Containers[i], b.Containers[j] = b.Containers[j], b.Containers[i]
|
||||
}
|
||||
|
||||
func (b byContainerName) Less(i, j int) bool {
|
||||
return b.Containers[i].Name < b.Containers[j].Name
|
||||
}
|
||||
|
||||
// TestFakePodWorkers verifies that the fakePodWorkers behaves the same way as the real podWorkers
|
||||
// for their invocation of the syncPodFn.
|
||||
func TestFakePodWorkers(t *testing.T) {
|
||||
fakeRecorder := &record.FakeRecorder{}
|
||||
fakeRuntime := &containertest.FakeRuntime{}
|
||||
fakeCache := containertest.NewFakeCache(fakeRuntime)
|
||||
|
||||
kubeletForRealWorkers := &simpleFakeKubelet{}
|
||||
kubeletForFakeWorkers := &simpleFakeKubelet{}
|
||||
|
||||
realPodWorkers := newPodWorkers(kubeletForRealWorkers.syncPodWithWaitGroup, fakeRecorder, queue.NewBasicWorkQueue(&clock.RealClock{}), time.Second, time.Second, fakeCache)
|
||||
fakePodWorkers := &fakePodWorkers{kubeletForFakeWorkers.syncPod, fakeCache, t}
|
||||
|
||||
tests := []struct {
|
||||
pod *v1.Pod
|
||||
mirrorPod *v1.Pod
|
||||
}{
|
||||
{
|
||||
&v1.Pod{},
|
||||
&v1.Pod{},
|
||||
},
|
||||
{
|
||||
podWithUIDNameNs("12345678", "foo", "new"),
|
||||
podWithUIDNameNs("12345678", "fooMirror", "new"),
|
||||
},
|
||||
{
|
||||
podWithUIDNameNs("98765", "bar", "new"),
|
||||
podWithUIDNameNs("98765", "barMirror", "new"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
kubeletForRealWorkers.wg.Add(1)
|
||||
realPodWorkers.UpdatePod(&UpdatePodOptions{
|
||||
Pod: tt.pod,
|
||||
MirrorPod: tt.mirrorPod,
|
||||
UpdateType: kubetypes.SyncPodUpdate,
|
||||
})
|
||||
fakePodWorkers.UpdatePod(&UpdatePodOptions{
|
||||
Pod: tt.pod,
|
||||
MirrorPod: tt.mirrorPod,
|
||||
UpdateType: kubetypes.SyncPodUpdate,
|
||||
})
|
||||
|
||||
kubeletForRealWorkers.wg.Wait()
|
||||
|
||||
if !reflect.DeepEqual(kubeletForRealWorkers.pod, kubeletForFakeWorkers.pod) {
|
||||
t.Errorf("%d: Expected: %#v, Actual: %#v", i, kubeletForRealWorkers.pod, kubeletForFakeWorkers.pod)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(kubeletForRealWorkers.mirrorPod, kubeletForFakeWorkers.mirrorPod) {
|
||||
t.Errorf("%d: Expected: %#v, Actual: %#v", i, kubeletForRealWorkers.mirrorPod, kubeletForFakeWorkers.mirrorPod)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(kubeletForRealWorkers.podStatus, kubeletForFakeWorkers.podStatus) {
|
||||
t.Errorf("%d: Expected: %#v, Actual: %#v", i, kubeletForRealWorkers.podStatus, kubeletForFakeWorkers.podStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestKillPodNowFunc tests the blocking kill pod function works with pod workers as expected.
|
||||
func TestKillPodNowFunc(t *testing.T) {
|
||||
fakeRecorder := &record.FakeRecorder{}
|
||||
podWorkers, processed := createPodWorkers()
|
||||
killPodFunc := killPodNow(podWorkers, fakeRecorder)
|
||||
pod := newPod("test", "test")
|
||||
gracePeriodOverride := int64(0)
|
||||
err := killPodFunc(pod, v1.PodStatus{Phase: v1.PodFailed, Reason: "reason", Message: "message"}, &gracePeriodOverride)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if len(processed) != 1 {
|
||||
t.Errorf("len(processed) expected: %v, actual: %v", 1, len(processed))
|
||||
return
|
||||
}
|
||||
syncPodRecords := processed[pod.UID]
|
||||
if len(syncPodRecords) != 1 {
|
||||
t.Errorf("Pod processed %v times, but expected %v", len(syncPodRecords), 1)
|
||||
}
|
||||
if syncPodRecords[0].updateType != kubetypes.SyncPodKill {
|
||||
t.Errorf("Pod update type was %v, but expected %v", syncPodRecords[0].updateType, kubetypes.SyncPodKill)
|
||||
}
|
||||
}
|
||||
69
vendor/k8s.io/kubernetes/pkg/kubelet/reason_cache_test.go
generated
vendored
69
vendor/k8s.io/kubernetes/pkg/kubelet/reason_cache_test.go
generated
vendored
|
|
@ -1,69 +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 kubelet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
)
|
||||
|
||||
func TestReasonCache(t *testing.T) {
|
||||
// Create test sync result
|
||||
syncResult := kubecontainer.PodSyncResult{}
|
||||
results := []*kubecontainer.SyncResult{
|
||||
// reason cache should be set for SyncResult with StartContainer action and error
|
||||
kubecontainer.NewSyncResult(kubecontainer.StartContainer, "container_1"),
|
||||
// reason cache should not be set for SyncResult with StartContainer action but without error
|
||||
kubecontainer.NewSyncResult(kubecontainer.StartContainer, "container_2"),
|
||||
// reason cache should not be set for SyncResult with other actions
|
||||
kubecontainer.NewSyncResult(kubecontainer.KillContainer, "container_3"),
|
||||
}
|
||||
results[0].Fail(kubecontainer.ErrRunContainer, "message_1")
|
||||
results[2].Fail(kubecontainer.ErrKillContainer, "message_3")
|
||||
syncResult.AddSyncResult(results...)
|
||||
uid := types.UID("pod_1")
|
||||
|
||||
reasonCache := NewReasonCache()
|
||||
reasonCache.Update(uid, syncResult)
|
||||
assertReasonInfo(t, reasonCache, uid, results[0], true)
|
||||
assertReasonInfo(t, reasonCache, uid, results[1], false)
|
||||
assertReasonInfo(t, reasonCache, uid, results[2], false)
|
||||
|
||||
reasonCache.Remove(uid, results[0].Target.(string))
|
||||
assertReasonInfo(t, reasonCache, uid, results[0], false)
|
||||
}
|
||||
|
||||
func assertReasonInfo(t *testing.T, cache *ReasonCache, uid types.UID, result *kubecontainer.SyncResult, found bool) {
|
||||
name := result.Target.(string)
|
||||
actualReason, ok := cache.Get(uid, name)
|
||||
if ok && !found {
|
||||
t.Fatalf("unexpected cache hit: %v, %q", actualReason.Err, actualReason.Message)
|
||||
}
|
||||
if !ok && found {
|
||||
t.Fatalf("corresponding reason info not found")
|
||||
}
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
reason := result.Error
|
||||
message := result.Message
|
||||
if actualReason.Err != reason || actualReason.Message != message {
|
||||
t.Errorf("expected %v %q, got %v %q", reason, message, actualReason.Err, actualReason.Message)
|
||||
}
|
||||
}
|
||||
175
vendor/k8s.io/kubernetes/pkg/kubelet/runonce_test.go
generated
vendored
175
vendor/k8s.io/kubernetes/pkg/kubelet/runonce_test.go
generated
vendored
|
|
@ -1,175 +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 kubelet
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
cadvisorapi "github.com/google/cadvisor/info/v1"
|
||||
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/record"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
||||
cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||
"k8s.io/kubernetes/pkg/kubelet/eviction"
|
||||
"k8s.io/kubernetes/pkg/kubelet/network"
|
||||
nettest "k8s.io/kubernetes/pkg/kubelet/network/testing"
|
||||
kubepod "k8s.io/kubernetes/pkg/kubelet/pod"
|
||||
podtest "k8s.io/kubernetes/pkg/kubelet/pod/testing"
|
||||
"k8s.io/kubernetes/pkg/kubelet/secret"
|
||||
"k8s.io/kubernetes/pkg/kubelet/server/stats"
|
||||
"k8s.io/kubernetes/pkg/kubelet/status"
|
||||
statustest "k8s.io/kubernetes/pkg/kubelet/status/testing"
|
||||
"k8s.io/kubernetes/pkg/kubelet/volumemanager"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||
)
|
||||
|
||||
func TestRunOnce(t *testing.T) {
|
||||
cadvisor := &cadvisortest.Mock{}
|
||||
cadvisor.On("MachineInfo").Return(&cadvisorapi.MachineInfo{}, nil)
|
||||
cadvisor.On("ImagesFsInfo").Return(cadvisorapiv2.FsInfo{
|
||||
Usage: 400,
|
||||
Capacity: 1000,
|
||||
Available: 600,
|
||||
}, nil)
|
||||
cadvisor.On("RootFsInfo").Return(cadvisorapiv2.FsInfo{
|
||||
Usage: 9,
|
||||
Capacity: 10,
|
||||
}, nil)
|
||||
fakeSecretManager := secret.NewFakeManager()
|
||||
fakeConfigMapManager := configmap.NewFakeManager()
|
||||
podManager := kubepod.NewBasicPodManager(
|
||||
podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager)
|
||||
fakeRuntime := &containertest.FakeRuntime{}
|
||||
basePath, err := utiltesting.MkTmpdir("kubelet")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp rootdir %v", err)
|
||||
}
|
||||
defer os.RemoveAll(basePath)
|
||||
kb := &Kubelet{
|
||||
rootDirectory: basePath,
|
||||
recorder: &record.FakeRecorder{},
|
||||
cadvisor: cadvisor,
|
||||
nodeInfo: testNodeInfo{},
|
||||
statusManager: status.NewManager(nil, podManager, &statustest.FakePodDeletionSafetyProvider{}),
|
||||
podManager: podManager,
|
||||
os: &containertest.FakeOS{},
|
||||
containerRuntime: fakeRuntime,
|
||||
reasonCache: NewReasonCache(),
|
||||
clock: clock.RealClock{},
|
||||
kubeClient: &fake.Clientset{},
|
||||
hostname: testKubeletHostname,
|
||||
nodeName: testKubeletHostname,
|
||||
runtimeState: newRuntimeState(time.Second),
|
||||
}
|
||||
kb.containerManager = cm.NewStubContainerManager()
|
||||
|
||||
plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil}
|
||||
kb.volumePluginMgr, err =
|
||||
NewInitializedVolumePluginMgr(kb, fakeSecretManager, fakeConfigMapManager, []volume.VolumePlugin{plug}, nil /* prober */)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to initialize VolumePluginMgr: %v", err)
|
||||
}
|
||||
kb.volumeManager = volumemanager.NewVolumeManager(
|
||||
true,
|
||||
kb.nodeName,
|
||||
kb.podManager,
|
||||
kb.statusManager,
|
||||
kb.kubeClient,
|
||||
kb.volumePluginMgr,
|
||||
fakeRuntime,
|
||||
kb.mounter,
|
||||
kb.getPodsDir(),
|
||||
kb.recorder,
|
||||
false, /* experimentalCheckNodeCapabilitiesBeforeMount */
|
||||
false /* keepTerminatedPodVolumes */)
|
||||
|
||||
kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", nettest.NewFakeHost(nil), kubeletconfig.HairpinNone, "", network.UseDefaultMTU)
|
||||
// TODO: Factor out "StatsProvider" from Kubelet so we don't have a cyclic dependency
|
||||
volumeStatsAggPeriod := time.Second * 10
|
||||
kb.resourceAnalyzer = stats.NewResourceAnalyzer(kb, volumeStatsAggPeriod)
|
||||
nodeRef := &v1.ObjectReference{
|
||||
Kind: "Node",
|
||||
Name: string(kb.nodeName),
|
||||
UID: types.UID(kb.nodeName),
|
||||
Namespace: "",
|
||||
}
|
||||
fakeKillPodFunc := func(pod *v1.Pod, podStatus v1.PodStatus, gracePeriodOverride *int64) error {
|
||||
return nil
|
||||
}
|
||||
evictionManager, evictionAdmitHandler := eviction.NewManager(kb.resourceAnalyzer, eviction.Config{}, fakeKillPodFunc, nil, nil, kb.recorder, nodeRef, kb.clock)
|
||||
|
||||
kb.evictionManager = evictionManager
|
||||
kb.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
|
||||
kb.mounter = &mount.FakeMounter{}
|
||||
if err := kb.setupDataDirs(); err != nil {
|
||||
t.Errorf("Failed to init data dirs: %v", err)
|
||||
}
|
||||
|
||||
pods := []*v1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: "12345678",
|
||||
Name: "foo",
|
||||
Namespace: "new",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{Name: "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
podManager.SetPods(pods)
|
||||
// The original test here is totally meaningless, because fakeruntime will always return an empty podStatus. While
|
||||
// the original logic of isPodRunning happens to return true when podstatus is empty, so the test can always pass.
|
||||
// Now the logic in isPodRunning is changed, to let the test pass, we set the podstatus directly in fake runtime.
|
||||
// This is also a meaningless test, because the isPodRunning will also always return true after setting this. However,
|
||||
// because runonce is never used in kubernetes now, we should deprioritize the cleanup work.
|
||||
// TODO(random-liu) Fix the test, make it meaningful.
|
||||
fakeRuntime.PodStatus = kubecontainer.PodStatus{
|
||||
ContainerStatuses: []*kubecontainer.ContainerStatus{
|
||||
{
|
||||
Name: "bar",
|
||||
State: kubecontainer.ContainerStateRunning,
|
||||
},
|
||||
},
|
||||
}
|
||||
results, err := kb.runOnce(pods, time.Millisecond)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if results[0].Err != nil {
|
||||
t.Errorf("unexpected run pod error: %v", results[0].Err)
|
||||
}
|
||||
if results[0].Pod.Name != "foo" {
|
||||
t.Errorf("unexpected pod: %q", results[0].Pod.Name)
|
||||
}
|
||||
}
|
||||
119
vendor/k8s.io/kubernetes/pkg/kubelet/types/labels_test.go
generated
vendored
119
vendor/k8s.io/kubernetes/pkg/kubelet/types/labels_test.go
generated
vendored
|
|
@ -1,119 +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 types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetContainerName(t *testing.T) {
|
||||
var cases = []struct {
|
||||
labels map[string]string
|
||||
containerName string
|
||||
}{
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.container.name": "c1",
|
||||
},
|
||||
containerName: "c1",
|
||||
},
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.container.name": "c2",
|
||||
},
|
||||
containerName: "c2",
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
containerName := GetContainerName(data.labels)
|
||||
assert.Equal(t, data.containerName, containerName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPodName(t *testing.T) {
|
||||
var cases = []struct {
|
||||
labels map[string]string
|
||||
podName string
|
||||
}{
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.pod.name": "p1",
|
||||
},
|
||||
podName: "p1",
|
||||
},
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.pod.name": "p2",
|
||||
},
|
||||
podName: "p2",
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
podName := GetPodName(data.labels)
|
||||
assert.Equal(t, data.podName, podName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPodUID(t *testing.T) {
|
||||
var cases = []struct {
|
||||
labels map[string]string
|
||||
podUID string
|
||||
}{
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.pod.uid": "uid1",
|
||||
},
|
||||
podUID: "uid1",
|
||||
},
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.pod.uid": "uid2",
|
||||
},
|
||||
podUID: "uid2",
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
podUID := GetPodUID(data.labels)
|
||||
assert.Equal(t, data.podUID, podUID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPodNamespace(t *testing.T) {
|
||||
var cases = []struct {
|
||||
labels map[string]string
|
||||
podNamespace string
|
||||
}{
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.pod.namespace": "ns1",
|
||||
},
|
||||
podNamespace: "ns1",
|
||||
},
|
||||
{
|
||||
labels: map[string]string{
|
||||
"io.kubernetes.pod.namespace": "ns2",
|
||||
},
|
||||
podNamespace: "ns2",
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
podNamespace := GetPodNamespace(data.labels)
|
||||
assert.Equal(t, data.podNamespace, podNamespace)
|
||||
}
|
||||
}
|
||||
178
vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update_test.go
generated
vendored
178
vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update_test.go
generated
vendored
|
|
@ -1,178 +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 types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestGetValidatedSources(t *testing.T) {
|
||||
// Empty.
|
||||
sources, err := GetValidatedSources([]string{""})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, sources, 0)
|
||||
|
||||
// Success.
|
||||
sources, err = GetValidatedSources([]string{FileSource, ApiserverSource})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, sources, 2)
|
||||
|
||||
// All.
|
||||
sources, err = GetValidatedSources([]string{AllSource})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, sources, 3)
|
||||
|
||||
// Unknown source.
|
||||
sources, err = GetValidatedSources([]string{"taco"})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestGetPodSource(t *testing.T) {
|
||||
cases := []struct {
|
||||
pod v1.Pod
|
||||
expected string
|
||||
errExpected bool
|
||||
}{
|
||||
{
|
||||
pod: v1.Pod{},
|
||||
expected: "",
|
||||
errExpected: true,
|
||||
},
|
||||
{
|
||||
pod: v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Annotations: map[string]string{
|
||||
"kubernetes.io/config.source": "host-ipc-sources",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "host-ipc-sources",
|
||||
errExpected: false,
|
||||
},
|
||||
}
|
||||
for i, data := range cases {
|
||||
source, err := GetPodSource(&data.pod)
|
||||
if data.errExpected {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, data.expected, source, "test[%d]", i)
|
||||
t.Logf("Test case [%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
cases := []struct {
|
||||
sp SyncPodType
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
sp: SyncPodCreate,
|
||||
expected: "create",
|
||||
},
|
||||
{
|
||||
sp: SyncPodUpdate,
|
||||
expected: "update",
|
||||
},
|
||||
{
|
||||
sp: SyncPodSync,
|
||||
expected: "sync",
|
||||
},
|
||||
{
|
||||
sp: SyncPodKill,
|
||||
expected: "kill",
|
||||
},
|
||||
{
|
||||
sp: 50,
|
||||
expected: "unknown",
|
||||
},
|
||||
}
|
||||
for i, data := range cases {
|
||||
syncPodString := data.sp.String()
|
||||
assert.Equal(t, data.expected, syncPodString, "test[%d]", i)
|
||||
t.Logf("Test case [%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsCriticalPod(t *testing.T) {
|
||||
cases := []struct {
|
||||
pod v1.Pod
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
pod: v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
Namespace: "ns",
|
||||
Annotations: map[string]string{
|
||||
"scheduler.alpha.kubernetes.io/critical-pod": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
pod: v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod2",
|
||||
Namespace: "ns",
|
||||
Annotations: map[string]string{
|
||||
"scheduler.alpha.kubernetes.io/critical-pod": "abc",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
pod: v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod3",
|
||||
Namespace: "kube-system",
|
||||
Annotations: map[string]string{
|
||||
"scheduler.alpha.kubernetes.io/critical-pod": "abc",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
pod: v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod4",
|
||||
Namespace: "kube-system",
|
||||
Annotations: map[string]string{
|
||||
"scheduler.alpha.kubernetes.io/critical-pod": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for i, data := range cases {
|
||||
actual := IsCriticalPod(&data.pod)
|
||||
if actual != data.expected {
|
||||
t.Errorf("IsCriticalPod result wrong:\nexpected: %v\nactual: %v for test[%d] with Annotations: %v",
|
||||
data.expected, actual, i, data.pod.Annotations)
|
||||
}
|
||||
}
|
||||
}
|
||||
138
vendor/k8s.io/kubernetes/pkg/kubelet/types/types_test.go
generated
vendored
138
vendor/k8s.io/kubernetes/pkg/kubelet/types/types_test.go
generated
vendored
|
|
@ -1,138 +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 types
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func TestConvertToTimestamp(t *testing.T) {
|
||||
timestamp := "2017-02-17T15:34:49.830882016+08:00"
|
||||
convertedTimeStamp := ConvertToTimestamp(timestamp).GetString()
|
||||
assert.Equal(t, timestamp, convertedTimeStamp)
|
||||
}
|
||||
|
||||
func TestLen(t *testing.T) {
|
||||
var cases = []struct {
|
||||
statuses SortedContainerStatuses
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
statuses: SortedContainerStatuses{{Name: "first"}},
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
statuses: SortedContainerStatuses{{Name: "first"}, {Name: "second"}},
|
||||
expected: 2,
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
assert.Equal(t, data.expected, data.statuses.Len())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSwap(t *testing.T) {
|
||||
var cases = []struct {
|
||||
statuses SortedContainerStatuses
|
||||
expected SortedContainerStatuses
|
||||
}{
|
||||
{
|
||||
statuses: SortedContainerStatuses{{Name: "first"}, {Name: "second"}},
|
||||
expected: SortedContainerStatuses{{Name: "second"}, {Name: "first"}},
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
data.statuses.Swap(0, 1)
|
||||
if !reflect.DeepEqual(data.statuses, data.expected) {
|
||||
t.Errorf(
|
||||
"failed Swap:\n\texpected: %v\n\t actual: %v",
|
||||
data.expected,
|
||||
data.statuses,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLess(t *testing.T) {
|
||||
var cases = []struct {
|
||||
statuses SortedContainerStatuses
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
statuses: SortedContainerStatuses{{Name: "first"}, {Name: "second"}},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
statuses: SortedContainerStatuses{{Name: "second"}, {Name: "first"}},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
actual := data.statuses.Less(0, 1)
|
||||
if actual != data.expected {
|
||||
t.Errorf(
|
||||
"failed Less:\n\texpected: %t\n\t actual: %t",
|
||||
data.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortInitContainerStatuses(t *testing.T) {
|
||||
pod := v1.Pod{
|
||||
Spec: v1.PodSpec{},
|
||||
}
|
||||
var cases = []struct {
|
||||
containers []v1.Container
|
||||
statuses []v1.ContainerStatus
|
||||
sortedStatuses []v1.ContainerStatus
|
||||
}{
|
||||
{
|
||||
containers: []v1.Container{{Name: "first"}, {Name: "second"}, {Name: "third"}, {Name: "fourth"}},
|
||||
statuses: []v1.ContainerStatus{{Name: "first"}, {Name: "second"}, {Name: "third"}, {Name: "fourth"}},
|
||||
sortedStatuses: []v1.ContainerStatus{{Name: "first"}, {Name: "second"}, {Name: "third"}, {Name: "fourth"}},
|
||||
},
|
||||
{
|
||||
containers: []v1.Container{{Name: "first"}, {Name: "second"}, {Name: "third"}, {Name: "fourth"}},
|
||||
statuses: []v1.ContainerStatus{{Name: "second"}, {Name: "first"}, {Name: "fourth"}, {Name: "third"}},
|
||||
sortedStatuses: []v1.ContainerStatus{{Name: "first"}, {Name: "second"}, {Name: "third"}, {Name: "fourth"}},
|
||||
},
|
||||
{
|
||||
containers: []v1.Container{{Name: "first"}, {Name: "second"}, {Name: "third"}, {Name: "fourth"}},
|
||||
statuses: []v1.ContainerStatus{{Name: "fourth"}, {Name: "first"}},
|
||||
sortedStatuses: []v1.ContainerStatus{{Name: "first"}, {Name: "fourth"}},
|
||||
},
|
||||
{
|
||||
containers: []v1.Container{{Name: "first"}, {Name: "second"}, {Name: "third"}, {Name: "fourth"}},
|
||||
statuses: []v1.ContainerStatus{{Name: "first"}, {Name: "third"}},
|
||||
sortedStatuses: []v1.ContainerStatus{{Name: "first"}, {Name: "third"}},
|
||||
},
|
||||
}
|
||||
for _, data := range cases {
|
||||
pod.Spec.InitContainers = data.containers
|
||||
SortInitContainerStatuses(&pod, data.statuses)
|
||||
if !reflect.DeepEqual(data.statuses, data.sortedStatuses) {
|
||||
t.Errorf("SortInitContainerStatuses result wrong:\nContainers order: %v\nExpected order: %v\nReturne order: %v",
|
||||
data.containers, data.sortedStatuses, data.statuses)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
vendor/k8s.io/kubernetes/pkg/kubelet/util/format/resources_test.go
generated
vendored
35
vendor/k8s.io/kubernetes/pkg/kubelet/util/format/resources_test.go
generated
vendored
|
|
@ -1,35 +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 format
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
)
|
||||
|
||||
func TestResourceList(t *testing.T) {
|
||||
resourceList := v1.ResourceList{}
|
||||
resourceList[v1.ResourceCPU] = resource.MustParse("100m")
|
||||
resourceList[v1.ResourceMemory] = resource.MustParse("5Gi")
|
||||
actual := ResourceList(resourceList)
|
||||
expected := "cpu=100m,memory=5Gi"
|
||||
if actual != expected {
|
||||
t.Errorf("Unexpected result, actual: %v, expected: %v", actual, expected)
|
||||
}
|
||||
}
|
||||
222
vendor/k8s.io/kubernetes/pkg/kubelet/util/sliceutils/sliceutils_test.go
generated
vendored
222
vendor/k8s.io/kubernetes/pkg/kubelet/util/sliceutils/sliceutils_test.go
generated
vendored
|
|
@ -1,222 +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 sliceutils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestStringInSlice(t *testing.T) {
|
||||
fooTests := []struct {
|
||||
s string
|
||||
list []string
|
||||
er bool
|
||||
}{
|
||||
{"first", []string{"first", "second"}, true},
|
||||
{"FIRST", []string{"first", "second"}, false},
|
||||
{"third", []string{"first", "second"}, false},
|
||||
{"first", nil, false},
|
||||
|
||||
{"", []string{"first", "second"}, false},
|
||||
{"", []string{"first", "second", ""}, true},
|
||||
{"", nil, false},
|
||||
}
|
||||
|
||||
for _, fooTest := range fooTests {
|
||||
r := StringInSlice(fooTest.s, fooTest.list)
|
||||
if r != fooTest.er {
|
||||
t.Errorf("returned %t but expected %t for s=%s & list=%s", r, fooTest.er, fooTest.s, fooTest.list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func buildPodsByCreationTime() PodsByCreationTime {
|
||||
return []*v1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo1",
|
||||
Namespace: v1.NamespaceDefault,
|
||||
CreationTimestamp: metav1.Time{
|
||||
Time: time.Now(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo2",
|
||||
Namespace: v1.NamespaceDefault,
|
||||
CreationTimestamp: metav1.Time{
|
||||
Time: time.Now().Add(time.Hour * 1),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo3",
|
||||
Namespace: v1.NamespaceDefault,
|
||||
CreationTimestamp: metav1.Time{
|
||||
Time: time.Now().Add(time.Hour * 2),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodsByCreationTimeLen(t *testing.T) {
|
||||
fooTests := []struct {
|
||||
pods PodsByCreationTime
|
||||
el int
|
||||
}{
|
||||
{[]*v1.Pod{}, 0},
|
||||
{buildPodsByCreationTime(), 3},
|
||||
{[]*v1.Pod{nil, {}}, 2},
|
||||
{nil, 0},
|
||||
}
|
||||
|
||||
for _, fooTest := range fooTests {
|
||||
r := fooTest.pods.Len()
|
||||
if r != fooTest.el {
|
||||
t.Errorf("returned %d but expected %d for the len of PodsByCreationTime=%s", r, fooTest.el, fooTest.pods)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodsByCreationTimeSwap(t *testing.T) {
|
||||
fooTests := []struct {
|
||||
pods PodsByCreationTime
|
||||
i int
|
||||
j int
|
||||
}{
|
||||
{buildPodsByCreationTime(), 0, 1},
|
||||
{buildPodsByCreationTime(), 2, 1},
|
||||
}
|
||||
|
||||
for _, fooTest := range fooTests {
|
||||
fooi := fooTest.pods[fooTest.i]
|
||||
fooj := fooTest.pods[fooTest.j]
|
||||
fooTest.pods.Swap(fooTest.i, fooTest.j)
|
||||
if fooi.GetName() != fooTest.pods[fooTest.j].GetName() || fooj.GetName() != fooTest.pods[fooTest.i].GetName() {
|
||||
t.Errorf("failed to swap for %v", fooTest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodsByCreationTimeLess(t *testing.T) {
|
||||
fooTests := []struct {
|
||||
pods PodsByCreationTime
|
||||
i int
|
||||
j int
|
||||
er bool
|
||||
}{
|
||||
// ascending order
|
||||
{buildPodsByCreationTime(), 0, 2, true},
|
||||
{buildPodsByCreationTime(), 1, 0, false},
|
||||
}
|
||||
|
||||
for _, fooTest := range fooTests {
|
||||
r := fooTest.pods.Less(fooTest.i, fooTest.j)
|
||||
if r != fooTest.er {
|
||||
t.Errorf("returned %t but expected %t for the foo=%s", r, fooTest.er, fooTest.pods)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func buildByImageSize() ByImageSize {
|
||||
return []kubecontainer.Image{
|
||||
{
|
||||
ID: "1",
|
||||
RepoTags: []string{"foo-tag11", "foo-tag12"},
|
||||
RepoDigests: []string{"foo-rd11", "foo-rd12"},
|
||||
Size: 1,
|
||||
},
|
||||
{
|
||||
ID: "2",
|
||||
RepoTags: []string{"foo-tag21", "foo-tag22"},
|
||||
RepoDigests: []string{"foo-rd21", "foo-rd22"},
|
||||
Size: 2,
|
||||
},
|
||||
{
|
||||
ID: "3",
|
||||
RepoTags: []string{"foo-tag31", "foo-tag32"},
|
||||
RepoDigests: []string{"foo-rd31", "foo-rd32"},
|
||||
Size: 3,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestByImageSizeLen(t *testing.T) {
|
||||
fooTests := []struct {
|
||||
images ByImageSize
|
||||
el int
|
||||
}{
|
||||
{[]kubecontainer.Image{}, 0},
|
||||
{buildByImageSize(), 3},
|
||||
{nil, 0},
|
||||
}
|
||||
|
||||
for _, fooTest := range fooTests {
|
||||
r := fooTest.images.Len()
|
||||
if r != fooTest.el {
|
||||
t.Errorf("returned %d but expected %d for the len of ByImageSize=%v", r, fooTest.el, fooTest.images)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestByImageSizeSwap(t *testing.T) {
|
||||
fooTests := []struct {
|
||||
images ByImageSize
|
||||
i int
|
||||
j int
|
||||
}{
|
||||
{buildByImageSize(), 0, 1},
|
||||
{buildByImageSize(), 2, 1},
|
||||
}
|
||||
|
||||
for _, fooTest := range fooTests {
|
||||
fooi := fooTest.images[fooTest.i]
|
||||
fooj := fooTest.images[fooTest.j]
|
||||
fooTest.images.Swap(fooTest.i, fooTest.j)
|
||||
if fooi.ID != fooTest.images[fooTest.j].ID || fooj.ID != fooTest.images[fooTest.i].ID {
|
||||
t.Errorf("failed to swap for %v", fooTest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestByImageSizeLess(t *testing.T) {
|
||||
fooTests := []struct {
|
||||
images ByImageSize
|
||||
i int
|
||||
j int
|
||||
er bool
|
||||
}{
|
||||
// descending order
|
||||
{buildByImageSize(), 0, 2, false},
|
||||
{buildByImageSize(), 1, 0, true},
|
||||
}
|
||||
|
||||
for _, fooTest := range fooTests {
|
||||
r := fooTest.images.Less(fooTest.i, fooTest.j)
|
||||
if r != fooTest.er {
|
||||
t.Errorf("returned %t but expected %t for the foo=%v", r, fooTest.er, fooTest.images)
|
||||
}
|
||||
}
|
||||
}
|
||||
64
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_test.go
generated
vendored
64
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_test.go
generated
vendored
|
|
@ -1,64 +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 util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseEndpoint(t *testing.T) {
|
||||
tests := []struct {
|
||||
endpoint string
|
||||
expectError bool
|
||||
expectedProtocol string
|
||||
expectedAddr string
|
||||
}{
|
||||
{
|
||||
endpoint: "unix:///tmp/s1.sock",
|
||||
expectedProtocol: "unix",
|
||||
expectedAddr: "/tmp/s1.sock",
|
||||
},
|
||||
{
|
||||
endpoint: "tcp://localhost:15880",
|
||||
expectedProtocol: "tcp",
|
||||
expectedAddr: "localhost:15880",
|
||||
},
|
||||
{
|
||||
endpoint: "tcp1://abc",
|
||||
expectedProtocol: "tcp1",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
endpoint: "a b c",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
protocol, addr, err := parseEndpoint(test.endpoint)
|
||||
assert.Equal(t, test.expectedProtocol, protocol)
|
||||
if test.expectError {
|
||||
assert.NotNil(t, err, "Expect error during parsing %q", test.endpoint)
|
||||
continue
|
||||
}
|
||||
assert.Nil(t, err, "Expect no error during parsing %q", test.endpoint)
|
||||
assert.Equal(t, test.expectedAddr, addr)
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue