mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Merge pull request #125379 from p0lyn0mial/upstream-unstructured-testdataconsistencychecker
client-go/consistencydetector: refactor TestDataConsistencyChecker to work with unstructured data
This commit is contained in:
commit
96815d6dc8
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
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/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/utils/ptr"
|
"k8s.io/utils/ptr"
|
||||||
@ -34,8 +35,9 @@ func TestDataConsistencyChecker(t *testing.T) {
|
|||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
||||||
listResponse *v1.PodList
|
lastSyncedResourceVersion string
|
||||||
retrievedItems []*v1.Pod
|
listResponse runtime.Object
|
||||||
|
retrievedItems []runtime.Object
|
||||||
requestOptions metav1.ListOptions
|
requestOptions metav1.ListOptions
|
||||||
|
|
||||||
expectedRequestOptions []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",
|
name: "data consistency check won't panic when data is consistent",
|
||||||
|
lastSyncedResourceVersion: "2",
|
||||||
listResponse: &v1.PodList{
|
listResponse: &v1.PodList{
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
||||||
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2")},
|
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2")},
|
||||||
},
|
},
|
||||||
requestOptions: metav1.ListOptions{TimeoutSeconds: ptr.To(int64(39))},
|
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,
|
expectedListRequests: 1,
|
||||||
expectedRequestOptions: []metav1.ListOptions{
|
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",
|
name: "legacy, the limit is removed from the list options when it wasn't honored by the watch cache",
|
||||||
|
lastSyncedResourceVersion: "2",
|
||||||
listResponse: &v1.PodList{
|
listResponse: &v1.PodList{
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
||||||
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
||||||
},
|
},
|
||||||
requestOptions: metav1.ListOptions{ResourceVersion: "0", Limit: 2},
|
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,
|
expectedListRequests: 1,
|
||||||
expectedRequestOptions: []metav1.ListOptions{
|
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",
|
name: "the limit is NOT removed from the list options for non-legacy request",
|
||||||
|
lastSyncedResourceVersion: "2",
|
||||||
listResponse: &v1.PodList{
|
listResponse: &v1.PodList{
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
||||||
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
||||||
},
|
},
|
||||||
requestOptions: metav1.ListOptions{ResourceVersion: "2", Limit: 2},
|
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,
|
expectedListRequests: 1,
|
||||||
expectedRequestOptions: []metav1.ListOptions{
|
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",
|
name: "legacy, the limit is NOT removed from the list options when the watch cache is disabled",
|
||||||
|
lastSyncedResourceVersion: "2",
|
||||||
listResponse: &v1.PodList{
|
listResponse: &v1.PodList{
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
||||||
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
||||||
},
|
},
|
||||||
requestOptions: metav1.ListOptions{ResourceVersion: "0", Limit: 5},
|
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,
|
expectedListRequests: 1,
|
||||||
expectedRequestOptions: []metav1.ListOptions{
|
expectedRequestOptions: []metav1.ListOptions{
|
||||||
{
|
{
|
||||||
@ -115,6 +149,7 @@ func TestDataConsistencyChecker(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
name: "data consistency check won't panic when there is no data",
|
name: "data consistency check won't panic when there is no data",
|
||||||
|
lastSyncedResourceVersion: "2",
|
||||||
listResponse: &v1.PodList{
|
listResponse: &v1.PodList{
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
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",
|
name: "data consistency check won't be performed when ResourceVersion was set to 0",
|
||||||
|
lastSyncedResourceVersion: "0",
|
||||||
listResponse: &v1.PodList{
|
listResponse: &v1.PodList{
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "0"},
|
ListMeta: metav1.ListMeta{ResourceVersion: "0"},
|
||||||
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2")},
|
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",
|
name: "data consistency panics when data is inconsistent",
|
||||||
|
lastSyncedResourceVersion: "2",
|
||||||
listResponse: &v1.PodList{
|
listResponse: &v1.PodList{
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
ListMeta: metav1.ListMeta{ResourceVersion: "2"},
|
||||||
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
|
||||||
},
|
},
|
||||||
requestOptions: metav1.ListOptions{TimeoutSeconds: ptr.To(int64(39))},
|
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,
|
expectedListRequests: 1,
|
||||||
expectedRequestOptions: []metav1.ListOptions{
|
expectedRequestOptions: []metav1.ListOptions{
|
||||||
{
|
{
|
||||||
@ -172,16 +209,16 @@ func TestDataConsistencyChecker(t *testing.T) {
|
|||||||
scenario.listResponse = &v1.PodList{}
|
scenario.listResponse = &v1.PodList{}
|
||||||
}
|
}
|
||||||
fakeLister := &listWrapper{response: scenario.listResponse}
|
fakeLister := &listWrapper{response: scenario.listResponse}
|
||||||
retrievedItemsFunc := func() []*v1.Pod {
|
retrievedItemsFunc := func() []runtime.Object {
|
||||||
return scenario.retrievedItems
|
return scenario.retrievedItems
|
||||||
}
|
}
|
||||||
|
|
||||||
if scenario.expectPanic {
|
if scenario.expectPanic {
|
||||||
require.Panics(t, func() {
|
require.Panics(t, func() {
|
||||||
CheckDataConsistency(ctx, "", scenario.listResponse.ResourceVersion, fakeLister.List, scenario.requestOptions, retrievedItemsFunc)
|
CheckDataConsistency(ctx, "", scenario.lastSyncedResourceVersion, fakeLister.List, scenario.requestOptions, retrievedItemsFunc)
|
||||||
})
|
})
|
||||||
} else {
|
} 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)
|
require.Equal(t, fakeLister.counter, scenario.expectedListRequests)
|
||||||
@ -218,10 +255,10 @@ func (lw *errorLister) List(_ context.Context, _ metav1.ListOptions) (runtime.Ob
|
|||||||
type listWrapper struct {
|
type listWrapper struct {
|
||||||
counter int
|
counter int
|
||||||
requestOptions []metav1.ListOptions
|
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.counter++
|
||||||
lw.requestOptions = append(lw.requestOptions, opts)
|
lw.requestOptions = append(lw.requestOptions, opts)
|
||||||
return lw.response, nil
|
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 {
|
func makePod(name, rv string) *v1.Pod {
|
||||||
return &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: name, ResourceVersion: rv, UID: types.UID(name)}}
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user