k8s.io/kubernetes@v1.29.3/test/e2e/instrumentation/events.go (about)

     1  /*
     2  Copyright 2020 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  	eventsv1 "k8s.io/api/events/v1"
    26  	apiequality "k8s.io/apimachinery/pkg/api/equality"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/util/strategicpatch"
    29  	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
    30  	typedeventsv1 "k8s.io/client-go/kubernetes/typed/events/v1"
    31  	"k8s.io/kubernetes/test/e2e/framework"
    32  	"k8s.io/kubernetes/test/e2e/instrumentation/common"
    33  	admissionapi "k8s.io/pod-security-admission/api"
    34  
    35  	"github.com/google/go-cmp/cmp"
    36  	"github.com/onsi/ginkgo/v2"
    37  	"github.com/onsi/gomega"
    38  	"k8s.io/apimachinery/pkg/types"
    39  )
    40  
    41  func newTestEvent(namespace, name, label string) *eventsv1.Event {
    42  	someTime := metav1.MicroTime{Time: time.Unix(1505828956, 0)}
    43  	return &eventsv1.Event{
    44  		ObjectMeta: metav1.ObjectMeta{
    45  			Name: name,
    46  			Labels: map[string]string{
    47  				label: "true",
    48  			},
    49  		},
    50  		Regarding: v1.ObjectReference{
    51  			Namespace: namespace,
    52  		},
    53  		EventTime:           someTime,
    54  		Note:                "This is " + name,
    55  		Action:              "Do",
    56  		Reason:              "Test",
    57  		Type:                "Normal",
    58  		ReportingController: "test-controller",
    59  		ReportingInstance:   "test-node",
    60  	}
    61  }
    62  
    63  func eventExistsInList(ctx context.Context, client typedeventsv1.EventInterface, namespace, name string) bool {
    64  	eventsList, err := client.List(ctx, metav1.ListOptions{
    65  		LabelSelector: "testevent-constant=true",
    66  	})
    67  	framework.ExpectNoError(err, "failed to list events")
    68  
    69  	for _, val := range eventsList.Items {
    70  		if val.ObjectMeta.Name == name && val.ObjectMeta.Namespace == namespace {
    71  			return true
    72  		}
    73  	}
    74  	return false
    75  }
    76  
    77  var _ = common.SIGDescribe("Events API", func() {
    78  	f := framework.NewDefaultFramework("events")
    79  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    80  	var coreClient corev1.EventInterface
    81  	var client typedeventsv1.EventInterface
    82  	var clientAllNamespaces typedeventsv1.EventInterface
    83  
    84  	ginkgo.BeforeEach(func() {
    85  		coreClient = f.ClientSet.CoreV1().Events(f.Namespace.Name)
    86  		client = f.ClientSet.EventsV1().Events(f.Namespace.Name)
    87  		clientAllNamespaces = f.ClientSet.EventsV1().Events(metav1.NamespaceAll)
    88  	})
    89  
    90  	/*
    91  		Release: v1.19
    92  		Testname: New Event resource lifecycle, testing a single event
    93  		Description: Create an event, the event MUST exist.
    94  		The event is patched with a new note, the check MUST have the update note.
    95  		The event is updated with a new series, the check MUST have the update series.
    96  		The event is deleted and MUST NOT show up when listing all events.
    97  	*/
    98  	framework.ConformanceIt("should ensure that an event can be fetched, patched, deleted, and listed", func(ctx context.Context) {
    99  		eventName := "event-test"
   100  
   101  		ginkgo.By("creating a test event")
   102  		_, err := client.Create(ctx, newTestEvent(f.Namespace.Name, eventName, "testevent-constant"), metav1.CreateOptions{})
   103  		framework.ExpectNoError(err, "failed to create test event")
   104  
   105  		ginkgo.By("listing events in all namespaces")
   106  		foundCreatedEvent := eventExistsInList(ctx, clientAllNamespaces, f.Namespace.Name, eventName)
   107  		if !foundCreatedEvent {
   108  			framework.Failf("Failed to find test event %s in namespace %s, in list with cluster scope", eventName, f.Namespace.Name)
   109  		}
   110  
   111  		ginkgo.By("listing events in test namespace")
   112  		foundCreatedEvent = eventExistsInList(ctx, client, f.Namespace.Name, eventName)
   113  		if !foundCreatedEvent {
   114  			framework.Failf("Failed to find test event %s in namespace %s, in list with namespace scope", eventName, f.Namespace.Name)
   115  		}
   116  
   117  		ginkgo.By("listing events with field selection filtering on source")
   118  		filteredCoreV1List, err := coreClient.List(ctx, metav1.ListOptions{FieldSelector: "source=test-controller"})
   119  		framework.ExpectNoError(err, "failed to get filtered list")
   120  		if len(filteredCoreV1List.Items) != 1 || filteredCoreV1List.Items[0].Name != eventName {
   121  			framework.Failf("expected single event, got %#v", filteredCoreV1List.Items)
   122  		}
   123  
   124  		ginkgo.By("listing events with field selection filtering on reportingController")
   125  		filteredEventsV1List, err := client.List(ctx, metav1.ListOptions{FieldSelector: "reportingController=test-controller"})
   126  		framework.ExpectNoError(err, "failed to get filtered list")
   127  		if len(filteredEventsV1List.Items) != 1 || filteredEventsV1List.Items[0].Name != eventName {
   128  			framework.Failf("expected single event, got %#v", filteredEventsV1List.Items)
   129  		}
   130  
   131  		ginkgo.By("getting the test event")
   132  		testEvent, err := client.Get(ctx, eventName, metav1.GetOptions{})
   133  		framework.ExpectNoError(err, "failed to get test event")
   134  
   135  		ginkgo.By("patching the test event")
   136  		oldData, err := json.Marshal(testEvent)
   137  		framework.ExpectNoError(err, "failed to marshal event")
   138  		newEvent := testEvent.DeepCopy()
   139  		eventSeries := &eventsv1.EventSeries{
   140  			Count:            2,
   141  			LastObservedTime: metav1.MicroTime{Time: time.Unix(1505828951, 0)},
   142  		}
   143  		newEvent.Series = eventSeries
   144  		newData, err := json.Marshal(newEvent)
   145  		framework.ExpectNoError(err, "failed to marshal new event")
   146  		patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, eventsv1.Event{})
   147  		framework.ExpectNoError(err, "failed to create two-way merge patch")
   148  
   149  		_, err = client.Patch(ctx, eventName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
   150  		framework.ExpectNoError(err, "failed to patch the test event")
   151  
   152  		ginkgo.By("getting the test event")
   153  		event, err := client.Get(ctx, eventName, metav1.GetOptions{})
   154  		framework.ExpectNoError(err, "failed to get test event")
   155  		// clear ResourceVersion and ManagedFields which are set by control-plane
   156  		event.ObjectMeta.ResourceVersion = ""
   157  		testEvent.ObjectMeta.ResourceVersion = ""
   158  		event.ObjectMeta.ManagedFields = nil
   159  		testEvent.ObjectMeta.ManagedFields = nil
   160  
   161  		testEvent.Series = eventSeries
   162  		if !apiequality.Semantic.DeepEqual(testEvent, event) {
   163  			framework.Failf("test event wasn't properly patched: %v", cmp.Diff(testEvent, event))
   164  		}
   165  
   166  		ginkgo.By("updating the test event")
   167  		testEvent.Series = &eventsv1.EventSeries{
   168  			Count:            100,
   169  			LastObservedTime: metav1.MicroTime{Time: time.Unix(1505828956, 0)},
   170  		}
   171  		_, err = client.Update(ctx, testEvent, metav1.UpdateOptions{})
   172  		framework.ExpectNoError(err, "failed to update the test event")
   173  
   174  		ginkgo.By("getting the test event")
   175  		event, err = client.Get(ctx, eventName, metav1.GetOptions{})
   176  		framework.ExpectNoError(err, "failed to get test event")
   177  		// clear ResourceVersion and ManagedFields which are set by control-plane
   178  		event.ObjectMeta.ResourceVersion = ""
   179  		event.ObjectMeta.ManagedFields = nil
   180  		if !apiequality.Semantic.DeepEqual(testEvent, event) {
   181  			framework.Failf("test event wasn't properly updated: %v", cmp.Diff(testEvent, event))
   182  		}
   183  
   184  		ginkgo.By("deleting the test event")
   185  		err = client.Delete(ctx, eventName, metav1.DeleteOptions{})
   186  		framework.ExpectNoError(err, "failed to delete the test event")
   187  
   188  		ginkgo.By("listing events in all namespaces")
   189  		foundCreatedEvent = eventExistsInList(ctx, clientAllNamespaces, f.Namespace.Name, eventName)
   190  		if foundCreatedEvent {
   191  			framework.Failf("Should not have found test event %s in namespace %s, in list with cluster scope after deletion", eventName, f.Namespace.Name)
   192  		}
   193  
   194  		ginkgo.By("listing events in test namespace")
   195  		foundCreatedEvent = eventExistsInList(ctx, client, f.Namespace.Name, eventName)
   196  		if foundCreatedEvent {
   197  			framework.Failf("Should not have found test event %s in namespace %s, in list with namespace scope after deletion", eventName, f.Namespace.Name)
   198  		}
   199  	})
   200  
   201  	/*
   202  		Release: v1.19
   203  		Testname: New Event resource lifecycle, testing a list of events
   204  		Description: Create a list of events, the events MUST exist.
   205  		The events are deleted and MUST NOT show up when listing all events.
   206  	*/
   207  	framework.ConformanceIt("should delete a collection of events", func(ctx context.Context) {
   208  		eventNames := []string{"test-event-1", "test-event-2", "test-event-3"}
   209  
   210  		ginkgo.By("Create set of events")
   211  		for _, eventName := range eventNames {
   212  			_, err := client.Create(ctx, newTestEvent(f.Namespace.Name, eventName, "testevent-set"), metav1.CreateOptions{})
   213  			framework.ExpectNoError(err, "failed to create event")
   214  		}
   215  
   216  		ginkgo.By("get a list of Events with a label in the current namespace")
   217  		eventList, err := client.List(ctx, metav1.ListOptions{
   218  			LabelSelector: "testevent-set=true",
   219  		})
   220  		framework.ExpectNoError(err, "failed to get a list of events")
   221  		gomega.Expect(eventList.Items).To(gomega.HaveLen(len(eventNames)), "unexpected event list: %#v", eventList)
   222  
   223  		ginkgo.By("delete a list of events")
   224  		framework.Logf("requesting DeleteCollection of events")
   225  		err = client.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{
   226  			LabelSelector: "testevent-set=true",
   227  		})
   228  		framework.ExpectNoError(err, "failed to delete the test event")
   229  
   230  		ginkgo.By("check that the list of events matches the requested quantity")
   231  		eventList, err = client.List(ctx, metav1.ListOptions{
   232  			LabelSelector: "testevent-set=true",
   233  		})
   234  		framework.ExpectNoError(err, "failed to get a list of events")
   235  		gomega.Expect(eventList.Items).To(gomega.BeEmpty(), "unexpected event list: %#v", eventList)
   236  	})
   237  })