Skip to content

Commit c951f4f

Browse files
committed
Add getGeneration in the interface
Signed-off-by: Jian Qiu <jqiu@redhat.com>
1 parent 3e85103 commit c951f4f

11 files changed

Lines changed: 66 additions & 68 deletions

File tree

pkg/cloudevents/clients/work/agent/client/manifestwork.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ func versoinCompare(new, old *workv1.ManifestWork) *errors.StatusError {
256256
if err != nil {
257257
return errors.NewInternalError(err)
258258
}
259+
260+
klog.Infof("last resource version is %d, resource version is %d", lastResourceVersion, newResourceVersion)
259261
// ensure the resource version of the work is not outdated
260262
if newResourceVersion < lastResourceVersion {
261263
// It's safe to return a conflict error here, even if the status update event

pkg/cloudevents/clients/work/agent/codec/manifestbundle.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package codec
33
import (
44
"encoding/json"
55
"fmt"
6-
"strconv"
7-
86
"github.com/bwmarrin/snowflake"
97
cloudevents "github.com/cloudevents/sdk-go/v2"
108
cloudeventstypes "github.com/cloudevents/sdk-go/v2/types"
@@ -50,16 +48,6 @@ func (c *ManifestBundleCodec) Encode(source string, eventType types.CloudEventsT
5048
return nil, fmt.Errorf("unsupported cloudevents data type %s", eventType.CloudEventsDataType)
5149
}
5250

53-
var resourceVersion int64
54-
// If resource version is empty, use 0 as default (e.g., when publishing status updates)
55-
if work.ResourceVersion != "" {
56-
var err error
57-
resourceVersion, err = strconv.ParseInt(work.ResourceVersion, 10, 64)
58-
if err != nil {
59-
return nil, fmt.Errorf("failed to parse the resourceversion of the work %s, %v", work.UID, err)
60-
}
61-
}
62-
6351
originalSource, ok := work.Labels[common.CloudEventsOriginalSourceLabelKey]
6452
if !ok {
6553
return nil, fmt.Errorf("failed to find originalsource from the work %s", work.UID)
@@ -68,7 +56,7 @@ func (c *ManifestBundleCodec) Encode(source string, eventType types.CloudEventsT
6856
evt := types.NewEventBuilder(source, eventType).
6957
WithResourceID(string(work.UID)).
7058
WithStatusUpdateSequenceID(sequenceGenerator.Generate().String()).
71-
WithResourceVersion(resourceVersion).
59+
WithResourceVersion(work.Generation).
7260
WithClusterName(work.Namespace).
7361
WithOriginalSource(originalSource).
7462
NewEvent()

pkg/cloudevents/clients/work/store/informer.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func (v *versioner) increment(name string) int64 {
111111
defer v.lock.Unlock()
112112

113113
if _, ok := v.versions[name]; !ok {
114-
v.versions[name] = 0
114+
v.versions[name] = 1
115115
} else {
116116
v.versions[name] = v.versions[name] + 1
117117
}
@@ -143,6 +143,7 @@ func (s *AgentInformerWatcherStore) Add(resource runtime.Object) error {
143143
return err
144144
}
145145
accessor.SetResourceVersion(strconv.FormatInt(s.versions.increment(accessor.GetName()), 10))
146+
klog.Infof("inc resource version to %s because of adding", accessor.GetResourceVersion())
146147
return s.AgentInformerWatcherStore.Add(resource)
147148
}
148149

@@ -152,6 +153,7 @@ func (s *AgentInformerWatcherStore) Update(resource runtime.Object) error {
152153
return err
153154
}
154155
accessor.SetResourceVersion(strconv.FormatInt(s.versions.increment(accessor.GetName()), 10))
156+
klog.Infof("inc resource version to %s because of updating", accessor.GetResourceVersion())
155157
return s.AgentInformerWatcherStore.Update(resource)
156158
}
157159

pkg/cloudevents/clients/work/store/informer_test.go

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@ func TestVersioner(t *testing.T) {
2020
t.Run("increment version for new resource", func(t *testing.T) {
2121
v := newVersioner()
2222
version := v.increment("test-work")
23-
if version != 0 {
24-
t.Errorf("expected version 0 for new resource, got %d", version)
23+
if version != 1 {
24+
t.Errorf("expected version 1 for new resource, got %d", version)
2525
}
2626
})
2727

2828
t.Run("increment version for existing resource", func(t *testing.T) {
2929
v := newVersioner()
3030
v.increment("test-work")
3131
version := v.increment("test-work")
32-
if version != 1 {
33-
t.Errorf("expected version 1 for existing resource, got %d", version)
32+
if version != 2 {
33+
t.Errorf("expected version 2 for existing resource, got %d", version)
3434
}
3535
})
3636

3737
t.Run("increment multiple times", func(t *testing.T) {
3838
v := newVersioner()
39-
for i := 0; i < 5; i++ {
39+
for i := 1; i <= 5; i++ {
4040
version := v.increment("test-work")
4141
if version != int64(i) {
4242
t.Errorf("expected version %d, got %d", i, version)
@@ -49,8 +49,8 @@ func TestVersioner(t *testing.T) {
4949
v.increment("test-work")
5050
v.delete("test-work")
5151
version := v.increment("test-work")
52-
if version != 0 {
53-
t.Errorf("expected version 0 after delete, got %d", version)
52+
if version != 1 {
53+
t.Errorf("expected version 1 after delete, got %d", version)
5454
}
5555
})
5656

@@ -70,8 +70,8 @@ func TestVersioner(t *testing.T) {
7070
}
7171

7272
finalVersion := v.increment("test-work")
73-
if finalVersion != 10 {
74-
t.Errorf("expected version 10 after 10 concurrent increments, got %d", finalVersion)
73+
if finalVersion != 11 {
74+
t.Errorf("expected version 11 after 10 concurrent increments, got %d", finalVersion)
7575
}
7676
})
7777
}
@@ -118,8 +118,8 @@ func TestAgentInformerWatcherStore_Add(t *testing.T) {
118118
t.Fatalf("unexpected error adding work: %v", err)
119119
}
120120

121-
if work.ResourceVersion != "0" {
122-
t.Errorf("expected resource version 0, got %s", work.ResourceVersion)
121+
if work.ResourceVersion != "1" {
122+
t.Errorf("expected resource version 1, got %s", work.ResourceVersion)
123123
}
124124

125125
// Add another work
@@ -135,8 +135,8 @@ func TestAgentInformerWatcherStore_Add(t *testing.T) {
135135
t.Fatalf("unexpected error adding work: %v", err)
136136
}
137137

138-
if work2.ResourceVersion != "1" {
139-
t.Errorf("expected resource version 1 for second add, got %s", work2.ResourceVersion)
138+
if work2.ResourceVersion != "2" {
139+
t.Errorf("expected resource version 2 for second add, got %s", work2.ResourceVersion)
140140
}
141141
}
142142

@@ -198,8 +198,8 @@ func TestAgentInformerWatcherStore_Update(t *testing.T) {
198198
t.Fatalf("unexpected error updating work: %v", err)
199199
}
200200

201-
if updatedWork.ResourceVersion != "1" {
202-
t.Errorf("expected resource version 1 after update, got %s", updatedWork.ResourceVersion)
201+
if updatedWork.ResourceVersion != "2" {
202+
t.Errorf("expected resource version 2 after update, got %s", updatedWork.ResourceVersion)
203203
}
204204

205205
// Update again
@@ -208,8 +208,8 @@ func TestAgentInformerWatcherStore_Update(t *testing.T) {
208208
t.Fatalf("unexpected error updating work: %v", err)
209209
}
210210

211-
if updatedWork.ResourceVersion != "2" {
212-
t.Errorf("expected resource version 2 after second update, got %s", updatedWork.ResourceVersion)
211+
if updatedWork.ResourceVersion != "3" {
212+
t.Errorf("expected resource version 3 after second update, got %s", updatedWork.ResourceVersion)
213213
}
214214
}
215215

@@ -267,7 +267,7 @@ func TestAgentInformerWatcherStore_Delete(t *testing.T) {
267267
t.Fatalf("unexpected error deleting work: %v", err)
268268
}
269269

270-
// Add the same work again, version should be reset to 0
270+
// Add the same work again, version should be reset to 1
271271
newWork := &workv1.ManifestWork{
272272
ObjectMeta: metav1.ObjectMeta{
273273
Name: "test-work",
@@ -280,8 +280,8 @@ func TestAgentInformerWatcherStore_Delete(t *testing.T) {
280280
t.Fatalf("unexpected error adding work after delete: %v", err)
281281
}
282282

283-
if newWork.ResourceVersion != "0" {
284-
t.Errorf("expected resource version 0 after delete and re-add, got %s", newWork.ResourceVersion)
283+
if newWork.ResourceVersion != "1" {
284+
t.Errorf("expected resource version 1 after delete and re-add, got %s", newWork.ResourceVersion)
285285
}
286286
}
287287

@@ -323,7 +323,7 @@ func TestAgentInformerWatcherStore_ResourceVersionIncrement(t *testing.T) {
323323
}
324324

325325
// Verify resource versions increment properly
326-
expectedVersions := []string{"0", "1", "2", "3"}
326+
expectedVersions := []string{"1", "2", "3", "4"}
327327

328328
// Add
329329
err = store.Add(work)

pkg/cloudevents/generic/clients/agentclient.go

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package clients
33
import (
44
"context"
55
"fmt"
6-
"strconv"
76
"time"
87

98
cloudevents "github.com/cloudevents/sdk-go/v2"
@@ -85,19 +84,9 @@ func (c *CloudEventAgentClient[T]) Resync(ctx context.Context, source string) er
8584

8685
resources := &payload.ResourceVersionList{Versions: make([]payload.ResourceVersion, len(objs))}
8786
for i, obj := range objs {
88-
var resourceVersion int64
89-
// If resource version is empty, use 0 as default
90-
if obj.GetResourceVersion() != "" {
91-
var err error
92-
resourceVersion, err = strconv.ParseInt(obj.GetResourceVersion(), 10, 64)
93-
if err != nil {
94-
return err
95-
}
96-
}
97-
9887
resources.Versions[i] = payload.ResourceVersion{
9988
ResourceID: string(obj.GetUID()),
100-
ResourceVersion: resourceVersion,
89+
ResourceVersion: obj.GetGeneration(),
10190
}
10291
}
10392

@@ -305,27 +294,11 @@ func (c *CloudEventAgentClient[T]) specAction(
305294

306295
// if both the current and the last object have the resource version "0" or empty, then object
307296
// is considered as modified, the message broker guarantees the order of the messages
308-
if (obj.GetResourceVersion() == "0" || obj.GetResourceVersion() == "") &&
309-
(lastObj.GetResourceVersion() == "0" || lastObj.GetResourceVersion() == "") {
297+
if lastObj.GetGeneration() == 0 && obj.GetGeneration() == 0 {
310298
return types.Modified, nil
311299
}
312300

313-
// If resource version is empty, treat as modified (cannot compare versions)
314-
if obj.GetResourceVersion() == "" || lastObj.GetResourceVersion() == "" {
315-
return types.Modified, nil
316-
}
317-
318-
resourceVersion, err := strconv.ParseInt(obj.GetResourceVersion(), 10, 64)
319-
if err != nil {
320-
return evt, err
321-
}
322-
323-
lastResourceVersion, err := strconv.ParseInt(lastObj.GetResourceVersion(), 10, 64)
324-
if err != nil {
325-
return evt, err
326-
}
327-
328-
if resourceVersion <= lastResourceVersion {
301+
if obj.GetGeneration() <= lastObj.GetGeneration() {
329302
return evt, nil
330303
}
331304

pkg/cloudevents/generic/clients/agentclient_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func TestAgentPublish(t *testing.T) {
116116
clusterName: "cluster1",
117117
resources: &generictesting.MockResource{
118118
UID: kubetypes.UID("1234"),
119+
Generation: 2,
119120
ResourceVersion: "2",
120121
Status: "test-status",
121122
Namespace: "cluster1",
@@ -396,6 +397,7 @@ func TestReceiveResourceSpec(t *testing.T) {
396397
eventType,
397398
&generictesting.MockResource{
398399
UID: kubetypes.UID("test1"),
400+
Generation: 1,
399401
ResourceVersion: "1",
400402
Namespace: "cluster1",
401403
})
@@ -422,6 +424,7 @@ func TestReceiveResourceSpec(t *testing.T) {
422424
eventType,
423425
&generictesting.MockResource{
424426
UID: kubetypes.UID("test1"),
427+
Generation: 2,
425428
ResourceVersion: "2",
426429
Namespace: "cluster1",
427430
})
@@ -492,14 +495,15 @@ func TestReceiveResourceSpec(t *testing.T) {
492495
eventType,
493496
&generictesting.MockResource{
494497
UID: kubetypes.UID("test1"),
498+
Generation: 2,
495499
ResourceVersion: "2",
496500
Namespace: "cluster1",
497501
})
498502
return *evt
499503
}(),
500504
resources: []*generictesting.MockResource{
501-
{UID: kubetypes.UID("test1"), ResourceVersion: "2", Namespace: "cluster1"},
502-
{UID: kubetypes.UID("test2"), ResourceVersion: "1", Namespace: "cluster1"},
505+
{UID: kubetypes.UID("test1"), Generation: 2, ResourceVersion: "2", Namespace: "cluster1"},
506+
{UID: kubetypes.UID("test2"), Generation: 1, ResourceVersion: "1", Namespace: "cluster1"},
503507
},
504508
validate: func(event types.ResourceAction, resource *generictesting.MockResource) {
505509
if len(event) != 0 {

pkg/cloudevents/generic/clients/sourceclient_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ func TestSourcePublish(t *testing.T) {
9999
resources: &generictesting.MockResource{
100100
UID: kubetypes.UID("1234"),
101101
ResourceVersion: "2",
102+
Generation: 2,
102103
Spec: "test-spec",
103104
},
104105
eventType: types.CloudEventsType{

pkg/cloudevents/generic/interface.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ type ResourceObject interface {
2525
// GetResourceVersion returns the resource version of this object. The resource version is a required int64 sequence
2626
// number property that must be incremented by the source whenever this resource changes.
2727
// The source should guarantee its incremental nature.
28+
// Deprecated: use GetGeneration() instead.
2829
GetResourceVersion() string
2930

31+
// GetGeneration returns the generation number of this object to reflect the spec change of the resource.
32+
GetGeneration() int64
33+
3034
// GetDeletionTimestamp returns the deletion timestamp of this object. The deletiontimestamp is an optional
3135
// timestamp property representing the resource is deleting from the source, the agent needs to clean up the
3236
// resource from its cluster.

pkg/cloudevents/generic/testing/resource.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package testing
22

33
import (
44
"fmt"
5+
"strconv"
56
"time"
67

78
cloudevents "github.com/cloudevents/sdk-go/v2"
@@ -22,6 +23,7 @@ var MockEventDataType = types.CloudEventsDataType{
2223
type MockResource struct {
2324
UID kubetypes.UID `json:"uid"`
2425
ResourceVersion string `json:"resourceVersion"`
26+
Generation int64 `json:"generation"`
2527
DeletionTimestamp *metav1.Time `json:"deletionTimestamp,omitempty"`
2628
Namespace string
2729
Spec string `json:"spec"`
@@ -36,6 +38,10 @@ func (r *MockResource) GetResourceVersion() string {
3638
return r.ResourceVersion
3739
}
3840

41+
func (r *MockResource) GetGeneration() int64 {
42+
return r.Generation
43+
}
44+
3945
func (r *MockResource) GetDeletionTimestamp() *metav1.Time {
4046
return r.DeletionTimestamp
4147
}
@@ -75,7 +81,7 @@ func (c *MockResourceCodec) Encode(source string, eventType types.CloudEventsTyp
7581
evt.SetType(eventType.String())
7682
evt.SetTime(time.Now())
7783
evt.SetExtension("resourceid", string(obj.UID))
78-
evt.SetExtension("resourceversion", obj.ResourceVersion)
84+
evt.SetExtension("resourceversion", strconv.FormatInt(obj.Generation, 10))
7985
evt.SetExtension("clustername", obj.Namespace)
8086
if obj.GetDeletionTimestamp() != nil {
8187
evt.SetExtension("deletiontimestamp", obj.DeletionTimestamp.Time)
@@ -97,9 +103,15 @@ func (c *MockResourceCodec) Decode(evt *cloudevents.Event) (*MockResource, error
97103
return nil, fmt.Errorf("failed to get resource version: %v", err)
98104
}
99105

106+
generation, err := strconv.ParseInt(fmt.Sprintf("%s", resourceVersion), 10, 64)
107+
if err != nil {
108+
return nil, fmt.Errorf("failed to parse resource generation: %v", err)
109+
}
110+
100111
res := &MockResource{
101112
UID: kubetypes.UID(fmt.Sprintf("%s", resourceID)),
102113
ResourceVersion: fmt.Sprintf("%s", resourceVersion),
114+
Generation: generation,
103115
Status: string(evt.Data()),
104116
}
105117

test/integration/cloudevents/manifestworkclients_watch_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,18 @@ var _ = ginkgo.Describe("ManifestWork Clients Test - Watch Only", func() {
185185
gomega.Eventually(func() error {
186186
workClient := agentClient.ManifestWorks(clusterName)
187187

188+
work, err := workClient.Get(ctx, workName, metav1.GetOptions{})
189+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
190+
ginkgo.By(fmt.Sprintf("resourceVersion is %s", work.ResourceVersion))
191+
188192
if err := util.AddWorkFinalizer(ctx, workClient, workName); err != nil {
189193
return err
190194
}
191195

196+
work, err = workClient.Get(ctx, workName, metav1.GetOptions{})
197+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
198+
ginkgo.By(fmt.Sprintf("resourceVersion is %s after patch", work.ResourceVersion))
199+
192200
return util.UpdateWorkStatus(ctx, workClient, workName, util.WorkCreatedCondition)
193201
}, 10*time.Second, 1*time.Second).Should(gomega.Succeed())
194202

0 commit comments

Comments
 (0)