Merge lp:~gz/pyjuju/0.5_unicode_token_backport into lp:pyjuju/0.5

Proposed by Martin Packman
Status: Merged
Merged at revision: 559
Proposed branch: lp:~gz/pyjuju/0.5_unicode_token_backport
Merge into: lp:pyjuju/0.5
Diff against target: 126 lines (+72/-9)
2 files modified
juju/providers/openstack/client.py (+6/-3)
juju/providers/openstack/tests/test_client.py (+66/-6)
To merge this branch: bzr merge lp:~gz/pyjuju/0.5_unicode_token_backport
Reviewer Review Type Date Requested Status
John A Meinel Approve
Martin Packman (community) Approve
Review via email: mp+156610@code.launchpad.net

Description of the change

Backport simple but niche issue with token encoding

See the original merge proposal for more details:

<https://code.launchpad.net/~gz/juju/os_token_string_type_1030897/+merge/127008>

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Test suite passes with change.

review: Approve
Revision history for this message
John A Meinel (jameinel) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'juju/providers/openstack/client.py'
2--- juju/providers/openstack/client.py 2012-09-27 19:07:21 +0000
3+++ juju/providers/openstack/client.py 2013-04-02 15:20:32 +0000
4@@ -33,9 +33,9 @@
5 from twisted.web.client import Agent
6 # Older twisted versions don't expose _newclient exceptions via client module
7 try:
8- from twisted.web.client import ResponseFailed
9+ from twisted.web.client import ResponseDone, ResponseFailed
10 except ImportError:
11- from twisted.web._newclient import ResponseFailed
12+ from twisted.web._newclient import ResponseDone, ResponseFailed
13 from twisted.web.http_headers import Headers
14 from zope.interface import implements
15
16@@ -249,7 +249,10 @@
17 def _handle_v2_auth(self, result):
18 access_details = self._json(result, 200, 'access')
19 token_details = access_details["token"]
20- self.token = token_details["id"]
21+ # Decoded json uses unicode for all string values, but that can upset
22+ # twisted when serialising headers later. Really should encode at that
23+ # point, but as keystone should only give ascii tokens a cast will do.
24+ self.token = token_details["id"].encode("ascii")
25
26 # TODO: care about token_details["expires"]
27 # Don't need to we're not preserving tokens.
28
29=== modified file 'juju/providers/openstack/tests/test_client.py'
30--- juju/providers/openstack/tests/test_client.py 2012-09-27 19:07:21 +0000
31+++ juju/providers/openstack/tests/test_client.py 2013-04-02 15:20:32 +0000
32@@ -62,10 +62,19 @@
33 class FakeResponse(object):
34 """Bare minimum needed to look like a twisted http response"""
35
36- def __init__(self, code, headers):
37+ def __init__(self, code, headers, body=None):
38 self.code = code
39 self.headers = headers
40- self.length = 0
41+ if body is None:
42+ self.length = 0
43+ else:
44+ self.length = len(body)
45+ self.body = body
46+
47+ def deliverBody(self, reader):
48+ reader.connectionMade()
49+ reader.dataReceived(self.body)
50+ reader.connectionLost(client.ResponseDone())
51
52
53 class ClientTests(testing.TestCase):
54@@ -106,6 +115,18 @@
55 self.mocker.result(self.mock_agent)
56 return config, osc
57
58+ def make_client_userpass(self):
59+ config = {
60+ "auth-url": "https://testing.invalid/v2.0/",
61+ "username": "user",
62+ "password": "pass",
63+ "project-name": "project",
64+ }
65+ osc = client._OpenStackClient(self.get_credentials(config), True)
66+ self.mock_agent(reactor, contextFactory=mocker.MATCH(self.is_checker))
67+ self.mocker.result(self.mock_agent)
68+ return config, osc
69+
70 @defer.inlineCallbacks
71 def test_auth_legacy(self):
72 config, osc = self.make_client_legacy()
73@@ -119,10 +140,49 @@
74 self.mocker.replay()
75 log = self.capture_logging()
76 yield osc.authenticate()
77- self.assertEqual("tok", osc.token)
78- self.assertEqual("http://testing.invalid/compute/path",
79- osc._make_url("compute", ["path"]))
80- self.assertIn("compute service not using secure", log.getvalue())
81+ self.assertIsInstance(osc.token, str)
82+ self.assertEqual("tok", osc.token)
83+ self.assertEqual("http://testing.invalid/compute/path",
84+ osc._make_url("compute", ["path"]))
85+ self.assertIn("compute service not using secure", log.getvalue())
86+
87+ @defer.inlineCallbacks
88+ def test_auth_userpass(self):
89+ config, osc = self.make_client_userpass()
90+ self.mock_agent.request("POST", "https://testing.invalid/v2.0/tokens",
91+ mocker.ANY, mocker.ANY)
92+ response = FakeResponse(200, http_headers.Headers({
93+ "Content-Type": ["application/json"],
94+ }),
95+ json.dumps({'access': {
96+ 'token': {'id': "tok", 'expires': "shortly"},
97+ 'serviceCatalog': [
98+ {
99+ 'type': "compute",
100+ 'endpoints': [
101+ {'publicURL': "http://testing.invalid/compute"},
102+ ],
103+ },
104+ {
105+ 'type': "object-store",
106+ 'endpoints': [
107+ {'publicURL': "http://testing.invalid/objstore"},
108+ ],
109+ },
110+ ],
111+ }}))
112+ self.mocker.result(defer.succeed(response))
113+ self.mocker.replay()
114+ log = self.capture_logging()
115+ yield osc.authenticate()
116+ self.assertIsInstance(osc.token, str)
117+ self.assertEqual("tok", osc.token)
118+ self.assertEqual("http://testing.invalid/compute/path",
119+ osc._make_url("compute", ["path"]))
120+ self.assertEqual("http://testing.invalid/objstore/path",
121+ osc._make_url("object-store", ["path"]))
122+ self.assertIn("compute service not using secure", log.getvalue())
123+ self.assertIn("object-store service not using secure", log.getvalue())
124
125 def test_cert_failure(self):
126 config, osc = self.make_client_legacy()

Subscribers

People subscribed via source and target branches