mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	Merge pull request #91230 from ii/heyste-create-delete-core-v1-collection-namespaced-event-test
Create deleteCoreV1CollectionNamespacedEvent test+promote - +1 endpoint coverage
This commit is contained in:
		
							
								
								
									
										2
									
								
								test/conformance/testdata/conformance.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								test/conformance/testdata/conformance.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -816,7 +816,7 @@ | |||||||
|     new message, the check MUST have the update message. The event is deleted and |     new message, the check MUST have the update message. The event is deleted and | ||||||
|     MUST NOT show up when listing all events. |     MUST NOT show up when listing all events. | ||||||
|   release: v1.19 |   release: v1.19 | ||||||
|   file: test/e2e/framework/events/events.go |   file: test/e2e/apimachinery/events.go | ||||||
| - testname: Garbage Collector, delete deployment,  propagation policy background | - testname: Garbage Collector, delete deployment,  propagation policy background | ||||||
|   codename: '[sig-api-machinery] Garbage collector should delete RS created by deployment |   codename: '[sig-api-machinery] Garbage collector should delete RS created by deployment | ||||||
|     when not orphaning [Conformance]' |     when not orphaning [Conformance]' | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ go_library( | |||||||
|         "custom_resource_definition.go", |         "custom_resource_definition.go", | ||||||
|         "discovery.go", |         "discovery.go", | ||||||
|         "etcd_failure.go", |         "etcd_failure.go", | ||||||
|  |         "events.go", | ||||||
|         "framework.go", |         "framework.go", | ||||||
|         "garbage_collector.go", |         "garbage_collector.go", | ||||||
|         "generated_clientset.go", |         "generated_clientset.go", | ||||||
|   | |||||||
							
								
								
									
										194
									
								
								test/e2e/apimachinery/events.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								test/e2e/apimachinery/events.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,194 @@ | |||||||
|  | /* | ||||||
|  | Copyright 2016 The Kubernetes Authors. | ||||||
|  |  | ||||||
|  | Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | you may not use this file except in compliance with the License. | ||||||
|  | You may obtain a copy of the License at | ||||||
|  |  | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  | ||||||
|  | Unless required by applicable law or agreed to in writing, software | ||||||
|  | distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | See the License for the specific language governing permissions and | ||||||
|  | limitations under the License. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | package apimachinery | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	v1 "k8s.io/api/core/v1" | ||||||
|  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | 	"k8s.io/apimachinery/pkg/util/wait" | ||||||
|  | 	"k8s.io/kubernetes/test/e2e/framework" | ||||||
|  |  | ||||||
|  | 	"github.com/onsi/ginkgo" | ||||||
|  | 	"k8s.io/apimachinery/pkg/types" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	eventRetryPeriod  = 1 * time.Second | ||||||
|  | 	eventRetryTimeout = 1 * time.Minute | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var _ = ginkgo.Describe("[sig-api-machinery] Events", func() { | ||||||
|  | 	f := framework.NewDefaultFramework("events") | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 			   Release : v1.19 | ||||||
|  | 			   Testname: Event resource lifecycle | ||||||
|  | 			   Description: Create an event, the event MUST exist. | ||||||
|  | 		           The event is patched with a new message, the check MUST have the update message. | ||||||
|  | 		           The event is deleted and MUST NOT show up when listing all events. | ||||||
|  | 	*/ | ||||||
|  | 	framework.ConformanceIt("should ensure that an event can be fetched, patched, deleted, and listed", func() { | ||||||
|  | 		eventTestName := "event-test" | ||||||
|  |  | ||||||
|  | 		ginkgo.By("creating a test event") | ||||||
|  | 		// create a test event in test namespace | ||||||
|  | 		_, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Create(context.TODO(), &v1.Event{ | ||||||
|  | 			ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 				Name: eventTestName, | ||||||
|  | 				Labels: map[string]string{ | ||||||
|  | 					"testevent-constant": "true", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			Message: "This is a test event", | ||||||
|  | 			Reason:  "Test", | ||||||
|  | 			Type:    "Normal", | ||||||
|  | 			Count:   1, | ||||||
|  | 			InvolvedObject: v1.ObjectReference{ | ||||||
|  | 				Namespace: f.Namespace.Name, | ||||||
|  | 			}, | ||||||
|  | 		}, metav1.CreateOptions{}) | ||||||
|  | 		framework.ExpectNoError(err, "failed to create test event") | ||||||
|  |  | ||||||
|  | 		ginkgo.By("listing all events in all namespaces") | ||||||
|  | 		// get a list of Events in all namespaces to ensure endpoint coverage | ||||||
|  | 		eventsList, err := f.ClientSet.CoreV1().Events("").List(context.TODO(), metav1.ListOptions{ | ||||||
|  | 			LabelSelector: "testevent-constant=true", | ||||||
|  | 		}) | ||||||
|  | 		framework.ExpectNoError(err, "failed list all events") | ||||||
|  |  | ||||||
|  | 		foundCreatedEvent := false | ||||||
|  | 		var eventCreatedName string | ||||||
|  | 		for _, val := range eventsList.Items { | ||||||
|  | 			if val.ObjectMeta.Name == eventTestName && val.ObjectMeta.Namespace == f.Namespace.Name { | ||||||
|  | 				foundCreatedEvent = true | ||||||
|  | 				eventCreatedName = val.ObjectMeta.Name | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		framework.ExpectEqual(foundCreatedEvent, true, "unable to find the test event") | ||||||
|  |  | ||||||
|  | 		ginkgo.By("patching the test event") | ||||||
|  | 		// patch the event's message | ||||||
|  | 		eventPatchMessage := "This is a test event - patched" | ||||||
|  | 		eventPatch, err := json.Marshal(map[string]interface{}{ | ||||||
|  | 			"message": eventPatchMessage, | ||||||
|  | 		}) | ||||||
|  | 		framework.ExpectNoError(err, "failed to marshal the patch JSON payload") | ||||||
|  |  | ||||||
|  | 		_, err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Patch(context.TODO(), eventTestName, types.StrategicMergePatchType, []byte(eventPatch), metav1.PatchOptions{}) | ||||||
|  | 		framework.ExpectNoError(err, "failed to patch the test event") | ||||||
|  |  | ||||||
|  | 		ginkgo.By("fetching the test event") | ||||||
|  | 		// get event by name | ||||||
|  | 		event, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Get(context.TODO(), eventCreatedName, metav1.GetOptions{}) | ||||||
|  | 		framework.ExpectNoError(err, "failed to fetch the test event") | ||||||
|  | 		framework.ExpectEqual(event.Message, eventPatchMessage, "test event message does not match patch message") | ||||||
|  |  | ||||||
|  | 		ginkgo.By("deleting the test event") | ||||||
|  | 		// delete original event | ||||||
|  | 		err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Delete(context.TODO(), eventCreatedName, metav1.DeleteOptions{}) | ||||||
|  | 		framework.ExpectNoError(err, "failed to delete the test event") | ||||||
|  |  | ||||||
|  | 		ginkgo.By("listing all events in all namespaces") | ||||||
|  | 		// get a list of Events list namespace | ||||||
|  | 		eventsList, err = f.ClientSet.CoreV1().Events("").List(context.TODO(), metav1.ListOptions{ | ||||||
|  | 			LabelSelector: "testevent-constant=true", | ||||||
|  | 		}) | ||||||
|  | 		framework.ExpectNoError(err, "fail to list all events") | ||||||
|  | 		foundCreatedEvent = false | ||||||
|  | 		for _, val := range eventsList.Items { | ||||||
|  | 			if val.ObjectMeta.Name == eventTestName && val.ObjectMeta.Namespace == f.Namespace.Name { | ||||||
|  | 				foundCreatedEvent = true | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		framework.ExpectEqual(foundCreatedEvent, false, "should not have found test event after deletion") | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	ginkgo.It("should delete a collection of events", func() { | ||||||
|  | 		eventTestNames := []string{"test-event-1", "test-event-2", "test-event-3"} | ||||||
|  |  | ||||||
|  | 		ginkgo.By("Create set of events") | ||||||
|  | 		// create a test event in test namespace | ||||||
|  | 		for _, eventTestName := range eventTestNames { | ||||||
|  | 			eventMessage := "This is " + eventTestName | ||||||
|  | 			_, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Create(context.TODO(), &v1.Event{ | ||||||
|  |  | ||||||
|  | 				ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 					Name:   eventTestName, | ||||||
|  | 					Labels: map[string]string{"testevent-set": "true"}, | ||||||
|  | 				}, | ||||||
|  | 				Message: eventMessage, | ||||||
|  | 				Reason:  "Test", | ||||||
|  | 				Type:    "Normal", | ||||||
|  | 				Count:   1, | ||||||
|  | 				InvolvedObject: v1.ObjectReference{ | ||||||
|  | 					Namespace: f.Namespace.Name, | ||||||
|  | 				}, | ||||||
|  | 			}, metav1.CreateOptions{}) | ||||||
|  | 			framework.ExpectNoError(err, "failed to create event") | ||||||
|  | 			framework.Logf("created %v", eventTestName) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ginkgo.By("get a list of Events with a label in the current namespace") | ||||||
|  | 		// get a list of events | ||||||
|  | 		eventList, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).List(context.TODO(), metav1.ListOptions{ | ||||||
|  | 			LabelSelector: "testevent-set=true", | ||||||
|  | 		}) | ||||||
|  | 		framework.ExpectNoError(err, "failed to get a list of events") | ||||||
|  |  | ||||||
|  | 		framework.ExpectEqual(len(eventList.Items), len(eventTestNames), "looking for expected number of pod templates events") | ||||||
|  |  | ||||||
|  | 		ginkgo.By("delete collection of events") | ||||||
|  | 		// delete collection | ||||||
|  |  | ||||||
|  | 		framework.Logf("requesting DeleteCollection of events") | ||||||
|  | 		err = f.ClientSet.CoreV1().Events(f.Namespace.Name).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{ | ||||||
|  | 			LabelSelector: "testevent-set=true"}) | ||||||
|  | 		framework.ExpectNoError(err, "failed to delete the test event") | ||||||
|  |  | ||||||
|  | 		ginkgo.By("check that the list of events matches the requested quantity") | ||||||
|  |  | ||||||
|  | 		err = wait.PollImmediate(eventRetryPeriod, eventRetryTimeout, checkEventListQuantity(f, "testevent-set=true", 0)) | ||||||
|  | 		framework.ExpectNoError(err, "failed to count required events") | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | func checkEventListQuantity(f *framework.Framework, label string, quantity int) func() (bool, error) { | ||||||
|  | 	return func() (bool, error) { | ||||||
|  | 		var err error | ||||||
|  |  | ||||||
|  | 		framework.Logf("requesting list of events to confirm quantity") | ||||||
|  |  | ||||||
|  | 		eventList, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).List(context.TODO(), metav1.ListOptions{ | ||||||
|  | 			LabelSelector: label}) | ||||||
|  |  | ||||||
|  | 		if err != nil { | ||||||
|  | 			return false, err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if len(eventList.Items) != quantity { | ||||||
|  | 			return false, err | ||||||
|  | 		} | ||||||
|  | 		return true, nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -6,13 +6,9 @@ go_library( | |||||||
|     importpath = "k8s.io/kubernetes/test/e2e/framework/events", |     importpath = "k8s.io/kubernetes/test/e2e/framework/events", | ||||||
|     visibility = ["//visibility:public"], |     visibility = ["//visibility:public"], | ||||||
|     deps = [ |     deps = [ | ||||||
|         "//staging/src/k8s.io/api/core/v1:go_default_library", |  | ||||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", |         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", | ||||||
|         "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", |  | ||||||
|         "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", |         "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", | ||||||
|         "//staging/src/k8s.io/client-go/kubernetes:go_default_library", |         "//staging/src/k8s.io/client-go/kubernetes:go_default_library", | ||||||
|         "//test/e2e/framework:go_default_library", |  | ||||||
|         "//vendor/github.com/onsi/ginkgo:go_default_library", |  | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,113 +18,18 @@ package events | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	v1 "k8s.io/api/core/v1" |  | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
| 	"k8s.io/apimachinery/pkg/util/wait" | 	"k8s.io/apimachinery/pkg/util/wait" | ||||||
| 	clientset "k8s.io/client-go/kubernetes" | 	clientset "k8s.io/client-go/kubernetes" | ||||||
| 	"k8s.io/kubernetes/test/e2e/framework" |  | ||||||
|  |  | ||||||
| 	"github.com/onsi/ginkgo" |  | ||||||
| 	"k8s.io/apimachinery/pkg/types" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Action is a function to be performed by the system. | // Action is a function to be performed by the system. | ||||||
| type Action func() error | type Action func() error | ||||||
|  |  | ||||||
| var _ = ginkgo.Describe("[sig-api-machinery] Events", func() { |  | ||||||
| 	f := framework.NewDefaultFramework("events") |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 			   Release : v1.19 |  | ||||||
| 			   Testname: Event resource lifecycle |  | ||||||
| 			   Description: Create an event, the event MUST exist. |  | ||||||
| 		           The event is patched with a new message, the check MUST have the update message. |  | ||||||
| 		           The event is deleted and MUST NOT show up when listing all events. |  | ||||||
| 	*/ |  | ||||||
| 	framework.ConformanceIt("should ensure that an event can be fetched, patched, deleted, and listed", func() { |  | ||||||
| 		eventTestName := "event-test" |  | ||||||
|  |  | ||||||
| 		ginkgo.By("creating a test event") |  | ||||||
| 		// create a test event in test namespace |  | ||||||
| 		_, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Create(context.TODO(), &v1.Event{ |  | ||||||
| 			ObjectMeta: metav1.ObjectMeta{ |  | ||||||
| 				Name: eventTestName, |  | ||||||
| 				Labels: map[string]string{ |  | ||||||
| 					"testevent-constant": "true", |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			Message: "This is a test event", |  | ||||||
| 			Reason:  "Test", |  | ||||||
| 			Type:    "Normal", |  | ||||||
| 			Count:   1, |  | ||||||
| 			InvolvedObject: v1.ObjectReference{ |  | ||||||
| 				Namespace: f.Namespace.Name, |  | ||||||
| 			}, |  | ||||||
| 		}, metav1.CreateOptions{}) |  | ||||||
| 		framework.ExpectNoError(err, "failed to create test event") |  | ||||||
|  |  | ||||||
| 		ginkgo.By("listing all events in all namespaces") |  | ||||||
| 		// get a list of Events in all namespaces to ensure endpoint coverage |  | ||||||
| 		eventsList, err := f.ClientSet.CoreV1().Events("").List(context.TODO(), metav1.ListOptions{ |  | ||||||
| 			LabelSelector: "testevent-constant=true", |  | ||||||
| 		}) |  | ||||||
| 		framework.ExpectNoError(err, "failed list all events") |  | ||||||
|  |  | ||||||
| 		foundCreatedEvent := false |  | ||||||
| 		var eventCreatedName string |  | ||||||
| 		for _, val := range eventsList.Items { |  | ||||||
| 			if val.ObjectMeta.Name == eventTestName && val.ObjectMeta.Namespace == f.Namespace.Name { |  | ||||||
| 				foundCreatedEvent = true |  | ||||||
| 				eventCreatedName = val.ObjectMeta.Name |  | ||||||
| 				break |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		framework.ExpectEqual(foundCreatedEvent, true, "unable to find the test event") |  | ||||||
|  |  | ||||||
| 		ginkgo.By("patching the test event") |  | ||||||
| 		// patch the event's message |  | ||||||
| 		eventPatchMessage := "This is a test event - patched" |  | ||||||
| 		eventPatch, err := json.Marshal(map[string]interface{}{ |  | ||||||
| 			"message": eventPatchMessage, |  | ||||||
| 		}) |  | ||||||
| 		framework.ExpectNoError(err, "failed to marshal the patch JSON payload") |  | ||||||
|  |  | ||||||
| 		_, err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Patch(context.TODO(), eventTestName, types.StrategicMergePatchType, []byte(eventPatch), metav1.PatchOptions{}) |  | ||||||
| 		framework.ExpectNoError(err, "failed to patch the test event") |  | ||||||
|  |  | ||||||
| 		ginkgo.By("fetching the test event") |  | ||||||
| 		// get event by name |  | ||||||
| 		event, err := f.ClientSet.CoreV1().Events(f.Namespace.Name).Get(context.TODO(), eventCreatedName, metav1.GetOptions{}) |  | ||||||
| 		framework.ExpectNoError(err, "failed to fetch the test event") |  | ||||||
| 		framework.ExpectEqual(event.Message, eventPatchMessage, "test event message does not match patch message") |  | ||||||
|  |  | ||||||
| 		ginkgo.By("deleting the test event") |  | ||||||
| 		// delete original event |  | ||||||
| 		err = f.ClientSet.CoreV1().Events(f.Namespace.Name).Delete(context.TODO(), eventCreatedName, metav1.DeleteOptions{}) |  | ||||||
| 		framework.ExpectNoError(err, "failed to delete the test event") |  | ||||||
|  |  | ||||||
| 		ginkgo.By("listing all events in all namespaces") |  | ||||||
| 		// get a list of Events list namespace |  | ||||||
| 		eventsList, err = f.ClientSet.CoreV1().Events("").List(context.TODO(), metav1.ListOptions{ |  | ||||||
| 			LabelSelector: "testevent-constant=true", |  | ||||||
| 		}) |  | ||||||
| 		framework.ExpectNoError(err, "fail to list all events") |  | ||||||
| 		foundCreatedEvent = false |  | ||||||
| 		for _, val := range eventsList.Items { |  | ||||||
| 			if val.ObjectMeta.Name == eventTestName && val.ObjectMeta.Namespace == f.Namespace.Name { |  | ||||||
| 				foundCreatedEvent = true |  | ||||||
| 				break |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		framework.ExpectEqual(foundCreatedEvent, false, "should not have found test event after deletion") |  | ||||||
| 	}) |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| // WaitTimeoutForEvent waits the given timeout duration for an event to occur. | // WaitTimeoutForEvent waits the given timeout duration for an event to occur. | ||||||
| func WaitTimeoutForEvent(c clientset.Interface, namespace, eventSelector, msg string, timeout time.Duration) error { | func WaitTimeoutForEvent(c clientset.Interface, namespace, eventSelector, msg string, timeout time.Duration) error { | ||||||
| 	interval := 2 * time.Second | 	interval := 2 * time.Second | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user