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  }