Merge pull request #103372 from verb/1.22-e2e-node

Create node_e2e test for ephemeral containers
This commit is contained in:
Kubernetes Prow Robot 2021-10-05 05:41:09 -07:00 committed by GitHub
commit c5ad58d8a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 0 deletions

View File

@ -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.
func LogPodStates(pods []v1.Pod) {
// Find maximum widths for pod, node, and phase strings for column printing.

View File

@ -565,3 +565,8 @@ func WaitForPodFailedReason(c clientset.Interface, pod *v1.Pod, reason string, t
}
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))
}

View File

@ -18,6 +18,7 @@ package framework
import (
"context"
"encoding/json"
"fmt"
"regexp"
"sync"
@ -27,7 +28,9 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes/scheme"
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
@ -37,6 +40,7 @@ import (
"github.com/onsi/gomega"
// TODO: Remove the following imports (ref: https://github.com/kubernetes/kubernetes/issues/81245)
"k8s.io/kubernetes/pkg/kubelet/util/format"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
)
@ -146,6 +150,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 %q", format.Pod(pod))
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 %q", format.Pod(pod))
patch, err := strategicpatch.CreateTwoWayMergePatch(podJS, ecJS, pod)
ExpectNoError(err, "error creating patch to add ephemeral container %q", format.Pod(pod))
_, err = c.Patch(context.TODO(), pod.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}, "ephemeralcontainers")
ExpectNoError(err, "Failed to patch ephemeral containers in pod %q", format.Pod(pod))
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
// disappear before the timeout, it will fail the test.
func (c *PodClient) DeleteSync(name string, options metav1.DeleteOptions, timeout time.Duration) {

View File

@ -0,0 +1,69 @@
/*
Copyright 2021 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")
})
})