Support Watch
mbohlool opened this issue · 13 comments
Watch is a non-standard method that swagger-codegen does not support and we need to add support for it like other clients (e.g. python here)
I have the bones of a working watch client here https://github.com/wayofthepie/kubernetes-watch/blob/master/src/Kubernetes/WatchClient.hs. I was going to create it directly within this repo, but it currently relies on the streaming-bytestring library and I can't see a way of adding non-generated dependencies to the cabal file.
What were your thoughts on a watch client, is it preferable to have it contained within this repo? Or as a separate package? I will be updating the watch client library above soon anyway, adding some docs and putting it to use.
you can exclude the cabal file from generation and edit it. It is reasonable to manually edit dependency list as we did the same in other clients. The watch is better to be in this repo for now and when we get to a stable repo, it should be moved to a -base repo.
Yeah this can be closed.
/close
@guoshimin: You can't close an active issue/PR unless you authored it or you are a collaborator.
In response to this:
/close
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.
Guess somebody else will have to close this then.
/close
@guoshimin: Closing this issue.
In response to this:
/close
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.
Is there a way to do watch in a type-safe way? such that the response isn't just a Stream of bytestrings?
There definitely is a way to make response not just be a stream of bytestrings. I wrote this program to demonstrate: https://gist.github.com/akshaymankar/8294788b6d9a9dd01a59573147f9afa1
However, there is a type which the dispatchTypedWatch
function cannot type-check as of now. If you look at the signature, it expects a consumer function of type (Stream (Of (Either String (WatchEvent a))) IO () -> IO ())
where a
is constrained as instance of FromJSON
. Ideally the KubernetesRequest
object should've been able to communicate the type which the watch should return, but it doesn't. This is either a limitation of the OpenAPI spec or the one generated by K/K. This is also a reason that (Stream (Of (Either String (WatchEvent a))) IO () -> IO ())
has Either String
and doesn't look like (Stream (Of (WatchEvent a)) IO () -> IO ())
.
But all is not lost, there is a (slightly twisted) way we could identify this, the openapi schema has x-kubernetes-group-version-kind
field which specifies the type of object a given API deals with. The openapi-generator could parse it and add some information to the KubernetesRequest
object. The generator as of now is very generic, there are a few benefits of making it specific for this project, but it sounds like a lot of work.
Also, until we can get to fix the openapi-generator, maybe we can add the dispatchTypedWatch
function to the client. Maybe with a better name as it is not as typed as one would hope.
I was wondering if we could make some of the types in the generator polymorphic to facilitate this
So have data EndpointsList f = EndpointList (f Endpoints))
Now we can do:
EndpointsList (Compose Stream (Compose Of WatchEvent))
for streaming requests
And EndpointsList []
for normal requests
If we write a custom generator, we can. But in plain openapi-spec, there is no indication about the return type of watch.
Consider spec for listing namespaced pods:
get:
description: list or watch objects of kind Pod
operationId: listNamespacedPod
parameters:
- description: object name and auth scope, such as for teams and projects
in: path
name: namespace
required: true
schema:
type: string
- description: If 'true', then the output is pretty printed.
in: query
name: pretty
schema:
type: string
- description: ".."
in: query
name: continue
schema:
type: string
- description: A selector to restrict the list of returned objects by their
fields. Defaults to everything.
in: query
name: fieldSelector
schema:
type: string
- description: A selector to restrict the list of returned objects by their
labels. Defaults to everything.
in: query
name: labelSelector
schema:
type: string
- description: ".."
in: query
name: limit
schema:
type: integer
- description: ".."
in: query
name: resourceVersion
schema:
type: string
- description: Timeout for the list/watch call. This limits the duration of
the call, regardless of any activity or inactivity.
in: query
name: timeoutSeconds
schema:
type: integer
- description: Watch for changes to the described resources and return them
as a stream of add, update, and remove notifications. Specify resourceVersion.
in: query
name: watch
schema:
type: boolean
responses:
200:
content:
application/json:
schema:
$ref: '#/components/schemas/v1.PodList'
application/yaml:
schema:
$ref: '#/components/schemas/v1.PodList'
application/vnd.kubernetes.protobuf:
schema:
$ref: '#/components/schemas/v1.PodList'
application/json;stream=watch:
schema:
$ref: '#/components/schemas/v1.PodList'
application/vnd.kubernetes.protobuf;stream=watch:
schema:
$ref: '#/components/schemas/v1.PodList'
description: OK
401:
content: {}
description: Unauthorized
tags:
- core_v1
x-kubernetes-action: list
x-kubernetes-group-version-kind:
group: ""
kind: Pod
version: v1
In case of 200, content can be one of these:
content:
application/json:
schema:
$ref: '#/components/schemas/v1.PodList'
application/yaml:
schema:
$ref: '#/components/schemas/v1.PodList'
application/vnd.kubernetes.protobuf:
schema:
$ref: '#/components/schemas/v1.PodList'
application/json;stream=watch:
schema:
$ref: '#/components/schemas/v1.PodList'
application/vnd.kubernetes.protobuf;stream=watch:
schema:
$ref: '#/components/schemas/v1.PodList'
Even when the content-type is application/json;stream=watch
, it says the schema has to be #/components/schemas/v1.PodList
, which looks wrong to me. I am not sure how the generator would deal with it if there were different $ref
s in the spec. Maybe then we could have it properly type checked.
I couldn't find any issues about this in K/K, it might be worth creating an issue there. But I am not very confident about my analysis.
Also, maybe it is worth creating a new issue for this in this repository.