Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add node e2e test for mirror pod. #24443

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions test/e2e_node/e2e_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type e2eService struct {
apiServerCombinedOut bytes.Buffer
kubeletCmd *exec.Cmd
kubeletCombinedOut bytes.Buffer
kubeletStaticPodDir string
nodeName string
}

Expand Down Expand Up @@ -83,6 +84,12 @@ func (es *e2eService) stop() {
glog.Errorf("Failed to stop kubelet.\n%v", err)
}
}
if es.kubeletStaticPodDir != "" {
err := os.RemoveAll(es.kubeletStaticPodDir)
if err != nil {
glog.Errorf("Failed to delete kubelet static pod directory %s.\n%v", es.kubeletStaticPodDir, err)
}
}
if es.apiServerCmd != nil {
err := es.apiServerCmd.Process.Kill()
if err != nil {
Expand Down Expand Up @@ -137,6 +144,11 @@ func (es *e2eService) startApiServer() (*exec.Cmd, error) {
}

func (es *e2eService) startKubeletServer() (*exec.Cmd, error) {
dataDir, err := ioutil.TempDir("", "node-e2e-pod")
if err != nil {
return nil, err
}
es.kubeletStaticPodDir = dataDir
cmd := exec.Command("sudo", getKubeletServerBin(),
"--v", "2", "--logtostderr", "--log_dir", "./",
"--api-servers", "http://127.0.0.1:8080",
Expand All @@ -146,6 +158,8 @@ func (es *e2eService) startKubeletServer() (*exec.Cmd, error) {
"--volume-stats-agg-period", "10s", // Aggregate volumes frequently so tests don't need to wait as long
"--allow-privileged", "true",
"--serialize-image-pulls", "false",
"--config", es.kubeletStaticPodDir,
"--file-check-frequency", "10s", // Check file frequently so tests won't wait too long
)
hcc := newHealthCheckCommand(
"http://127.0.0.1:10255/healthz",
Expand Down
189 changes: 189 additions & 0 deletions test/e2e_node/mirror_pod_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
Copyright 2016 The Kubernetes Authors 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.
*/

package e2e_node

import (
"fmt"
"os"
"path/filepath"
"time"

"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/restclient"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("MirrorPod", func() {
var cl *client.Client
BeforeEach(func() {
// Setup the apiserver client
cl = client.NewOrDie(&restclient.Config{Host: *apiServerAddress})
})
ns := "mirror-pod"
Context("when create a mirror pod ", func() {
var staticPodName, mirrorPodName string
BeforeEach(func() {
staticPodName = "static-pod-" + string(util.NewUUID())
mirrorPodName = staticPodName + "-" + e2es.nodeName

By("create the static pod")
err := createStaticPod(e2es.kubeletStaticPodDir, staticPodName, ns, "gcr.io/google_containers/nginx:1.7.9", api.RestartPolicyAlways)
Expect(err).ShouldNot(HaveOccurred())

By("wait for the mirror pod to be running")
Eventually(func() error {
return checkMirrorPodRunning(cl, mirrorPodName, ns)
}, 2*time.Minute, time.Second*4).Should(BeNil())
})
It("should be updated when static pod updated", func() {
By("get mirror pod uid")
pod, err := cl.Pods(ns).Get(mirrorPodName)
Expect(err).ShouldNot(HaveOccurred())
uid := pod.UID

By("update the static pod container image")
image := "gcr.io/google_containers/pause:2.0"
err = createStaticPod(e2es.kubeletStaticPodDir, staticPodName, ns, image, api.RestartPolicyAlways)
Expect(err).ShouldNot(HaveOccurred())

By("wait for the mirror pod to be updated")
Eventually(func() error {
return checkMirrorPodRecreatedAndRunnig(cl, mirrorPodName, ns, uid)
}, 2*time.Minute, time.Second*4).Should(BeNil())

By("check the mirror pod container image is updated")
pod, err = cl.Pods(ns).Get(mirrorPodName)
Expect(err).ShouldNot(HaveOccurred())
Expect(len(pod.Spec.Containers)).Should(Equal(1))
Expect(pod.Spec.Containers[0].Image).Should(Equal(image))
})
It("should be recreated when mirror pod gracefully deleted", func() {
By("get mirror pod uid")
pod, err := cl.Pods(ns).Get(mirrorPodName)
Expect(err).ShouldNot(HaveOccurred())
uid := pod.UID

By("delete the mirror pod with grace period 30s")
err = cl.Pods(ns).Delete(mirrorPodName, api.NewDeleteOptions(30))
Expect(err).ShouldNot(HaveOccurred())

By("wait for the mirror pod to be recreated")
Eventually(func() error {
return checkMirrorPodRecreatedAndRunnig(cl, mirrorPodName, ns, uid)
}, 2*time.Minute, time.Second*4).Should(BeNil())
})
It("should be recreated when mirror pod forcibly deleted", func() {
By("get mirror pod uid")
pod, err := cl.Pods(ns).Get(mirrorPodName)
Expect(err).ShouldNot(HaveOccurred())
uid := pod.UID

By("delete the mirror pod with grace period 0s")
err = cl.Pods(ns).Delete(mirrorPodName, api.NewDeleteOptions(0))
Expect(err).ShouldNot(HaveOccurred())

By("wait for the mirror pod to be recreated")
Eventually(func() error {
return checkMirrorPodRecreatedAndRunnig(cl, mirrorPodName, ns, uid)
}, 2*time.Minute, time.Second*4).Should(BeNil())
})
AfterEach(func() {
By("delete the static pod")
err := deleteStaticPod(e2es.kubeletStaticPodDir, staticPodName, ns)
Expect(err).ShouldNot(HaveOccurred())

By("wait for the mirror pod to disappear")
Eventually(func() error {
return checkMirrorPodDisappear(cl, mirrorPodName, ns)
}, 2*time.Minute, time.Second*4).Should(BeNil())
})
})
})

func staticPodPath(dir, name, namespace string) string {
return filepath.Join(dir, namespace+"-"+name+".yaml")
}

func createStaticPod(dir, name, namespace, image string, restart api.RestartPolicy) error {
template := `
apiVersion: v1
kind: Pod
metadata:
name: %s
namespace: %s
spec:
containers:
- name: test
image: %s
restartPolicy: %s
`
file := staticPodPath(dir, name, namespace)
podYaml := fmt.Sprintf(template, name, namespace, image, string(restart))

f, err := os.OpenFile(file, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
if err != nil {
return err
}
defer f.Close()

_, err = f.WriteString(podYaml)
return err
}

func deleteStaticPod(dir, name, namespace string) error {
file := staticPodPath(dir, name, namespace)
return os.Remove(file)
}

func checkMirrorPodDisappear(cl *client.Client, name, namespace string) error {
_, err := cl.Pods(namespace).Get(name)
if errors.IsNotFound(err) {
return nil
}
return err
}

func checkMirrorPodRunning(cl *client.Client, name, namespace string) error {
pod, err := cl.Pods(namespace).Get(name)
if err != nil {
return fmt.Errorf("expected the mirror pod %q to appear: %v", name, err)
}
if pod.Status.Phase != api.PodRunning {
return fmt.Errorf("expected the mirror pod %q to be running, got %q", name, pod.Status.Phase)
}
return nil
}

func checkMirrorPodRecreatedAndRunnig(cl *client.Client, name, namespace string, oUID types.UID) error {
pod, err := cl.Pods(namespace).Get(name)
if err != nil {
return fmt.Errorf("expected the mirror pod %q to appear: %v", name, err)
}
if pod.UID == oUID {
return fmt.Errorf("expected the uid of mirror pod %q to be changed, got %q", name, pod.UID)
}
if pod.Status.Phase != api.PodRunning {
return fmt.Errorf("expected the mirror pod %q to be running, got %q", name, pod.Status.Phase)
}
return nil
}