Create node_e2e test for ephemeral containers
This commit is contained in:
		@@ -335,6 +335,23 @@ func podContainerStarted(c clientset.Interface, namespace, podName string, conta
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isContainerRunning(c clientset.Interface, namespace, podName, containerName string) wait.ConditionFunc {
 | 
				
			||||||
 | 
						return func() (bool, error) {
 | 
				
			||||||
 | 
							pod, err := c.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return false, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, statuses := range [][]v1.ContainerStatus{pod.Status.ContainerStatuses, pod.Status.InitContainerStatuses, pod.Status.EphemeralContainerStatuses} {
 | 
				
			||||||
 | 
								for _, cs := range statuses {
 | 
				
			||||||
 | 
									if cs.Name == containerName {
 | 
				
			||||||
 | 
										return cs.State.Running != nil, nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LogPodStates logs basic info of provided pods for debugging.
 | 
					// LogPodStates logs basic info of provided pods for debugging.
 | 
				
			||||||
func LogPodStates(pods []v1.Pod) {
 | 
					func LogPodStates(pods []v1.Pod) {
 | 
				
			||||||
	// Find maximum widths for pod, node, and phase strings for column printing.
 | 
						// Find maximum widths for pod, node, and phase strings for column printing.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -565,3 +565,8 @@ func WaitForPodFailedReason(c clientset.Interface, pod *v1.Pod, reason string, t
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WaitForContainerRunning waits for the given Pod container to have a state of running
 | 
				
			||||||
 | 
					func WaitForContainerRunning(c clientset.Interface, namespace, podName, containerName string, timeout time.Duration) error {
 | 
				
			||||||
 | 
						return wait.PollImmediate(poll, timeout, isContainerRunning(c, namespace, podName, containerName))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ package framework
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
@@ -27,7 +28,9 @@ import (
 | 
				
			|||||||
	apierrors "k8s.io/apimachinery/pkg/api/errors"
 | 
						apierrors "k8s.io/apimachinery/pkg/api/errors"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/labels"
 | 
						"k8s.io/apimachinery/pkg/labels"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/strategicpatch"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	"k8s.io/client-go/kubernetes/scheme"
 | 
						"k8s.io/client-go/kubernetes/scheme"
 | 
				
			||||||
	v1core "k8s.io/client-go/kubernetes/typed/core/v1"
 | 
						v1core "k8s.io/client-go/kubernetes/typed/core/v1"
 | 
				
			||||||
@@ -146,6 +149,27 @@ func (c *PodClient) Update(name string, updateFn func(pod *v1.Pod)) {
 | 
				
			|||||||
	}))
 | 
						}))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddEphemeralContainerSync adds an EphemeralContainer to a pod and waits for it to be running.
 | 
				
			||||||
 | 
					func (c *PodClient) AddEphemeralContainerSync(pod *v1.Pod, ec *v1.EphemeralContainer, timeout time.Duration) {
 | 
				
			||||||
 | 
						namespace := c.f.Namespace.Name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						podJS, err := json.Marshal(pod)
 | 
				
			||||||
 | 
						ExpectNoError(err, "error creating JSON for pod: %v", err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ecPod := pod.DeepCopy()
 | 
				
			||||||
 | 
						ecPod.Spec.EphemeralContainers = append(ecPod.Spec.EphemeralContainers, *ec)
 | 
				
			||||||
 | 
						ecJS, err := json.Marshal(ecPod)
 | 
				
			||||||
 | 
						ExpectNoError(err, "error creating JSON for pod with ephemeral container: %v", err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						patch, err := strategicpatch.CreateTwoWayMergePatch(podJS, ecJS, pod)
 | 
				
			||||||
 | 
						ExpectNoError(err, "error creating patch to add ephemeral container: %v", err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = c.Patch(context.TODO(), pod.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}, "ephemeralcontainers")
 | 
				
			||||||
 | 
						ExpectNoError(err, "Failed to patch ephemeral containers in pod %q: %v", pod.Name, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ExpectNoError(e2epod.WaitForContainerRunning(c.f.ClientSet, namespace, pod.Name, ec.Name, timeout))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteSync deletes the pod and wait for the pod to disappear for `timeout`. If the pod doesn't
 | 
					// DeleteSync deletes the pod and wait for the pod to disappear for `timeout`. If the pod doesn't
 | 
				
			||||||
// disappear before the timeout, it will fail the test.
 | 
					// disappear before the timeout, it will fail the test.
 | 
				
			||||||
func (c *PodClient) DeleteSync(name string, options metav1.DeleteOptions, timeout time.Duration) {
 | 
					func (c *PodClient) DeleteSync(name string, options metav1.DeleteOptions, timeout time.Duration) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										69
									
								
								test/e2e_node/ephemeral_containers_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								test/e2e_node/ephemeral_containers_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package e2enode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/test/e2e/framework"
 | 
				
			||||||
 | 
						imageutils "k8s.io/kubernetes/test/utils/image"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/onsi/ginkgo"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = SIGDescribe("Ephemeral Containers [Feature:EphemeralContainers][NodeAlphaFeature:EphemeralContainers]", func() {
 | 
				
			||||||
 | 
						f := framework.NewDefaultFramework("ephemeral-containers-test")
 | 
				
			||||||
 | 
						var podClient *framework.PodClient
 | 
				
			||||||
 | 
						ginkgo.BeforeEach(func() {
 | 
				
			||||||
 | 
							podClient = f.PodClient()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ginkgo.It("will start an ephemeral container in an existing pod", func() {
 | 
				
			||||||
 | 
							ginkgo.By("creating a target pod")
 | 
				
			||||||
 | 
							pod := podClient.CreateSync(&v1.Pod{
 | 
				
			||||||
 | 
								ObjectMeta: metav1.ObjectMeta{Name: "ephemeral-containers-target-pod"},
 | 
				
			||||||
 | 
								Spec: v1.PodSpec{
 | 
				
			||||||
 | 
									Containers: []v1.Container{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Name:    "test-container-1",
 | 
				
			||||||
 | 
											Image:   imageutils.GetE2EImage(imageutils.BusyBox),
 | 
				
			||||||
 | 
											Command: []string{"/bin/sleep"},
 | 
				
			||||||
 | 
											Args:    []string{"10000"},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ginkgo.By("adding an ephemeral container")
 | 
				
			||||||
 | 
							ec := &v1.EphemeralContainer{
 | 
				
			||||||
 | 
								EphemeralContainerCommon: v1.EphemeralContainerCommon{
 | 
				
			||||||
 | 
									Name:    "debugger",
 | 
				
			||||||
 | 
									Image:   imageutils.GetE2EImage(imageutils.BusyBox),
 | 
				
			||||||
 | 
									Command: []string{"/bin/sh"},
 | 
				
			||||||
 | 
									Stdin:   true,
 | 
				
			||||||
 | 
									TTY:     true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							podClient.AddEphemeralContainerSync(pod, ec, time.Minute)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ginkgo.By("confirm that the container is really running")
 | 
				
			||||||
 | 
							marco := f.ExecCommandInContainer(pod.Name, "debugger", "/bin/echo", "polo")
 | 
				
			||||||
 | 
							framework.ExpectEqual(marco, "polo")
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
		Reference in New Issue
	
	Block a user