mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 16:29:21 +00:00
Merge pull request #827 from brendandburns/kubelet
Add container hashing to the container name, and restart containers on changes.
This commit is contained in:
commit
4c00acdde0
@ -19,12 +19,15 @@ package kubelet
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/adler32"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/fsouza/go-dockerclient"
|
"github.com/fsouza/go-dockerclient"
|
||||||
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DockerContainerData is the structured representation of the JSON object returned by Docker inspect
|
// DockerContainerData is the structured representation of the JSON object returned by Docker inspect
|
||||||
@ -106,21 +109,21 @@ func (p dockerPuller) Pull(image string) error {
|
|||||||
// DockerContainers is a map of containers
|
// DockerContainers is a map of containers
|
||||||
type DockerContainers map[DockerID]*docker.APIContainers
|
type DockerContainers map[DockerID]*docker.APIContainers
|
||||||
|
|
||||||
func (c DockerContainers) FindPodContainer(podFullName, containerName string) (*docker.APIContainers, bool) {
|
func (c DockerContainers) FindPodContainer(podFullName, containerName string) (*docker.APIContainers, bool, uint64) {
|
||||||
for _, dockerContainer := range c {
|
for _, dockerContainer := range c {
|
||||||
dockerManifestID, dockerContainerName := parseDockerName(dockerContainer.Names[0])
|
dockerManifestID, dockerContainerName, hash := parseDockerName(dockerContainer.Names[0])
|
||||||
if dockerManifestID == podFullName && dockerContainerName == containerName {
|
if dockerManifestID == podFullName && dockerContainerName == containerName {
|
||||||
return dockerContainer, true
|
return dockerContainer, true, hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c DockerContainers) FindContainersByPodFullName(podFullName string) map[string]*docker.APIContainers {
|
func (c DockerContainers) FindContainersByPodFullName(podFullName string) map[string]*docker.APIContainers {
|
||||||
containers := make(map[string]*docker.APIContainers)
|
containers := make(map[string]*docker.APIContainers)
|
||||||
|
|
||||||
for _, dockerContainer := range c {
|
for _, dockerContainer := range c {
|
||||||
dockerManifestID, dockerContainerName := parseDockerName(dockerContainer.Names[0])
|
dockerManifestID, dockerContainerName, _ := parseDockerName(dockerContainer.Names[0])
|
||||||
if dockerManifestID == podFullName {
|
if dockerManifestID == podFullName {
|
||||||
containers[dockerContainerName] = dockerContainer
|
containers[dockerContainerName] = dockerContainer
|
||||||
}
|
}
|
||||||
@ -160,7 +163,7 @@ func getDockerPodInfo(client DockerInterface, podFullName string) (api.PodInfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range containers {
|
for _, value := range containers {
|
||||||
dockerManifestID, dockerContainerName := parseDockerName(value.Names[0])
|
dockerManifestID, dockerContainerName, _ := parseDockerName(value.Names[0])
|
||||||
if dockerManifestID != podFullName {
|
if dockerManifestID != podFullName {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -198,15 +201,22 @@ func unescapeDash(in string) (out string) {
|
|||||||
|
|
||||||
const containerNamePrefix = "k8s"
|
const containerNamePrefix = "k8s"
|
||||||
|
|
||||||
|
func hashContainer(container *api.Container) uint64 {
|
||||||
|
hash := adler32.New()
|
||||||
|
fmt.Fprintf(hash, "%#v", *container)
|
||||||
|
return uint64(hash.Sum32())
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a name which can be reversed to identify both full pod name and container name.
|
// Creates a name which can be reversed to identify both full pod name and container name.
|
||||||
func buildDockerName(pod *Pod, container *api.Container) string {
|
func buildDockerName(pod *Pod, container *api.Container) string {
|
||||||
|
containerName := escapeDash(container.Name) + "." + strconv.FormatUint(hashContainer(container), 16)
|
||||||
// Note, manifest.ID could be blank.
|
// Note, manifest.ID could be blank.
|
||||||
return fmt.Sprintf("%s--%s--%s--%08x", containerNamePrefix, escapeDash(container.Name), escapeDash(GetPodFullName(pod)), rand.Uint32())
|
return fmt.Sprintf("%s--%s--%s--%08x", containerNamePrefix, containerName, escapeDash(GetPodFullName(pod)), rand.Uint32())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upacks a container name, returning the pod full name and container name we would have used to
|
// Upacks a container name, returning the pod full name and container name we would have used to
|
||||||
// construct the docker name. If the docker name isn't one we created, we may return empty strings.
|
// construct the docker name. If the docker name isn't one we created, we may return empty strings.
|
||||||
func parseDockerName(name string) (podFullName, containerName string) {
|
func parseDockerName(name string) (podFullName, containerName string, hash uint64) {
|
||||||
// For some reason docker appears to be appending '/' to names.
|
// For some reason docker appears to be appending '/' to names.
|
||||||
// If it's there, strip it.
|
// If it's there, strip it.
|
||||||
if name[0] == '/' {
|
if name[0] == '/' {
|
||||||
@ -217,7 +227,15 @@ func parseDockerName(name string) (podFullName, containerName string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(parts) > 1 {
|
if len(parts) > 1 {
|
||||||
containerName = unescapeDash(parts[1])
|
pieces := strings.Split(parts[1], ".")
|
||||||
|
containerName = unescapeDash(pieces[0])
|
||||||
|
if len(pieces) > 1 {
|
||||||
|
var err error
|
||||||
|
hash, err = strconv.ParseUint(pieces[1], 16, 32)
|
||||||
|
if err != nil {
|
||||||
|
glog.Infof("invalid container hash: %s", pieces[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(parts) > 2 {
|
if len(parts) > 2 {
|
||||||
podFullName = unescapeDash(parts[2])
|
podFullName = unescapeDash(parts[2])
|
||||||
|
@ -322,7 +322,7 @@ func (kl *Kubelet) runContainer(pod *Pod, container *api.Container, podVolumes v
|
|||||||
func (kl *Kubelet) killContainer(dockerContainer *docker.APIContainers) error {
|
func (kl *Kubelet) killContainer(dockerContainer *docker.APIContainers) error {
|
||||||
glog.Infof("Killing: %s", dockerContainer.ID)
|
glog.Infof("Killing: %s", dockerContainer.ID)
|
||||||
err := kl.dockerClient.StopContainer(dockerContainer.ID, 10)
|
err := kl.dockerClient.StopContainer(dockerContainer.ID, 10)
|
||||||
podFullName, containerName := parseDockerName(dockerContainer.Names[0])
|
podFullName, containerName, _ := parseDockerName(dockerContainer.Names[0])
|
||||||
kl.LogEvent(&api.Event{
|
kl.LogEvent(&api.Event{
|
||||||
Event: "STOP",
|
Event: "STOP",
|
||||||
Manifest: &api.ContainerManifest{
|
Manifest: &api.ContainerManifest{
|
||||||
@ -366,7 +366,7 @@ func (kl *Kubelet) deleteAllContainers(pod *Pod, podFullName string, dockerConta
|
|||||||
errs := make(chan error, len(pod.Manifest.Containers))
|
errs := make(chan error, len(pod.Manifest.Containers))
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
for _, container := range pod.Manifest.Containers {
|
for _, container := range pod.Manifest.Containers {
|
||||||
if dockerContainer, found := dockerContainers.FindPodContainer(podFullName, container.Name); found {
|
if dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, container.Name); found {
|
||||||
count++
|
count++
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -400,7 +400,7 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
|||||||
|
|
||||||
// Make sure we have a network container
|
// Make sure we have a network container
|
||||||
var netID DockerID
|
var netID DockerID
|
||||||
if networkDockerContainer, found := dockerContainers.FindPodContainer(podFullName, networkContainerName); found {
|
if networkDockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, networkContainerName); found {
|
||||||
netID = DockerID(networkDockerContainer.ID)
|
netID = DockerID(networkDockerContainer.ID)
|
||||||
} else {
|
} else {
|
||||||
glog.Infof("Network container doesn't exist, creating")
|
glog.Infof("Network container doesn't exist, creating")
|
||||||
@ -442,23 +442,28 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, container := range pod.Manifest.Containers {
|
for _, container := range pod.Manifest.Containers {
|
||||||
if dockerContainer, found := dockerContainers.FindPodContainer(podFullName, container.Name); found {
|
expectedHash := hashContainer(&container)
|
||||||
|
if dockerContainer, found, hash := dockerContainers.FindPodContainer(podFullName, container.Name); found {
|
||||||
containerID := DockerID(dockerContainer.ID)
|
containerID := DockerID(dockerContainer.ID)
|
||||||
glog.Infof("pod %s container %s exists as %v", podFullName, container.Name, containerID)
|
glog.Infof("pod %s container %s exists as %v", podFullName, container.Name, containerID)
|
||||||
glog.V(1).Infof("pod %s container %s exists as %v", podFullName, container.Name, containerID)
|
glog.V(1).Infof("pod %s container %s exists as %v", podFullName, container.Name, containerID)
|
||||||
|
|
||||||
// TODO: This should probably be separated out into a separate goroutine.
|
// look for changes in the container.
|
||||||
healthy, err := kl.healthy(podState, container, dockerContainer)
|
if hash == 0 || hash == expectedHash {
|
||||||
if err != nil {
|
// TODO: This should probably be separated out into a separate goroutine.
|
||||||
glog.V(1).Infof("health check errored: %v", err)
|
healthy, err := kl.healthy(podState, container, dockerContainer)
|
||||||
continue
|
if err != nil {
|
||||||
|
glog.V(1).Infof("health check errored: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if healthy == health.Healthy {
|
||||||
|
containersToKeep[containerID] = empty{}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
glog.V(1).Infof("pod %s container %s is unhealthy.", podFullName, container.Name, healthy)
|
||||||
|
} else {
|
||||||
|
glog.V(1).Infof("container hash changed %d vs %d.", hash, expectedHash)
|
||||||
}
|
}
|
||||||
if healthy == health.Healthy {
|
|
||||||
containersToKeep[containerID] = empty{}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(1).Infof("pod %s container %s is unhealthy.", podFullName, container.Name, healthy)
|
|
||||||
if err := kl.killContainer(dockerContainer); err != nil {
|
if err := kl.killContainer(dockerContainer); err != nil {
|
||||||
glog.V(1).Infof("Failed to kill container %s: %v", dockerContainer.ID, err)
|
glog.V(1).Infof("Failed to kill container %s: %v", dockerContainer.ID, err)
|
||||||
continue
|
continue
|
||||||
@ -482,7 +487,7 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
|||||||
|
|
||||||
// Kill any containers in this pod which were not identified above (guards against duplicates).
|
// Kill any containers in this pod which were not identified above (guards against duplicates).
|
||||||
for id, container := range dockerContainers {
|
for id, container := range dockerContainers {
|
||||||
curPodFullName, _ := parseDockerName(container.Names[0])
|
curPodFullName, _, _ := parseDockerName(container.Names[0])
|
||||||
if curPodFullName == podFullName {
|
if curPodFullName == podFullName {
|
||||||
// Don't kill containers we want to keep or those we already killed.
|
// Don't kill containers we want to keep or those we already killed.
|
||||||
_, keep := containersToKeep[id]
|
_, keep := containersToKeep[id]
|
||||||
@ -577,7 +582,7 @@ func (kl *Kubelet) SyncPods(pods []Pod) error {
|
|||||||
}
|
}
|
||||||
for _, container := range existingContainers {
|
for _, container := range existingContainers {
|
||||||
// Don't kill containers that are in the desired pods.
|
// Don't kill containers that are in the desired pods.
|
||||||
podFullName, containerName := parseDockerName(container.Names[0])
|
podFullName, containerName, _ := parseDockerName(container.Names[0])
|
||||||
if _, ok := desiredContainers[podContainer{podFullName, containerName}]; !ok {
|
if _, ok := desiredContainers[podContainer{podFullName, containerName}]; !ok {
|
||||||
err = kl.killContainer(container)
|
err = kl.killContainer(container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -681,7 +686,7 @@ func (kl *Kubelet) GetContainerInfo(podFullName, containerName string, req *info
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dockerContainer, found := dockerContainers.FindPodContainer(podFullName, containerName)
|
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, containerName)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, errors.New("couldn't find container")
|
return nil, errors.New("couldn't find container")
|
||||||
}
|
}
|
||||||
@ -727,7 +732,7 @@ func (kl *Kubelet) RunInContainer(pod *Pod, container string, cmd []string) ([]b
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dockerContainer, found := dockerContainers.FindPodContainer(podFullName, container)
|
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, container)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, fmt.Errorf("container not found (%s)", container)
|
return nil, fmt.Errorf("container not found (%s)", container)
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,10 @@ package kubelet
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/adler32"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -70,14 +72,19 @@ func verifyStringArrayEquals(t *testing.T, actual, expected []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func verifyPackUnpack(t *testing.T, podNamespace, podName, containerName string) {
|
func verifyPackUnpack(t *testing.T, podNamespace, podName, containerName string) {
|
||||||
|
container := &api.Container{Name: containerName}
|
||||||
|
hasher := adler32.New()
|
||||||
|
data := fmt.Sprintf("%#v", *container)
|
||||||
|
hasher.Write([]byte(data))
|
||||||
|
computedHash := uint64(hasher.Sum32())
|
||||||
name := buildDockerName(
|
name := buildDockerName(
|
||||||
&Pod{Name: podName, Namespace: podNamespace},
|
&Pod{Name: podName, Namespace: podNamespace},
|
||||||
&api.Container{Name: containerName},
|
container,
|
||||||
)
|
)
|
||||||
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
||||||
returnedPodFullName, returnedContainerName := parseDockerName(name)
|
returnedPodFullName, returnedContainerName, hash := parseDockerName(name)
|
||||||
if podFullName != returnedPodFullName || containerName != returnedContainerName {
|
if podFullName != returnedPodFullName || containerName != returnedContainerName || computedHash != hash {
|
||||||
t.Errorf("For (%s, %s), unpacked (%s, %s)", podFullName, containerName, returnedPodFullName, returnedContainerName)
|
t.Errorf("For (%s, %s, %d), unpacked (%s, %s, %d)", podFullName, containerName, computedHash, returnedPodFullName, returnedContainerName, hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +100,17 @@ func TestContainerManifestNaming(t *testing.T) {
|
|||||||
verifyPackUnpack(t, "file", "--manifest", "__container")
|
verifyPackUnpack(t, "file", "--manifest", "__container")
|
||||||
verifyPackUnpack(t, "", "m___anifest_", "container-_-")
|
verifyPackUnpack(t, "", "m___anifest_", "container-_-")
|
||||||
verifyPackUnpack(t, "other", "_m___anifest", "-_-container")
|
verifyPackUnpack(t, "other", "_m___anifest", "-_-container")
|
||||||
|
|
||||||
|
container := &api.Container{Name: "container"}
|
||||||
|
pod := &Pod{Name: "foo", Namespace: "test"}
|
||||||
|
name := fmt.Sprintf("k8s--%s--%s.%s--12345", container.Name, pod.Name, pod.Namespace)
|
||||||
|
|
||||||
|
podFullName := fmt.Sprintf("%s.%s", pod.Name, pod.Namespace)
|
||||||
|
returnedPodFullName, returnedContainerName, hash := parseDockerName(name)
|
||||||
|
if returnedPodFullName != podFullName || returnedContainerName != container.Name || hash != 0 {
|
||||||
|
t.Errorf("unexpected parse: %s %s %d", returnedPodFullName, returnedContainerName, hash)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContainerID(t *testing.T) {
|
func TestGetContainerID(t *testing.T) {
|
||||||
@ -119,13 +137,13 @@ func TestGetContainerID(t *testing.T) {
|
|||||||
t.Errorf("Expected %#v, Got %#v", fakeDocker.containerList, dockerContainers)
|
t.Errorf("Expected %#v, Got %#v", fakeDocker.containerList, dockerContainers)
|
||||||
}
|
}
|
||||||
verifyCalls(t, fakeDocker, []string{"list"})
|
verifyCalls(t, fakeDocker, []string{"list"})
|
||||||
dockerContainer, found := dockerContainers.FindPodContainer("qux", "foo")
|
dockerContainer, found, _ := dockerContainers.FindPodContainer("qux", "foo")
|
||||||
if dockerContainer == nil || !found {
|
if dockerContainer == nil || !found {
|
||||||
t.Errorf("Failed to find container %#v", dockerContainer)
|
t.Errorf("Failed to find container %#v", dockerContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeDocker.clearCalls()
|
fakeDocker.clearCalls()
|
||||||
dockerContainer, found = dockerContainers.FindPodContainer("foobar", "foo")
|
dockerContainer, found, _ = dockerContainers.FindPodContainer("foobar", "foo")
|
||||||
verifyCalls(t, fakeDocker, []string{})
|
verifyCalls(t, fakeDocker, []string{})
|
||||||
if dockerContainer != nil || found {
|
if dockerContainer != nil || found {
|
||||||
t.Errorf("Should not have found container %#v", dockerContainer)
|
t.Errorf("Should not have found container %#v", dockerContainer)
|
||||||
@ -206,10 +224,11 @@ func (cr *channelReader) GetList() [][]Pod {
|
|||||||
|
|
||||||
func TestSyncPodsDoesNothing(t *testing.T) {
|
func TestSyncPodsDoesNothing(t *testing.T) {
|
||||||
kubelet, _, fakeDocker := makeTestKubelet(t)
|
kubelet, _, fakeDocker := makeTestKubelet(t)
|
||||||
|
container := api.Container{Name: "bar"}
|
||||||
fakeDocker.containerList = []docker.APIContainers{
|
fakeDocker.containerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// format is k8s--<container-id>--<pod-fullname>
|
// format is k8s--<container-id>--<pod-fullname>
|
||||||
Names: []string{"/k8s--bar--foo.test"},
|
Names: []string{"/k8s--bar." + strconv.FormatUint(hashContainer(&container), 16) + "--foo.test"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -218,9 +237,6 @@ func TestSyncPodsDoesNothing(t *testing.T) {
|
|||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeDocker.container = &docker.Container{
|
|
||||||
ID: "1234",
|
|
||||||
}
|
|
||||||
err := kubelet.SyncPods([]Pod{
|
err := kubelet.SyncPods([]Pod{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
@ -228,7 +244,7 @@ func TestSyncPodsDoesNothing(t *testing.T) {
|
|||||||
Manifest: api.ContainerManifest{
|
Manifest: api.ContainerManifest{
|
||||||
ID: "foo",
|
ID: "foo",
|
||||||
Containers: []api.Container{
|
Containers: []api.Container{
|
||||||
{Name: "bar"},
|
container,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -253,6 +269,14 @@ func (kl *Kubelet) drainWorkers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
|
func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
|
||||||
kubelet, _, fakeDocker := makeTestKubelet(t)
|
kubelet, _, fakeDocker := makeTestKubelet(t)
|
||||||
fakeDocker.containerList = []docker.APIContainers{}
|
fakeDocker.containerList = []docker.APIContainers{}
|
||||||
@ -278,8 +302,8 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
|
|||||||
|
|
||||||
fakeDocker.lock.Lock()
|
fakeDocker.lock.Lock()
|
||||||
if len(fakeDocker.Created) != 2 ||
|
if len(fakeDocker.Created) != 2 ||
|
||||||
!strings.HasPrefix(fakeDocker.Created[0], "k8s--net--foo.test--") ||
|
!matchString(t, "k8s--net\\.[a-f0-9]+--foo.test--", fakeDocker.Created[0]) ||
|
||||||
!strings.HasPrefix(fakeDocker.Created[1], "k8s--bar--foo.test--") {
|
!matchString(t, "k8s--bar\\.[a-f0-9]+--foo.test--", fakeDocker.Created[1]) {
|
||||||
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
||||||
}
|
}
|
||||||
fakeDocker.lock.Unlock()
|
fakeDocker.lock.Unlock()
|
||||||
@ -316,7 +340,7 @@ func TestSyncPodsWithNetCreatesContainer(t *testing.T) {
|
|||||||
|
|
||||||
fakeDocker.lock.Lock()
|
fakeDocker.lock.Lock()
|
||||||
if len(fakeDocker.Created) != 1 ||
|
if len(fakeDocker.Created) != 1 ||
|
||||||
!strings.HasPrefix(fakeDocker.Created[0], "k8s--bar--foo.test--") {
|
!matchString(t, "k8s--bar\\.[a-f0-9]+--foo.test--", fakeDocker.Created[0]) {
|
||||||
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
||||||
}
|
}
|
||||||
fakeDocker.lock.Unlock()
|
fakeDocker.lock.Unlock()
|
||||||
@ -453,6 +477,48 @@ func (f *FalseHealthChecker) HealthCheck(state api.PodState, container api.Conta
|
|||||||
return health.Unhealthy, nil
|
return health.Unhealthy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSyncPodBadHash(t *testing.T) {
|
||||||
|
kubelet, _, fakeDocker := makeTestKubelet(t)
|
||||||
|
kubelet.healthChecker = &FalseHealthChecker{}
|
||||||
|
dockerContainers := DockerContainers{
|
||||||
|
"1234": &docker.APIContainers{
|
||||||
|
// the k8s prefix is required for the kubelet to manage the container
|
||||||
|
Names: []string{"/k8s--bar.1234--foo.test"},
|
||||||
|
ID: "1234",
|
||||||
|
},
|
||||||
|
"9876": &docker.APIContainers{
|
||||||
|
// network container
|
||||||
|
Names: []string{"/k8s--net--foo.test--"},
|
||||||
|
ID: "9876",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err := kubelet.syncPod(&Pod{
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "test",
|
||||||
|
Manifest: api.ContainerManifest{
|
||||||
|
ID: "foo",
|
||||||
|
Containers: []api.Container{
|
||||||
|
{Name: "bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, dockerContainers)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{"list", "stop", "create", "start"})
|
||||||
|
|
||||||
|
// A map interation is used to delete containers, so must not depend on
|
||||||
|
// order here.
|
||||||
|
expectedToStop := map[string]bool{
|
||||||
|
"1234": true,
|
||||||
|
}
|
||||||
|
if len(fakeDocker.stopped) != 1 ||
|
||||||
|
!expectedToStop[fakeDocker.stopped[0]] {
|
||||||
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.stopped)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSyncPodUnhealthy(t *testing.T) {
|
func TestSyncPodUnhealthy(t *testing.T) {
|
||||||
kubelet, _, fakeDocker := makeTestKubelet(t)
|
kubelet, _, fakeDocker := makeTestKubelet(t)
|
||||||
kubelet.healthChecker = &FalseHealthChecker{}
|
kubelet.healthChecker = &FalseHealthChecker{}
|
||||||
|
Loading…
Reference in New Issue
Block a user