2014-06-06 23:40:48 +00:00
|
|
|
/*
|
|
|
|
Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
2014-06-23 18:32:11 +00:00
|
|
|
|
2014-06-06 23:40:48 +00:00
|
|
|
package kubelet
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2014-11-23 15:47:25 +00:00
|
|
|
"io/ioutil"
|
2014-09-03 20:39:56 +00:00
|
|
|
"net/http"
|
2014-11-29 19:02:28 +00:00
|
|
|
"os"
|
|
|
|
"path"
|
2014-06-09 20:47:25 +00:00
|
|
|
"reflect"
|
2014-08-07 23:59:18 +00:00
|
|
|
"regexp"
|
|
|
|
"strconv"
|
2014-10-02 18:58:58 +00:00
|
|
|
"strings"
|
2014-06-06 23:40:48 +00:00
|
|
|
"sync"
|
|
|
|
"testing"
|
2014-08-08 04:49:17 +00:00
|
|
|
"time"
|
2014-06-06 23:40:48 +00:00
|
|
|
|
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
2014-09-09 04:33:17 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
2014-11-23 15:47:25 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
|
|
|
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/host_path"
|
2015-01-14 23:22:21 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
|
2014-09-03 20:39:56 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
2014-06-06 23:40:48 +00:00
|
|
|
"github.com/fsouza/go-dockerclient"
|
2014-06-19 20:22:20 +00:00
|
|
|
"github.com/google/cadvisor/info"
|
|
|
|
"github.com/stretchr/testify/mock"
|
2014-06-06 23:40:48 +00:00
|
|
|
)
|
|
|
|
|
2014-12-10 01:53:29 +00:00
|
|
|
func init() {
|
|
|
|
api.ForTesting_ReferencesAllowBlankSelfLinks = true
|
|
|
|
util.ReallyCrash = true
|
|
|
|
}
|
|
|
|
|
2015-01-15 21:52:27 +00:00
|
|
|
func newTestKubelet(t *testing.T) (*Kubelet, *dockertools.FakeDockerClient) {
|
2014-12-22 19:54:07 +00:00
|
|
|
fakeDocker := &dockertools.FakeDockerClient{
|
|
|
|
RemovedImages: util.StringSet{},
|
|
|
|
}
|
2014-07-01 16:15:49 +00:00
|
|
|
|
2014-07-22 21:40:59 +00:00
|
|
|
kubelet := &Kubelet{}
|
|
|
|
kubelet.dockerClient = fakeDocker
|
2014-09-09 04:33:17 +00:00
|
|
|
kubelet.dockerPuller = &dockertools.FakeDockerPuller{}
|
2014-11-23 15:47:25 +00:00
|
|
|
if tempDir, err := ioutil.TempDir("/tmp", "kubelet_test."); err != nil {
|
|
|
|
t.Fatalf("can't make a temp rootdir: %v", err)
|
|
|
|
} else {
|
|
|
|
kubelet.rootDirectory = tempDir
|
|
|
|
}
|
|
|
|
if err := os.MkdirAll(kubelet.rootDirectory, 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %v", kubelet.rootDirectory, err)
|
|
|
|
}
|
2014-07-18 18:42:47 +00:00
|
|
|
kubelet.podWorkers = newPodWorkers()
|
2015-01-13 05:47:49 +00:00
|
|
|
kubelet.sourceReady = func(source string) bool { return true }
|
2014-11-21 21:14:30 +00:00
|
|
|
kubelet.masterServiceNamespace = api.NamespaceDefault
|
|
|
|
kubelet.serviceLister = testServiceLister{}
|
2015-02-02 18:51:52 +00:00
|
|
|
kubelet.readiness = newReadinessStates()
|
2014-11-23 15:47:25 +00:00
|
|
|
if err := kubelet.setupDataDirs(); err != nil {
|
|
|
|
t.Fatalf("can't initialize kubelet data dirs: %v", err)
|
|
|
|
}
|
2015-01-08 15:25:14 +00:00
|
|
|
|
2015-01-15 21:52:27 +00:00
|
|
|
return kubelet, fakeDocker
|
2014-06-24 23:31:33 +00:00
|
|
|
}
|
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
func verifyCalls(t *testing.T, fakeDocker *dockertools.FakeDockerClient, calls []string) {
|
|
|
|
err := fakeDocker.AssertCalls(calls)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func verifyStringArrayEquals(t *testing.T, actual, expected []string) {
|
|
|
|
invalid := len(actual) != len(expected)
|
2014-07-03 05:35:50 +00:00
|
|
|
if !invalid {
|
|
|
|
for ix, value := range actual {
|
|
|
|
if expected[ix] != value {
|
|
|
|
invalid = true
|
|
|
|
}
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if invalid {
|
|
|
|
t.Errorf("Expected: %#v, Actual: %#v", expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-09 23:50:44 +00:00
|
|
|
func verifyBoolean(t *testing.T, expected, value bool) {
|
|
|
|
if expected != value {
|
2014-07-18 19:03:22 +00:00
|
|
|
t.Errorf("Unexpected boolean. Expected %t. Found %t", expected, value)
|
2014-06-09 23:50:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-29 19:02:28 +00:00
|
|
|
func TestKubeletDirs(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, _ := newTestKubelet(t)
|
2014-11-29 19:02:28 +00:00
|
|
|
root := kubelet.rootDirectory
|
|
|
|
|
|
|
|
var exp, got string
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodsDir()
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "pods")
|
2014-11-29 19:02:28 +00:00
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPluginsDir()
|
|
|
|
exp = path.Join(root, "plugins")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
got = kubelet.getPluginDir("foobar")
|
|
|
|
exp = path.Join(root, "plugins/foobar")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
got = kubelet.getPodDir("abc123")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "pods/abc123")
|
2014-11-29 19:02:28 +00:00
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodVolumesDir("abc123")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "pods/abc123/volumes")
|
2014-11-29 19:02:28 +00:00
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodVolumeDir("abc123", "plugin", "foobar")
|
|
|
|
exp = path.Join(root, "pods/abc123/volumes/plugin/foobar")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
got = kubelet.getPodPluginsDir("abc123")
|
|
|
|
exp = path.Join(root, "pods/abc123/plugins")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
got = kubelet.getPodPluginDir("abc123", "foobar")
|
|
|
|
exp = path.Join(root, "pods/abc123/plugins/foobar")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
got = kubelet.getPodContainerDir("abc123", "def456")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "pods/abc123/containers/def456")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKubeletDirsCompat(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, _ := newTestKubelet(t)
|
2014-11-29 19:02:28 +00:00
|
|
|
root := kubelet.rootDirectory
|
|
|
|
if err := os.MkdirAll(root, 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var exp, got string
|
|
|
|
|
|
|
|
// Old-style pod dir.
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/oldpod", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
// New-style pod dir.
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/pods/newpod", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
// Both-style pod dir.
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/bothpod", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/pods/bothpod", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodDir("oldpod")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "oldpod")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodDir("newpod")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "pods/newpod")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodDir("bothpod")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "pods/bothpod")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodDir("neitherpod")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "pods/neitherpod")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
root = kubelet.getPodDir("newpod")
|
2014-11-29 19:02:28 +00:00
|
|
|
|
|
|
|
// Old-style container dir.
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/oldctr", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
// New-style container dir.
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/containers/newctr", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
// Both-style container dir.
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/bothctr", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
if err := os.MkdirAll(fmt.Sprintf("%s/containers/bothctr", root), 0750); err != nil {
|
|
|
|
t.Fatalf("can't mkdir(%q): %s", root, err)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodContainerDir("newpod", "oldctr")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "oldctr")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodContainerDir("newpod", "newctr")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "containers/newctr")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodContainerDir("newpod", "bothctr")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "containers/bothctr")
|
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
got = kubelet.getPodContainerDir("newpod", "neitherctr")
|
2014-11-29 19:02:28 +00:00
|
|
|
exp = path.Join(root, "containers/neitherctr")
|
2014-11-29 19:02:28 +00:00
|
|
|
if got != exp {
|
|
|
|
t.Errorf("expected %q', got %q", exp, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-06 23:40:48 +00:00
|
|
|
func TestKillContainerWithError(t *testing.T) {
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker := &dockertools.FakeDockerClient{
|
|
|
|
Err: fmt.Errorf("sample error"),
|
|
|
|
ContainerList: []docker.APIContainers{
|
2014-06-12 21:09:40 +00:00
|
|
|
{
|
2014-06-25 23:24:20 +00:00
|
|
|
ID: "1234",
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_foo_qux_1234_42"},
|
2014-06-06 23:40:48 +00:00
|
|
|
},
|
2014-06-12 21:09:40 +00:00
|
|
|
{
|
2014-06-25 23:24:20 +00:00
|
|
|
ID: "5678",
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_bar_qux_5678_42"},
|
2014-06-06 23:40:48 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, _ := newTestKubelet(t)
|
2014-07-22 21:40:59 +00:00
|
|
|
kubelet.dockerClient = fakeDocker
|
2014-09-09 04:33:17 +00:00
|
|
|
err := kubelet.killContainer(&fakeDocker.ContainerList[0])
|
2014-08-03 23:59:47 +00:00
|
|
|
if err == nil {
|
|
|
|
t.Errorf("expected error, found nil")
|
|
|
|
}
|
2014-06-25 23:24:20 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"stop"})
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestKillContainer(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-06-12 21:09:40 +00:00
|
|
|
{
|
2014-06-25 23:24:20 +00:00
|
|
|
ID: "1234",
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_foo_qux_1234_42"},
|
2014-06-06 23:40:48 +00:00
|
|
|
},
|
2014-06-12 21:09:40 +00:00
|
|
|
{
|
2014-06-25 23:24:20 +00:00
|
|
|
ID: "5678",
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_bar_qux_5678_42"},
|
2014-06-06 23:40:48 +00:00
|
|
|
},
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Container = &docker.Container{
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foobar",
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
err := kubelet.killContainer(&fakeDocker.ContainerList[0])
|
2014-08-03 23:59:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
2014-06-25 23:24:20 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"stop"})
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type channelReader struct {
|
2014-10-08 19:56:02 +00:00
|
|
|
list [][]api.BoundPod
|
2014-06-06 23:40:48 +00:00
|
|
|
wg sync.WaitGroup
|
|
|
|
}
|
|
|
|
|
2014-07-15 20:24:41 +00:00
|
|
|
func startReading(channel <-chan interface{}) *channelReader {
|
2014-06-06 23:40:48 +00:00
|
|
|
cr := &channelReader{}
|
|
|
|
cr.wg.Add(1)
|
|
|
|
go func() {
|
|
|
|
for {
|
2014-06-21 21:20:35 +00:00
|
|
|
update, ok := <-channel
|
2014-06-06 23:40:48 +00:00
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
2014-07-15 20:24:41 +00:00
|
|
|
cr.list = append(cr.list, update.(PodUpdate).Pods)
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
cr.wg.Done()
|
|
|
|
}()
|
|
|
|
return cr
|
|
|
|
}
|
|
|
|
|
2014-10-08 19:56:02 +00:00
|
|
|
func (cr *channelReader) GetList() [][]api.BoundPod {
|
2014-06-06 23:40:48 +00:00
|
|
|
cr.wg.Wait()
|
|
|
|
return cr.list
|
|
|
|
}
|
|
|
|
|
2014-07-15 20:24:41 +00:00
|
|
|
func TestSyncPodsDoesNothing(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-08-07 23:59:18 +00:00
|
|
|
container := api.Container{Name: "bar"}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-06-12 21:09:40 +00:00
|
|
|
{
|
2015-01-05 01:30:30 +00:00
|
|
|
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>_<random>
|
|
|
|
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo.new.test_12345678_0"},
|
2014-06-06 23:40:48 +00:00
|
|
|
ID: "1234",
|
|
|
|
},
|
2014-06-20 03:30:42 +00:00
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
|
2014-06-20 03:30:42 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
2014-06-12 21:09:40 +00:00
|
|
|
{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-05 01:30:30 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-07-15 20:24:41 +00:00
|
|
|
Containers: []api.Container{
|
2014-08-07 23:59:18 +00:00
|
|
|
container,
|
2014-07-15 20:24:41 +00:00
|
|
|
},
|
2014-06-06 23:40:48 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2014-08-03 23:59:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
2014-10-31 16:52:01 +00:00
|
|
|
kubelet.drainWorkers()
|
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "list", "inspect_container", "inspect_container"})
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
|
2014-11-07 06:41:16 +00:00
|
|
|
func TestSyncPodsWithTerminationLog(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-11-07 06:41:16 +00:00
|
|
|
container := api.Container{
|
|
|
|
Name: "bar",
|
|
|
|
TerminationMessagePath: "/dev/somepath",
|
|
|
|
}
|
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-11-07 06:41:16 +00:00
|
|
|
Name: "foo",
|
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
|
|
|
Containers: []api.Container{
|
|
|
|
container,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
kubelet.drainWorkers()
|
|
|
|
verifyCalls(t, fakeDocker, []string{
|
|
|
|
"list", "create", "start", "list", "inspect_container", "list", "create", "start"})
|
|
|
|
|
|
|
|
fakeDocker.Lock()
|
|
|
|
parts := strings.Split(fakeDocker.Container.HostConfig.Binds[0], ":")
|
2014-11-23 15:47:25 +00:00
|
|
|
if !matchString(t, kubelet.getPodContainerDir("12345678", "bar")+"/k8s_bar\\.[a-f0-9]", parts[0]) {
|
2014-11-29 19:02:28 +00:00
|
|
|
t.Errorf("Unexpected host path: %s", parts[0])
|
|
|
|
}
|
|
|
|
if parts[1] != "/dev/somepath" {
|
|
|
|
t.Errorf("Unexpected container path: %s", parts[1])
|
2014-11-07 06:41:16 +00:00
|
|
|
}
|
|
|
|
fakeDocker.Unlock()
|
|
|
|
}
|
|
|
|
|
2014-08-08 04:49:17 +00:00
|
|
|
// drainWorkers waits until all workers are done. Should only used for testing.
|
|
|
|
func (kl *Kubelet) drainWorkers() {
|
|
|
|
for {
|
|
|
|
kl.podWorkers.lock.Lock()
|
|
|
|
length := len(kl.podWorkers.workers)
|
|
|
|
kl.podWorkers.lock.Unlock()
|
|
|
|
if length == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
time.Sleep(time.Millisecond * 100)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-07 23:59:18 +00:00
|
|
|
func matchString(t *testing.T, pattern, str string) bool {
|
|
|
|
match, err := regexp.MatchString(pattern, str)
|
|
|
|
if err != nil {
|
|
|
|
t.Logf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
return match
|
|
|
|
}
|
|
|
|
|
2014-08-08 04:49:17 +00:00
|
|
|
func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2015-01-21 00:59:26 +00:00
|
|
|
kubelet.podInfraContainerImage = "custom_image_name"
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
2014-08-08 04:49:17 +00:00
|
|
|
{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-08-08 04:49:17 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
kubelet.drainWorkers()
|
|
|
|
|
|
|
|
verifyCalls(t, fakeDocker, []string{
|
2014-10-20 04:35:08 +00:00
|
|
|
"list", "create", "start", "list", "inspect_container", "list", "create", "start"})
|
2014-08-08 04:49:17 +00:00
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Lock()
|
2014-10-02 18:58:58 +00:00
|
|
|
|
|
|
|
found := false
|
|
|
|
for _, c := range fakeDocker.ContainerList {
|
2015-01-21 00:59:26 +00:00
|
|
|
if c.Image == "custom_image_name" && strings.HasPrefix(c.Names[0], "/k8s_POD") {
|
2014-10-02 18:58:58 +00:00
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
2015-01-28 23:03:06 +00:00
|
|
|
t.Errorf("Custom pod infra container not found: %v", fakeDocker.ContainerList)
|
2014-10-02 18:58:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(fakeDocker.Created) != 2 ||
|
2015-01-21 00:59:26 +00:00
|
|
|
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
|
2014-10-08 19:56:02 +00:00
|
|
|
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) {
|
2014-10-02 18:58:58 +00:00
|
|
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
|
|
}
|
|
|
|
fakeDocker.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-10-02 18:58:58 +00:00
|
|
|
puller := kubelet.dockerPuller.(*dockertools.FakeDockerPuller)
|
|
|
|
puller.HasImages = []string{}
|
2015-01-21 00:59:26 +00:00
|
|
|
kubelet.podInfraContainerImage = "custom_image_name"
|
2014-10-02 18:58:58 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
2014-10-02 18:58:58 +00:00
|
|
|
{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-10-02 18:58:58 +00:00
|
|
|
Containers: []api.Container{
|
2015-01-21 04:30:42 +00:00
|
|
|
{Name: "bar", Image: "something", ImagePullPolicy: "IfNotPresent"},
|
2014-10-02 18:58:58 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
kubelet.drainWorkers()
|
|
|
|
|
|
|
|
verifyCalls(t, fakeDocker, []string{
|
2014-10-20 04:35:08 +00:00
|
|
|
"list", "create", "start", "list", "inspect_container", "list", "create", "start"})
|
2014-10-02 18:58:58 +00:00
|
|
|
|
|
|
|
fakeDocker.Lock()
|
|
|
|
|
2015-01-17 00:55:19 +00:00
|
|
|
if !reflect.DeepEqual(puller.ImagesPulled, []string{"custom_image_name", "something"}) {
|
2014-10-02 18:58:58 +00:00
|
|
|
t.Errorf("Unexpected pulled containers: %v", puller.ImagesPulled)
|
|
|
|
}
|
|
|
|
|
2014-08-08 04:49:17 +00:00
|
|
|
if len(fakeDocker.Created) != 2 ||
|
2015-01-21 00:59:26 +00:00
|
|
|
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
|
2014-10-08 19:56:02 +00:00
|
|
|
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) {
|
2014-08-08 04:49:17 +00:00
|
|
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Unlock()
|
2014-08-08 04:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSyncPodsWithNetCreatesContainer(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-08-08 04:49:17 +00:00
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
|
2014-08-08 04:49:17 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
2014-08-08 04:49:17 +00:00
|
|
|
{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-05 01:30:30 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-08-08 04:49:17 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
kubelet.drainWorkers()
|
|
|
|
|
|
|
|
verifyCalls(t, fakeDocker, []string{
|
2014-10-20 04:35:08 +00:00
|
|
|
"list", "list", "inspect_container", "list", "create", "start"})
|
2014-08-08 04:49:17 +00:00
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Lock()
|
2014-08-08 04:49:17 +00:00
|
|
|
if len(fakeDocker.Created) != 1 ||
|
2014-10-08 19:56:02 +00:00
|
|
|
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) {
|
2014-08-08 04:49:17 +00:00
|
|
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Unlock()
|
2014-08-08 04:49:17 +00:00
|
|
|
}
|
|
|
|
|
2014-09-03 20:39:56 +00:00
|
|
|
func TestSyncPodsWithNetCreatesContainerCallsHandler(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-03 20:39:56 +00:00
|
|
|
fakeHttp := fakeHTTP{}
|
|
|
|
kubelet.httpClient = &fakeHttp
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-09-03 20:39:56 +00:00
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
|
2014-09-03 20:39:56 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
2014-09-03 20:39:56 +00:00
|
|
|
{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-05 01:30:30 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-09-03 20:39:56 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{
|
|
|
|
Name: "bar",
|
|
|
|
Lifecycle: &api.Lifecycle{
|
|
|
|
PostStart: &api.Handler{
|
|
|
|
HTTPGet: &api.HTTPGetAction{
|
|
|
|
Host: "foo",
|
|
|
|
Port: util.IntOrString{IntVal: 8080, Kind: util.IntstrInt},
|
|
|
|
Path: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
kubelet.drainWorkers()
|
|
|
|
|
|
|
|
verifyCalls(t, fakeDocker, []string{
|
2014-10-20 04:35:08 +00:00
|
|
|
"list", "list", "inspect_container", "list", "create", "start"})
|
2014-09-03 20:39:56 +00:00
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Lock()
|
2014-09-03 20:39:56 +00:00
|
|
|
if len(fakeDocker.Created) != 1 ||
|
2014-10-08 19:56:02 +00:00
|
|
|
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) {
|
2014-09-03 20:39:56 +00:00
|
|
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Unlock()
|
2014-09-03 20:39:56 +00:00
|
|
|
if fakeHttp.url != "http://foo:8080/bar" {
|
|
|
|
t.Errorf("Unexpected handler: %s", fakeHttp.url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-08 04:49:17 +00:00
|
|
|
func TestSyncPodsDeletesWithNoNetContainer(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-08-08 04:49:17 +00:00
|
|
|
{
|
2015-01-05 01:30:30 +00:00
|
|
|
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
|
|
|
|
Names: []string{"/k8s_bar_foo.new.test_12345678_0"},
|
2014-08-08 04:49:17 +00:00
|
|
|
ID: "1234",
|
|
|
|
},
|
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
2014-08-08 04:49:17 +00:00
|
|
|
{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-05 01:30:30 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-08-08 04:49:17 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
kubelet.drainWorkers()
|
|
|
|
|
|
|
|
verifyCalls(t, fakeDocker, []string{
|
2014-10-20 04:35:08 +00:00
|
|
|
"list", "stop", "create", "start", "list", "list", "inspect_container", "list", "create", "start"})
|
2014-08-08 04:49:17 +00:00
|
|
|
|
|
|
|
// A map iteration is used to delete containers, so must not depend on
|
|
|
|
// order here.
|
|
|
|
expectedToStop := map[string]bool{
|
|
|
|
"1234": true,
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Lock()
|
|
|
|
if len(fakeDocker.Stopped) != 1 || !expectedToStop[fakeDocker.Stopped[0]] {
|
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
2014-08-08 04:49:17 +00:00
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.Unlock()
|
2014-08-08 04:49:17 +00:00
|
|
|
}
|
|
|
|
|
2014-12-17 05:11:27 +00:00
|
|
|
func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) {
|
|
|
|
ready := false
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2015-01-13 05:47:49 +00:00
|
|
|
kubelet.sourceReady = func(source string) bool { return ready }
|
2014-12-17 05:11:27 +00:00
|
|
|
|
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
|
|
|
{
|
|
|
|
// the k8s prefix is required for the kubelet to manage the container
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_foo_bar.new.test_12345678_42"},
|
2014-12-17 05:11:27 +00:00
|
|
|
ID: "1234",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
|
2014-12-17 05:11:27 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := kubelet.SyncPods([]api.BoundPod{}); err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
// Validate nothing happened.
|
|
|
|
verifyCalls(t, fakeDocker, []string{"list"})
|
|
|
|
fakeDocker.ClearCalls()
|
|
|
|
|
|
|
|
ready = true
|
|
|
|
if err := kubelet.SyncPods([]api.BoundPod{}); err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
2015-02-03 20:14:16 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "stop", "stop", "inspect_container", "inspect_container"})
|
2014-12-17 05:11:27 +00:00
|
|
|
|
|
|
|
// A map iteration is used to delete containers, so must not depend on
|
|
|
|
// order here.
|
|
|
|
expectedToStop := map[string]bool{
|
|
|
|
"1234": true,
|
|
|
|
"9876": true,
|
|
|
|
}
|
|
|
|
if len(fakeDocker.Stopped) != 2 ||
|
|
|
|
!expectedToStop[fakeDocker.Stopped[0]] ||
|
|
|
|
!expectedToStop[fakeDocker.Stopped[1]] {
|
2015-01-13 05:47:49 +00:00
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSyncPodsDeletesWhenContainerSourceReady(t *testing.T) {
|
|
|
|
ready := false
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2015-01-13 05:47:49 +00:00
|
|
|
kubelet.sourceReady = func(source string) bool {
|
|
|
|
if source == "testSource" {
|
|
|
|
return ready
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
|
|
|
{
|
|
|
|
// the k8s prefix is required for the kubelet to manage the container
|
|
|
|
Names: []string{"/k8s_boo_bar.default.testSource_12345678_42"},
|
|
|
|
ID: "7492",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_boo.default.testSource_12345678_42"},
|
2015-01-13 05:47:49 +00:00
|
|
|
ID: "3542",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
// the k8s prefix is required for the kubelet to manage the container
|
|
|
|
Names: []string{"/k8s_foo_bar.new.otherSource_12345678_42"},
|
|
|
|
ID: "1234",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.otherSource_12345678_42"},
|
2015-01-13 05:47:49 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := kubelet.SyncPods([]api.BoundPod{}); err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
// Validate nothing happened.
|
|
|
|
verifyCalls(t, fakeDocker, []string{"list"})
|
|
|
|
fakeDocker.ClearCalls()
|
|
|
|
|
|
|
|
ready = true
|
|
|
|
if err := kubelet.SyncPods([]api.BoundPod{}); err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
2015-02-03 20:14:16 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "stop", "stop", "inspect_container", "inspect_container"})
|
2015-01-13 05:47:49 +00:00
|
|
|
|
|
|
|
// Validate container for testSource are killed because testSource is reported as seen, but
|
|
|
|
// containers for otherSource are not killed because otherSource has not.
|
|
|
|
expectedToStop := map[string]bool{
|
|
|
|
"7492": true,
|
|
|
|
"3542": true,
|
|
|
|
"1234": false,
|
|
|
|
"9876": false,
|
|
|
|
}
|
|
|
|
if len(fakeDocker.Stopped) != 2 ||
|
|
|
|
!expectedToStop[fakeDocker.Stopped[0]] ||
|
|
|
|
!expectedToStop[fakeDocker.Stopped[1]] {
|
2014-12-17 05:11:27 +00:00
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-15 20:24:41 +00:00
|
|
|
func TestSyncPodsDeletes(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-06-12 21:09:40 +00:00
|
|
|
{
|
2014-06-21 20:16:20 +00:00
|
|
|
// the k8s prefix is required for the kubelet to manage the container
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_foo_bar.new.test_12345678_42"},
|
2014-06-06 23:40:48 +00:00
|
|
|
ID: "1234",
|
|
|
|
},
|
2014-06-20 03:30:42 +00:00
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
|
2014-06-20 03:30:42 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
2014-06-13 19:09:48 +00:00
|
|
|
{
|
|
|
|
Names: []string{"foo"},
|
|
|
|
ID: "4567",
|
|
|
|
},
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.SyncPods([]api.BoundPod{})
|
2014-08-03 23:59:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-02-03 20:14:16 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "stop", "stop", "inspect_container", "inspect_container"})
|
2014-06-27 22:29:13 +00:00
|
|
|
|
2014-07-18 18:42:47 +00:00
|
|
|
// A map iteration is used to delete containers, so must not depend on
|
2014-06-27 22:29:13 +00:00
|
|
|
// order here.
|
|
|
|
expectedToStop := map[string]bool{
|
|
|
|
"1234": true,
|
|
|
|
"9876": true,
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
if len(fakeDocker.Stopped) != 2 ||
|
|
|
|
!expectedToStop[fakeDocker.Stopped[0]] ||
|
|
|
|
!expectedToStop[fakeDocker.Stopped[1]] {
|
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-09 20:47:25 +00:00
|
|
|
|
2014-07-18 18:42:47 +00:00
|
|
|
func TestSyncPodDeletesDuplicate(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
dockerContainers := dockertools.DockerContainers{
|
2014-07-18 18:42:47 +00:00
|
|
|
"1234": &docker.APIContainers{
|
|
|
|
// the k8s prefix is required for the kubelet to manage the container
|
2015-01-05 01:30:30 +00:00
|
|
|
Names: []string{"/k8s_foo_bar.new.test_12345678_1111"},
|
2014-07-18 18:42:47 +00:00
|
|
|
ID: "1234",
|
|
|
|
},
|
|
|
|
"9876": &docker.APIContainers{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_bar.new.test_12345678_2222"},
|
2014-07-18 18:42:47 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
"4567": &docker.APIContainers{
|
|
|
|
// Duplicate for the same container.
|
2015-01-05 01:30:30 +00:00
|
|
|
Names: []string{"/k8s_foo_bar.new.test_12345678_3333"},
|
2014-07-18 18:42:47 +00:00
|
|
|
ID: "4567",
|
|
|
|
},
|
|
|
|
"2304": &docker.APIContainers{
|
|
|
|
// Container for another pod, untouched.
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_baz_fiz.new.test_6_42"},
|
2014-07-18 18:42:47 +00:00
|
|
|
ID: "2304",
|
|
|
|
},
|
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.syncPod(&api.BoundPod{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-05 01:30:30 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "bar",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-07-18 18:42:47 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "foo"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, dockerContainers)
|
2014-08-03 23:59:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-08-01 00:35:54 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "stop"})
|
2014-07-18 18:42:47 +00:00
|
|
|
|
|
|
|
// Expect one of the duplicates to be killed.
|
2015-01-05 01:30:30 +00:00
|
|
|
if len(fakeDocker.Stopped) != 1 || (fakeDocker.Stopped[0] != "1234" && fakeDocker.Stopped[0] != "4567") {
|
2014-09-09 04:33:17 +00:00
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
2014-07-18 18:42:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-07 23:59:18 +00:00
|
|
|
func TestSyncPodBadHash(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
dockerContainers := dockertools.DockerContainers{
|
2014-08-07 23:59:18 +00:00
|
|
|
"1234": &docker.APIContainers{
|
|
|
|
// the k8s prefix is required for the kubelet to manage the container
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_bar.1234_foo.new.test_12345678_42"},
|
2014-08-07 23:59:18 +00:00
|
|
|
ID: "1234",
|
|
|
|
},
|
|
|
|
"9876": &docker.APIContainers{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
|
2014-08-07 23:59:18 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.syncPod(&api.BoundPod{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-08-07 23:59:18 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, dockerContainers)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-11-04 22:26:21 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "stop", "stop", "list", "create", "start"})
|
2014-08-07 23:59:18 +00:00
|
|
|
|
|
|
|
// A map interation is used to delete containers, so must not depend on
|
|
|
|
// order here.
|
|
|
|
expectedToStop := map[string]bool{
|
|
|
|
"1234": true,
|
2014-11-04 22:26:21 +00:00
|
|
|
"9876": true,
|
2014-08-07 23:59:18 +00:00
|
|
|
}
|
2014-11-04 22:26:21 +00:00
|
|
|
if len(fakeDocker.Stopped) != 2 ||
|
|
|
|
(!expectedToStop[fakeDocker.Stopped[0]] &&
|
|
|
|
!expectedToStop[fakeDocker.Stopped[1]]) {
|
2014-09-09 04:33:17 +00:00
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
2014-08-07 23:59:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-18 18:42:47 +00:00
|
|
|
func TestSyncPodUnhealthy(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
dockerContainers := dockertools.DockerContainers{
|
2014-07-18 18:42:47 +00:00
|
|
|
"1234": &docker.APIContainers{
|
2014-07-03 05:35:50 +00:00
|
|
|
// the k8s prefix is required for the kubelet to manage the container
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_bar_foo.new.test_12345678_42"},
|
2014-07-03 05:35:50 +00:00
|
|
|
ID: "1234",
|
|
|
|
},
|
2014-07-18 18:42:47 +00:00
|
|
|
"9876": &docker.APIContainers{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
|
2014-07-03 05:35:50 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.syncPod(&api.BoundPod{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-07-18 18:42:47 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "bar",
|
2015-01-27 00:35:52 +00:00
|
|
|
LivenessProbe: &api.Probe{
|
2014-09-28 04:16:30 +00:00
|
|
|
// Always returns healthy == false
|
2014-07-03 05:35:50 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2014-07-18 18:42:47 +00:00
|
|
|
},
|
|
|
|
}, dockerContainers)
|
2014-08-03 23:59:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-11-04 22:26:21 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "stop", "stop", "list", "create", "start"})
|
2014-07-03 05:35:50 +00:00
|
|
|
|
|
|
|
// A map interation is used to delete containers, so must not depend on
|
|
|
|
// order here.
|
|
|
|
expectedToStop := map[string]bool{
|
|
|
|
"1234": true,
|
2014-11-04 22:26:21 +00:00
|
|
|
"9876": true,
|
2014-07-03 05:35:50 +00:00
|
|
|
}
|
2014-11-04 22:26:21 +00:00
|
|
|
if len(fakeDocker.Stopped) != 2 ||
|
|
|
|
(!expectedToStop[fakeDocker.Stopped[0]] &&
|
|
|
|
expectedToStop[fakeDocker.Stopped[0]]) {
|
2014-09-09 04:33:17 +00:00
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
2014-07-03 05:35:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-15 01:39:30 +00:00
|
|
|
func TestMountExternalVolumes(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, _ := newTestKubelet(t)
|
2014-11-23 15:47:25 +00:00
|
|
|
kubelet.volumePluginMgr.InitPlugins([]volume.Plugin{&volume.FakePlugin{"fake", nil}}, &volumeHost{kubelet})
|
|
|
|
|
2014-10-08 19:56:02 +00:00
|
|
|
pod := api.BoundPod{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "test",
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
|
|
|
Volumes: []api.Volume{
|
|
|
|
{
|
2014-11-23 15:47:25 +00:00
|
|
|
Name: "vol1",
|
2015-01-21 01:40:43 +00:00
|
|
|
Source: api.VolumeSource{},
|
2014-07-16 19:32:59 +00:00
|
|
|
},
|
2014-07-15 01:39:30 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2014-11-23 15:47:25 +00:00
|
|
|
podVolumes, err := kubelet.mountExternalVolumes(&pod)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Expected sucess: %v", err)
|
|
|
|
}
|
|
|
|
expectedPodVolumes := []string{"vol1"}
|
2014-07-15 01:39:30 +00:00
|
|
|
if len(expectedPodVolumes) != len(podVolumes) {
|
2014-10-08 19:56:02 +00:00
|
|
|
t.Errorf("Unexpected volumes. Expected %#v got %#v. Manifest was: %#v", expectedPodVolumes, podVolumes, pod)
|
2014-07-15 01:39:30 +00:00
|
|
|
}
|
2014-11-23 15:47:25 +00:00
|
|
|
for _, name := range expectedPodVolumes {
|
2014-07-15 01:39:30 +00:00
|
|
|
if _, ok := podVolumes[name]; !ok {
|
2014-11-23 15:47:25 +00:00
|
|
|
t.Errorf("api.BoundPod volumes map is missing key: %s. %#v", name, podVolumes)
|
2014-07-15 01:39:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
func TestGetPodVolumesFromDisk(t *testing.T) {
|
|
|
|
kubelet, _ := newTestKubelet(t)
|
|
|
|
plug := &volume.FakePlugin{"fake", nil}
|
|
|
|
kubelet.volumePluginMgr.InitPlugins([]volume.Plugin{plug}, &volumeHost{kubelet})
|
|
|
|
|
|
|
|
volsOnDisk := []struct {
|
|
|
|
podUID types.UID
|
|
|
|
volName string
|
|
|
|
}{
|
|
|
|
{"pod1", "vol1"},
|
|
|
|
{"pod1", "vol2"},
|
|
|
|
{"pod2", "vol1"},
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedPaths := []string{}
|
|
|
|
for i := range volsOnDisk {
|
|
|
|
fv := volume.FakeVolume{volsOnDisk[i].podUID, volsOnDisk[i].volName, plug}
|
|
|
|
fv.SetUp()
|
|
|
|
expectedPaths = append(expectedPaths, fv.GetPath())
|
|
|
|
}
|
|
|
|
|
|
|
|
volumesFound := kubelet.getPodVolumesFromDisk()
|
|
|
|
if len(volumesFound) != len(expectedPaths) {
|
|
|
|
t.Errorf("Expected to find %d cleaners, got %d", len(expectedPaths), len(volumesFound))
|
|
|
|
}
|
|
|
|
for _, ep := range expectedPaths {
|
|
|
|
found := false
|
|
|
|
for _, cl := range volumesFound {
|
|
|
|
if ep == cl.GetPath() {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
t.Errorf("Could not find a volume with path %s", ep)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type stubVolume struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *stubVolume) GetPath() string {
|
|
|
|
return f.path
|
|
|
|
}
|
|
|
|
|
2014-06-09 20:47:25 +00:00
|
|
|
func TestMakeVolumesAndBinds(t *testing.T) {
|
|
|
|
container := api.Container{
|
|
|
|
VolumeMounts: []api.VolumeMount{
|
2014-06-13 01:34:47 +00:00
|
|
|
{
|
2014-06-09 20:47:25 +00:00
|
|
|
MountPath: "/mnt/path",
|
|
|
|
Name: "disk",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
2014-06-19 23:59:48 +00:00
|
|
|
{
|
|
|
|
MountPath: "/mnt/path3",
|
2014-08-27 05:08:06 +00:00
|
|
|
Name: "disk",
|
|
|
|
ReadOnly: true,
|
2014-06-09 20:47:25 +00:00
|
|
|
},
|
2014-07-15 01:39:30 +00:00
|
|
|
{
|
|
|
|
MountPath: "/mnt/path4",
|
|
|
|
Name: "disk4",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
2014-07-19 00:13:34 +00:00
|
|
|
{
|
|
|
|
MountPath: "/mnt/path5",
|
|
|
|
Name: "disk5",
|
|
|
|
ReadOnly: false,
|
|
|
|
},
|
2014-06-09 20:47:25 +00:00
|
|
|
},
|
|
|
|
}
|
2014-07-15 01:39:30 +00:00
|
|
|
|
2014-10-08 19:56:02 +00:00
|
|
|
pod := api.BoundPod{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "pod",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "test",
|
|
|
|
},
|
2014-07-15 20:24:41 +00:00
|
|
|
}
|
|
|
|
|
2014-08-27 05:08:06 +00:00
|
|
|
podVolumes := volumeMap{
|
2014-11-23 15:47:25 +00:00
|
|
|
"disk": &stubVolume{"/mnt/disk"},
|
|
|
|
"disk4": &stubVolume{"/mnt/host"},
|
|
|
|
"disk5": &stubVolume{"/var/lib/kubelet/podID/volumes/empty/disk5"},
|
2014-08-27 05:08:06 +00:00
|
|
|
}
|
2014-06-19 23:59:48 +00:00
|
|
|
|
2014-08-27 05:08:06 +00:00
|
|
|
binds := makeBinds(&pod, &container, podVolumes)
|
2014-07-15 20:24:41 +00:00
|
|
|
|
2014-08-27 05:08:06 +00:00
|
|
|
expectedBinds := []string{
|
|
|
|
"/mnt/disk:/mnt/path",
|
|
|
|
"/mnt/disk:/mnt/path3:ro",
|
|
|
|
"/mnt/host:/mnt/path4",
|
|
|
|
"/var/lib/kubelet/podID/volumes/empty/disk5:/mnt/path5",
|
2014-06-09 20:47:25 +00:00
|
|
|
}
|
2014-08-27 05:08:06 +00:00
|
|
|
|
2014-06-19 23:59:48 +00:00
|
|
|
if len(binds) != len(expectedBinds) {
|
2014-07-18 19:03:22 +00:00
|
|
|
t.Errorf("Unexpected binds: Expected %#v got %#v. Container was: %#v", expectedBinds, binds, container)
|
2014-06-19 23:59:48 +00:00
|
|
|
}
|
|
|
|
verifyStringArrayEquals(t, binds, expectedBinds)
|
2014-06-09 20:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestMakePortsAndBindings(t *testing.T) {
|
|
|
|
container := api.Container{
|
|
|
|
Ports: []api.Port{
|
2014-06-13 01:34:47 +00:00
|
|
|
{
|
2014-06-09 20:47:25 +00:00
|
|
|
ContainerPort: 80,
|
|
|
|
HostPort: 8080,
|
2014-07-09 05:44:15 +00:00
|
|
|
HostIP: "127.0.0.1",
|
2014-06-09 20:47:25 +00:00
|
|
|
},
|
2014-06-13 01:34:47 +00:00
|
|
|
{
|
2014-06-09 20:47:25 +00:00
|
|
|
ContainerPort: 443,
|
|
|
|
HostPort: 443,
|
2014-06-16 04:57:29 +00:00
|
|
|
Protocol: "tcp",
|
2014-06-16 04:19:35 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ContainerPort: 444,
|
|
|
|
HostPort: 444,
|
2014-06-16 04:57:29 +00:00
|
|
|
Protocol: "udp",
|
2014-06-16 04:19:35 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ContainerPort: 445,
|
|
|
|
HostPort: 445,
|
2014-06-16 04:57:29 +00:00
|
|
|
Protocol: "foobar",
|
2014-06-09 20:47:25 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
exposedPorts, bindings := makePortsAndBindings(&container)
|
|
|
|
if len(container.Ports) != len(exposedPorts) ||
|
|
|
|
len(container.Ports) != len(bindings) {
|
|
|
|
t.Errorf("Unexpected ports and bindings, %#v %#v %#v", container, exposedPorts, bindings)
|
|
|
|
}
|
2014-06-16 04:57:29 +00:00
|
|
|
for key, value := range bindings {
|
|
|
|
switch value[0].HostPort {
|
2014-06-16 04:19:35 +00:00
|
|
|
case "8080":
|
2014-06-16 04:57:29 +00:00
|
|
|
if !reflect.DeepEqual(docker.Port("80/tcp"), key) {
|
|
|
|
t.Errorf("Unexpected docker port: %#v", key)
|
2014-06-16 04:19:35 +00:00
|
|
|
}
|
2014-12-18 19:15:35 +00:00
|
|
|
if value[0].HostIP != "127.0.0.1" {
|
|
|
|
t.Errorf("Unexpected host IP: %s", value[0].HostIP)
|
2014-07-09 05:44:15 +00:00
|
|
|
}
|
2014-06-16 04:19:35 +00:00
|
|
|
case "443":
|
2014-06-16 04:57:29 +00:00
|
|
|
if !reflect.DeepEqual(docker.Port("443/tcp"), key) {
|
|
|
|
t.Errorf("Unexpected docker port: %#v", key)
|
2014-06-16 04:19:35 +00:00
|
|
|
}
|
2014-12-18 19:15:35 +00:00
|
|
|
if value[0].HostIP != "" {
|
|
|
|
t.Errorf("Unexpected host IP: %s", value[0].HostIP)
|
2014-07-09 05:44:15 +00:00
|
|
|
}
|
2014-06-16 04:19:35 +00:00
|
|
|
case "444":
|
2014-06-16 04:57:29 +00:00
|
|
|
if !reflect.DeepEqual(docker.Port("444/udp"), key) {
|
|
|
|
t.Errorf("Unexpected docker port: %#v", key)
|
2014-06-16 04:19:35 +00:00
|
|
|
}
|
2014-12-18 19:15:35 +00:00
|
|
|
if value[0].HostIP != "" {
|
|
|
|
t.Errorf("Unexpected host IP: %s", value[0].HostIP)
|
2014-07-09 05:44:15 +00:00
|
|
|
}
|
2014-06-16 04:19:35 +00:00
|
|
|
case "445":
|
2014-06-16 04:57:29 +00:00
|
|
|
if !reflect.DeepEqual(docker.Port("445/tcp"), key) {
|
|
|
|
t.Errorf("Unexpected docker port: %#v", key)
|
2014-06-16 04:19:35 +00:00
|
|
|
}
|
2014-12-18 19:15:35 +00:00
|
|
|
if value[0].HostIP != "" {
|
|
|
|
t.Errorf("Unexpected host IP: %s", value[0].HostIP)
|
2014-07-09 05:44:15 +00:00
|
|
|
}
|
2014-06-16 04:57:29 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-08 04:48:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCheckHostPortConflicts(t *testing.T) {
|
2014-10-08 19:56:02 +00:00
|
|
|
successCaseAll := []api.BoundPod{
|
|
|
|
{Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 80}}}}}},
|
|
|
|
{Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 81}}}}}},
|
|
|
|
{Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 82}}}}}},
|
2014-07-08 04:48:47 +00:00
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
successCaseNew := api.BoundPod{
|
|
|
|
Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 83}}}}},
|
2014-07-08 04:48:47 +00:00
|
|
|
}
|
2014-07-15 20:24:41 +00:00
|
|
|
expected := append(successCaseAll, successCaseNew)
|
|
|
|
if actual := filterHostPortConflicts(expected); !reflect.DeepEqual(actual, expected) {
|
|
|
|
t.Errorf("Expected %#v, Got %#v", expected, actual)
|
2014-07-08 04:48:47 +00:00
|
|
|
}
|
2014-06-16 04:19:35 +00:00
|
|
|
|
2014-10-08 19:56:02 +00:00
|
|
|
failureCaseAll := []api.BoundPod{
|
|
|
|
{Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 80}}}}}},
|
|
|
|
{Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 81}}}}}},
|
|
|
|
{Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 82}}}}}},
|
2014-07-08 04:48:47 +00:00
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
failureCaseNew := api.BoundPod{
|
|
|
|
Spec: api.PodSpec{Containers: []api.Container{{Ports: []api.Port{{HostPort: 81}}}}},
|
2014-07-08 04:48:47 +00:00
|
|
|
}
|
2014-07-15 20:24:41 +00:00
|
|
|
if actual := filterHostPortConflicts(append(failureCaseAll, failureCaseNew)); !reflect.DeepEqual(failureCaseAll, actual) {
|
|
|
|
t.Errorf("Expected %#v, Got %#v", expected, actual)
|
2014-06-09 20:47:25 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-19 20:22:20 +00:00
|
|
|
|
2014-12-10 01:06:39 +00:00
|
|
|
func TestFieldPath(t *testing.T) {
|
|
|
|
pod := &api.BoundPod{Spec: api.PodSpec{Containers: []api.Container{
|
|
|
|
{Name: "foo"},
|
|
|
|
{Name: "bar"},
|
2014-12-30 01:10:38 +00:00
|
|
|
{Name: ""},
|
2014-12-10 01:06:39 +00:00
|
|
|
{Name: "baz"},
|
|
|
|
}}}
|
|
|
|
table := map[string]struct {
|
|
|
|
pod *api.BoundPod
|
|
|
|
container *api.Container
|
|
|
|
path string
|
|
|
|
success bool
|
|
|
|
}{
|
2014-12-30 01:10:38 +00:00
|
|
|
"basic": {pod, &api.Container{Name: "foo"}, "spec.containers{foo}", true},
|
|
|
|
"basic2": {pod, &api.Container{Name: "baz"}, "spec.containers{baz}", true},
|
|
|
|
"emptyName": {pod, &api.Container{Name: ""}, "spec.containers[2]", true},
|
|
|
|
"basicSamePointer": {pod, &pod.Spec.Containers[0], "spec.containers{foo}", true},
|
2014-12-10 01:06:39 +00:00
|
|
|
"missing": {pod, &api.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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-19 20:22:20 +00:00
|
|
|
type mockCadvisorClient struct {
|
|
|
|
mock.Mock
|
|
|
|
}
|
|
|
|
|
2014-07-10 12:26:24 +00:00
|
|
|
// ContainerInfo is a mock implementation of CadvisorInterface.ContainerInfo.
|
2014-07-14 21:48:51 +00:00
|
|
|
func (c *mockCadvisorClient) ContainerInfo(name string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
|
|
|
|
args := c.Called(name, req)
|
2014-06-19 20:22:20 +00:00
|
|
|
return args.Get(0).(*info.ContainerInfo), args.Error(1)
|
|
|
|
}
|
|
|
|
|
2014-12-01 11:10:59 +00:00
|
|
|
// DockerContainer is a mock implementation of CadvisorInterface.DockerContainer.
|
|
|
|
func (c *mockCadvisorClient) DockerContainer(name string, req *info.ContainerInfoRequest) (info.ContainerInfo, error) {
|
|
|
|
args := c.Called(name, req)
|
|
|
|
return args.Get(0).(info.ContainerInfo), args.Error(1)
|
|
|
|
}
|
|
|
|
|
2014-07-10 12:26:24 +00:00
|
|
|
// MachineInfo is a mock implementation of CadvisorInterface.MachineInfo.
|
|
|
|
func (c *mockCadvisorClient) MachineInfo() (*info.MachineInfo, error) {
|
|
|
|
args := c.Called()
|
2014-06-19 20:22:20 +00:00
|
|
|
return args.Get(0).(*info.MachineInfo), args.Error(1)
|
|
|
|
}
|
|
|
|
|
2014-07-15 22:40:02 +00:00
|
|
|
func TestGetContainerInfo(t *testing.T) {
|
2014-07-02 18:21:29 +00:00
|
|
|
containerID := "ab2cdf"
|
|
|
|
containerPath := fmt.Sprintf("/docker/%v", containerID)
|
2014-12-01 11:10:59 +00:00
|
|
|
containerInfo := info.ContainerInfo{
|
2014-06-19 20:22:20 +00:00
|
|
|
ContainerReference: info.ContainerReference{
|
|
|
|
Name: containerPath,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
mockCadvisor := &mockCadvisorClient{}
|
2014-10-20 03:54:52 +00:00
|
|
|
cadvisorReq := &info.ContainerInfoRequest{}
|
2014-12-01 11:10:59 +00:00
|
|
|
mockCadvisor.On("DockerContainer", containerID, cadvisorReq).Return(containerInfo, nil)
|
2014-06-19 20:22:20 +00:00
|
|
|
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-07-22 21:40:59 +00:00
|
|
|
kubelet.cadvisorClient = mockCadvisor
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-06-19 20:22:20 +00:00
|
|
|
{
|
2014-07-01 21:05:10 +00:00
|
|
|
ID: containerID,
|
|
|
|
// pod id: qux
|
|
|
|
// container id: foo
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_foo_qux_1234_42"},
|
2014-07-01 21:05:10 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2014-10-20 03:54:52 +00:00
|
|
|
stats, err := kubelet.GetContainerInfo("qux", "", "foo", cadvisorReq)
|
2014-07-01 21:05:10 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
2014-07-15 17:26:56 +00:00
|
|
|
if stats == nil {
|
|
|
|
t.Fatalf("stats should not be nil")
|
|
|
|
}
|
2014-07-01 21:05:10 +00:00
|
|
|
mockCadvisor.AssertExpectations(t)
|
|
|
|
}
|
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
func TestGetRootInfo(t *testing.T) {
|
2014-07-01 21:05:10 +00:00
|
|
|
containerPath := "/"
|
|
|
|
containerInfo := &info.ContainerInfo{
|
|
|
|
ContainerReference: info.ContainerReference{
|
|
|
|
Name: containerPath,
|
|
|
|
},
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker := dockertools.FakeDockerClient{}
|
2014-06-19 20:22:20 +00:00
|
|
|
|
2014-07-01 21:05:10 +00:00
|
|
|
mockCadvisor := &mockCadvisorClient{}
|
2014-10-20 03:54:52 +00:00
|
|
|
cadvisorReq := &info.ContainerInfoRequest{}
|
2014-07-14 21:48:51 +00:00
|
|
|
mockCadvisor.On("ContainerInfo", containerPath, cadvisorReq).Return(containerInfo, nil)
|
2014-07-01 21:05:10 +00:00
|
|
|
|
|
|
|
kubelet := Kubelet{
|
2014-07-22 21:40:59 +00:00
|
|
|
dockerClient: &fakeDocker,
|
2014-09-09 04:33:17 +00:00
|
|
|
dockerPuller: &dockertools.FakeDockerPuller{},
|
2014-07-22 21:40:59 +00:00
|
|
|
cadvisorClient: mockCadvisor,
|
2014-07-18 18:42:47 +00:00
|
|
|
podWorkers: newPodWorkers(),
|
2014-07-01 21:05:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the container name is an empty string, then it means the root container.
|
2014-10-20 03:54:52 +00:00
|
|
|
_, err := kubelet.GetRootInfo(cadvisorReq)
|
2014-06-19 20:22:20 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
mockCadvisor.AssertExpectations(t)
|
|
|
|
}
|
2014-06-19 20:25:54 +00:00
|
|
|
|
2014-07-15 22:40:02 +00:00
|
|
|
func TestGetContainerInfoWithoutCadvisor(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-06-19 20:25:54 +00:00
|
|
|
{
|
2014-07-01 21:05:10 +00:00
|
|
|
ID: "foobar",
|
|
|
|
// pod id: qux
|
|
|
|
// container id: foo
|
2014-09-25 00:05:53 +00:00
|
|
|
Names: []string{"/k8s_foo_qux_uuid_1234"},
|
2014-06-19 20:25:54 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2014-09-05 09:49:11 +00:00
|
|
|
stats, _ := kubelet.GetContainerInfo("qux", "uuid", "foo", nil)
|
2014-06-19 20:25:54 +00:00
|
|
|
// When there's no cAdvisor, the stats should be either nil or empty
|
|
|
|
if stats == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2014-06-19 20:34:26 +00:00
|
|
|
|
2014-07-15 22:40:02 +00:00
|
|
|
func TestGetContainerInfoWhenCadvisorFailed(t *testing.T) {
|
2014-07-02 18:21:29 +00:00
|
|
|
containerID := "ab2cdf"
|
2014-06-19 20:34:26 +00:00
|
|
|
|
2014-12-01 11:10:59 +00:00
|
|
|
containerInfo := info.ContainerInfo{}
|
2014-06-19 20:34:26 +00:00
|
|
|
mockCadvisor := &mockCadvisorClient{}
|
2014-10-20 03:54:52 +00:00
|
|
|
cadvisorReq := &info.ContainerInfoRequest{}
|
2014-06-19 20:34:26 +00:00
|
|
|
expectedErr := fmt.Errorf("some error")
|
2014-12-01 11:10:59 +00:00
|
|
|
mockCadvisor.On("DockerContainer", containerID, cadvisorReq).Return(containerInfo, expectedErr)
|
2014-06-19 20:34:26 +00:00
|
|
|
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-07-22 21:40:59 +00:00
|
|
|
kubelet.cadvisorClient = mockCadvisor
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-06-19 20:34:26 +00:00
|
|
|
{
|
2014-07-01 21:05:10 +00:00
|
|
|
ID: containerID,
|
|
|
|
// pod id: qux
|
|
|
|
// container id: foo
|
2014-09-25 00:05:53 +00:00
|
|
|
Names: []string{"/k8s_foo_qux_uuid_1234"},
|
2014-06-19 20:34:26 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2014-10-20 03:54:52 +00:00
|
|
|
stats, err := kubelet.GetContainerInfo("qux", "uuid", "foo", cadvisorReq)
|
2014-06-19 20:34:26 +00:00
|
|
|
if stats != nil {
|
|
|
|
t.Errorf("non-nil stats on error")
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("expect error but received nil error")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if err.Error() != expectedErr.Error() {
|
|
|
|
t.Errorf("wrong error message. expect %v, got %v", err, expectedErr)
|
|
|
|
}
|
|
|
|
mockCadvisor.AssertExpectations(t)
|
|
|
|
}
|
|
|
|
|
2014-07-15 22:40:02 +00:00
|
|
|
func TestGetContainerInfoOnNonExistContainer(t *testing.T) {
|
2014-06-19 20:34:26 +00:00
|
|
|
mockCadvisor := &mockCadvisorClient{}
|
|
|
|
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-07-22 21:40:59 +00:00
|
|
|
kubelet.cadvisorClient = mockCadvisor
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
2014-06-19 20:34:26 +00:00
|
|
|
|
2014-09-05 09:49:11 +00:00
|
|
|
stats, _ := kubelet.GetContainerInfo("qux", "", "foo", nil)
|
2014-06-19 20:34:26 +00:00
|
|
|
if stats != nil {
|
|
|
|
t.Errorf("non-nil stats on non exist container")
|
|
|
|
}
|
|
|
|
mockCadvisor.AssertExpectations(t)
|
|
|
|
}
|
2014-06-19 12:29:42 +00:00
|
|
|
|
2014-08-07 18:15:11 +00:00
|
|
|
type fakeContainerCommandRunner struct {
|
|
|
|
Cmd []string
|
|
|
|
ID string
|
|
|
|
E error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *fakeContainerCommandRunner) RunInContainer(id string, cmd []string) ([]byte, error) {
|
|
|
|
f.Cmd = cmd
|
|
|
|
f.ID = id
|
|
|
|
return []byte{}, f.E
|
|
|
|
}
|
|
|
|
|
2015-02-04 19:50:21 +00:00
|
|
|
func (f *fakeContainerCommandRunner) GetDockerServerVersion() ([]uint, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2014-08-07 18:15:11 +00:00
|
|
|
func TestRunInContainerNoSuchPod(t *testing.T) {
|
|
|
|
fakeCommandRunner := fakeContainerCommandRunner{}
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
2014-08-07 18:15:11 +00:00
|
|
|
kubelet.runner = &fakeCommandRunner
|
|
|
|
|
|
|
|
podName := "podFoo"
|
|
|
|
podNamespace := "etcd"
|
|
|
|
containerName := "containerFoo"
|
|
|
|
output, err := kubelet.RunInContainer(
|
2014-10-23 20:51:34 +00:00
|
|
|
GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{Name: podName, Namespace: podNamespace}}),
|
2014-09-05 09:49:11 +00:00
|
|
|
"",
|
2014-08-07 18:15:11 +00:00
|
|
|
containerName,
|
|
|
|
[]string{"ls"})
|
|
|
|
if output != nil {
|
|
|
|
t.Errorf("unexpected non-nil command: %v", output)
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
t.Error("unexpected non-error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRunInContainer(t *testing.T) {
|
|
|
|
fakeCommandRunner := fakeContainerCommandRunner{}
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-08-07 18:15:11 +00:00
|
|
|
kubelet.runner = &fakeCommandRunner
|
|
|
|
|
|
|
|
containerID := "abc1234"
|
|
|
|
podName := "podFoo"
|
|
|
|
podNamespace := "etcd"
|
|
|
|
containerName := "containerFoo"
|
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-08-07 18:15:11 +00:00
|
|
|
{
|
|
|
|
ID: containerID,
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + ".test_12345678_42"},
|
2014-08-07 18:15:11 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd := []string{"ls"}
|
|
|
|
_, err := kubelet.RunInContainer(
|
2014-10-08 19:56:02 +00:00
|
|
|
GetPodFullName(&api.BoundPod{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: podName,
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: podNamespace,
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
}),
|
2014-09-05 09:49:11 +00:00
|
|
|
"",
|
2014-08-07 18:15:11 +00:00
|
|
|
containerName,
|
|
|
|
cmd)
|
|
|
|
if fakeCommandRunner.ID != containerID {
|
2015-01-18 07:32:34 +00:00
|
|
|
t.Errorf("unexpected Name: %s", fakeCommandRunner.ID)
|
2014-08-07 18:15:11 +00:00
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(fakeCommandRunner.Cmd, cmd) {
|
2015-01-18 07:32:34 +00:00
|
|
|
t.Errorf("unexpected command: %s", fakeCommandRunner.Cmd)
|
2014-08-07 18:15:11 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-03 20:39:56 +00:00
|
|
|
func TestRunHandlerExec(t *testing.T) {
|
|
|
|
fakeCommandRunner := fakeContainerCommandRunner{}
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-03 20:39:56 +00:00
|
|
|
kubelet.runner = &fakeCommandRunner
|
|
|
|
|
|
|
|
containerID := "abc1234"
|
|
|
|
podName := "podFoo"
|
|
|
|
podNamespace := "etcd"
|
|
|
|
containerName := "containerFoo"
|
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{
|
2014-09-03 20:39:56 +00:00
|
|
|
{
|
|
|
|
ID: containerID,
|
2015-01-10 01:19:31 +00:00
|
|
|
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + "_12345678_42"},
|
2014-09-03 20:39:56 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
container := api.Container{
|
|
|
|
Name: containerName,
|
|
|
|
Lifecycle: &api.Lifecycle{
|
|
|
|
PostStart: &api.Handler{
|
|
|
|
Exec: &api.ExecAction{
|
|
|
|
Command: []string{"ls", "-a"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2014-09-05 09:49:11 +00:00
|
|
|
err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart)
|
2014-09-03 20:39:56 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if fakeCommandRunner.ID != containerID ||
|
|
|
|
!reflect.DeepEqual(container.Lifecycle.PostStart.Exec.Command, fakeCommandRunner.Cmd) {
|
|
|
|
t.Errorf("unexpected commands: %v", fakeCommandRunner)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type fakeHTTP struct {
|
|
|
|
url string
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *fakeHTTP) Get(url string) (*http.Response, error) {
|
|
|
|
f.url = url
|
|
|
|
return nil, f.err
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRunHandlerHttp(t *testing.T) {
|
|
|
|
fakeHttp := fakeHTTP{}
|
|
|
|
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, _ := newTestKubelet(t)
|
2014-09-03 20:39:56 +00:00
|
|
|
kubelet.httpClient = &fakeHttp
|
|
|
|
|
|
|
|
podName := "podFoo"
|
|
|
|
podNamespace := "etcd"
|
|
|
|
containerName := "containerFoo"
|
|
|
|
|
|
|
|
container := api.Container{
|
|
|
|
Name: containerName,
|
|
|
|
Lifecycle: &api.Lifecycle{
|
|
|
|
PostStart: &api.Handler{
|
|
|
|
HTTPGet: &api.HTTPGetAction{
|
|
|
|
Host: "foo",
|
|
|
|
Port: util.IntOrString{IntVal: 8080, Kind: util.IntstrInt},
|
|
|
|
Path: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2014-09-05 09:49:11 +00:00
|
|
|
err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart)
|
2014-09-03 20:39:56 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if fakeHttp.url != "http://foo:8080/bar" {
|
|
|
|
t.Errorf("unexpected url: %s", fakeHttp.url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewHandler(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, _ := newTestKubelet(t)
|
2014-09-03 20:39:56 +00:00
|
|
|
handler := &api.Handler{
|
|
|
|
HTTPGet: &api.HTTPGetAction{
|
|
|
|
Host: "foo",
|
|
|
|
Port: util.IntOrString{IntVal: 8080, Kind: util.IntstrInt},
|
|
|
|
Path: "bar",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
actionHandler := kubelet.newActionHandler(handler)
|
|
|
|
if actionHandler == nil {
|
|
|
|
t.Error("unexpected nil action handler.")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = &api.Handler{
|
|
|
|
Exec: &api.ExecAction{
|
|
|
|
Command: []string{"ls", "-l"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
actionHandler = kubelet.newActionHandler(handler)
|
|
|
|
if actionHandler == nil {
|
|
|
|
t.Error("unexpected nil action handler.")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = &api.Handler{}
|
|
|
|
actionHandler = kubelet.newActionHandler(handler)
|
|
|
|
if actionHandler != nil {
|
|
|
|
t.Errorf("unexpected non-nil action handler: %v", actionHandler)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSyncPodEventHandlerFails(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-09-03 20:39:56 +00:00
|
|
|
kubelet.httpClient = &fakeHTTP{
|
|
|
|
err: fmt.Errorf("test error"),
|
|
|
|
}
|
2014-09-09 04:33:17 +00:00
|
|
|
dockerContainers := dockertools.DockerContainers{
|
2014-09-03 20:39:56 +00:00
|
|
|
"9876": &docker.APIContainers{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
|
2014-09-03 20:39:56 +00:00
|
|
|
ID: "9876",
|
|
|
|
},
|
|
|
|
}
|
2014-10-08 19:56:02 +00:00
|
|
|
err := kubelet.syncPod(&api.BoundPod{
|
2014-10-23 20:51:34 +00:00
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-10-22 17:02:02 +00:00
|
|
|
Name: "foo",
|
2014-10-08 19:56:02 +00:00
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
2014-09-03 20:39:56 +00:00
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "bar",
|
|
|
|
Lifecycle: &api.Lifecycle{
|
|
|
|
PostStart: &api.Handler{
|
|
|
|
HTTPGet: &api.HTTPGetAction{
|
|
|
|
Host: "does.no.exist",
|
|
|
|
Port: util.IntOrString{IntVal: 8080, Kind: util.IntstrInt},
|
|
|
|
Path: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, dockerContainers)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-08-26 18:25:17 +00:00
|
|
|
verifyCalls(t, fakeDocker, []string{"list", "list", "create", "start", "stop"})
|
2014-09-03 20:39:56 +00:00
|
|
|
|
2014-09-09 04:33:17 +00:00
|
|
|
if len(fakeDocker.Stopped) != 1 {
|
|
|
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
2014-09-03 20:39:56 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-28 00:29:55 +00:00
|
|
|
|
|
|
|
func TestKubeletGarbageCollection(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
containers []docker.APIContainers
|
|
|
|
containerDetails map[string]*docker.Container
|
|
|
|
expectedRemoved []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
containers: []docker.APIContainers{
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "1876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "2876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "3876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "4876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "5876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "6876",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
containerDetails: map[string]*docker.Container{
|
|
|
|
"1876": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "1876",
|
|
|
|
Created: time.Now(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedRemoved: []string{"1876"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
containers: []docker.APIContainers{
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "1876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "2876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "3876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "4876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "5876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "6876",
|
|
|
|
},
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "7876",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
containerDetails: map[string]*docker.Container{
|
|
|
|
"1876": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: true,
|
|
|
|
},
|
|
|
|
ID: "1876",
|
|
|
|
Created: time.Now(),
|
|
|
|
},
|
|
|
|
"2876": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "2876",
|
|
|
|
Created: time.Now(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedRemoved: []string{"2876"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
containers: []docker.APIContainers{
|
|
|
|
{
|
2015-01-21 00:59:26 +00:00
|
|
|
// pod infra container
|
|
|
|
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
|
2014-10-28 00:29:55 +00:00
|
|
|
ID: "1876",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-10-28 00:29:55 +00:00
|
|
|
kubelet.maxContainerCount = 5
|
|
|
|
fakeDocker.ContainerList = test.containers
|
|
|
|
fakeDocker.ContainerMap = test.containerDetails
|
|
|
|
fakeDocker.Container = &docker.Container{ID: "error", Created: time.Now()}
|
|
|
|
err := kubelet.GarbageCollectContainers()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(fakeDocker.Removed, test.expectedRemoved) {
|
|
|
|
t.Errorf("expected: %v, got: %v", test.expectedRemoved, fakeDocker.Removed)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPurgeOldest(t *testing.T) {
|
|
|
|
created := time.Now()
|
|
|
|
tests := []struct {
|
|
|
|
ids []string
|
|
|
|
containerDetails map[string]*docker.Container
|
|
|
|
expectedRemoved []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
ids: []string{"1", "2", "3", "4", "5"},
|
|
|
|
containerDetails: map[string]*docker.Container{
|
|
|
|
"1": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: true,
|
|
|
|
},
|
|
|
|
ID: "1",
|
|
|
|
Created: created,
|
|
|
|
},
|
|
|
|
"2": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "2",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"3": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "3",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"4": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "4",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"5": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "5",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ids: []string{"1", "2", "3", "4", "5", "6"},
|
|
|
|
containerDetails: map[string]*docker.Container{
|
|
|
|
"1": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "1",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"2": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "2",
|
|
|
|
Created: created.Add(time.Millisecond),
|
|
|
|
},
|
|
|
|
"3": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "3",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"4": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "4",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"5": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "5",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"6": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "6",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedRemoved: []string{"2"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ids: []string{"1", "2", "3", "4", "5", "6", "7"},
|
|
|
|
containerDetails: map[string]*docker.Container{
|
|
|
|
"1": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "1",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"2": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "2",
|
|
|
|
Created: created.Add(time.Millisecond),
|
|
|
|
},
|
|
|
|
"3": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "3",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"4": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "4",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"5": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "5",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
"6": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "6",
|
|
|
|
Created: created.Add(time.Microsecond),
|
|
|
|
},
|
|
|
|
"7": {
|
|
|
|
State: docker.State{
|
|
|
|
Running: false,
|
|
|
|
},
|
|
|
|
ID: "7",
|
|
|
|
Created: created.Add(time.Second),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedRemoved: []string{"2", "6"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-10-28 00:29:55 +00:00
|
|
|
kubelet.maxContainerCount = 5
|
|
|
|
fakeDocker.ContainerMap = test.containerDetails
|
|
|
|
kubelet.purgeOldest(test.ids)
|
|
|
|
if !reflect.DeepEqual(fakeDocker.Removed, test.expectedRemoved) {
|
|
|
|
t.Errorf("expected: %v, got: %v", test.expectedRemoved, fakeDocker.Removed)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-15 00:05:29 +00:00
|
|
|
|
|
|
|
func TestSyncPodsWithPullPolicy(t *testing.T) {
|
2015-01-15 21:52:27 +00:00
|
|
|
kubelet, fakeDocker := newTestKubelet(t)
|
2014-11-15 00:05:29 +00:00
|
|
|
puller := kubelet.dockerPuller.(*dockertools.FakeDockerPuller)
|
|
|
|
puller.HasImages = []string{"existing_one", "want:latest"}
|
2015-01-21 00:59:26 +00:00
|
|
|
kubelet.podInfraContainerImage = "custom_image_name"
|
2014-11-15 00:05:29 +00:00
|
|
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
|
|
|
err := kubelet.SyncPods([]api.BoundPod{
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{
|
2015-01-10 01:19:31 +00:00
|
|
|
UID: "12345678",
|
2014-11-15 00:05:29 +00:00
|
|
|
Name: "foo",
|
|
|
|
Namespace: "new",
|
|
|
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "bar", Image: "pull_always_image", ImagePullPolicy: api.PullAlways},
|
|
|
|
{Name: "bar1", Image: "pull_never_image", ImagePullPolicy: api.PullNever},
|
|
|
|
{Name: "bar2", Image: "pull_if_not_present_image", ImagePullPolicy: api.PullIfNotPresent},
|
|
|
|
{Name: "bar3", Image: "existing_one", ImagePullPolicy: api.PullIfNotPresent},
|
|
|
|
{Name: "bar4", Image: "want:latest", ImagePullPolicy: api.PullIfNotPresent},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
kubelet.drainWorkers()
|
|
|
|
|
|
|
|
fakeDocker.Lock()
|
|
|
|
|
2015-01-17 00:55:19 +00:00
|
|
|
if !reflect.DeepEqual(puller.ImagesPulled, []string{"custom_image_name", "pull_always_image", "pull_if_not_present_image"}) {
|
2014-11-15 00:05:29 +00:00
|
|
|
t.Errorf("Unexpected pulled containers: %v", puller.ImagesPulled)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(fakeDocker.Created) != 6 {
|
|
|
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
|
|
}
|
|
|
|
fakeDocker.Unlock()
|
|
|
|
}
|
2014-12-22 19:54:07 +00:00
|
|
|
|
2014-11-12 05:21:40 +00:00
|
|
|
func TestParseResolvConf(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
data string
|
|
|
|
nameservers []string
|
|
|
|
searches []string
|
|
|
|
}{
|
|
|
|
{"", []string{}, []string{}},
|
|
|
|
{" ", []string{}, []string{}},
|
|
|
|
{"\n", []string{}, []string{}},
|
|
|
|
{"\t\n\t", []string{}, []string{}},
|
|
|
|
{"#comment\n", []string{}, []string{}},
|
|
|
|
{" #comment\n", []string{}, []string{}},
|
|
|
|
{"#comment\n#comment", []string{}, []string{}},
|
|
|
|
{"#comment\nnameserver", []string{}, []string{}},
|
|
|
|
{"#comment\nnameserver\nsearch", []string{}, []string{}},
|
|
|
|
{"nameserver 1.2.3.4", []string{"1.2.3.4"}, []string{}},
|
|
|
|
{" nameserver 1.2.3.4", []string{"1.2.3.4"}, []string{}},
|
|
|
|
{"\tnameserver 1.2.3.4", []string{"1.2.3.4"}, []string{}},
|
|
|
|
{"nameserver\t1.2.3.4", []string{"1.2.3.4"}, []string{}},
|
|
|
|
{"nameserver \t 1.2.3.4", []string{"1.2.3.4"}, []string{}},
|
|
|
|
{"nameserver 1.2.3.4\nnameserver 5.6.7.8", []string{"1.2.3.4", "5.6.7.8"}, []string{}},
|
|
|
|
{"search foo", []string{}, []string{"foo"}},
|
|
|
|
{"search foo bar", []string{}, []string{"foo", "bar"}},
|
|
|
|
{"search foo bar bat\n", []string{}, []string{"foo", "bar", "bat"}},
|
|
|
|
{"search foo\nsearch bar", []string{}, []string{"bar"}},
|
|
|
|
{"nameserver 1.2.3.4\nsearch foo bar", []string{"1.2.3.4"}, []string{"foo", "bar"}},
|
|
|
|
{"nameserver 1.2.3.4\nsearch foo\nnameserver 5.6.7.8\nsearch bar", []string{"1.2.3.4", "5.6.7.8"}, []string{"bar"}},
|
|
|
|
{"#comment\nnameserver 1.2.3.4\n#comment\nsearch foo\ncomment", []string{"1.2.3.4"}, []string{"foo"}},
|
|
|
|
}
|
|
|
|
for i, tc := range testCases {
|
|
|
|
ns, srch, err := parseResolvConf(strings.NewReader(tc.data))
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("expected success, got %v", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(ns, tc.nameservers) {
|
|
|
|
t.Errorf("[%d] expected nameservers %#v, got %#v", i, tc.nameservers, ns)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(srch, tc.searches) {
|
|
|
|
t.Errorf("[%d] expected searches %#v, got %#v", i, tc.searches, srch)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-08 15:25:14 +00:00
|
|
|
|
|
|
|
type testServiceLister struct {
|
|
|
|
services []api.Service
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ls testServiceLister) List() (api.ServiceList, error) {
|
|
|
|
return api.ServiceList{
|
|
|
|
Items: ls.services,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMakeEnvironmentVariables(t *testing.T) {
|
|
|
|
services := []api.Service{
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "kubernetes", Namespace: api.NamespaceDefault},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8081,
|
|
|
|
PortalIP: "1.2.3.1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "kubernetes-ro", Namespace: api.NamespaceDefault},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8082,
|
|
|
|
PortalIP: "1.2.3.2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "test", Namespace: "test1"},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8083,
|
|
|
|
PortalIP: "1.2.3.3",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "kubernetes", Namespace: "test2"},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8084,
|
|
|
|
PortalIP: "1.2.3.4",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "test", Namespace: "test2"},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8085,
|
|
|
|
PortalIP: "1.2.3.5",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "kubernetes", Namespace: "kubernetes"},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8086,
|
|
|
|
PortalIP: "1.2.3.6",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "kubernetes-ro", Namespace: "kubernetes"},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8087,
|
|
|
|
PortalIP: "1.2.3.7",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: api.ObjectMeta{Name: "not-special", Namespace: "kubernetes"},
|
|
|
|
Spec: api.ServiceSpec{
|
|
|
|
Port: 8088,
|
|
|
|
PortalIP: "1.2.3.8",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
name string // the name of the test case
|
|
|
|
ns string // the namespace to generate environment for
|
|
|
|
container *api.Container // the container to use
|
|
|
|
masterServiceNamespace string // the namespace to read master service info from
|
|
|
|
nilLister bool // whether the lister should be nil
|
|
|
|
expectedEnvs util.StringSet // a set of expected environment vars
|
|
|
|
expectedEnvSize int // total number of expected env vars
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"api server = Y, kubelet = Y",
|
|
|
|
"test1",
|
|
|
|
&api.Container{
|
|
|
|
Env: []api.EnvVar{
|
|
|
|
{Name: "FOO", Value: "BAR"},
|
|
|
|
{Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
|
|
|
|
{Name: "TEST_SERVICE_PORT", Value: "8083"},
|
|
|
|
{Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.NamespaceDefault,
|
|
|
|
false,
|
|
|
|
util.NewStringSet("FOO=BAR",
|
|
|
|
"TEST_SERVICE_HOST=1.2.3.3",
|
|
|
|
"TEST_SERVICE_PORT=8083",
|
|
|
|
"TEST_PORT=tcp://1.2.3.3:8083",
|
|
|
|
"TEST_PORT_8083_TCP=tcp://1.2.3.3:8083",
|
|
|
|
"TEST_PORT_8083_TCP_PROTO=tcp",
|
|
|
|
"TEST_PORT_8083_TCP_PORT=8083",
|
|
|
|
"TEST_PORT_8083_TCP_ADDR=1.2.3.3",
|
|
|
|
"KUBERNETES_SERVICE_HOST=1.2.3.1",
|
|
|
|
"KUBERNETES_SERVICE_PORT=8081",
|
|
|
|
"KUBERNETES_PORT=tcp://1.2.3.1:8081",
|
|
|
|
"KUBERNETES_PORT_8081_TCP=tcp://1.2.3.1:8081",
|
|
|
|
"KUBERNETES_PORT_8081_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_PORT_8081_TCP_PORT=8081",
|
|
|
|
"KUBERNETES_PORT_8081_TCP_ADDR=1.2.3.1",
|
|
|
|
"KUBERNETES_RO_SERVICE_HOST=1.2.3.2",
|
|
|
|
"KUBERNETES_RO_SERVICE_PORT=8082",
|
|
|
|
"KUBERNETES_RO_PORT=tcp://1.2.3.2:8082",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP=tcp://1.2.3.2:8082",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP_PORT=8082",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP_ADDR=1.2.3.2"),
|
|
|
|
22,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"api server = Y, kubelet = N",
|
|
|
|
"test1",
|
|
|
|
&api.Container{
|
|
|
|
Env: []api.EnvVar{
|
|
|
|
{Name: "FOO", Value: "BAR"},
|
|
|
|
{Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
|
|
|
|
{Name: "TEST_SERVICE_PORT", Value: "8083"},
|
|
|
|
{Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
|
|
|
|
{Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.NamespaceDefault,
|
|
|
|
true,
|
|
|
|
util.NewStringSet("FOO=BAR",
|
|
|
|
"TEST_SERVICE_HOST=1.2.3.3",
|
|
|
|
"TEST_SERVICE_PORT=8083",
|
|
|
|
"TEST_PORT=tcp://1.2.3.3:8083",
|
|
|
|
"TEST_PORT_8083_TCP=tcp://1.2.3.3:8083",
|
|
|
|
"TEST_PORT_8083_TCP_PROTO=tcp",
|
|
|
|
"TEST_PORT_8083_TCP_PORT=8083",
|
|
|
|
"TEST_PORT_8083_TCP_ADDR=1.2.3.3"),
|
|
|
|
8,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"api server = N; kubelet = Y",
|
|
|
|
"test1",
|
|
|
|
&api.Container{
|
|
|
|
Env: []api.EnvVar{
|
|
|
|
{Name: "FOO", Value: "BAZ"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.NamespaceDefault,
|
|
|
|
false,
|
|
|
|
util.NewStringSet("FOO=BAZ",
|
|
|
|
"TEST_SERVICE_HOST=1.2.3.3",
|
|
|
|
"TEST_SERVICE_PORT=8083",
|
|
|
|
"TEST_PORT=tcp://1.2.3.3:8083",
|
|
|
|
"TEST_PORT_8083_TCP=tcp://1.2.3.3:8083",
|
|
|
|
"TEST_PORT_8083_TCP_PROTO=tcp",
|
|
|
|
"TEST_PORT_8083_TCP_PORT=8083",
|
|
|
|
"TEST_PORT_8083_TCP_ADDR=1.2.3.3",
|
|
|
|
"KUBERNETES_SERVICE_HOST=1.2.3.1",
|
|
|
|
"KUBERNETES_SERVICE_PORT=8081",
|
|
|
|
"KUBERNETES_PORT=tcp://1.2.3.1:8081",
|
|
|
|
"KUBERNETES_PORT_8081_TCP=tcp://1.2.3.1:8081",
|
|
|
|
"KUBERNETES_PORT_8081_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_PORT_8081_TCP_PORT=8081",
|
|
|
|
"KUBERNETES_PORT_8081_TCP_ADDR=1.2.3.1",
|
|
|
|
"KUBERNETES_RO_SERVICE_HOST=1.2.3.2",
|
|
|
|
"KUBERNETES_RO_SERVICE_PORT=8082",
|
|
|
|
"KUBERNETES_RO_PORT=tcp://1.2.3.2:8082",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP=tcp://1.2.3.2:8082",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP_PORT=8082",
|
|
|
|
"KUBERNETES_RO_PORT_8082_TCP_ADDR=1.2.3.2"),
|
|
|
|
22,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"master service in pod ns",
|
|
|
|
"test2",
|
|
|
|
&api.Container{
|
|
|
|
Env: []api.EnvVar{
|
|
|
|
{Name: "FOO", Value: "ZAP"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"kubernetes",
|
|
|
|
false,
|
|
|
|
util.NewStringSet("FOO=ZAP",
|
|
|
|
"TEST_SERVICE_HOST=1.2.3.5",
|
|
|
|
"TEST_SERVICE_PORT=8085",
|
|
|
|
"TEST_PORT=tcp://1.2.3.5:8085",
|
|
|
|
"TEST_PORT_8085_TCP=tcp://1.2.3.5:8085",
|
|
|
|
"TEST_PORT_8085_TCP_PROTO=tcp",
|
|
|
|
"TEST_PORT_8085_TCP_PORT=8085",
|
|
|
|
"TEST_PORT_8085_TCP_ADDR=1.2.3.5",
|
|
|
|
"KUBERNETES_SERVICE_HOST=1.2.3.4",
|
|
|
|
"KUBERNETES_SERVICE_PORT=8084",
|
|
|
|
"KUBERNETES_PORT=tcp://1.2.3.4:8084",
|
|
|
|
"KUBERNETES_PORT_8084_TCP=tcp://1.2.3.4:8084",
|
|
|
|
"KUBERNETES_PORT_8084_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_PORT_8084_TCP_PORT=8084",
|
|
|
|
"KUBERNETES_PORT_8084_TCP_ADDR=1.2.3.4",
|
|
|
|
"KUBERNETES_RO_SERVICE_HOST=1.2.3.7",
|
|
|
|
"KUBERNETES_RO_SERVICE_PORT=8087",
|
|
|
|
"KUBERNETES_RO_PORT=tcp://1.2.3.7:8087",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP=tcp://1.2.3.7:8087",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP_PORT=8087",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP_ADDR=1.2.3.7"),
|
|
|
|
22,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pod in master service ns",
|
|
|
|
"kubernetes",
|
|
|
|
&api.Container{},
|
|
|
|
"kubernetes",
|
|
|
|
false,
|
|
|
|
util.NewStringSet(
|
|
|
|
"NOT_SPECIAL_SERVICE_HOST=1.2.3.8",
|
|
|
|
"NOT_SPECIAL_SERVICE_PORT=8088",
|
|
|
|
"NOT_SPECIAL_PORT=tcp://1.2.3.8:8088",
|
|
|
|
"NOT_SPECIAL_PORT_8088_TCP=tcp://1.2.3.8:8088",
|
|
|
|
"NOT_SPECIAL_PORT_8088_TCP_PROTO=tcp",
|
|
|
|
"NOT_SPECIAL_PORT_8088_TCP_PORT=8088",
|
|
|
|
"NOT_SPECIAL_PORT_8088_TCP_ADDR=1.2.3.8",
|
|
|
|
"KUBERNETES_SERVICE_HOST=1.2.3.6",
|
|
|
|
"KUBERNETES_SERVICE_PORT=8086",
|
|
|
|
"KUBERNETES_PORT=tcp://1.2.3.6:8086",
|
|
|
|
"KUBERNETES_PORT_8086_TCP=tcp://1.2.3.6:8086",
|
|
|
|
"KUBERNETES_PORT_8086_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_PORT_8086_TCP_PORT=8086",
|
|
|
|
"KUBERNETES_PORT_8086_TCP_ADDR=1.2.3.6",
|
|
|
|
"KUBERNETES_RO_SERVICE_HOST=1.2.3.7",
|
|
|
|
"KUBERNETES_RO_SERVICE_PORT=8087",
|
|
|
|
"KUBERNETES_RO_PORT=tcp://1.2.3.7:8087",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP=tcp://1.2.3.7:8087",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP_PROTO=tcp",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP_PORT=8087",
|
|
|
|
"KUBERNETES_RO_PORT_8087_TCP_ADDR=1.2.3.7"),
|
|
|
|
21,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
2015-01-15 21:52:27 +00:00
|
|
|
kl, _ := newTestKubelet(t)
|
2015-01-08 15:25:14 +00:00
|
|
|
kl.masterServiceNamespace = tc.masterServiceNamespace
|
|
|
|
if tc.nilLister {
|
|
|
|
kl.serviceLister = nil
|
|
|
|
} else {
|
|
|
|
kl.serviceLister = testServiceLister{services}
|
|
|
|
}
|
|
|
|
|
|
|
|
result, err := kl.makeEnvironmentVariables(tc.ns, tc.container)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("[%v] Unexpected error: %v", tc.name, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
resultSet := util.NewStringSet(result...)
|
|
|
|
if !resultSet.IsSuperset(tc.expectedEnvs) {
|
|
|
|
t.Errorf("[%v] Unexpected env entries; expected {%v}, got {%v}", tc.name, tc.expectedEnvs, resultSet)
|
|
|
|
}
|
|
|
|
|
|
|
|
if a := len(resultSet); a != tc.expectedEnvSize {
|
|
|
|
t.Errorf("[%v] Unexpected number of env vars; expected %v, got %v", tc.name, tc.expectedEnvSize, a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-28 17:56:35 +00:00
|
|
|
|
|
|
|
func TestPodPhaseWithRestartAlways(t *testing.T) {
|
|
|
|
desiredState := api.PodSpec{
|
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "containerA"},
|
|
|
|
{Name: "containerB"},
|
|
|
|
},
|
|
|
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
|
|
|
}
|
|
|
|
currentState := api.PodStatus{
|
|
|
|
Host: "machine",
|
|
|
|
}
|
|
|
|
runningState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Running: &api.ContainerStateRunning{},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
stoppedState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Termination: &api.ContainerStateTerminated{},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
pod *api.Pod
|
|
|
|
status api.PodPhase
|
|
|
|
test string
|
|
|
|
}{
|
|
|
|
{&api.Pod{Spec: desiredState, Status: currentState}, api.PodPending, "waiting"},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
"containerB": runningState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"all running",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": stoppedState,
|
|
|
|
"containerB": stoppedState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"all stopped with restart always",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
"containerB": stoppedState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"mixed state #1 with restart always",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodPending,
|
|
|
|
"mixed state #2 with restart always",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
if status := getPhase(&test.pod.Spec, test.pod.Status.Info); status != test.status {
|
|
|
|
t.Errorf("In test %s, expected %v, got %v", test.test, test.status, status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPodPhaseWithRestartNever(t *testing.T) {
|
|
|
|
desiredState := api.PodSpec{
|
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "containerA"},
|
|
|
|
{Name: "containerB"},
|
|
|
|
},
|
|
|
|
RestartPolicy: api.RestartPolicy{Never: &api.RestartPolicyNever{}},
|
|
|
|
}
|
|
|
|
currentState := api.PodStatus{
|
|
|
|
Host: "machine",
|
|
|
|
}
|
|
|
|
runningState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Running: &api.ContainerStateRunning{},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
succeededState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Termination: &api.ContainerStateTerminated{
|
|
|
|
ExitCode: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
failedState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Termination: &api.ContainerStateTerminated{
|
|
|
|
ExitCode: -1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
pod *api.Pod
|
|
|
|
status api.PodPhase
|
|
|
|
test string
|
|
|
|
}{
|
|
|
|
{&api.Pod{Spec: desiredState, Status: currentState}, api.PodPending, "waiting"},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
"containerB": runningState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"all running with restart never",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": succeededState,
|
|
|
|
"containerB": succeededState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodSucceeded,
|
|
|
|
"all succeeded with restart never",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": failedState,
|
|
|
|
"containerB": failedState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodFailed,
|
|
|
|
"all failed with restart never",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
"containerB": succeededState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"mixed state #1 with restart never",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodPending,
|
|
|
|
"mixed state #2 with restart never",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
if status := getPhase(&test.pod.Spec, test.pod.Status.Info); status != test.status {
|
|
|
|
t.Errorf("In test %s, expected %v, got %v", test.test, test.status, status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPodPhaseWithRestartOnFailure(t *testing.T) {
|
|
|
|
desiredState := api.PodSpec{
|
|
|
|
Containers: []api.Container{
|
|
|
|
{Name: "containerA"},
|
|
|
|
{Name: "containerB"},
|
|
|
|
},
|
|
|
|
RestartPolicy: api.RestartPolicy{OnFailure: &api.RestartPolicyOnFailure{}},
|
|
|
|
}
|
|
|
|
currentState := api.PodStatus{
|
|
|
|
Host: "machine",
|
|
|
|
}
|
|
|
|
runningState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Running: &api.ContainerStateRunning{},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
succeededState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Termination: &api.ContainerStateTerminated{
|
|
|
|
ExitCode: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
failedState := api.ContainerStatus{
|
|
|
|
State: api.ContainerState{
|
|
|
|
Termination: &api.ContainerStateTerminated{
|
|
|
|
ExitCode: -1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
pod *api.Pod
|
|
|
|
status api.PodPhase
|
|
|
|
test string
|
|
|
|
}{
|
|
|
|
{&api.Pod{Spec: desiredState, Status: currentState}, api.PodPending, "waiting"},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
"containerB": runningState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"all running with restart onfailure",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": succeededState,
|
|
|
|
"containerB": succeededState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodSucceeded,
|
|
|
|
"all succeeded with restart onfailure",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": failedState,
|
|
|
|
"containerB": failedState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"all failed with restart never",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
"containerB": succeededState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodRunning,
|
|
|
|
"mixed state #1 with restart onfailure",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&api.Pod{
|
|
|
|
Spec: desiredState,
|
|
|
|
Status: api.PodStatus{
|
|
|
|
Info: map[string]api.ContainerStatus{
|
|
|
|
"containerA": runningState,
|
|
|
|
},
|
|
|
|
Host: "machine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
api.PodPending,
|
|
|
|
"mixed state #2 with restart onfailure",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
if status := getPhase(&test.pod.Spec, test.pod.Status.Info); status != test.status {
|
|
|
|
t.Errorf("In test %s, expected %v, got %v", test.test, test.status, status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|