k8s.io/kubernetes@v1.29.3/test/e2e/apimachinery/generated_clientset.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package apimachinery 18 19 import ( 20 "context" 21 "strconv" 22 "time" 23 24 batchv1 "k8s.io/api/batch/v1" 25 v1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/labels" 28 "k8s.io/apimachinery/pkg/runtime" 29 "k8s.io/apimachinery/pkg/util/intstr" 30 "k8s.io/apimachinery/pkg/util/uuid" 31 "k8s.io/apimachinery/pkg/watch" 32 "k8s.io/kubernetes/test/e2e/framework" 33 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 34 imageutils "k8s.io/kubernetes/test/utils/image" 35 admissionapi "k8s.io/pod-security-admission/api" 36 37 "github.com/onsi/ginkgo/v2" 38 "github.com/onsi/gomega" 39 ) 40 41 func testingPod(name, value string) v1.Pod { 42 return v1.Pod{ 43 ObjectMeta: metav1.ObjectMeta{ 44 Name: name, 45 Labels: map[string]string{ 46 "name": "foo", 47 "time": value, 48 }, 49 }, 50 Spec: v1.PodSpec{ 51 Containers: []v1.Container{ 52 { 53 Name: "nginx", 54 Image: imageutils.GetE2EImage(imageutils.Nginx), 55 Ports: []v1.ContainerPort{{ContainerPort: 80}}, 56 LivenessProbe: &v1.Probe{ 57 ProbeHandler: v1.ProbeHandler{ 58 HTTPGet: &v1.HTTPGetAction{ 59 Path: "/index.html", 60 Port: intstr.FromInt32(8080), 61 }, 62 }, 63 InitialDelaySeconds: 30, 64 }, 65 }, 66 }, 67 }, 68 } 69 } 70 71 func observeCreation(w watch.Interface) { 72 select { 73 case event := <-w.ResultChan(): 74 if event.Type != watch.Added { 75 framework.Failf("Failed to observe the creation: %v", event) 76 } 77 case <-time.After(30 * time.Second): 78 framework.Failf("Timeout while waiting for observing the creation") 79 } 80 } 81 82 func observerUpdate(w watch.Interface, expectedUpdate func(runtime.Object) bool) { 83 timer := time.After(30 * time.Second) 84 updated := false 85 timeout := false 86 for !updated && !timeout { 87 select { 88 case event := <-w.ResultChan(): 89 if event.Type == watch.Modified { 90 if expectedUpdate(event.Object) { 91 updated = true 92 } 93 } 94 case <-timer: 95 timeout = true 96 } 97 } 98 if !updated { 99 framework.Failf("Failed to observe pod update") 100 } 101 } 102 103 var _ = SIGDescribe("Generated clientset", func() { 104 f := framework.NewDefaultFramework("clientset") 105 f.NamespacePodSecurityEnforceLevel = admissionapi.LevelBaseline 106 ginkgo.It("should create pods, set the deletionTimestamp and deletionGracePeriodSeconds of the pod", func(ctx context.Context) { 107 podClient := f.ClientSet.CoreV1().Pods(f.Namespace.Name) 108 ginkgo.By("constructing the pod") 109 name := "pod" + string(uuid.NewUUID()) 110 value := strconv.Itoa(time.Now().Nanosecond()) 111 podCopy := testingPod(name, value) 112 pod := &podCopy 113 ginkgo.By("setting up watch") 114 selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})).String() 115 options := metav1.ListOptions{LabelSelector: selector} 116 pods, err := podClient.List(ctx, options) 117 if err != nil { 118 framework.Failf("Failed to query for pods: %v", err) 119 } 120 gomega.Expect(pods.Items).To(gomega.BeEmpty()) 121 options = metav1.ListOptions{ 122 LabelSelector: selector, 123 ResourceVersion: pods.ListMeta.ResourceVersion, 124 } 125 w, err := podClient.Watch(ctx, options) 126 if err != nil { 127 framework.Failf("Failed to set up watch: %v", err) 128 } 129 130 ginkgo.By("creating the pod") 131 pod, err = podClient.Create(ctx, pod, metav1.CreateOptions{}) 132 if err != nil { 133 framework.Failf("Failed to create pod: %v", err) 134 } 135 136 ginkgo.By("verifying the pod is in kubernetes") 137 options = metav1.ListOptions{ 138 LabelSelector: selector, 139 ResourceVersion: pod.ResourceVersion, 140 } 141 pods, err = podClient.List(ctx, options) 142 if err != nil { 143 framework.Failf("Failed to query for pods: %v", err) 144 } 145 gomega.Expect(pods.Items).To(gomega.HaveLen(1)) 146 147 ginkgo.By("verifying pod creation was observed") 148 observeCreation(w) 149 150 // We need to wait for the pod to be scheduled, otherwise the deletion 151 // will be carried out immediately rather than gracefully. 152 framework.ExpectNoError(e2epod.WaitForPodNameRunningInNamespace(ctx, f.ClientSet, pod.Name, f.Namespace.Name)) 153 154 ginkgo.By("deleting the pod gracefully") 155 gracePeriod := int64(31) 156 if err := podClient.Delete(ctx, pod.Name, *metav1.NewDeleteOptions(gracePeriod)); err != nil { 157 framework.Failf("Failed to delete pod: %v", err) 158 } 159 160 ginkgo.By("verifying the deletionTimestamp and deletionGracePeriodSeconds of the pod is set") 161 observerUpdate(w, func(obj runtime.Object) bool { 162 pod := obj.(*v1.Pod) 163 return pod.ObjectMeta.DeletionTimestamp != nil && *pod.ObjectMeta.DeletionGracePeriodSeconds == gracePeriod 164 }) 165 }) 166 }) 167 168 func newTestingCronJob(name string, value string) *batchv1.CronJob { 169 parallelism := int32(1) 170 completions := int32(1) 171 return &batchv1.CronJob{ 172 ObjectMeta: metav1.ObjectMeta{ 173 Name: name, 174 Labels: map[string]string{ 175 "time": value, 176 }, 177 }, 178 Spec: batchv1.CronJobSpec{ 179 Schedule: "*/1 * * * ?", 180 ConcurrencyPolicy: batchv1.AllowConcurrent, 181 JobTemplate: batchv1.JobTemplateSpec{ 182 Spec: batchv1.JobSpec{ 183 Parallelism: ¶llelism, 184 Completions: &completions, 185 Template: v1.PodTemplateSpec{ 186 Spec: v1.PodSpec{ 187 RestartPolicy: v1.RestartPolicyOnFailure, 188 Volumes: []v1.Volume{ 189 { 190 Name: "data", 191 VolumeSource: v1.VolumeSource{ 192 EmptyDir: &v1.EmptyDirVolumeSource{}, 193 }, 194 }, 195 }, 196 Containers: []v1.Container{ 197 { 198 Name: "c", 199 Image: imageutils.GetE2EImage(imageutils.BusyBox), 200 VolumeMounts: []v1.VolumeMount{ 201 { 202 MountPath: "/data", 203 Name: "data", 204 }, 205 }, 206 }, 207 }, 208 }, 209 }, 210 }, 211 }, 212 }, 213 } 214 } 215 216 var _ = SIGDescribe("Generated clientset", func() { 217 f := framework.NewDefaultFramework("clientset") 218 f.NamespacePodSecurityEnforceLevel = admissionapi.LevelPrivileged 219 220 ginkgo.It("should create v1 cronJobs, delete cronJobs, watch cronJobs", func(ctx context.Context) { 221 cronJobClient := f.ClientSet.BatchV1().CronJobs(f.Namespace.Name) 222 ginkgo.By("constructing the cronJob") 223 name := "cronjob" + string(uuid.NewUUID()) 224 value := strconv.Itoa(time.Now().Nanosecond()) 225 cronJob := newTestingCronJob(name, value) 226 ginkgo.By("setting up watch") 227 selector := labels.SelectorFromSet(labels.Set(map[string]string{"time": value})).String() 228 options := metav1.ListOptions{LabelSelector: selector} 229 cronJobs, err := cronJobClient.List(ctx, options) 230 if err != nil { 231 framework.Failf("Failed to query for cronJobs: %v", err) 232 } 233 gomega.Expect(cronJobs.Items).To(gomega.BeEmpty()) 234 options = metav1.ListOptions{ 235 LabelSelector: selector, 236 ResourceVersion: cronJobs.ListMeta.ResourceVersion, 237 } 238 w, err := cronJobClient.Watch(ctx, options) 239 if err != nil { 240 framework.Failf("Failed to set up watch: %v", err) 241 } 242 243 ginkgo.By("creating the cronJob") 244 cronJob, err = cronJobClient.Create(ctx, cronJob, metav1.CreateOptions{}) 245 if err != nil { 246 framework.Failf("Failed to create cronJob: %v", err) 247 } 248 249 ginkgo.By("verifying the cronJob is in kubernetes") 250 options = metav1.ListOptions{ 251 LabelSelector: selector, 252 ResourceVersion: cronJob.ResourceVersion, 253 } 254 cronJobs, err = cronJobClient.List(ctx, options) 255 if err != nil { 256 framework.Failf("Failed to query for cronJobs: %v", err) 257 } 258 gomega.Expect(cronJobs.Items).To(gomega.HaveLen(1)) 259 260 ginkgo.By("verifying cronJob creation was observed") 261 observeCreation(w) 262 263 ginkgo.By("deleting the cronJob") 264 // Use DeletePropagationBackground so the CronJob is really gone when the call returns. 265 propagationPolicy := metav1.DeletePropagationBackground 266 if err := cronJobClient.Delete(ctx, cronJob.Name, metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { 267 framework.Failf("Failed to delete cronJob: %v", err) 268 } 269 270 options = metav1.ListOptions{LabelSelector: selector} 271 cronJobs, err = cronJobClient.List(ctx, options) 272 if err != nil { 273 framework.Failf("Failed to list cronJobs to verify deletion: %v", err) 274 } 275 gomega.Expect(cronJobs.Items).To(gomega.BeEmpty()) 276 }) 277 })