kvstore: Fix missing Folder field in listModifiedSinceEventStore data lookup (#113131)

* fix: ListModifiedSince for resources in folders

* fix: ListModifiedSince for resources in folders
This commit is contained in:
Georges Chaudy
2025-10-28 23:18:15 +01:00
committed by GitHub
parent d72e048bfe
commit 9533cc4dbb
2 changed files with 106 additions and 8 deletions
@@ -737,14 +737,7 @@ func (k *kvStorageBackend) listModifiedSinceEventStore(ctx context.Context, key
}
seen[evtKey.Name] = struct{}{}
value, err := k.getValueFromDataStore(ctx, DataKey{
Group: evtKey.Group,
Resource: evtKey.Resource,
Namespace: evtKey.Namespace,
Name: evtKey.Name,
ResourceVersion: evtKey.ResourceVersion,
Action: evtKey.Action,
})
value, err := k.getValueFromDataStore(ctx, DataKey(evtKey))
if err != nil {
yield(&ModifiedResource{}, err)
return
@@ -785,6 +785,111 @@ func seedBackend(t *testing.T, backend *kvStorageBackend, ctx context.Context, n
return expectations
}
func TestKvStorageBackend_ListModifiedSince_WithFolder(t *testing.T) {
backend := setupTestStorageBackend(t)
ctx := context.Background()
// Use a unique resource type to avoid conflicts with other tests
ns := NamespacedResource{
Namespace: "test-folder-ns",
Group: "test.folder.app",
Resource: "test-resources",
}
// Create test objects with folder field set
testObj1, err := createTestObjectWithName("dashboard-1", ns, "data-1")
require.NoError(t, err)
metaAccessor1, err := utils.MetaAccessor(testObj1)
require.NoError(t, err)
metaAccessor1.SetFolder("folder-abc")
testObj2, err := createTestObjectWithName("dashboard-2", ns, "data-2")
require.NoError(t, err)
metaAccessor2, err := utils.MetaAccessor(testObj2)
require.NoError(t, err)
metaAccessor2.SetFolder("folder-xyz")
// Write first dashboard
writeEvent1 := WriteEvent{
Type: resourcepb.WatchEvent_ADDED,
Key: &resourcepb.ResourceKey{
Namespace: ns.Namespace,
Group: ns.Group,
Resource: ns.Resource,
Name: "dashboard-1",
},
Value: objectToJSONBytes(t, testObj1),
Object: metaAccessor1,
PreviousRV: 0,
}
rv1, err := backend.WriteEvent(ctx, writeEvent1)
require.NoError(t, err)
// Write second dashboard
writeEvent2 := WriteEvent{
Type: resourcepb.WatchEvent_ADDED,
Key: &resourcepb.ResourceKey{
Namespace: ns.Namespace,
Group: ns.Group,
Resource: ns.Resource,
Name: "dashboard-2",
},
Value: objectToJSONBytes(t, testObj2),
Object: metaAccessor2,
PreviousRV: 0,
}
rv2, err := backend.WriteEvent(ctx, writeEvent2)
require.NoError(t, err)
tests := []struct {
name string
sinceRV func() int64
codePath string
}{
{
name: "via event store (recent RV < 1 hour)",
sinceRV: func() int64 { return rv1 - 1 },
codePath: "listModifiedSinceEventStore",
},
{
name: "via data store (old RV > 1 hour)",
sinceRV: func() int64 { return generateOldSnowflake(t) },
codePath: "listModifiedSinceDataStore",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sinceRV := tt.sinceRV()
// List resources
rv, seq := backend.ListModifiedSince(ctx, ns, sinceRV)
changes := make(map[string]*ModifiedResource)
for mr, err := range seq {
require.NoError(t, err, "Should not get error when Folder field is included")
require.Equal(t, ns.Group, mr.Key.Group)
require.Equal(t, ns.Namespace, mr.Key.Namespace)
require.Equal(t, ns.Resource, mr.Key.Resource)
changes[mr.Key.Name] = mr
}
require.Greater(t, rv, sinceRV)
require.Len(t, changes, 2, "Should return 2 resources")
// Verify dashboard-1
require.Contains(t, changes, "dashboard-1")
require.Equal(t, rv1, changes["dashboard-1"].ResourceVersion)
require.Equal(t, objectToJSONBytes(t, testObj1), changes["dashboard-1"].Value)
// Verify dashboard-2
require.Contains(t, changes, "dashboard-2")
require.Equal(t, rv2, changes["dashboard-2"].ResourceVersion)
require.Equal(t, objectToJSONBytes(t, testObj2), changes["dashboard-2"].Value)
})
}
}
func createAndSaveTestObject(t *testing.T, backend *kvStorageBackend, ctx context.Context, ns NamespacedResource, uniqueStringGen func() string, updates int, deleted bool) *ModifiedResource {
name := uniqueStringGen()
action := resourcepb.WatchEvent_ADDED