Merge lp:~sseman/juju-ci-tools/ssl-cert into lp:juju-ci-tools

Proposed by Seman
Status: Merged
Merged at revision: 1344
Proposed branch: lp:~sseman/juju-ci-tools/ssl-cert
Merge into: lp:juju-ci-tools
Diff against target: 190 lines (+84/-19)
3 files modified
tests/test_verify_mediawiki_bundle.py (+64/-17)
verify_landscape_bundle.py (+3/-0)
verify_mediawiki_bundle.py (+17/-2)
To merge this branch: bzr merge lp:~sseman/juju-ci-tools/ssl-cert
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+291079@code.launchpad.net

Description of the change

Currently, the Python installed on Jenkins servers have different versions (2.7.6 and 2.7.11). The verify_landscape_bundle.py script uses https to access the front page of the Landscape UI. With Python 2.7.9 and above, we explicitly have to tell it to ignore SSL certificate verification or it throws an URLError exception. In order to do this, I used SSLContext and set the SSLContext.verify_mode to ssl.CERT_NONE. But SSLContext is introduced in 2.7.9 and can't be used in version lower than 2.7.9.

I created _get_ssl_ctx() function that returns ssl context based on the Python version that is used. The ssl.create_default_context() is introduced in 2.7.9. If accessing the ssl.create_default_context doesn't generate AttributeError exception we must be using Python 2.7.9 and the function returns SSL context; otherwise, it returns None. Based on the SSL context returned, either I call urllib2.urlopen(url) or urllib2.urlopen(url, context=ssl-context)

I also noticed that the Landscape bundle occasionally fails waiting for the front page to be accessible. I increased the wait_for_http() timeout to 10min.

To post a comment you must log in.
lp:~sseman/juju-ci-tools/ssl-cert updated
1343. By Seman

Increase wait_for_http timeout to 10min.

Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/test_verify_mediawiki_bundle.py'
2--- tests/test_verify_mediawiki_bundle.py 2016-04-04 22:32:27 +0000
3+++ tests/test_verify_mediawiki_bundle.py 2016-04-06 06:48:02 +0000
4@@ -9,8 +9,10 @@
5 from assess_min_version import JujuAssertionError
6 import tests
7 from tests.test_jujupy import FakeJujuClient
8+import verify_mediawiki_bundle
9 from verify_mediawiki_bundle import(
10 assess_mediawiki_bundle,
11+ _get_ssl_ctx,
12 parse_args,
13 verify_services,
14 wait_for_http,
15@@ -28,30 +30,50 @@
16
17 def test_wait_for_http(self):
18 fake_res = FakeResponse()
19- with patch('urllib2.urlopen', autospec=True,
20- return_value=fake_res) as uo_mock:
21+ with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
22+ return_value=None) as ssl_mock:
23+ with patch('urllib2.urlopen', autospec=True,
24+ return_value=fake_res) as uo_mock:
25 wait_for_http("example.com")
26 uo_mock.assert_called_once_with('example.com')
27+ ssl_mock.assert_called_once_with()
28+
29+ def test_wait_for_http_ssl_ctx(self):
30+ fake_res = FakeResponse()
31+ with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
32+ return_value=FakeSslCtx()) as ssl_mock:
33+ with patch('urllib2.urlopen', return_value=fake_res) as uo_mock:
34+ wait_for_http("example.com")
35+ uo_mock.assert_called_once_with(
36+ 'example.com', context=ssl_mock.return_value)
37+ ssl_mock.assert_called_once_with()
38
39 def test_wait_for_http_timeout(self):
40 fake_res = FakeResponse()
41- with patch('urllib2.urlopen', autospec=True,
42- return_value=fake_res):
43- with self.assertRaisesRegexp(
44- JujuAssertionError, 'example.com is not reachable'):
45- wait_for_http("example.com", timeout=0)
46-
47- def test_wait_for_http_httperror(self):
48- with patch('urllib2.urlopen', autospec=True,
49- return_value=urllib2.HTTPError(
50- None, None, None, None, None)) as uo_mock:
51- with patch('verify_mediawiki_bundle.until_timeout',
52- autospec=True, return_value=[1]) as ut_mock:
53+ with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
54+ return_value=None) as ssl_mock:
55+ with patch('urllib2.urlopen', autospec=True,
56+ return_value=fake_res):
57 with self.assertRaisesRegexp(
58 JujuAssertionError, 'example.com is not reachable'):
59- wait_for_http("example.com")
60+ wait_for_http("example.com", timeout=0)
61+ ssl_mock.assert_called_once_with()
62+
63+ def test_wait_for_http_httperror(self):
64+ with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
65+ return_value=None) as ssl_mock:
66+ with patch('urllib2.urlopen', autospec=True,
67+ return_value=urllib2.HTTPError(
68+ None, None, None, None, None)) as uo_mock:
69+ with patch('verify_mediawiki_bundle.until_timeout',
70+ autospec=True, return_value=[1]) as ut_mock:
71+ with self.assertRaisesRegexp(
72+ JujuAssertionError,
73+ 'example.com is not reachable'):
74+ wait_for_http("example.com")
75 uo_mock.assert_called_once_with('example.com')
76- self.assertEqual(ut_mock.mock_calls, [call(60)])
77+ self.assertEqual(ut_mock.mock_calls, [call(600)])
78+ ssl_mock.assert_called_once_with()
79
80 def test_verify_services(self):
81 client = self.deploy_mediawiki()
82@@ -60,8 +82,11 @@
83 'mysql-slave']
84 with patch('urllib2.urlopen', autospec=True,
85 return_value=fake_res) as url_mock:
86- verify_services(client, services, text='foo')
87+ with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
88+ return_value=None) as ssl_mock:
89+ verify_services(client, services, text='foo')
90 url_mock.assert_called_once_with('http://1.example.com')
91+ ssl_mock.assert_called_once_with()
92
93 def test_verify_service_misconfigured(self):
94 client = FakeJujuClient()
95@@ -115,6 +140,19 @@
96 assess_mediawiki_bundle(client)
97 vs_mock.assert_called_once_with(client, services)
98
99+ def test_get_ssl_ctx(self):
100+ ssl_mock = Mock(spec=['create_default_context'], CERT_NONE=0)
101+ ssl_mock.create_default_context.return_value = FakeSslCtx()
102+ verify_mediawiki_bundle.ssl = ssl_mock
103+ ctx = _get_ssl_ctx()
104+ self.assertIs(ctx.check_hostname, False)
105+ self.assertEqual(ctx.verify_mode, 0)
106+
107+ def test_get_ssl_ctx_none(self):
108+ verify_mediawiki_bundle.ssl = Mock(spec=[])
109+ ctx = _get_ssl_ctx()
110+ self.assertIsNone(ctx)
111+
112 def deploy_mediawiki(self):
113 client = FakeJujuClient()
114 client.bootstrap()
115@@ -126,6 +164,15 @@
116 return client
117
118
119+class FakeSslCtx:
120+ check_hostname = None
121+ verify_mode = None
122+
123+
124+class FakeSslOld:
125+ pass
126+
127+
128 class FakeResponse:
129
130 def __init__(self, code=200):
131
132=== modified file 'verify_landscape_bundle.py'
133--- verify_landscape_bundle.py 2016-04-04 22:32:27 +0000
134+++ verify_landscape_bundle.py 2016-04-06 06:48:02 +0000
135@@ -4,6 +4,8 @@
136 import logging
137 import sys
138
139+
140+from utility import configure_logging
141 from verify_mediawiki_bundle import (
142 parse_args,
143 verify_services,
144@@ -23,6 +25,7 @@
145
146 def main(argv=None):
147 args = parse_args(argv)
148+ configure_logging(args.verbose)
149 assess_landscape_bundle(args.client)
150
151
152
153=== modified file 'verify_mediawiki_bundle.py'
154--- verify_mediawiki_bundle.py 2016-04-05 01:08:36 +0000
155+++ verify_mediawiki_bundle.py 2016-04-06 06:48:02 +0000
156@@ -5,6 +5,7 @@
157 import logging
158 import pickle
159 import sys
160+import ssl
161 from time import sleep
162 import urllib2
163
164@@ -21,10 +22,24 @@
165 log = logging.getLogger("mediawiki_bundle")
166
167
168-def wait_for_http(url, timeout=60):
169+def _get_ssl_ctx():
170+ try:
171+ ctx = ssl.create_default_context()
172+ except AttributeError:
173+ return None
174+ ctx.check_hostname = False
175+ ctx.verify_mode = ssl.CERT_NONE
176+ return ctx
177+
178+
179+def wait_for_http(url, timeout=600):
180+ ctx = _get_ssl_ctx()
181 for _ in until_timeout(timeout):
182 try:
183- req = urllib2.urlopen(url)
184+ if ctx is None:
185+ req = urllib2.urlopen(url)
186+ else:
187+ req = urllib2.urlopen(url, context=ctx)
188 if 200 == req.getcode():
189 break
190 except (urllib2.URLError, urllib2.HTTPError):

Subscribers

People subscribed via source and target branches