Merge pull request #125379 from p0lyn0mial/upstream-unstructured-testdataconsistencychecker
client-go/consistencydetector: refactor TestDataConsistencyChecker to work with unstructured data
This commit is contained in:
		| @@ -25,6 +25,7 @@ import ( | ||||
|  | ||||
| 	v1 "k8s.io/api/core/v1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	"k8s.io/utils/ptr" | ||||
| @@ -34,8 +35,9 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
| 	scenarios := []struct { | ||||
| 		name string | ||||
|  | ||||
| 		listResponse   *v1.PodList | ||||
| 		retrievedItems []*v1.Pod | ||||
| 		lastSyncedResourceVersion string | ||||
| 		listResponse              runtime.Object | ||||
| 		retrievedItems            []runtime.Object | ||||
| 		requestOptions            metav1.ListOptions | ||||
|  | ||||
| 		expectedRequestOptions []metav1.ListOptions | ||||
| @@ -44,12 +46,41 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name:                      "data consistency check won't panic when data is consistent", | ||||
| 			lastSyncedResourceVersion: "2", | ||||
| 			listResponse: &v1.PodList{ | ||||
| 				ListMeta: metav1.ListMeta{ResourceVersion: "2"}, | ||||
| 				Items:    []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2")}, | ||||
| 			}, | ||||
| 			requestOptions:       metav1.ListOptions{TimeoutSeconds: ptr.To(int64(39))}, | ||||
| 			retrievedItems:       []*v1.Pod{makePod("p1", "1"), makePod("p2", "2")}, | ||||
| 			retrievedItems:       []runtime.Object{makePod("p1", "1"), makePod("p2", "2")}, | ||||
| 			expectedListRequests: 1, | ||||
| 			expectedRequestOptions: []metav1.ListOptions{ | ||||
| 				{ | ||||
| 					ResourceVersion:      "2", | ||||
| 					ResourceVersionMatch: metav1.ResourceVersionMatchExact, | ||||
| 					TimeoutSeconds:       ptr.To(int64(39)), | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| 			name:                      "data consistency check works with unstructured data (dynamic client)", | ||||
| 			lastSyncedResourceVersion: "2", | ||||
| 			listResponse: &unstructured.UnstructuredList{ | ||||
| 				Object: map[string]interface{}{ | ||||
| 					"apiVersion": "vTest", | ||||
| 					"kind":       "rTestList", | ||||
| 				}, | ||||
| 				Items: []unstructured.Unstructured{ | ||||
| 					*makeUnstructuredObject("vTest", "rTest", "item1"), | ||||
| 					*makeUnstructuredObject("vTest", "rTest", "item2"), | ||||
| 				}, | ||||
| 			}, | ||||
| 			requestOptions: metav1.ListOptions{TimeoutSeconds: ptr.To(int64(39))}, | ||||
| 			retrievedItems: []runtime.Object{ | ||||
| 				makeUnstructuredObject("vTest", "rTest", "item1"), | ||||
| 				makeUnstructuredObject("vTest", "rTest", "item2"), | ||||
| 			}, | ||||
| 			expectedListRequests: 1, | ||||
| 			expectedRequestOptions: []metav1.ListOptions{ | ||||
| 				{ | ||||
| @@ -62,12 +93,13 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
|  | ||||
| 		{ | ||||
| 			name:                      "legacy, the limit is removed from the list options when it wasn't honored by the watch cache", | ||||
| 			lastSyncedResourceVersion: "2", | ||||
| 			listResponse: &v1.PodList{ | ||||
| 				ListMeta: metav1.ListMeta{ResourceVersion: "2"}, | ||||
| 				Items:    []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")}, | ||||
| 			}, | ||||
| 			requestOptions:       metav1.ListOptions{ResourceVersion: "0", Limit: 2}, | ||||
| 			retrievedItems:       []*v1.Pod{makePod("p1", "1"), makePod("p2", "2"), makePod("p3", "3")}, | ||||
| 			retrievedItems:       []runtime.Object{makePod("p1", "1"), makePod("p2", "2"), makePod("p3", "3")}, | ||||
| 			expectedListRequests: 1, | ||||
| 			expectedRequestOptions: []metav1.ListOptions{ | ||||
| 				{ | ||||
| @@ -79,12 +111,13 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
|  | ||||
| 		{ | ||||
| 			name:                      "the limit is NOT removed from the list options for non-legacy request", | ||||
| 			lastSyncedResourceVersion: "2", | ||||
| 			listResponse: &v1.PodList{ | ||||
| 				ListMeta: metav1.ListMeta{ResourceVersion: "2"}, | ||||
| 				Items:    []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")}, | ||||
| 			}, | ||||
| 			requestOptions:       metav1.ListOptions{ResourceVersion: "2", Limit: 2}, | ||||
| 			retrievedItems:       []*v1.Pod{makePod("p1", "1"), makePod("p2", "2"), makePod("p3", "3")}, | ||||
| 			retrievedItems:       []runtime.Object{makePod("p1", "1"), makePod("p2", "2"), makePod("p3", "3")}, | ||||
| 			expectedListRequests: 1, | ||||
| 			expectedRequestOptions: []metav1.ListOptions{ | ||||
| 				{ | ||||
| @@ -97,12 +130,13 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
|  | ||||
| 		{ | ||||
| 			name:                      "legacy, the limit is NOT removed from the list options when the watch cache is disabled", | ||||
| 			lastSyncedResourceVersion: "2", | ||||
| 			listResponse: &v1.PodList{ | ||||
| 				ListMeta: metav1.ListMeta{ResourceVersion: "2"}, | ||||
| 				Items:    []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")}, | ||||
| 			}, | ||||
| 			requestOptions:       metav1.ListOptions{ResourceVersion: "0", Limit: 5}, | ||||
| 			retrievedItems:       []*v1.Pod{makePod("p1", "1"), makePod("p2", "2"), makePod("p3", "3")}, | ||||
| 			retrievedItems:       []runtime.Object{makePod("p1", "1"), makePod("p2", "2"), makePod("p3", "3")}, | ||||
| 			expectedListRequests: 1, | ||||
| 			expectedRequestOptions: []metav1.ListOptions{ | ||||
| 				{ | ||||
| @@ -115,6 +149,7 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
|  | ||||
| 		{ | ||||
| 			name:                      "data consistency check won't panic when there is no data", | ||||
| 			lastSyncedResourceVersion: "2", | ||||
| 			listResponse: &v1.PodList{ | ||||
| 				ListMeta: metav1.ListMeta{ResourceVersion: "2"}, | ||||
| 			}, | ||||
| @@ -137,6 +172,7 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
|  | ||||
| 		{ | ||||
| 			name:                      "data consistency check won't be performed when ResourceVersion was set to 0", | ||||
| 			lastSyncedResourceVersion: "0", | ||||
| 			listResponse: &v1.PodList{ | ||||
| 				ListMeta: metav1.ListMeta{ResourceVersion: "0"}, | ||||
| 				Items:    []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2")}, | ||||
| @@ -147,12 +183,13 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
|  | ||||
| 		{ | ||||
| 			name:                      "data consistency panics when data is inconsistent", | ||||
| 			lastSyncedResourceVersion: "2", | ||||
| 			listResponse: &v1.PodList{ | ||||
| 				ListMeta: metav1.ListMeta{ResourceVersion: "2"}, | ||||
| 				Items:    []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")}, | ||||
| 			}, | ||||
| 			requestOptions:       metav1.ListOptions{TimeoutSeconds: ptr.To(int64(39))}, | ||||
| 			retrievedItems:       []*v1.Pod{makePod("p1", "1"), makePod("p2", "2")}, | ||||
| 			retrievedItems:       []runtime.Object{makePod("p1", "1"), makePod("p2", "2")}, | ||||
| 			expectedListRequests: 1, | ||||
| 			expectedRequestOptions: []metav1.ListOptions{ | ||||
| 				{ | ||||
| @@ -172,16 +209,16 @@ func TestDataConsistencyChecker(t *testing.T) { | ||||
| 				scenario.listResponse = &v1.PodList{} | ||||
| 			} | ||||
| 			fakeLister := &listWrapper{response: scenario.listResponse} | ||||
| 			retrievedItemsFunc := func() []*v1.Pod { | ||||
| 			retrievedItemsFunc := func() []runtime.Object { | ||||
| 				return scenario.retrievedItems | ||||
| 			} | ||||
|  | ||||
| 			if scenario.expectPanic { | ||||
| 				require.Panics(t, func() { | ||||
| 					CheckDataConsistency(ctx, "", scenario.listResponse.ResourceVersion, fakeLister.List, scenario.requestOptions, retrievedItemsFunc) | ||||
| 					CheckDataConsistency(ctx, "", scenario.lastSyncedResourceVersion, fakeLister.List, scenario.requestOptions, retrievedItemsFunc) | ||||
| 				}) | ||||
| 			} else { | ||||
| 				CheckDataConsistency(ctx, "", scenario.listResponse.ResourceVersion, fakeLister.List, scenario.requestOptions, retrievedItemsFunc) | ||||
| 				CheckDataConsistency(ctx, "", scenario.lastSyncedResourceVersion, fakeLister.List, scenario.requestOptions, retrievedItemsFunc) | ||||
| 			} | ||||
|  | ||||
| 			require.Equal(t, fakeLister.counter, scenario.expectedListRequests) | ||||
| @@ -218,10 +255,10 @@ func (lw *errorLister) List(_ context.Context, _ metav1.ListOptions) (runtime.Ob | ||||
| type listWrapper struct { | ||||
| 	counter        int | ||||
| 	requestOptions []metav1.ListOptions | ||||
| 	response       *v1.PodList | ||||
| 	response       runtime.Object | ||||
| } | ||||
|  | ||||
| func (lw *listWrapper) List(_ context.Context, opts metav1.ListOptions) (*v1.PodList, error) { | ||||
| func (lw *listWrapper) List(_ context.Context, opts metav1.ListOptions) (runtime.Object, error) { | ||||
| 	lw.counter++ | ||||
| 	lw.requestOptions = append(lw.requestOptions, opts) | ||||
| 	return lw.response, nil | ||||
| @@ -230,3 +267,15 @@ func (lw *listWrapper) List(_ context.Context, opts metav1.ListOptions) (*v1.Pod | ||||
| func makePod(name, rv string) *v1.Pod { | ||||
| 	return &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: name, ResourceVersion: rv, UID: types.UID(name)}} | ||||
| } | ||||
|  | ||||
| func makeUnstructuredObject(version, kind, name string) *unstructured.Unstructured { | ||||
| 	return &unstructured.Unstructured{ | ||||
| 		Object: map[string]interface{}{ | ||||
| 			"apiVersion": version, | ||||
| 			"kind":       kind, | ||||
| 			"metadata": map[string]interface{}{ | ||||
| 				"name": name, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot