ManageIQ / kubeclient

A Ruby client for Kubernetes REST API
MIT License
419 stars 167 forks source link

HTTP requests to arbitrary path #389

Open cben opened 5 years ago

cben commented 5 years ago

STATUS: exists on master, undocumented

A few use cases have come up over time for making arbitrary HTTP requests to the server, that probably don't justify builtin methods in kubeclient. Generally, users wish the library covered 100% of their needs, but it's not always reasonable to inflate API surface (especially for k8s derivative-specific stuff like openshift), nor to force users to wait until their use case is added to the library.

Use cases

Non-goals, until proven otherwise

Shouldn't expose underlying client

I think adding a generic "custom request to this path" is a good escape hatch, IFF we can cover it with a small API.

Technically, you can already do arbitrary requests via kclient.create_rest_client(path).get.body but that's deliberately undocumented, we'd like to switch away from RestClient (#237, more pressing as RestClient is presently unmaintained). Even if we switch, by same logic, kubeclient shouldn't tie its API to specific client.

UPDATE: I've changed my opinion since; after master moved to RestClient -> Faraday, we decided that Faraday actually provides reasonably abstracted API how to make http requests, and it's better to use an "aspiring standard one" than invent our own.

Proposed minimal viable API

kclient.http_get(path, as: :ros)

Performs GET request.
path is relative to api server "root" (cf. #318), not this Client's apis/group/version.
Does kubeclient-typical error handling and parsing (use as: :raw to get unparsed string).

cben commented 5 years ago

Naming is hard

Shouldn't call it .get because that'd collide with the #332 family of .get, .create etc.

My next idea was .get_path but should also avoid any name starting with .get_... to avoid confusion with .get_pod etc.

=> Provisionally calling it .http_get but open to better ideas...

cben commented 4 years ago

428 has a use case for requesting same discovery info kubeclient does, which would be a wasteful request. And generally, many use cases here like /version are safe to cache if user makes the call several time. But some like /healthz must not be cached.

Extended proposal (not atomic, just the first is already valuable):

Could/should .http_get automagically honor response HTTP headers? I think explicit intent is better here. Much kubeclient usage involves calls like .get_pods with the expectation you're getting fresh info so let's stick to that?

pedro-stanaka commented 3 years ago

@cben did you make any progress here? I want to use the client to consume https://github.com/kubernetes-sigs/metrics-server/ but the api lives in /apis/metrics.k8s.io/v1beta1 therefore I would need this.

How exactly can I help here? I would be happy to get my hands dirty if you give me some insight on what design you were thinking of following.

cben commented 3 years ago

Yes we did! Since #466 on master branch Client objects now have .faraday_client method you can use for arbitrary requests. It's not documented yet, and not in any release yet :-( Gonna be in 5.0 release, which I'm afraid will take some more time (#435).

But /apis/metrics.k8s.io/v1beta1 sounds like a regular k8s API group. You shouldn't need this "escape hatch" for regular resources, just a Client object configured for this group. Try this:

client = Kubeclient::Client.new('http://SERVER:6443/apis/metrics.k8s.io', 'v1beta1')
pedro-stanaka commented 3 years ago

This worked flawlessly. Thanks a bunch. I am using master with ruby 3.