Refactor disruption e2e test and add some eviction test cases.
This commit is contained in:
		@@ -23,14 +23,24 @@ import (
 | 
			
		||||
	. "github.com/onsi/ginkgo"
 | 
			
		||||
	. "github.com/onsi/gomega"
 | 
			
		||||
	release_1_4 "k8s.io/client-go/1.4/kubernetes"
 | 
			
		||||
	apiapi "k8s.io/client-go/1.4/pkg/api"
 | 
			
		||||
	"k8s.io/client-go/1.4/pkg/api/unversioned"
 | 
			
		||||
	api "k8s.io/client-go/1.4/pkg/api/v1"
 | 
			
		||||
	extensions "k8s.io/client-go/1.4/pkg/apis/extensions/v1beta1"
 | 
			
		||||
	policy "k8s.io/client-go/1.4/pkg/apis/policy/v1alpha1"
 | 
			
		||||
	"k8s.io/client-go/1.4/pkg/util/intstr"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/wait"
 | 
			
		||||
	"k8s.io/kubernetes/test/e2e/framework"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// timeout is used for most polling/waiting activities
 | 
			
		||||
const timeout = 60 * time.Second
 | 
			
		||||
 | 
			
		||||
// schedulingTimeout is longer specifically because sometimes we need to wait
 | 
			
		||||
// awhile to guarantee that we've been patient waiting for something ordinary
 | 
			
		||||
// to happen: a pod to get scheduled and move into Ready
 | 
			
		||||
const schedulingTimeout = 5 * time.Minute
 | 
			
		||||
 | 
			
		||||
var _ = framework.KubeDescribe("DisruptionController", func() {
 | 
			
		||||
	f := framework.NewDefaultFramework("disruption")
 | 
			
		||||
	var ns string
 | 
			
		||||
@@ -55,7 +65,7 @@ var _ = framework.KubeDescribe("DisruptionController", func() {
 | 
			
		||||
 | 
			
		||||
		// Since disruptionAllowed starts out false, if we see it ever become true,
 | 
			
		||||
		// that means the controller is working.
 | 
			
		||||
		err := wait.PollImmediate(framework.Poll, 60*time.Second, func() (bool, error) {
 | 
			
		||||
		err := wait.PollImmediate(framework.Poll, timeout, func() (bool, error) {
 | 
			
		||||
			pdb, err := cs.Policy().PodDisruptionBudgets(ns).Get("foo")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return false, err
 | 
			
		||||
@@ -66,29 +76,75 @@ var _ = framework.KubeDescribe("DisruptionController", func() {
 | 
			
		||||
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	It("should allow an eviction when there is no PDB", func() {
 | 
			
		||||
		createPodsOrDie(cs, ns, 1)
 | 
			
		||||
 | 
			
		||||
		pod, err := cs.Pods(ns).Get("pod-0")
 | 
			
		||||
		Expect(err).NotTo(HaveOccurred())
 | 
			
		||||
 | 
			
		||||
		e := &policy.Eviction{
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      pod.Name,
 | 
			
		||||
				Namespace: ns,
 | 
			
		||||
	evictionCases := []struct {
 | 
			
		||||
		description    string
 | 
			
		||||
		minAvailable   intstr.IntOrString
 | 
			
		||||
		podCount       int
 | 
			
		||||
		replicaSetSize int32
 | 
			
		||||
		shouldDeny     bool
 | 
			
		||||
		exclusive      bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			description:  "no PDB",
 | 
			
		||||
			minAvailable: intstr.FromString(""),
 | 
			
		||||
			podCount:     1,
 | 
			
		||||
			shouldDeny:   false,
 | 
			
		||||
		}, {
 | 
			
		||||
			description:  "too few pods, absolute",
 | 
			
		||||
			minAvailable: intstr.FromInt(2),
 | 
			
		||||
			podCount:     1,
 | 
			
		||||
			shouldDeny:   true,
 | 
			
		||||
		}, {
 | 
			
		||||
			description:  "enough pods, absolute",
 | 
			
		||||
			minAvailable: intstr.FromInt(2),
 | 
			
		||||
			podCount:     2,
 | 
			
		||||
			shouldDeny:   false,
 | 
			
		||||
		}, {
 | 
			
		||||
			description:    "enough pods, replicaSet, percentage",
 | 
			
		||||
			minAvailable:   intstr.FromString("100%"),
 | 
			
		||||
			replicaSetSize: 10,
 | 
			
		||||
			exclusive:      false,
 | 
			
		||||
			shouldDeny:     false,
 | 
			
		||||
		}, {
 | 
			
		||||
			description:    "too few pods, replicaSet, percentage",
 | 
			
		||||
			minAvailable:   intstr.FromString("100%"),
 | 
			
		||||
			replicaSetSize: 10,
 | 
			
		||||
			exclusive:      true,
 | 
			
		||||
			shouldDeny:     true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, c := range evictionCases {
 | 
			
		||||
		expectation := "should allow an eviction"
 | 
			
		||||
		if c.shouldDeny {
 | 
			
		||||
			expectation = "should not allow an eviction"
 | 
			
		||||
		}
 | 
			
		||||
		It(fmt.Sprintf("evictions: %s => %s", c.description, expectation), func() {
 | 
			
		||||
			createPodsOrDie(cs, ns, c.podCount)
 | 
			
		||||
			if c.replicaSetSize > 0 {
 | 
			
		||||
				createReplicaSetOrDie(cs, ns, c.replicaSetSize, c.exclusive)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		err = cs.Pods(ns).Evict(e)
 | 
			
		||||
		Expect(err).NotTo(HaveOccurred())
 | 
			
		||||
			if c.minAvailable.String() != "" {
 | 
			
		||||
				createPodDisruptionBudgetOrDie(cs, ns, c.minAvailable)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Locate a running pod.
 | 
			
		||||
			var pod api.Pod
 | 
			
		||||
			err := wait.PollImmediate(framework.Poll, schedulingTimeout, func() (bool, error) {
 | 
			
		||||
				podList, err := cs.Pods(ns).List(apiapi.ListOptions{})
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return false, err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				for i := range podList.Items {
 | 
			
		||||
					if podList.Items[i].Status.Phase == api.PodRunning {
 | 
			
		||||
						pod = podList.Items[i]
 | 
			
		||||
						return true, nil
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return false, nil
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
	It("should not allow an eviction when too few pods", func() {
 | 
			
		||||
		createPodDisruptionBudgetOrDie(cs, ns, intstr.FromInt(2))
 | 
			
		||||
 | 
			
		||||
		createPodsOrDie(cs, ns, 1)
 | 
			
		||||
 | 
			
		||||
		pod, err := cs.Pods(ns).Get("pod-0")
 | 
			
		||||
			Expect(err).NotTo(HaveOccurred())
 | 
			
		||||
 | 
			
		||||
			e := &policy.Eviction{
 | 
			
		||||
@@ -98,32 +154,17 @@ var _ = framework.KubeDescribe("DisruptionController", func() {
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if c.shouldDeny {
 | 
			
		||||
				// Since disruptionAllowed starts out false, wait at least 60s hoping that
 | 
			
		||||
				// this gives the controller enough time to have truly set the status.
 | 
			
		||||
		time.Sleep(60 * time.Second)
 | 
			
		||||
				time.Sleep(timeout)
 | 
			
		||||
 | 
			
		||||
				err = cs.Pods(ns).Evict(e)
 | 
			
		||||
				Expect(err).Should(MatchError("Cannot evict pod as it would violate the pod's disruption budget."))
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	It("should allow an eviction when enough pods", func() {
 | 
			
		||||
		createPodDisruptionBudgetOrDie(cs, ns, intstr.FromInt(2))
 | 
			
		||||
 | 
			
		||||
		createPodsOrDie(cs, ns, 2)
 | 
			
		||||
 | 
			
		||||
		pod, err := cs.Pods(ns).Get("pod-0")
 | 
			
		||||
		Expect(err).NotTo(HaveOccurred())
 | 
			
		||||
 | 
			
		||||
		e := &policy.Eviction{
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      pod.Name,
 | 
			
		||||
				Namespace: ns,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			} else {
 | 
			
		||||
				// Since disruptionAllowed starts out false, if an eviction is ever allowed,
 | 
			
		||||
				// that means the controller is working.
 | 
			
		||||
		err = wait.PollImmediate(framework.Poll, 60*time.Second, func() (bool, error) {
 | 
			
		||||
				err = wait.PollImmediate(framework.Poll, timeout, func() (bool, error) {
 | 
			
		||||
					err = cs.Pods(ns).Evict(e)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return false, nil
 | 
			
		||||
@@ -132,7 +173,10 @@ var _ = framework.KubeDescribe("DisruptionController", func() {
 | 
			
		||||
					}
 | 
			
		||||
				})
 | 
			
		||||
				Expect(err).NotTo(HaveOccurred())
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func createPodDisruptionBudgetOrDie(cs *release_1_4.Clientset, ns string, minAvailable intstr.IntOrString) {
 | 
			
		||||
@@ -173,3 +217,39 @@ func createPodsOrDie(cs *release_1_4.Clientset, ns string, n int) {
 | 
			
		||||
		framework.ExpectNoError(err, "Creating pod %q in namespace %q", pod.Name, ns)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createReplicaSetOrDie(cs *release_1_4.Clientset, ns string, size int32, exclusive bool) {
 | 
			
		||||
	container := api.Container{
 | 
			
		||||
		Name:  "busybox",
 | 
			
		||||
		Image: "gcr.io/google_containers/echoserver:1.4",
 | 
			
		||||
	}
 | 
			
		||||
	if exclusive {
 | 
			
		||||
		container.Ports = []api.ContainerPort{
 | 
			
		||||
			{HostPort: 5555, ContainerPort: 5555},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rs := &extensions.ReplicaSet{
 | 
			
		||||
		ObjectMeta: api.ObjectMeta{
 | 
			
		||||
			Name:      "rs",
 | 
			
		||||
			Namespace: ns,
 | 
			
		||||
		},
 | 
			
		||||
		Spec: extensions.ReplicaSetSpec{
 | 
			
		||||
			Replicas: &size,
 | 
			
		||||
			Selector: &extensions.LabelSelector{
 | 
			
		||||
				MatchLabels: map[string]string{"foo": "bar"},
 | 
			
		||||
			},
 | 
			
		||||
			Template: api.PodTemplateSpec{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					Labels: map[string]string{"foo": "bar"},
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.PodSpec{
 | 
			
		||||
					Containers: []api.Container{container},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := cs.Extensions().ReplicaSets(ns).Create(rs)
 | 
			
		||||
	framework.ExpectNoError(err, "Creating replica set %q in namespace %q", rs.Name, ns)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user