k8s.io/kubernetes@v1.29.3/test/e2e/instrumentation/core_events.go (about) 1 /* 2 Copyright 2016 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 instrumentation 18 19 import ( 20 "context" 21 "encoding/json" 22 "time" 23 24 v1 "k8s.io/api/core/v1" 25 apiequality "k8s.io/apimachinery/pkg/api/equality" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/util/wait" 28 "k8s.io/kubernetes/test/e2e/framework" 29 "k8s.io/kubernetes/test/e2e/instrumentation/common" 30 admissionapi "k8s.io/pod-security-admission/api" 31 32 "github.com/google/go-cmp/cmp" 33 "github.com/onsi/ginkgo/v2" 34 "github.com/onsi/gomega" 35 "k8s.io/apimachinery/pkg/types" 36 ) 37 38 const ( 39 eventRetryPeriod = 1 * time.Second 40 eventRetryTimeout = 1 * time.Minute 41 ) 42 43 var _ = common.SIGDescribe("Events", func() { 44 f := framework.NewDefaultFramework("events") 45 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 46 47 /* 48 Release: v1.25 49 Testname: Event, manage lifecycle of an Event 50 Description: Attempt to create an event which MUST succeed. 51 Attempt to list all namespaces with a label selector which MUST 52 succeed. One list MUST be found. The event is patched with a 53 new message, the check MUST have the update message. The event 54 is updated with a new series of events, the check MUST confirm 55 this update. The event is deleted and MUST NOT show up when 56 listing all events. 57 */ 58 framework.ConformanceIt("should manage the lifecycle of an event", func(ctx context.Context) { 59 // As per SIG-Arch meeting 14 July 2022 this e2e test now supersede 60 // e2e test "Event resource lifecycle", which has been removed. 61 62 eventTestName := "event-test" 63 64 ginkgo.By("creating a test event") 65 // create a test event in test namespace 66 _, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Create(ctx, &v1.Event{ 67 ObjectMeta: metav1.ObjectMeta{ 68 Name: eventTestName, 69 Labels: map[string]string{ 70 "testevent-constant": "true", 71 }, 72 }, 73 Message: "This is a test event", 74 Reason: "Test", 75 Type: "Normal", 76 Count: 1, 77 InvolvedObject: v1.ObjectReference{ 78 Namespace: f.Namespace.Name, 79 }, 80 }, metav1.CreateOptions{}) 81 framework.ExpectNoError(err, "failed to create test event") 82 83 ginkgo.By("listing all events in all namespaces") 84 // get a list of Events in all namespaces to ensure endpoint coverage 85 eventsList, err := f.ClientSet.CoreV1().Events("").List(ctx, metav1.ListOptions{ 86 LabelSelector: "testevent-constant=true", 87 }) 88 framework.ExpectNoError(err, "failed list all events") 89 90 foundCreatedEvent := false 91 var eventCreatedName string 92 for _, val := range eventsList.Items { 93 if val.ObjectMeta.Name == eventTestName && val.ObjectMeta.Namespace == f.Namespace.Name { 94 foundCreatedEvent = true 95 eventCreatedName = val.ObjectMeta.Name 96 break 97 } 98 } 99 if !foundCreatedEvent { 100 framework.Failf("unable to find test event %s in namespace %s, full list of events is %+v", eventTestName, f.Namespace.Name, eventsList.Items) 101 } 102 103 ginkgo.By("patching the test event") 104 // patch the event's message 105 eventPatchMessage := "This is a test event - patched" 106 eventPatch, err := json.Marshal(map[string]interface{}{ 107 "message": eventPatchMessage, 108 }) 109 framework.ExpectNoError(err, "failed to marshal the patch JSON payload") 110 111 _, err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Patch(ctx, eventTestName, types.StrategicMergePatchType, []byte(eventPatch), metav1.PatchOptions{}) 112 framework.ExpectNoError(err, "failed to patch the test event") 113 114 ginkgo.By("fetching the test event") 115 // get event by name 116 event, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Get(ctx, eventCreatedName, metav1.GetOptions{}) 117 framework.ExpectNoError(err, "failed to fetch the test event") 118 gomega.Expect(event.Message).To(gomega.Equal(eventPatchMessage), "test event message does not match patch message") 119 120 ginkgo.By("updating the test event") 121 122 testEvent, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Get(ctx, event.Name, metav1.GetOptions{}) 123 framework.ExpectNoError(err, "failed to get test event") 124 125 testEvent.Series = &v1.EventSeries{ 126 Count: 100, 127 LastObservedTime: metav1.MicroTime{Time: time.Unix(1505828956, 0)}, 128 } 129 130 // clear ResourceVersion and ManagedFields which are set by control-plane 131 testEvent.ObjectMeta.ResourceVersion = "" 132 testEvent.ObjectMeta.ManagedFields = nil 133 134 _, err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Update(ctx, testEvent, metav1.UpdateOptions{}) 135 framework.ExpectNoError(err, "failed to update the test event") 136 137 ginkgo.By("getting the test event") 138 event, err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Get(ctx, testEvent.Name, metav1.GetOptions{}) 139 framework.ExpectNoError(err, "failed to get test event") 140 // clear ResourceVersion and ManagedFields which are set by control-plane 141 event.ObjectMeta.ResourceVersion = "" 142 event.ObjectMeta.ManagedFields = nil 143 if !apiequality.Semantic.DeepEqual(testEvent, event) { 144 framework.Failf("test event wasn't properly updated: %v", cmp.Diff(testEvent, event)) 145 } 146 147 ginkgo.By("deleting the test event") 148 // delete original event 149 err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Delete(ctx, eventCreatedName, metav1.DeleteOptions{}) 150 framework.ExpectNoError(err, "failed to delete the test event") 151 152 ginkgo.By("listing all events in all namespaces") 153 // get a list of Events list namespace 154 eventsList, err = f.ClientSet.CoreV1().Events("").List(ctx, metav1.ListOptions{ 155 LabelSelector: "testevent-constant=true", 156 }) 157 framework.ExpectNoError(err, "fail to list all events") 158 foundCreatedEvent = false 159 for _, val := range eventsList.Items { 160 if val.ObjectMeta.Name == eventTestName && val.ObjectMeta.Namespace == f.Namespace.Name { 161 foundCreatedEvent = true 162 break 163 } 164 } 165 if foundCreatedEvent { 166 framework.Failf("Should not have found test event %s in namespace %s, full list of events %+v", eventTestName, f.Namespace.Name, eventsList.Items) 167 } 168 }) 169 170 /* 171 Release: v1.20 172 Testname: Event, delete a collection 173 Description: A set of events is created with a label selector which MUST be found when listed. 174 The set of events is deleted and MUST NOT show up when listed by its label selector. 175 */ 176 framework.ConformanceIt("should delete a collection of events", func(ctx context.Context) { 177 eventTestNames := []string{"test-event-1", "test-event-2", "test-event-3"} 178 179 ginkgo.By("Create set of events") 180 // create a test event in test namespace 181 for _, eventTestName := range eventTestNames { 182 eventMessage := "This is " + eventTestName 183 _, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Create(ctx, &v1.Event{ 184 185 ObjectMeta: metav1.ObjectMeta{ 186 Name: eventTestName, 187 Labels: map[string]string{"testevent-set": "true"}, 188 }, 189 Message: eventMessage, 190 Reason: "Test", 191 Type: "Normal", 192 Count: 1, 193 InvolvedObject: v1.ObjectReference{ 194 Namespace: f.Namespace.Name, 195 }, 196 }, metav1.CreateOptions{}) 197 framework.ExpectNoError(err, "failed to create event") 198 framework.Logf("created %v", eventTestName) 199 } 200 201 ginkgo.By("get a list of Events with a label in the current namespace") 202 // get a list of events 203 eventList, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).List(ctx, metav1.ListOptions{ 204 LabelSelector: "testevent-set=true", 205 }) 206 framework.ExpectNoError(err, "failed to get a list of events") 207 208 gomega.Expect(eventList.Items).To(gomega.HaveLen(len(eventTestNames)), "looking for expected number of pod templates events") 209 210 ginkgo.By("delete collection of events") 211 // delete collection 212 213 framework.Logf("requesting DeleteCollection of events") 214 err = f.ClientSet.CoreV1().Events(f.Namespace.Name).DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{ 215 LabelSelector: "testevent-set=true"}) 216 framework.ExpectNoError(err, "failed to delete the test event") 217 218 ginkgo.By("check that the list of events matches the requested quantity") 219 220 err = wait.PollUntilContextTimeout(ctx, eventRetryPeriod, eventRetryTimeout, true, checkEventListQuantity(f, "testevent-set=true", 0)) 221 framework.ExpectNoError(err, "failed to count required events") 222 }) 223 224 }) 225 226 func checkEventListQuantity(f *framework.Framework, label string, quantity int) func(ctx context.Context) (bool, error) { 227 return func(ctx context.Context) (bool, error) { 228 var err error 229 230 framework.Logf("requesting list of events to confirm quantity") 231 232 eventList, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).List(ctx, metav1.ListOptions{ 233 LabelSelector: label}) 234 235 if err != nil { 236 return false, err 237 } 238 239 if len(eventList.Items) != quantity { 240 return false, err 241 } 242 return true, nil 243 } 244 }