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
=== modified file 'tests/test_verify_mediawiki_bundle.py'
--- tests/test_verify_mediawiki_bundle.py 2016-04-04 22:32:27 +0000
+++ tests/test_verify_mediawiki_bundle.py 2016-04-06 06:48:02 +0000
@@ -9,8 +9,10 @@
9from assess_min_version import JujuAssertionError9from assess_min_version import JujuAssertionError
10import tests10import tests
11from tests.test_jujupy import FakeJujuClient11from tests.test_jujupy import FakeJujuClient
12import verify_mediawiki_bundle
12from verify_mediawiki_bundle import(13from verify_mediawiki_bundle import(
13 assess_mediawiki_bundle,14 assess_mediawiki_bundle,
15 _get_ssl_ctx,
14 parse_args,16 parse_args,
15 verify_services,17 verify_services,
16 wait_for_http,18 wait_for_http,
@@ -28,30 +30,50 @@
2830
29 def test_wait_for_http(self):31 def test_wait_for_http(self):
30 fake_res = FakeResponse()32 fake_res = FakeResponse()
31 with patch('urllib2.urlopen', autospec=True,33 with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
32 return_value=fake_res) as uo_mock:34 return_value=None) as ssl_mock:
35 with patch('urllib2.urlopen', autospec=True,
36 return_value=fake_res) as uo_mock:
33 wait_for_http("example.com")37 wait_for_http("example.com")
34 uo_mock.assert_called_once_with('example.com')38 uo_mock.assert_called_once_with('example.com')
39 ssl_mock.assert_called_once_with()
40
41 def test_wait_for_http_ssl_ctx(self):
42 fake_res = FakeResponse()
43 with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
44 return_value=FakeSslCtx()) as ssl_mock:
45 with patch('urllib2.urlopen', return_value=fake_res) as uo_mock:
46 wait_for_http("example.com")
47 uo_mock.assert_called_once_with(
48 'example.com', context=ssl_mock.return_value)
49 ssl_mock.assert_called_once_with()
3550
36 def test_wait_for_http_timeout(self):51 def test_wait_for_http_timeout(self):
37 fake_res = FakeResponse()52 fake_res = FakeResponse()
38 with patch('urllib2.urlopen', autospec=True,53 with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
39 return_value=fake_res):54 return_value=None) as ssl_mock:
40 with self.assertRaisesRegexp(55 with patch('urllib2.urlopen', autospec=True,
41 JujuAssertionError, 'example.com is not reachable'):56 return_value=fake_res):
42 wait_for_http("example.com", timeout=0)
43
44 def test_wait_for_http_httperror(self):
45 with patch('urllib2.urlopen', autospec=True,
46 return_value=urllib2.HTTPError(
47 None, None, None, None, None)) as uo_mock:
48 with patch('verify_mediawiki_bundle.until_timeout',
49 autospec=True, return_value=[1]) as ut_mock:
50 with self.assertRaisesRegexp(57 with self.assertRaisesRegexp(
51 JujuAssertionError, 'example.com is not reachable'):58 JujuAssertionError, 'example.com is not reachable'):
52 wait_for_http("example.com")59 wait_for_http("example.com", timeout=0)
60 ssl_mock.assert_called_once_with()
61
62 def test_wait_for_http_httperror(self):
63 with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
64 return_value=None) as ssl_mock:
65 with patch('urllib2.urlopen', autospec=True,
66 return_value=urllib2.HTTPError(
67 None, None, None, None, None)) as uo_mock:
68 with patch('verify_mediawiki_bundle.until_timeout',
69 autospec=True, return_value=[1]) as ut_mock:
70 with self.assertRaisesRegexp(
71 JujuAssertionError,
72 'example.com is not reachable'):
73 wait_for_http("example.com")
53 uo_mock.assert_called_once_with('example.com')74 uo_mock.assert_called_once_with('example.com')
54 self.assertEqual(ut_mock.mock_calls, [call(60)])75 self.assertEqual(ut_mock.mock_calls, [call(600)])
76 ssl_mock.assert_called_once_with()
5577
56 def test_verify_services(self):78 def test_verify_services(self):
57 client = self.deploy_mediawiki()79 client = self.deploy_mediawiki()
@@ -60,8 +82,11 @@
60 'mysql-slave']82 'mysql-slave']
61 with patch('urllib2.urlopen', autospec=True,83 with patch('urllib2.urlopen', autospec=True,
62 return_value=fake_res) as url_mock:84 return_value=fake_res) as url_mock:
63 verify_services(client, services, text='foo')85 with patch('verify_mediawiki_bundle._get_ssl_ctx', autospec=True,
86 return_value=None) as ssl_mock:
87 verify_services(client, services, text='foo')
64 url_mock.assert_called_once_with('http://1.example.com')88 url_mock.assert_called_once_with('http://1.example.com')
89 ssl_mock.assert_called_once_with()
6590
66 def test_verify_service_misconfigured(self):91 def test_verify_service_misconfigured(self):
67 client = FakeJujuClient()92 client = FakeJujuClient()
@@ -115,6 +140,19 @@
115 assess_mediawiki_bundle(client)140 assess_mediawiki_bundle(client)
116 vs_mock.assert_called_once_with(client, services)141 vs_mock.assert_called_once_with(client, services)
117142
143 def test_get_ssl_ctx(self):
144 ssl_mock = Mock(spec=['create_default_context'], CERT_NONE=0)
145 ssl_mock.create_default_context.return_value = FakeSslCtx()
146 verify_mediawiki_bundle.ssl = ssl_mock
147 ctx = _get_ssl_ctx()
148 self.assertIs(ctx.check_hostname, False)
149 self.assertEqual(ctx.verify_mode, 0)
150
151 def test_get_ssl_ctx_none(self):
152 verify_mediawiki_bundle.ssl = Mock(spec=[])
153 ctx = _get_ssl_ctx()
154 self.assertIsNone(ctx)
155
118 def deploy_mediawiki(self):156 def deploy_mediawiki(self):
119 client = FakeJujuClient()157 client = FakeJujuClient()
120 client.bootstrap()158 client.bootstrap()
@@ -126,6 +164,15 @@
126 return client164 return client
127165
128166
167class FakeSslCtx:
168 check_hostname = None
169 verify_mode = None
170
171
172class FakeSslOld:
173 pass
174
175
129class FakeResponse:176class FakeResponse:
130177
131 def __init__(self, code=200):178 def __init__(self, code=200):
132179
=== modified file 'verify_landscape_bundle.py'
--- verify_landscape_bundle.py 2016-04-04 22:32:27 +0000
+++ verify_landscape_bundle.py 2016-04-06 06:48:02 +0000
@@ -4,6 +4,8 @@
4import logging4import logging
5import sys5import sys
66
7
8from utility import configure_logging
7from verify_mediawiki_bundle import (9from verify_mediawiki_bundle import (
8 parse_args,10 parse_args,
9 verify_services,11 verify_services,
@@ -23,6 +25,7 @@
2325
24def main(argv=None):26def main(argv=None):
25 args = parse_args(argv)27 args = parse_args(argv)
28 configure_logging(args.verbose)
26 assess_landscape_bundle(args.client)29 assess_landscape_bundle(args.client)
2730
2831
2932
=== modified file 'verify_mediawiki_bundle.py'
--- verify_mediawiki_bundle.py 2016-04-05 01:08:36 +0000
+++ verify_mediawiki_bundle.py 2016-04-06 06:48:02 +0000
@@ -5,6 +5,7 @@
5import logging5import logging
6import pickle6import pickle
7import sys7import sys
8import ssl
8from time import sleep9from time import sleep
9import urllib210import urllib2
1011
@@ -21,10 +22,24 @@
21log = logging.getLogger("mediawiki_bundle")22log = logging.getLogger("mediawiki_bundle")
2223
2324
24def wait_for_http(url, timeout=60):25def _get_ssl_ctx():
26 try:
27 ctx = ssl.create_default_context()
28 except AttributeError:
29 return None
30 ctx.check_hostname = False
31 ctx.verify_mode = ssl.CERT_NONE
32 return ctx
33
34
35def wait_for_http(url, timeout=600):
36 ctx = _get_ssl_ctx()
25 for _ in until_timeout(timeout):37 for _ in until_timeout(timeout):
26 try:38 try:
27 req = urllib2.urlopen(url)39 if ctx is None:
40 req = urllib2.urlopen(url)
41 else:
42 req = urllib2.urlopen(url, context=ctx)
28 if 200 == req.getcode():43 if 200 == req.getcode():
29 break44 break
30 except (urllib2.URLError, urllib2.HTTPError):45 except (urllib2.URLError, urllib2.HTTPError):

Subscribers

People subscribed via source and target branches