Skip to content

Commit 0712ebd

Browse files
justinsbtomasaschan
andcommitted
mockkubeapiserver: set generation on objects
Aiming for a little bit more fidelity, also enables us to test observedGeneration (in future). Co-authored-by: Tomas Aschan <[email protected]>
1 parent 187c2bb commit 0712ebd

File tree

10 files changed

+68
-29
lines changed

10 files changed

+68
-29
lines changed

mockkubeapiserver/hooks/crd.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,6 @@ func (s *CRDHook) updateCRDConditions(ev *storage.WatchEvent) error {
5757
return fmt.Errorf("status was of unexpected type %T", statusObj)
5858
}
5959

60-
generation := u.GetGeneration()
61-
if generation == 0 {
62-
generation = 1
63-
u.SetGeneration(generation)
64-
}
65-
6660
var conditions []interface{}
6761
conditions = append(conditions, map[string]interface{}{
6862
"type": "NamesAccepted",

mockkubeapiserver/hooks/deployment.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ func (s *DeploymentHook) deploymentChanged(ev *storage.WatchEvent) error {
5353
return fmt.Errorf("status was of unexpected type %T", statusObj)
5454
}
5555

56-
generation := u.GetGeneration()
57-
if generation == 0 {
58-
generation = 1
59-
u.SetGeneration(generation)
60-
}
61-
6256
replicasVal, _, err := unstructured.NestedFieldNoCopy(u.Object, "spec", "replicas")
6357
if err != nil {
6458
return fmt.Errorf("error getting spec.replicas: %w", err)
@@ -91,7 +85,7 @@ func (s *DeploymentHook) deploymentChanged(ev *storage.WatchEvent) error {
9185
status["replicas"] = replicas
9286
status["updatedReplicas"] = replicas
9387

94-
observedGeneration := generation
88+
observedGeneration := u.GetGeneration()
9589
status["observedGeneration"] = observedGeneration
9690

9791
return nil

mockkubeapiserver/patchresource.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"io"
2424
"net/http"
25+
"reflect"
2526
"strconv"
2627

2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -79,6 +80,11 @@ func (req *patchResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
7980
// TODO: Should we treat this like an apply to an empty object?
8081

8182
patched := body
83+
84+
if resource.SetsGeneration() {
85+
patched.SetGeneration(1)
86+
}
87+
8288
if err := resource.CreateObject(ctx, id, patched); err != nil {
8389
return err
8490
}
@@ -124,6 +130,15 @@ func (req *patchResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
124130
klog.Infof("skipping write, object not changed")
125131
return req.writeResponse(existingObj)
126132
} else {
133+
if resource.SetsGeneration() {
134+
specIsSame := reflect.DeepEqual(existingObj.Object["spec"], updated.Object["spec"])
135+
if !specIsSame {
136+
generation := updated.GetGeneration()
137+
generation++
138+
updated.SetGeneration(generation)
139+
}
140+
}
141+
127142
if err := resource.UpdateObject(ctx, id, updated); err != nil {
128143
return err
129144
}

mockkubeapiserver/postresource.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ func (req *postResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
6969
return fmt.Errorf("name must be provided in payload")
7070
}
7171

72+
if resource.SetsGeneration() {
73+
obj.SetGeneration(1)
74+
}
75+
7276
if err := resource.CreateObject(ctx, id, obj); err != nil {
7377
return err
7478
}

mockkubeapiserver/putresource.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ func (req *putResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
8989
return req.writeResponse(original)
9090
}
9191

92+
if resource.SetsGeneration() {
93+
specIsSame := reflect.DeepEqual(original.Object["spec"], updated.Object["spec"])
94+
if !specIsSame {
95+
generation := updated.GetGeneration()
96+
generation++
97+
updated.SetGeneration(generation)
98+
}
99+
}
100+
92101
if err := resource.UpdateObject(ctx, id, updated); err != nil {
93102
return err
94103
}

mockkubeapiserver/storage/memorystorage/memorystorage.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ func (s *MemoryStorage) AddObject(obj *unstructured.Unstructured) error {
125125
return fmt.Errorf("object group/version/kind %v not known", gvk)
126126
}
127127

128+
if resource.SetsGeneration() {
129+
obj.SetGeneration(1)
130+
}
131+
128132
return resource.CreateObject(ctx, id, obj)
129133
}
130134

mockkubeapiserver/storage/memorystorage/resourceinfo.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,19 @@ func (r *memoryResourceInfo) ListGVK() schema.GroupVersionKind {
3333
func (r *memoryResourceInfo) ParseableType() *typed.ParseableType {
3434
return r.parseableType
3535
}
36+
37+
func (r *memoryResourceInfo) SetsGeneration() bool {
38+
// Not all resources support metadata.generation; it looks like only those with status do (?)
39+
// For now, exclude some well-known types that do not set metadata.generation.
40+
switch r.gvk.GroupKind() {
41+
case schema.GroupKind{Group: "", Kind: "ConfigMap"}:
42+
return false
43+
case schema.GroupKind{Group: "", Kind: "Secret"}:
44+
return false
45+
case schema.GroupKind{Group: "", Kind: "Namespace"}:
46+
return false
47+
48+
default:
49+
return true
50+
}
51+
}

mockkubeapiserver/storage/resourceinfo.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ type ResourceInfo interface {
2222
ListGVK() schema.GroupVersionKind
2323
ParseableType() *typed.ParseableType
2424

25+
// SetsGeneration is true if we should automatically set metadata.generation for this resource kind.
26+
SetsGeneration() bool
27+
2528
GetObject(ctx context.Context, id types.NamespacedName) (*unstructured.Unstructured, bool, error)
2629

2730
ListObjects(ctx context.Context, filter ListFilter) (*unstructured.UnstructuredList, error)

pkg/test/testreconciler/simpletest/testdata/reconcile/direct/create/expected-http.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ Accept: application/json, */*
1616

1717
200 OK
1818
Cache-Control: no-cache, private
19-
Content-Length: 364
19+
Content-Length: 379
2020
Content-Type: application/json
2121
Date: (removed)
2222

23-
{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}
23+
{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}
2424

2525
---
2626

@@ -219,16 +219,16 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
219219
Accept: application/json, */*
220220
Content-Type: application/json
221221

222-
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}
222+
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","generation":1,"creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}
223223

224224

225225
200 OK
226226
Cache-Control: no-cache, private
227-
Content-Length: 276
227+
Content-Length: 291
228228
Content-Type: application/json
229229
Date: (removed)
230230

231-
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}
231+
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}
232232

233233
---
234234

@@ -301,13 +301,13 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
301301
Accept: application/json, */*
302302
Content-Type: application/json
303303

304-
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"5","creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}
304+
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"5","generation":1,"creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}
305305

306306

307307
200 OK
308308
Cache-Control: no-cache, private
309-
Content-Length: 276
309+
Content-Length: 291
310310
Content-Type: application/json
311311
Date: (removed)
312312

313-
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}
313+
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}

pkg/test/testreconciler/simpletest/testdata/reconcile/ssa/create/expected-http.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ Accept: application/json, */*
1616

1717
200 OK
1818
Cache-Control: no-cache, private
19-
Content-Length: 364
19+
Content-Length: 379
2020
Content-Type: application/json
2121
Date: (removed)
2222

23-
{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}
23+
{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}
2424

2525
---
2626

@@ -118,16 +118,16 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
118118
Accept: application/json, */*
119119
Content-Type: application/json
120120

121-
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"}},"spec":{"channel":"stable"},"status":{"healthy":false}}
121+
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","generation":1,"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"}},"spec":{"channel":"stable"},"status":{"healthy":false}}
122122

123123

124124
200 OK
125125
Cache-Control: no-cache, private
126-
Content-Length: 561
126+
Content-Length: 576
127127
Content-Type: application/json
128128
Date: (removed)
129129

130-
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":false}}
130+
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":false}}
131131

132132
---
133133

@@ -193,15 +193,15 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
193193
Accept: application/json, */*
194194
Content-Type: application/json
195195

196-
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}
196+
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}
197197

198198
200 OK
199199
Cache-Control: no-cache, private
200-
Content-Length: 730
200+
Content-Length: 745
201201
Content-Type: application/json
202202
Date: (removed)
203203

204-
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"6","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}
204+
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"6","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}
205205

206206
---
207207

0 commit comments

Comments
 (0)