Description:
Updated quickstart dependencies for utopic.
Quickstart now uses the dependency versions we
expect to be available in utopic.
Update the code parts in which quickstart interacts
with the juju client and the websocket Python
libraries: ensure we only log the textual WebSocket
messages we are interested in.
Also remove the deprecated --use-mirrors pip option.
Tests: `make check`
QA:
Use quickstart as usual to bootstrap local, ec2 and HP
environments: `.venv/bin/python juju-quickstart -e ...`
Affected files (+58, -30 lines):
M Makefile
A [revision details]
M quickstart/juju.py
M quickstart/tests/helpers.py
M quickstart/tests/test_juju.py
M requirements.pip
M test-requirements.pip
Index: requirements.pip
=== modified file 'requirements.pip'
--- requirements.pip 2014-06-09 20:31:01 +0000
+++ requirements.pip 2014-09-05 14:54:31 +0000
@@ -25,7 +25,7 @@
# version of websocket-client to use. Remove websocket-client as a
dependency
# here when moving to a newer jujuclient that correctly specifies the
# version.
-websocket-client==0.12.0
-jujuclient==0.17.5
-PyYAML==3.10
-urwid==1.1.1
+websocket-client==0.18.0
+jujuclient==0.18.4
+PyYAML==3.11
+urwid==1.2.1
Index: test-requirements.pip
=== modified file 'test-requirements.pip'
--- test-requirements.pip 2014-06-09 20:31:01 +0000
+++ test-requirements.pip 2014-09-05 14:54:31 +0000
@@ -17,7 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+OPCODE_TEXT = websocket.ABNF.OPCODE_TEXT
+# Define the options used to initiate the secure WebSocket connection.
+SSLOPT = {
+ 'cert_reqs': ssl.CERT_NONE,
+ 'ssl_version': ssl.PROTOCOL_TLSv1,
+}
+
+
def connect(api_url):
"""Return an Environment instance connected to the given API URL."""
- connection = WebSocketConnection(
- sslopt={'ssl_version': ssl.PROTOCOL_TLSv1})
+ connection = WebSocketConnection(sslopt=SSLOPT)
# See the websocket.create_connection function.
connection.settimeout(websocket.default_timeout)
connection.connect(api_url, origin=api_url)
@@ -124,19 +131,23 @@
class WebSocketConnection(websocket.WebSocket):
"""A WebSocket client connection."""
- def send(self, message):
+ def send(self, payload, opcode=OPCODE_TEXT):
"""Send the given WebSocket message.
- Overridden to add logging.
+ Overridden to add logging in the case the payload is text.
"""
- logging.debug('API message: -->
{}'.format(message.decode('utf-8')))
- return super(WebSocketConnection, self).send(message)
+ if opcode == OPCODE_TEXT:
+ message = payload.decode('utf-8')
+ logging.debug('API message: --> {}'.format(message))
+ return super(WebSocketConnection, self).send(payload,
opcode=opcode)
def recv(self): """Receive a message from the WebSocket server.
- Overridden to add logging.
+ Overridden to add logging in the case the received data is text.
"""
- message = super(WebSocketConnection, self).recv()
- logging.debug('API message: <--
{}'.format(message.decode('utf-8')))
- return message
+ data = super(WebSocketConnection, self).recv()
+ if isinstance(data, bytes):
+ message = data.decode('utf-8')
+ logging.debug('API message: <-- {}'.format(message))
+ return data
Index: quickstart/tests/helpers.py
=== modified file 'quickstart/tests/helpers.py'
--- quickstart/tests/helpers.py 2014-04-23 13:08:12 +0000
+++ quickstart/tests/helpers.py 2014-09-08 17:49:51 +0000
@@ -36,8 +36,11 @@
"""
with mock.patch('logging.{}'.format(level.lower())) as mock_log:
yield
- expected_calls = [mock.call(message) for message in messages]
- mock_log.assert_has_calls(expected_calls)
+ if messages:
+ expected_calls = [mock.call(message) for message in messages]
+ mock_log.assert_has_calls(expected_calls)
+ else:
+ assert not mock_log.called, 'logging unexpectedly called'
Reviewers: mp+233770_ code.launchpad. net,
Message:
Please take a look.
Description:
Updated quickstart dependencies for utopic.
Quickstart now uses the dependency versions we
expect to be available in utopic.
Update the code parts in which quickstart interacts
with the juju client and the websocket Python
libraries: ensure we only log the textual WebSocket
messages we are interested in.
Also remove the deprecated --use-mirrors pip option.
Tests: `make check`
QA:
Use quickstart as usual to bootstrap local, ec2 and HP
environments: `.venv/bin/python juju-quickstart -e ...`
https:/ /code.launchpad .net/~frankban/ juju-quickstart /utopic- update- dependencies/ +merge/ 233770
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/139350043/
Affected files (+58, -30 lines): tests/helpers. py tests/test_ juju.py ts.pip
M Makefile
A [revision details]
M quickstart/juju.py
M quickstart/
M quickstart/
M requirements.pip
M test-requiremen
Index: Makefile
=== modified file 'Makefile'
--- Makefile 2014-04-07 09:03:11 +0000
+++ Makefile 2014-09-05 14:54:31 +0000
@@ -23,7 +23,7 @@
$(VENV_ACTIVATE): test-requiremen ts.pip requirements.pip ts.pip || \ ts.pip || \ ts.pip; exit 1)
virtualenv --distribute -p $(PYTHON) $(VENV)
- $(VENV)/bin/pip install --use-mirrors -r test-requiremen
+ $(VENV)/bin/pip install -r test-requiremen
(touch test-requiremen
@touch $(VENV_ACTIVATE)
Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision:
<email address hidden>
+New revision:
<email address hidden>
Index: requirements.pip client= =0.12.0 client= =0.18.0
=== modified file 'requirements.pip'
--- requirements.pip 2014-06-09 20:31:01 +0000
+++ requirements.pip 2014-09-05 14:54:31 +0000
@@ -25,7 +25,7 @@
# version of websocket-client to use. Remove websocket-client as a
dependency
# here when moving to a newer jujuclient that correctly specifies the
# version.
-websocket-
-jujuclient==0.17.5
-PyYAML==3.10
-urwid==1.1.1
+websocket-
+jujuclient==0.18.4
+PyYAML==3.11
+urwid==1.2.1
Index: test-requiremen ts.pip nts.pip' ts.pip 2014-06-09 20:31:01 +0000 ts.pip 2014-09-05 14:54:31 +0000 www.gnu. org/licenses/>.
=== modified file 'test-requireme
--- test-requiremen
+++ test-requiremen
@@ -17,7 +17,7 @@
# along with this program. If not, see <http://
coverage==3.7.1
-flake8==2.1.0
+flake8==2.2.3
mock==1.0.1
-nose==1.3.1
+nose==1.3.4
-r requirements.pip
Index: quickstart/juju.py juju.py'
=== modified file 'quickstart/
--- quickstart/juju.py 2014-06-03 20:39:11 +0000
+++ quickstart/juju.py 2014-09-08 17:49:51 +0000
@@ -19,16 +19,23 @@
from __future__ import unicode_literals
import logging
+import ssl
import jujuclient
-import ssl
import websocket
+OPCODE_TEXT = websocket. ABNF.OPCODE_ TEXT tion( {'ssl_version' : ssl.PROTOCOL_ TLSv1}) tion(sslopt= SSLOPT) create_ connection function. n.settimeout( websocket. default_ timeout) n.connect( api_url, origin=api_url) tion(websocket. WebSocket) :
+# Define the options used to initiate the secure WebSocket connection.
+SSLOPT = {
+ 'cert_reqs': ssl.CERT_NONE,
+ 'ssl_version': ssl.PROTOCOL_TLSv1,
+}
+
+
def connect(api_url):
"""Return an Environment instance connected to the given API URL."""
- connection = WebSocketConnec
- sslopt=
+ connection = WebSocketConnec
# See the websocket.
connectio
connectio
@@ -124,19 +131,23 @@
class WebSocketConnec
"""A WebSocket client connection."""
- def send(self, message): OPCODE_ TEXT):
+ def send(self, payload, opcode=
"""Send the given WebSocket message.
- Overridden to add logging. message. decode( 'utf-8' ))) Connection, self).send(message) decode( 'utf-8' ) message) ) Connection, self).send(payload,
+ Overridden to add logging in the case the payload is text.
"""
- logging.debug('API message: -->
{}'.format(
- return super(WebSocket
+ if opcode == OPCODE_TEXT:
+ message = payload.
+ logging.debug('API message: --> {}'.format(
+ return super(WebSocket
opcode=opcode)
def recv(self):
"""Receive a message from the WebSocket server.
- Overridden to add logging. Connection, self).recv() message. decode( 'utf-8' ))) Connection, self).recv() 'utf-8' ) message) )
+ Overridden to add logging in the case the received data is text.
"""
- message = super(WebSocket
- logging.debug('API message: <--
{}'.format(
- return message
+ data = super(WebSocket
+ if isinstance(data, bytes):
+ message = data.decode(
+ logging.debug('API message: <-- {}'.format(
+ return data
Index: quickstart/ tests/helpers. py tests/helpers. py' tests/helpers. py 2014-04-23 13:08:12 +0000 tests/helpers. py 2014-09-08 17:49:51 +0000 'logging. {}'.format( level.lower( ))) as mock_log: assert_ has_calls( expected_ calls) assert_ has_calls( expected_ calls)
=== modified file 'quickstart/
--- quickstart/
+++ quickstart/
@@ -36,8 +36,11 @@
"""
with mock.patch(
yield
- expected_calls = [mock.call(message) for message in messages]
- mock_log.
+ if messages:
+ expected_calls = [mock.call(message) for message in messages]
+ mock_log.
+ else:
+ assert not mock_log.called, 'logging unexpectedly called'
class BundleFileTests Mixin(object) :
Index: quickstart/ tests/test_ juju.py tests/test_ juju.py' tests/test_ juju.py 2014-06-03 19:10:21 +0000 tests/test_ juju.py 2014-09-08 17:49:51 +0000
=== modified file 'quickstart/
--- quickstart/
+++ quickstart/
@@ -21,7 +21,6 @@
import unittest
import mock
-import ssl
import websocket
from quickstart import juju t_connection( self, mock_conn): self.api_ url) assert_ called_ once_with( {'ssl_version' : ssl.PROTOCOL_ TLSv1}) assert_ called_ once_with( sslopt= juju.SSLOPT)
conn. assert_ has_calls( [
mock.call. settimeout( websocket. default_ timeout) , 'websocket. create_ connection' ) as mock_connect:
self.env = juju.Environmen t(api_url) assert_ called_ once_with( api_url, origin=api_url) assert_ called_ once_with(
self. changesets = []
@@ -39,8 +38,7 @@
def test_environmen
# A connected Environment instance is correctly returned.
env = juju.connect(
- mock_conn.
- sslopt=
+ mock_conn.
conn = mock_conn()
@@ -65,7 +63,8 @@
api_url = self.api_url
with mock.patch(
- mock_connect.
+ mock_connect.
+ api_url, origin=api_url, sslopt=juju.SSLOPT)
# Keep track of watcher changes in the changesets list.
@@ -325,10 +324,9 @@
snowman = 'Here is a snowman\u00a1: \u2603'
def setUp(self): 'socket. socket' ) as mock_socket: onnection( ) onnection( ) send_frame = self.mock_send = mock.Mock()
self. conn.recv_ data = self.mock_recv = mock.Mock()
- with mock.patch(
- self.conn = juju.WebSocketC
- # Patch the socket.send() function used by the send method.
- self.mock_send = mock_socket().send
+ self.conn = juju.WebSocketC
+ # The send method calls the send_frame one.
+ self.conn.
# The recv method calls the recv_data one.
@@ -345,17 +343,31 @@
self.conn. send(self. snowman. encode( 'utf-8' ))
self. assertTrue( self.mock_ send.called)
+ def test_send_ not_text( self): assert_ logs([] , 'debug'): websocket. ABNF.OPCODE_ BINARY) (self.mock_ send.called) recv.return_ value = (42, 'my message') recv.return_ value = (juju.OPCODE_TEXT, b'my message') assert_ logs([' API message: <-- my message'], 'debug'):
self.conn. recv()
self. mock_recv. assert_ called_ once_with( )
+ # Outgoing non-textual messages are not logged.
+ with helpers.
+ self.conn.send(0x0, opcode=
+ self.assertTrue
+
def test_recv(self):
# Incoming messages are properly logged.
- self.mock_
+ self.mock_
with helpers.
def test_recv_ unicode( self): recv.return_ value = (42, self.snowman. encode( 'utf-8' )) recv.return_ value = ( encode( 'utf-8' )) self.snowman) assert_ logs([expected] , 'debug'):
self.conn. recv()
self. mock_recv. assert_ called_ once_with( ) not_text( self): recv.return_ value = (websocket. ABNF.OPCODE_ BINARY, 0x0) assert_ logs([] , 'debug'): recv.assert_ called_ once_with( )
# Incoming unicode messages are properly logged.
- self.mock_
+ self.mock_
+ juju.OPCODE_TEXT, self.snowman.
expected = 'API message: <-- {}'.format(
with helpers.
+
+ def test_recv_
+ # Incoming non-textual messages are not logged.
+ self.mock_
+ with helpers.
+ self.conn.recv()
+ self.mock_