Skip to content

Commit a362a02

Browse files
authored
Merge pull request #8898 from killianmuldoon/pr-improve-in-memory-watch
🌱 Fixups for watch in in-memory apiServer
2 parents 03830a5 + acb27de commit a362a02

File tree

3 files changed

+42
-28
lines changed

3 files changed

+42
-28
lines changed

test/infrastructure/inmemory/internal/cloud/runtime/cache/client.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -422,11 +422,6 @@ func (c *cache) doTryDeleteLocked(resourceGroup string, tracker *resourceGroupTr
422422
return false, apierrors.NewBadRequest(err.Error())
423423
}
424424

425-
// TODO: (killianmuldoon) Understand if setting this twice is necessary.
426-
// Required to override default beforeUpdate behaviour
427-
// that prevent changes to automatically managed fields.
428-
obj.SetDeletionTimestamp(&now)
429-
430425
objects[objKey] = obj
431426
c.afterUpdate(resourceGroup, oldObj, obj)
432427
}

test/infrastructure/inmemory/internal/server/api/handler.go

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,29 +73,33 @@ func NewAPIServerHandler(manager cmanager.Manager, log logr.Logger, resolver Res
7373

7474
// CRUD endpoints (global objects)
7575
ws.Route(ws.POST("/api/v1/{resource}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Create))
76-
ws.Route(ws.GET("/api/v1/{resource}").To(apiServer.apiV1List))
76+
ws.Route(ws.GET("/api/v1/{resource}").If(isList).To(apiServer.apiV1List))
77+
ws.Route(ws.GET("/api/v1/{resource}").If(isWatch).To(apiServer.apiV1Watch))
7778
ws.Route(ws.GET("/api/v1/{resource}/{name}").To(apiServer.apiV1Get))
7879
ws.Route(ws.PUT("/api/v1/{resource}/{name}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Update))
7980
ws.Route(ws.PATCH("/api/v1/{resource}/{name}").Consumes(string(types.MergePatchType), string(types.StrategicMergePatchType)).To(apiServer.apiV1Patch))
8081
ws.Route(ws.DELETE("/api/v1/{resource}/{name}").Consumes(runtime.ContentTypeProtobuf, runtime.ContentTypeJSON).To(apiServer.apiV1Delete))
8182

8283
ws.Route(ws.POST("/apis/{group}/{version}/{resource}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Create))
83-
ws.Route(ws.GET("/apis/{group}/{version}/{resource}").To(apiServer.apiV1List))
84+
ws.Route(ws.GET("/apis/{group}/{version}/{resource}").If(isList).To(apiServer.apiV1List))
85+
ws.Route(ws.GET("/apis/{group}/{version}/{resource}").If(isWatch).To(apiServer.apiV1Watch))
8486
ws.Route(ws.GET("/apis/{group}/{version}/{resource}/{name}").To(apiServer.apiV1Get))
8587
ws.Route(ws.PUT("/apis/{group}/{version}/{resource}/{name}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Update))
8688
ws.Route(ws.PATCH("/apis/{group}/{version}/{resource}/{name}").Consumes(string(types.MergePatchType), string(types.StrategicMergePatchType)).To(apiServer.apiV1Patch))
8789
ws.Route(ws.DELETE("/apis/{group}/{version}/{resource}/{name}").Consumes(runtime.ContentTypeProtobuf, runtime.ContentTypeJSON).To(apiServer.apiV1Delete))
8890

8991
// CRUD endpoints (namespaced objects)
9092
ws.Route(ws.POST("/api/v1/namespaces/{namespace}/{resource}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Create))
91-
ws.Route(ws.GET("/api/v1/namespaces/{namespace}/{resource}").To(apiServer.apiV1List))
93+
ws.Route(ws.GET("/api/v1/namespaces/{namespace}/{resource}").If(isList).To(apiServer.apiV1List))
94+
ws.Route(ws.GET("/api/v1/namespaces/{namespace}/{resource}").If(isWatch).To(apiServer.apiV1Watch))
9295
ws.Route(ws.GET("/api/v1/namespaces/{namespace}/{resource}/{name}").To(apiServer.apiV1Get))
9396
ws.Route(ws.PUT("/api/v1/namespaces/{namespace}/{resource}/{name}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Update))
9497
ws.Route(ws.PATCH("/api/v1/namespaces/{namespace}/{resource}/{name}").Consumes(string(types.MergePatchType), string(types.StrategicMergePatchType)).To(apiServer.apiV1Patch))
9598
ws.Route(ws.DELETE("/api/v1/namespaces/{namespace}/{resource}/{name}").Consumes(runtime.ContentTypeProtobuf, runtime.ContentTypeJSON).To(apiServer.apiV1Delete))
9699

97100
ws.Route(ws.POST("/apis/{group}/{version}/namespaces/{namespace}/{resource}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Create))
98-
ws.Route(ws.GET("/apis/{group}/{version}/namespaces/{namespace}/{resource}").To(apiServer.apiV1List))
101+
ws.Route(ws.GET("/apis/{group}/{version}/namespaces/{namespace}/{resource}").If(isList).To(apiServer.apiV1List))
102+
ws.Route(ws.GET("/apis/{group}/{version}/namespaces/{namespace}/{resource}").If(isWatch).To(apiServer.apiV1Watch))
99103
ws.Route(ws.GET("/apis/{group}/{version}/namespaces/{namespace}/{resource}/{name}").To(apiServer.apiV1Get))
100104
ws.Route(ws.PUT("/apis/{group}/{version}/namespaces/{namespace}/{resource}/{name}").Consumes(runtime.ContentTypeProtobuf).To(apiServer.apiV1Update))
101105
ws.Route(ws.PATCH("/apis/{group}/{version}/namespaces/{namespace}/{resource}/{name}").Consumes(string(types.MergePatchType), string(types.StrategicMergePatchType)).To(apiServer.apiV1Patch))
@@ -230,16 +234,6 @@ func (h *apiServerHandler) apiV1List(req *restful.Request, resp *restful.Respons
230234
return
231235
}
232236

233-
// If the request is a Watch handle it using watchForResource.
234-
if isWatch(req) {
235-
err = h.watchForResource(req, resp, resourceGroup, *gvk)
236-
if err != nil {
237-
_ = resp.WriteErrorString(http.StatusInternalServerError, err.Error())
238-
return
239-
}
240-
return
241-
}
242-
243237
// Reads and returns the requested data.
244238
list := &unstructured.UnstructuredList{}
245239
list.SetAPIVersion(gvk.GroupVersion().String())
@@ -260,6 +254,29 @@ func (h *apiServerHandler) apiV1List(req *restful.Request, resp *restful.Respons
260254
}
261255
}
262256

257+
func (h *apiServerHandler) apiV1Watch(req *restful.Request, resp *restful.Response) {
258+
// Gets the resource group the request targets (the resolver is aware of the mapping host<->resourceGroup)
259+
resourceGroup, err := h.resourceGroupResolver(req.Request.Host)
260+
if err != nil {
261+
_ = resp.WriteErrorString(http.StatusInternalServerError, err.Error())
262+
return
263+
}
264+
265+
// Maps the requested resource to a gvk.
266+
gvk, err := requestToGVK(req)
267+
if err != nil {
268+
_ = resp.WriteErrorString(http.StatusInternalServerError, err.Error())
269+
return
270+
}
271+
272+
// If the request is a Watch handle it using watchForResource.
273+
err = h.watchForResource(req, resp, resourceGroup, *gvk)
274+
if err != nil {
275+
_ = resp.WriteErrorString(http.StatusInternalServerError, err.Error())
276+
return
277+
}
278+
}
279+
263280
func (h *apiServerHandler) apiV1Get(req *restful.Request, resp *restful.Response) {
264281
ctx := req.Request.Context()
265282

@@ -539,3 +556,13 @@ func getAPIResourceList(req *restful.Request) *metav1.APIResourceList {
539556
}
540557
return corev1APIResourceList
541558
}
559+
560+
// isWatch is true if the request contains `watch="true"` as a query parameter.
561+
func isWatch(req *http.Request) bool {
562+
return req.URL.Query().Get("watch") == "true"
563+
}
564+
565+
// isList is true if the request does not have `watch="true` as a query parameter.
566+
func isList(req *http.Request) bool {
567+
return !isWatch(req)
568+
}

test/infrastructure/inmemory/internal/server/api/watch.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ func (m *WatchEventDispatcher) OnGeneric(resourceGroup string, o client.Object)
8686
}
8787
}
8888

89-
// isWatch is true if the request contains `watch="true"` as a query parameter.
90-
func isWatch(req *restful.Request) bool {
91-
return req.QueryParameter("watch") == "true"
92-
}
93-
9489
func (h *apiServerHandler) watchForResource(req *restful.Request, resp *restful.Response, resourceGroup string, gvk schema.GroupVersionKind) (reterr error) {
9590
ctx := req.Request.Context()
9691
queryTimeout := req.QueryParameter("timeoutSeconds")
@@ -126,10 +121,7 @@ func (h *apiServerHandler) watchForResource(req *restful.Request, resp *restful.
126121
}
127122
}()
128123

129-
if err = watcher.Run(ctx, queryTimeout, resp); err != nil {
130-
return err
131-
}
132-
return reterr
124+
return watcher.Run(ctx, queryTimeout, resp)
133125
}
134126

135127
// Run serves a series of encoded events via HTTP with Transfer-Encoding: chunked.

0 commit comments

Comments
 (0)