Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web socket support. #19

Merged
merged 1 commit into from Jun 17, 2017
Merged

Web socket support. #19

merged 1 commit into from Jun 17, 2017

Conversation

brendandburns
Copy link
Contributor

@brendandburns brendandburns commented May 16, 2017

Ready for review

Fixes #18

Depends on #17

@brendandburns
Copy link
Contributor Author

@mbohlool this is ready for review.

@brendandburns
Copy link
Contributor Author

Friendly friday evening ping on this one (feel free to wait until next week to review :)

@brendandburns
Copy link
Contributor Author

@mbohlool friendly ping on this one.

Thanks!

Copy link
Contributor

@lwander lwander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - maybe drop a link to https://tools.ietf.org/html/rfc6455, it was helpful for reviewing this code.

@@ -0,0 +1,107 @@
package io.kubernetes.client.util;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No license header?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please add license header to all files. we need a check for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@@ -0,0 +1,107 @@
package io.kubernetes.client.util;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please add license header to all files. we need a check for that.

import java.util.ArrayList;
import java.util.HashMap;

import okio.Buffer;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import should be in second group I guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved.

/**
* A simple interface for a listener on a web socket
*/
public interface SocketListener {
Copy link
Contributor

@mbohlool mbohlool Jun 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a wrapper on top of this interface that understands kubernetes streams from different channels (stdout, stderr). It can be done in another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*/
public static void stream(String path, String method, ApiClient client, SocketListener listener) throws ApiException, IOException {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("X-Stream-Protocol-Version", "v4.channel.k8s.io,v3.channel.k8s.io,v2.channel.k8s.io,channel.k8s.io");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract constants please. Also are these protocols the only protocol k8s supports? if there is a documentation somewhere in k8s repo, a link would be nice. Ideally these should be extensions in OpenAPI spec and should be populated from there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, ideally these would be in the OpenAPI spec but I couldn't find them. They're constants in the code as far as I can tell, e.g.

https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiserver/pkg/util/wsstream/conn.go#L48

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally lean toward extracting constant as much as possible but this is not a deal breaker for me. If you prefer to keep them this way, I can live with it :)

public static void stream(String path, String method, ApiClient client, SocketListener listener) throws ApiException, IOException {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("X-Stream-Protocol-Version", "v4.channel.k8s.io,v3.channel.k8s.io,v2.channel.k8s.io,channel.k8s.io");
headers.put("Connection", "Upgrade");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it is cleaner to have all string literals as constant? If you agree, we can make it an style guide. Of course there could be exceptions (that should be well defined).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For one-off things like this where values aren't often repeated, I don't really see the value, personally. I don't feel super strongly, but I don't personally find it to be useful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but done.

listener.close();
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New line at the end of the file. I think this one should be an style guide too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

* limitations under the License.
*/
// This has been cloned from the okhttp-ws package so that I could remove
// the requirement that websockets use the "GET" method
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between exec/attach get vs post? If post works, I prefer not to clone this file. Otherwise is there a way to push a feature upstream in okhttp-ws and support post when that is merged?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually GET is a requirement. I suggest we remove this file and only support GET. from rfc6455:

The method of the request MUST be GET, and the HTTP version MUST
be at least 1.1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

POST is defined in the API swagger/openapi specificaction.

https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json

Does that mean that we should edit the swagger first?

Copy link
Contributor

@mbohlool mbohlool Jun 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should fix that too but we should not wait for that. I will investigate it (to see why it gets into the spec and if we actually support POST) but I don't think there is anything we can do with POST that we can't do with GET. Websocket reuse the connection and ignores http method, thus I think we should not support POST in java client (or any other client). We can always add POST back if we see any usecase for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have validated that both GET and POST work.

(fwiw) the kubectl client uses POST:

https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/exec.go#L312

So I don't think we can remove POST support (unless we also update kubectl)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, and I think remember why it is this way... I think the theory is that exec/attach have the possibility to modify the state in the container, thus POST feels more right than GET since GET is supposed to be idempotent.

<java.version>1.7</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
</project>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line at the end of the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@mbohlool
Copy link
Contributor

mbohlool commented Jun 14, 2017

Sorry for the delay. I am attending a conference and have limited time. Done one round of review.

@brendandburns
Copy link
Contributor Author

Comments addressed, please take another look.

Thanks!
--brendan

@mbohlool
Copy link
Contributor

mbohlool commented Jun 16, 2017

I still have concern about websocket with POST. If the reason is kubectl is doing it and if we conclude that it is wrong, do you think we should repeat the mistake?
I think it is wrong on two level, interface and implementation (and rfc as the bonus :) ).

Interface:
We use websocket connections to connect to pods or watch objects. None of them is changing the actual object (connecting to a pod can change things inside it, but the kubernetes object pod/container, the one we store in etcd, would not change by that). The interface should not be watch_get_pod_... or connect_post_pod_exec... or something like that. interface should be watch_pod..., or connect_pod_exec..., etc. The http verb doesn't mean anything to be in the interface at all.

Implementation:
Even if we disagree on interface point, the implementation still doesn't care about verb. We can keep whatever interface we desire and the implementation can still be only GET. It makes no practical difference to start connection with POST or GET because websocket is not bond to http verb rules and reuses the connection. My point is even if we have post_websocket and get_websocket interfaces (for any reason), we can still implement both of them with standard websocket library that usesGET and it will make no practical difference to clone part of library and support POST.

rfc
While we can diverse from rfc if we see good reason, I don't see one here.

What do you think?

@brendandburns
Copy link
Contributor Author

brendandburns commented Jun 16, 2017 via email

@mbohlool
Copy link
Contributor

mbohlool commented Jun 16, 2017

lgtm. can you squash commits before I merge? Thanks.

@mbohlool mbohlool mentioned this pull request Jun 16, 2017
@brendandburns
Copy link
Contributor Author

Squashed and ready for merge.

Thanks!

@mbohlool mbohlool merged commit 2d418a8 into kubernetes-client:master Jun 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants