Skip to content
This repository was archived by the owner on Mar 13, 2022. It is now read-only.

Add Websocket streaming support to base #33

Merged
merged 1 commit into from
Sep 22, 2017

Conversation

mbohlool
Copy link
Contributor

@mbohlool mbohlool commented Sep 19, 2017

as part of kubernetes-client/python#341 I moved the websocket support in the base here as well as adding a stream package to support websocket calls instead of hacking api_client.py. User facing change would be instead of calling api directly like this:

resp = api.connect_get_namespaced_pod_exec( name, 'default',
              command=exec_command,
              stderr=True, stdin=False,
              stdout=True, tty=False)

user need to add a stream before it (and import it of course):

resp = stream(api.connect_get_namespaced_pod_exec, name, 'default',
              command=exec_command,
              stderr=True, stdin=False,
              stdout=True, tty=False)

The actual change that make this happen will be send to the main repo but we need this here first.

Note to reviewers: stream/ws_client.py and stream/ws_client_test.py are just copied from main repo and do not need reviewing.

@codecov-io
Copy link

codecov-io commented Sep 19, 2017

Codecov Report

Merging #33 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master      #33   +/-   ##
=======================================
  Coverage   93.93%   93.93%           
=======================================
  Files          11       11           
  Lines         824      824           
=======================================
  Hits          774      774           
  Misses         50       50

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 84d1284...86361f0. Read the comment docs.

stream/stream.py Outdated
def _request(self, _, url, query_params=None, headers=None,
post_params=None, body=None, _preload_content=True,
_request_timeout=None):
#pylint: disable=unused-argument
Copy link

Choose a reason for hiding this comment

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

Maybe it's worth a comment about the second argument and why it's unused.

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.

stream/stream.py Outdated
def __init__(self):
self._config = None

def _request(self, _, url, query_params=None, headers=None,
Copy link

Choose a reason for hiding this comment

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

Is really required to make a class method? I'm wondering if it's possible to use an anonymous function inside the intercept_request_call

This will have the benefit that we don't need to store the config object as class property but can be referenced as variable directly. Something like:

def intercept_request_call(...):
    config = ...
    def request(...):
           ws_client.websocket_call(config, url, ...)

Indeed, if we follow this pattern the _streamer class can be also removed.

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 Author

@pokoli comments addressed. PTAL.

# See the License for the specific language governing permissions and
# limitations under the License.

from stream import stream
Copy link

Choose a reason for hiding this comment

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

I will prefer to use a relative import here to indicate that stream is from current pacakg (like we do for ws_client)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Make sense. Done.

stream/stream.py Outdated
post_params=None, body=None, _preload_content=True,
_request_timeout=None):
#pylint: disable=unused-argument
# Not all of the arguments in request call is necessary for
Copy link

Choose a reason for hiding this comment

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

After reading this comment I'm wondering if it won't be better to use **kwargs for the optional arguments and pass them directly to websocket_call

Of course the websocket_call must be adapted to define the default values for this parameters (so they are not required).

I think this will easy the maintenance of new parameters in websocket_call as it won't be required to be added here which is now.

Copy link
Contributor Author

@mbohlool mbohlool Sep 19, 2017

Choose a reason for hiding this comment

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

Websocket call is not using all request arguments. The list need to be mutated to remove undefined variables or call to websocket_call will fail or they need to be added to websocket_call that will be unused 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.

more context: this code is basically try to remove this manual change from api_client.py:

return ws_client.websocket_call(self.config,

Copy link

Choose a reason for hiding this comment

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

On python there is not problem to pass extra args or kwargs as far as the function accepts args or kwargs: See

def function(a=1, *args, **kwargs):
... print a
...
function(b=12)
1

So what I propose is not to pass all the parameters, but manage only args and kwargs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes but I wasn't sure I need to change websocket parameters. But I did it because I have no strong opinion either way. The code is certainly simpler now. Please take another look.

stream/stream.py Outdated
method, url, query_params=None, headers=None,
post_params=None, body=None, _preload_content=True,
_request_timeout=None):
#pylint: disable=unused-argument
Copy link

Choose a reason for hiding this comment

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

Il will prefer to remove this pylint line. If method and url are required arguments it can be done using args.

def _intercept_request_call(*args, **kwargs):
   _, url = args[:2]
   ....

Note that the slicing is required in case additional arguments are passed.

Copy link
Contributor Author

@mbohlool mbohlool Sep 19, 2017

Choose a reason for hiding this comment

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

Unused argument is not only method but other named arguments. I can use _ for method in the argument itself but other named argument (that I cannot remove or convert to kwarg as I explained in the next comment) will be unused.

@mbohlool
Copy link
Contributor Author

@pokoli PTAL

headers = kwargs.get("headers")

# Extract the command from the list of tuples
commands = None
Copy link

Choose a reason for hiding this comment

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

can be written as comands = query_params.pop('command', None)

Copy link
Contributor Author

@mbohlool mbohlool Sep 21, 2017

Choose a reason for hiding this comment

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

This is an already reviewed code. I will fix it anyway :) I am blocked on this. so I will create a new PR for improvements on ws_client.py and merge this one. I assume you are done with the other files?

Copy link
Contributor Author

@mbohlool mbohlool Sep 21, 2017

Choose a reason for hiding this comment

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

query_params is a list of tuples. pop does not work the way you expected it to work. It is possible to probably make it work, but I would like to ask you to ignore ws_client* files as they are copied from main repo. If we need to improve them, we need to create a separate PR/issue for it.

Copy link

Choose a reason for hiding this comment

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

@mbohlool yes done with other files. Sorry for the mess.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No mess. My main repo PR was blocked on this. I will send it your (and @dims) way.

break

# drop command from query_params as we will be processing it separately
query_params = [(key, value) for key, value in query_params if
Copy link

Choose a reason for hiding this comment

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

Not required if using pop

@dims
Copy link

dims commented Sep 21, 2017

LGTM, we could add a test for the new proposed api soon-ish

@pokoli
Copy link

pokoli commented Sep 22, 2017

LGTM

I don't think it's worth to add a test for the new API as it's simply a wrapper.

@mbohlool mbohlool merged commit 31e13b1 into kubernetes-client:master Sep 22, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants