mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 09:52:49 +00:00
Merge pull request #116631 from bobbypage/standalone-repro
test: Update standalone test in node e2e
This commit is contained in:
commit
742316ee21
@ -30,8 +30,9 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
"k8s.io/kubernetes/pkg/cluster/ports"
|
"k8s.io/kubernetes/pkg/cluster/ports"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||||
@ -39,66 +40,78 @@ import (
|
|||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
"github.com/onsi/gomega"
|
"github.com/onsi/gomega"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
testutils "k8s.io/kubernetes/test/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = SIGDescribe("[Feature:StandaloneMode] ", func() {
|
var _ = SIGDescribe("[Feature:StandaloneMode] ", func() {
|
||||||
f := framework.NewDefaultFramework("static-pod")
|
f := framework.NewDefaultFramework("static-pod")
|
||||||
f.NamespacePodSecurityEnforceLevel = admissionapi.LevelPrivileged
|
f.NamespacePodSecurityEnforceLevel = admissionapi.LevelBaseline
|
||||||
ginkgo.It("can create a static Pod ", func(ctx context.Context) {
|
ginkgo.Context("when creating a static pod", func() {
|
||||||
|
|
||||||
var ns, podPath, staticPodName string
|
var ns, podPath, staticPodName string
|
||||||
|
|
||||||
ns = f.Namespace.Name
|
ginkgo.It("the pod should be running", func(ctx context.Context) {
|
||||||
staticPodName = "static-pod-" + string(uuid.NewUUID())
|
ns = f.Namespace.Name
|
||||||
|
staticPodName = "static-pod-" + string(uuid.NewUUID())
|
||||||
|
podPath = framework.TestContext.KubeletConfig.StaticPodPath
|
||||||
|
|
||||||
podPath = framework.TestContext.KubeletConfig.StaticPodPath
|
err := createBasicStaticPod(podPath, staticPodName, ns)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
err := createBasicStaticPod(podPath, staticPodName, ns,
|
gomega.Eventually(ctx, func(ctx context.Context) error {
|
||||||
imageutils.GetE2EImage(imageutils.Nginx), v1.RestartPolicyAlways)
|
pod, err := getPodFromStandaloneKubelet(ctx, ns, staticPodName)
|
||||||
framework.ExpectNoError(err)
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting pod(%v/%v) from standalone kubelet: %v", ns, staticPodName, err)
|
||||||
|
}
|
||||||
|
|
||||||
file := staticPodPath(podPath, staticPodName, ns)
|
isReady, err := testutils.PodRunningReady(pod)
|
||||||
defer os.Remove(file)
|
if err != nil {
|
||||||
|
return fmt.Errorf("error checking if pod (%v/%v) is running ready: %v", ns, staticPodName, err)
|
||||||
|
}
|
||||||
|
if !isReady {
|
||||||
|
return fmt.Errorf("pod (%v/%v) is not running", ns, staticPodName)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}, f.Timeouts.PodStart, time.Second*5).Should(gomega.BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
gomega.Eventually(ctx, func() error {
|
ginkgo.AfterEach(func(ctx context.Context) {
|
||||||
pod, err := getPodStatus(ctx, staticPodName)
|
ginkgo.By(fmt.Sprintf("delete the static pod (%v/%v)", ns, staticPodName))
|
||||||
if err != nil {
|
err := deleteStaticPod(podPath, staticPodName, ns)
|
||||||
return err
|
framework.ExpectNoError(err)
|
||||||
}
|
|
||||||
if pod.Status.Phase != v1.PodRunning {
|
ginkgo.By(fmt.Sprintf("wait for pod to disappear (%v/%v)", ns, staticPodName))
|
||||||
return fmt.Errorf("pod %s is not running. Status: %v", staticPodName, pod.Status.Phase)
|
gomega.Eventually(ctx, func(ctx context.Context) error {
|
||||||
}
|
_, err := getPodFromStandaloneKubelet(ctx, ns, staticPodName)
|
||||||
return nil
|
|
||||||
}, 1*time.Minute, 5*time.Second).Should(gomega.Succeed())
|
if apierrors.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("pod (%v/%v) still exists", ns, staticPodName)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
func createBasicStaticPod(dir, name, namespace, image string, restart v1.RestartPolicy) error {
|
func createBasicStaticPod(dir, name, namespace string) error {
|
||||||
podSpec := &v1.Pod{
|
podSpec := &v1.Pod{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "Pod",
|
||||||
|
APIVersion: "v1",
|
||||||
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
},
|
},
|
||||||
Spec: v1.PodSpec{
|
Spec: v1.PodSpec{
|
||||||
RestartPolicy: v1.RestartPolicyAlways,
|
RestartPolicy: v1.RestartPolicyAlways,
|
||||||
InitContainers: []v1.Container{
|
|
||||||
{
|
|
||||||
Name: "init-1",
|
|
||||||
Image: busyboxImage,
|
|
||||||
Command: ExecCommand("init-1", execCommand{
|
|
||||||
Delay: 1,
|
|
||||||
ExitCode: 0,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Containers: []v1.Container{
|
Containers: []v1.Container{
|
||||||
{
|
{
|
||||||
Name: "regular1",
|
Name: "regular1",
|
||||||
Image: busyboxImage,
|
Image: imageutils.GetE2EImage(imageutils.BusyBox),
|
||||||
Command: ExecCommand("regular1", execCommand{
|
Command: []string{
|
||||||
Delay: 1000,
|
"/bin/sh", "-c", "touch /tmp/healthy; sleep 10000",
|
||||||
ExitCode: 0,
|
},
|
||||||
}),
|
|
||||||
Resources: v1.ResourceRequirements{
|
Resources: v1.ResourceRequirements{
|
||||||
Requests: v1.ResourceList{
|
Requests: v1.ResourceList{
|
||||||
v1.ResourceMemory: resource.MustParse("15Mi"),
|
v1.ResourceMemory: resource.MustParse("15Mi"),
|
||||||
@ -107,30 +120,34 @@ func createBasicStaticPod(dir, name, namespace, image string, restart v1.Restart
|
|||||||
v1.ResourceMemory: resource.MustParse("15Mi"),
|
v1.ResourceMemory: resource.MustParse("15Mi"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ReadinessProbe: &v1.Probe{
|
||||||
|
InitialDelaySeconds: 2,
|
||||||
|
TimeoutSeconds: 2,
|
||||||
|
ProbeHandler: v1.ProbeHandler{
|
||||||
|
Exec: &v1.ExecAction{
|
||||||
|
Command: []string{"/bin/sh", "-c", "cat /tmp/healthy"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
podYaml, err := kubeadmutil.MarshalToYaml(podSpec, v1.SchemeGroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
file := staticPodPath(dir, name, namespace)
|
file := staticPodPath(dir, name, namespace)
|
||||||
|
|
||||||
f, err := os.OpenFile(file, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
|
f, err := os.OpenFile(file, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
_, err = f.Write(podYaml)
|
y := printers.YAMLPrinter{}
|
||||||
return err
|
y.PrintObj(podSpec, f)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns a status 200 response from the /configz endpoint or nil if fails
|
func getPodFromStandaloneKubelet(ctx context.Context, podNamespace string, podName string) (*v1.Pod, error) {
|
||||||
func getPodStatus(ctx context.Context, name string) (*v1.Pod, error) {
|
|
||||||
endpoint := fmt.Sprintf("http://127.0.0.1:%d/pods", ports.KubeletReadOnlyPort)
|
endpoint := fmt.Sprintf("http://127.0.0.1:%d/pods", ports.KubeletReadOnlyPort)
|
||||||
// TODO: we do not need TLS and bearer token for this test
|
// TODO: we do not need TLS and bearer token for this test
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
@ -142,40 +159,37 @@ func getPodStatus(ctx context.Context, name string) (*v1.Pod, error) {
|
|||||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", framework.TestContext.BearerToken))
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", framework.TestContext.BearerToken))
|
||||||
req.Header.Add("Accept", "application/json")
|
req.Header.Add("Accept", "application/json")
|
||||||
|
|
||||||
var pod *v1.Pod
|
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
framework.Logf("Failed to get /pods: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
return nil, fmt.Errorf("/pods response status not 200. Response was: %+v", resp)
|
framework.Logf("/pods response status not 200. Response was: %+v", resp)
|
||||||
|
return nil, fmt.Errorf("/pods response was not 200: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
respBody, err := io.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read body from /pods response %w", err)
|
return nil, fmt.Errorf("/pods response was unable to be read: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pods, err := decodePods(respBody)
|
pods, err := decodePods(respBody)
|
||||||
framework.ExpectNoError(err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to decode /pods: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, p := range pods.Items {
|
for _, p := range pods.Items {
|
||||||
// Static pods has a node name suffix so comparing as substring
|
// Static pods has a node name suffix so comparing as substring
|
||||||
if strings.Contains(p.Name, name) {
|
p := p
|
||||||
found = true
|
if strings.Contains(p.Name, podName) && strings.Contains(p.Namespace, podNamespace) {
|
||||||
pod = &p
|
return &p, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
return nil, apierrors.NewNotFound(schema.GroupResource{Resource: "pods"}, podName)
|
||||||
return nil, fmt.Errorf("pod %s not found in /pods response. Pods were: %v", name, string(respBody))
|
|
||||||
}
|
|
||||||
|
|
||||||
return pod, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decodes the http response from /configz and returns a kubeletconfig.KubeletConfiguration (internal type).
|
// Decodes the http response from /configz and returns a kubeletconfig.KubeletConfiguration (internal type).
|
||||||
|
Loading…
Reference in New Issue
Block a user