Merge lp:~stub/charm-helpers/py3-2 into lp:charm-helpers
- py3-2
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 258 | ||||
Proposed branch: | lp:~stub/charm-helpers/py3-2 | ||||
Merge into: | lp:charm-helpers | ||||
Diff against target: |
3281 lines (+625/-393) 62 files modified
.bzrignore (+2/-0) Makefile (+30/-7) charmhelpers/__init__.py (+22/-0) charmhelpers/cli/__init__.py (+3/-2) charmhelpers/contrib/amulet/deployment.py (+3/-3) charmhelpers/contrib/amulet/utils.py (+6/-4) charmhelpers/contrib/charmhelpers/__init__.py (+26/-19) charmhelpers/contrib/hahelpers/cluster.py (+4/-3) charmhelpers/contrib/network/ip.py (+2/-2) charmhelpers/contrib/openstack/amulet/deployment.py (+2/-1) charmhelpers/contrib/openstack/amulet/utils.py (+3/-1) charmhelpers/contrib/openstack/context.py (+14/-13) charmhelpers/contrib/openstack/neutron.py (+2/-2) charmhelpers/contrib/openstack/templates/haproxy.cfg (+2/-2) charmhelpers/contrib/openstack/templating.py (+5/-5) charmhelpers/contrib/openstack/utils.py (+8/-7) charmhelpers/contrib/peerstorage/__init__.py (+4/-3) charmhelpers/contrib/python/packages.py (+1/-1) charmhelpers/contrib/ssl/__init__.py (+1/-1) charmhelpers/contrib/storage/linux/ceph.py (+9/-6) charmhelpers/contrib/storage/linux/loopback.py (+4/-4) charmhelpers/contrib/storage/linux/lvm.py (+1/-0) charmhelpers/contrib/storage/linux/utils.py (+3/-2) charmhelpers/contrib/templating/contexts.py (+5/-3) charmhelpers/core/fstab.py (+10/-8) charmhelpers/core/hookenv.py (+20/-12) charmhelpers/core/host.py (+22/-17) charmhelpers/core/services/helpers.py (+9/-5) charmhelpers/core/templating.py (+2/-1) charmhelpers/fetch/__init__.py (+13/-11) charmhelpers/fetch/archiveurl.py (+53/-16) charmhelpers/fetch/bzrurl.py (+5/-1) charmhelpers/fetch/giturl.py (+6/-2) test_requirements.txt (+17/-18) tests/cli/test_cmdline.py (+7/-7) tests/cli/test_function_signature_analysis.py (+2/-2) tests/contrib/charmhelpers/test_charmhelpers.py (+6/-6) tests/contrib/hahelpers/test_cluster_utils.py (+2/-2) tests/contrib/network/test_ip.py (+11/-10) tests/contrib/openstack/test_neutron_utils.py (+2/-2) tests/contrib/openstack/test_openstack_utils.py (+33/-24) tests/contrib/openstack/test_os_contexts.py (+28/-27) tests/contrib/openstack/test_os_templating.py (+9/-3) tests/contrib/storage/test_linux_ceph.py (+8/-8) tests/contrib/storage/test_linux_storage_lvm.py (+2/-2) tests/contrib/storage/test_linux_storage_utils.py (+8/-8) tests/contrib/templating/test_contexts.py (+9/-6) tests/contrib/unison/test_unison.py (+2/-2) tests/core/test_fstab.py (+1/-1) tests/core/test_hookenv.py (+34/-32) tests/core/test_host.py (+19/-20) tests/core/test_services.py (+4/-4) tests/core/test_sysctl.py (+10/-3) tests/fetch/test_archiveurl.py (+12/-5) tests/fetch/test_bzrurl.py (+25/-8) tests/fetch/test_fetch.py (+13/-3) tests/fetch/test_giturl.py (+24/-8) tests/helpers.py (+15/-6) tests/payload/test_archive.py (+1/-1) tests/payload/test_execd.py (+1/-1) tests/tools/test_charm_helper_sync.py (+13/-6) tools/charm_helpers_sync/charm_helpers_sync.py (+5/-4) |
||||
To merge this branch: | bzr merge lp:~stub/charm-helpers/py3-2 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Van Steenburgh | Approve | ||
Jorge Niedbalski (community) | Approve | ||
Jorge Niedbalski | Pending | ||
Review via email: mp+242653@code.launchpad.net |
Commit message
Description of the change
Per https:/
precise charms attempting to use the Python 3 updated charm-helperers generally will not work, as the version of six they will have installed is very, very old.
This branch backports charm-helpers to use six 1.1, rather than six 1.18.
I believe this version will be good enough until precise charms stop being maintained by maintained, or until the charm-helpers distribution story is improved (if we distribute charm-helpers as a package or similar, we can distribute modern six with it).
An alternative approach I looked at on the previous MP was embedding a copy of six. This worked fine, but would have required people to sync six.py into their charm as well as the rest of charm-helpers.
- 196. By Stuart Bishop
-
Bootstrap six on import
- 197. By Stuart Bishop
-
Bootstrap yaml package
- 198. By Stuart Bishop
-
Fix reliance on implicit casts, such as treating subprocess.
check_output result as text instead of bytes - 199. By Stuart Bishop
-
Revert Py3 syntax hidden by mocking
- 200. By Stuart Bishop
-
antique six
- 201. By Stuart Bishop
-
Need modern distribute under precise
Tim Van Steenburgh (tvansteenburgh) wrote : | # |
- 202. By Stuart Bishop
-
Python3.2 backport for precise
- 203. By Stuart Bishop
-
Don't need simplejson
Jorge Niedbalski (niedbalski) wrote : | # |
My preliminary review shows everything OK.
- Trusty tests OK [python2.7, python3.4]
- No import errors
- Precise tests OK [python2.7, python3.2]
- No import errors
-------
TOTAL 3683 236 94%
-------
Ran 773 tests in 7.484s
OK (SKIP=7)
OK
ubuntu@
Python 2.7.3 (default, Feb 27 2014, 19:58:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import charmhelpers
>>>
Python 3.2.3 (default, Feb 27 2014, 21:31:18)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import charmhelpers
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
python3-six
0 upgraded, 1 newly installed, 0 to remove and 54 not upgraded.
Need to get 5,894 B of archives.
After this operation, 50.2 kB of additional disk space will be used.
Get:1 http://
Fetched 5,894 B in 0s (16.7 kB/s)
Selecting previously unselected package python3-six.
(Reading database ... 58662 files and directories currently installed.)
Unpacking python3-six (from .../python3-
Setting up python3-six (1.1.0-2) ...
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
python3-yaml
0 upgraded, 1 newly installed, 0 to remove and 54 not upgraded.
Need to get 111 kB of archives.
After this operation, 442 kB of additional disk space will be used.
Get:1 http://
Fetched 111 kB in 0s (120 kB/s)
Selecting previously unselected package python3-yaml.
(Reading database ... 58667 files and directories currently installed.)
Unpacking python3-yaml (from .../python3-
Setting up python3-yaml (3.10-2) ...
>>>
- 204. By Stuart Bishop
-
merge trunk, revert reversion
Jorge Niedbalski (niedbalski) wrote : | # |
After the latest merge, conflicts resolved. LGTM +1
Tim Van Steenburgh (tvansteenburgh) wrote : | # |
> Running make test in a clean precise lxc:
>
> Checking for Python syntax...
> Py2 OK
> charmhelpers/
> syntax
> tests/contrib/
> syntax
> tests/core/
> make: *** [lint] Error 1
>
>
> Also, running apt-get as an import side-effect makes me grimace.
Retested on precise and tests pass. Sorry for the noise, not sure what happened the first time.
Tim Van Steenburgh (tvansteenburgh) wrote : | # |
+1 LGTM
Preview Diff
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2014-11-25 14:35:22 +0000 | |||
3 | +++ .bzrignore 2014-11-25 15:09:14 +0000 | |||
4 | @@ -7,3 +7,5 @@ | |||
5 | 7 | .env/ | 7 | .env/ |
6 | 8 | coverage.xml | 8 | coverage.xml |
7 | 9 | docs/_build | 9 | docs/_build |
8 | 10 | .venv | ||
9 | 11 | .venv3 | ||
10 | 10 | 12 | ||
11 | === modified file 'Makefile' | |||
12 | --- Makefile 2014-11-25 14:35:22 +0000 | |||
13 | +++ Makefile 2014-11-25 15:09:14 +0000 | |||
14 | @@ -23,11 +23,12 @@ | |||
15 | 23 | python setup.py sdist | 23 | python setup.py sdist |
16 | 24 | 24 | ||
17 | 25 | clean: | 25 | clean: |
19 | 26 | python setup.py clean | 26 | -python setup.py clean |
20 | 27 | rm -rf build/ MANIFEST | 27 | rm -rf build/ MANIFEST |
21 | 28 | find . -name '*.pyc' -delete | 28 | find . -name '*.pyc' -delete |
22 | 29 | rm -rf dist/* | 29 | rm -rf dist/* |
23 | 30 | rm -rf .venv | 30 | rm -rf .venv |
24 | 31 | rm -rf .venv3 | ||
25 | 31 | (which dh_clean && dh_clean) || true | 32 | (which dh_clean && dh_clean) || true |
26 | 32 | 33 | ||
27 | 33 | userinstall: | 34 | userinstall: |
28 | @@ -38,19 +39,41 @@ | |||
29 | 38 | sudo apt-get install -y gcc python-dev python-virtualenv python-apt | 39 | sudo apt-get install -y gcc python-dev python-virtualenv python-apt |
30 | 39 | virtualenv .venv --system-site-packages | 40 | virtualenv .venv --system-site-packages |
31 | 40 | .venv/bin/pip install -U pip | 41 | .venv/bin/pip install -U pip |
32 | 42 | .venv/bin/pip install -U distribute | ||
33 | 41 | .venv/bin/pip install -I -r test_requirements.txt | 43 | .venv/bin/pip install -I -r test_requirements.txt |
37 | 42 | 44 | .venv/bin/pip install bzr | |
38 | 43 | test: .venv | 45 | .venv/bin/pip install GitPython |
39 | 44 | @echo Starting tests... | 46 | |
40 | 47 | .venv3: | ||
41 | 48 | sudo apt-get install -y gcc python3-dev python-virtualenv python3-apt | ||
42 | 49 | virtualenv .venv3 --python=python3 --system-site-packages | ||
43 | 50 | .venv3/bin/pip install -U pip | ||
44 | 51 | .venv3/bin/pip install -U distribute | ||
45 | 52 | .venv3/bin/pip install -I -r test_requirements.txt | ||
46 | 53 | |||
47 | 54 | # Note we don't even attempt to run tests if lint isn't passing. | ||
48 | 55 | test: lint test2 test3 | ||
49 | 56 | @echo OK | ||
50 | 57 | |||
51 | 58 | test2: | ||
52 | 59 | @echo Starting Py2 tests... | ||
53 | 45 | .venv/bin/nosetests -s --nologcapture tests/ | 60 | .venv/bin/nosetests -s --nologcapture tests/ |
54 | 46 | 61 | ||
56 | 47 | ftest: .venv | 62 | test3: |
57 | 63 | @echo Starting Py3 tests... | ||
58 | 64 | .venv3/bin/nosetests -s --nologcapture tests/ | ||
59 | 65 | |||
60 | 66 | ftest: lint | ||
61 | 48 | @echo Starting fast tests... | 67 | @echo Starting fast tests... |
62 | 49 | .venv/bin/nosetests --attr '!slow' --nologcapture tests/ | 68 | .venv/bin/nosetests --attr '!slow' --nologcapture tests/ |
63 | 69 | .venv3/bin/nosetests --attr '!slow' --nologcapture tests/ | ||
64 | 50 | 70 | ||
66 | 51 | lint: | 71 | lint: .venv .venv3 |
67 | 52 | @echo Checking for Python syntax... | 72 | @echo Checking for Python syntax... |
69 | 53 | @flake8 --ignore=E123,E501 $(PROJECT) $(TESTS) && echo OK | 73 | @.venv/bin/flake8 --ignore=E501 $(PROJECT) $(TESTS) tools/ \ |
70 | 74 | && echo Py2 OK | ||
71 | 75 | @.venv3/bin/flake8 --ignore=E501 $(PROJECT) $(TESTS) tools/ \ | ||
72 | 76 | && echo Py3 OK | ||
73 | 54 | 77 | ||
74 | 55 | docs: | 78 | docs: |
75 | 56 | - [ -z "`dpkg -l | grep python-sphinx`" ] && sudo apt-get install python-sphinx -y | 79 | - [ -z "`dpkg -l | grep python-sphinx`" ] && sudo apt-get install python-sphinx -y |
76 | 57 | 80 | ||
77 | === modified file 'charmhelpers/__init__.py' | |||
78 | --- charmhelpers/__init__.py 2013-05-11 19:55:58 +0000 | |||
79 | +++ charmhelpers/__init__.py 2014-11-25 15:09:14 +0000 | |||
80 | @@ -0,0 +1,22 @@ | |||
81 | 1 | # Bootstrap charm-helpers, installing its dependencies if necessary using | ||
82 | 2 | # only standard libraries. | ||
83 | 3 | import subprocess | ||
84 | 4 | import sys | ||
85 | 5 | |||
86 | 6 | try: | ||
87 | 7 | import six # flake8: noqa | ||
88 | 8 | except ImportError: | ||
89 | 9 | if sys.version_info.major == 2: | ||
90 | 10 | subprocess.check_call(['apt-get', 'install', '-y', 'python-six']) | ||
91 | 11 | else: | ||
92 | 12 | subprocess.check_call(['apt-get', 'install', '-y', 'python3-six']) | ||
93 | 13 | import six # flake8: noqa | ||
94 | 14 | |||
95 | 15 | try: | ||
96 | 16 | import yaml # flake8: noqa | ||
97 | 17 | except ImportError: | ||
98 | 18 | if sys.version_info.major == 2: | ||
99 | 19 | subprocess.check_call(['apt-get', 'install', '-y', 'python-yaml']) | ||
100 | 20 | else: | ||
101 | 21 | subprocess.check_call(['apt-get', 'install', '-y', 'python3-yaml']) | ||
102 | 22 | import yaml # flake8: noqa | ||
103 | 0 | 23 | ||
104 | === modified file 'charmhelpers/cli/__init__.py' | |||
105 | --- charmhelpers/cli/__init__.py 2014-11-25 14:35:22 +0000 | |||
106 | +++ charmhelpers/cli/__init__.py 2014-11-25 15:09:14 +0000 | |||
107 | @@ -1,8 +1,9 @@ | |||
108 | 1 | import inspect | 1 | import inspect |
109 | 2 | import itertools | ||
110 | 3 | import argparse | 2 | import argparse |
111 | 4 | import sys | 3 | import sys |
112 | 5 | 4 | ||
113 | 5 | from six.moves import zip | ||
114 | 6 | |||
115 | 6 | 7 | ||
116 | 7 | class OutputFormatter(object): | 8 | class OutputFormatter(object): |
117 | 8 | def __init__(self, outfile=sys.stdout): | 9 | def __init__(self, outfile=sys.stdout): |
118 | @@ -136,7 +137,7 @@ | |||
119 | 136 | if argspec.defaults: | 137 | if argspec.defaults: |
120 | 137 | positional_args = argspec.args[:-len(argspec.defaults)] | 138 | positional_args = argspec.args[:-len(argspec.defaults)] |
121 | 138 | keyword_names = argspec.args[-len(argspec.defaults):] | 139 | keyword_names = argspec.args[-len(argspec.defaults):] |
123 | 139 | for arg, default in itertools.izip(keyword_names, argspec.defaults): | 140 | for arg, default in zip(keyword_names, argspec.defaults): |
124 | 140 | yield ('--{}'.format(arg),), {'default': default} | 141 | yield ('--{}'.format(arg),), {'default': default} |
125 | 141 | else: | 142 | else: |
126 | 142 | positional_args = argspec.args | 143 | positional_args = argspec.args |
127 | 143 | 144 | ||
128 | === modified file 'charmhelpers/contrib/amulet/deployment.py' | |||
129 | --- charmhelpers/contrib/amulet/deployment.py 2014-11-25 14:35:22 +0000 | |||
130 | +++ charmhelpers/contrib/amulet/deployment.py 2014-11-25 15:09:14 +0000 | |||
131 | @@ -1,6 +1,6 @@ | |||
132 | 1 | import amulet | 1 | import amulet |
133 | 2 | |||
134 | 3 | import os | 2 | import os |
135 | 3 | import six | ||
136 | 4 | 4 | ||
137 | 5 | 5 | ||
138 | 6 | class AmuletDeployment(object): | 6 | class AmuletDeployment(object): |
139 | @@ -52,12 +52,12 @@ | |||
140 | 52 | 52 | ||
141 | 53 | def _add_relations(self, relations): | 53 | def _add_relations(self, relations): |
142 | 54 | """Add all of the relations for the services.""" | 54 | """Add all of the relations for the services.""" |
144 | 55 | for k, v in relations.iteritems(): | 55 | for k, v in six.iteritems(relations): |
145 | 56 | self.d.relate(k, v) | 56 | self.d.relate(k, v) |
146 | 57 | 57 | ||
147 | 58 | def _configure_services(self, configs): | 58 | def _configure_services(self, configs): |
148 | 59 | """Configure all of the services.""" | 59 | """Configure all of the services.""" |
150 | 60 | for service, config in configs.iteritems(): | 60 | for service, config in six.iteritems(configs): |
151 | 61 | self.d.configure(service, config) | 61 | self.d.configure(service, config) |
152 | 62 | 62 | ||
153 | 63 | def _deploy(self): | 63 | def _deploy(self): |
154 | 64 | 64 | ||
155 | === modified file 'charmhelpers/contrib/amulet/utils.py' | |||
156 | --- charmhelpers/contrib/amulet/utils.py 2014-11-25 14:35:22 +0000 | |||
157 | +++ charmhelpers/contrib/amulet/utils.py 2014-11-25 15:09:14 +0000 | |||
158 | @@ -5,6 +5,8 @@ | |||
159 | 5 | import sys | 5 | import sys |
160 | 6 | import time | 6 | import time |
161 | 7 | 7 | ||
162 | 8 | import six | ||
163 | 9 | |||
164 | 8 | 10 | ||
165 | 9 | class AmuletUtils(object): | 11 | class AmuletUtils(object): |
166 | 10 | """Amulet utilities. | 12 | """Amulet utilities. |
167 | @@ -58,7 +60,7 @@ | |||
168 | 58 | Verify the specified services are running on the corresponding | 60 | Verify the specified services are running on the corresponding |
169 | 59 | service units. | 61 | service units. |
170 | 60 | """ | 62 | """ |
172 | 61 | for k, v in commands.iteritems(): | 63 | for k, v in six.iteritems(commands): |
173 | 62 | for cmd in v: | 64 | for cmd in v: |
174 | 63 | output, code = k.run(cmd) | 65 | output, code = k.run(cmd) |
175 | 64 | if code != 0: | 66 | if code != 0: |
176 | @@ -100,11 +102,11 @@ | |||
177 | 100 | longs, or can be a function that evaluate a variable and returns a | 102 | longs, or can be a function that evaluate a variable and returns a |
178 | 101 | bool. | 103 | bool. |
179 | 102 | """ | 104 | """ |
181 | 103 | for k, v in expected.iteritems(): | 105 | for k, v in six.iteritems(expected): |
182 | 104 | if k in actual: | 106 | if k in actual: |
184 | 105 | if (isinstance(v, basestring) or | 107 | if (isinstance(v, six.string_types) or |
185 | 106 | isinstance(v, bool) or | 108 | isinstance(v, bool) or |
187 | 107 | isinstance(v, (int, long))): | 109 | isinstance(v, six.integer_types)): |
188 | 108 | if v != actual[k]: | 110 | if v != actual[k]: |
189 | 109 | return "{}:{}".format(k, actual[k]) | 111 | return "{}:{}".format(k, actual[k]) |
190 | 110 | elif not v(actual[k]): | 112 | elif not v(actual[k]): |
191 | 111 | 113 | ||
192 | === modified file 'charmhelpers/contrib/charmhelpers/__init__.py' | |||
193 | --- charmhelpers/contrib/charmhelpers/__init__.py 2014-11-25 14:35:22 +0000 | |||
194 | +++ charmhelpers/contrib/charmhelpers/__init__.py 2014-11-25 15:09:14 +0000 | |||
195 | @@ -8,19 +8,19 @@ | |||
196 | 8 | 8 | ||
197 | 9 | __metaclass__ = type | 9 | __metaclass__ = type |
198 | 10 | __all__ = [ | 10 | __all__ = [ |
212 | 11 | #'get_config', # core.hookenv.config() | 11 | # 'get_config', # core.hookenv.config() |
213 | 12 | #'log', # core.hookenv.log() | 12 | # 'log', # core.hookenv.log() |
214 | 13 | #'log_entry', # core.hookenv.log() | 13 | # 'log_entry', # core.hookenv.log() |
215 | 14 | #'log_exit', # core.hookenv.log() | 14 | # 'log_exit', # core.hookenv.log() |
216 | 15 | #'relation_get', # core.hookenv.relation_get() | 15 | # 'relation_get', # core.hookenv.relation_get() |
217 | 16 | #'relation_set', # core.hookenv.relation_set() | 16 | # 'relation_set', # core.hookenv.relation_set() |
218 | 17 | #'relation_ids', # core.hookenv.relation_ids() | 17 | # 'relation_ids', # core.hookenv.relation_ids() |
219 | 18 | #'relation_list', # core.hookenv.relation_units() | 18 | # 'relation_list', # core.hookenv.relation_units() |
220 | 19 | #'config_get', # core.hookenv.config() | 19 | # 'config_get', # core.hookenv.config() |
221 | 20 | #'unit_get', # core.hookenv.unit_get() | 20 | # 'unit_get', # core.hookenv.unit_get() |
222 | 21 | #'open_port', # core.hookenv.open_port() | 21 | # 'open_port', # core.hookenv.open_port() |
223 | 22 | #'close_port', # core.hookenv.close_port() | 22 | # 'close_port', # core.hookenv.close_port() |
224 | 23 | #'service_control', # core.host.service() | 23 | # 'service_control', # core.host.service() |
225 | 24 | 'unit_info', # client-side, NOT IMPLEMENTED | 24 | 'unit_info', # client-side, NOT IMPLEMENTED |
226 | 25 | 'wait_for_machine', # client-side, NOT IMPLEMENTED | 25 | 'wait_for_machine', # client-side, NOT IMPLEMENTED |
227 | 26 | 'wait_for_page_contents', # client-side, NOT IMPLEMENTED | 26 | 'wait_for_page_contents', # client-side, NOT IMPLEMENTED |
228 | @@ -31,17 +31,24 @@ | |||
229 | 31 | import operator | 31 | import operator |
230 | 32 | import tempfile | 32 | import tempfile |
231 | 33 | import time | 33 | import time |
232 | 34 | import urllib2 | ||
233 | 35 | import yaml | 34 | import yaml |
234 | 36 | import subprocess | 35 | import subprocess |
235 | 37 | 36 | ||
236 | 37 | import six | ||
237 | 38 | if six.PY3: | ||
238 | 39 | from urllib.request import urlopen | ||
239 | 40 | from urllib.error import (HTTPError, URLError) | ||
240 | 41 | else: | ||
241 | 42 | from urllib2 import (urlopen, HTTPError, URLError) | ||
242 | 43 | |||
243 | 44 | |||
244 | 38 | SLEEP_AMOUNT = 0.1 | 45 | SLEEP_AMOUNT = 0.1 |
245 | 39 | # We create a juju_status Command here because it makes testing much, | 46 | # We create a juju_status Command here because it makes testing much, |
246 | 40 | # much easier. | 47 | # much easier. |
247 | 41 | juju_status = lambda: subprocess.check_call(['juju', 'status']) | 48 | juju_status = lambda: subprocess.check_call(['juju', 'status']) |
248 | 42 | 49 | ||
249 | 43 | # re-implemented as charmhelpers.fetch.configure_sources() | 50 | # re-implemented as charmhelpers.fetch.configure_sources() |
251 | 44 | #def configure_source(update=False): | 51 | # def configure_source(update=False): |
252 | 45 | # source = config_get('source') | 52 | # source = config_get('source') |
253 | 46 | # if ((source.startswith('ppa:') or | 53 | # if ((source.startswith('ppa:') or |
254 | 47 | # source.startswith('cloud:') or | 54 | # source.startswith('cloud:') or |
255 | @@ -55,7 +62,7 @@ | |||
256 | 55 | 62 | ||
257 | 56 | # DEPRECATED: client-side only | 63 | # DEPRECATED: client-side only |
258 | 57 | def make_charm_config_file(charm_config): | 64 | def make_charm_config_file(charm_config): |
260 | 58 | charm_config_file = tempfile.NamedTemporaryFile() | 65 | charm_config_file = tempfile.NamedTemporaryFile(mode='w+') |
261 | 59 | charm_config_file.write(yaml.dump(charm_config)) | 66 | charm_config_file.write(yaml.dump(charm_config)) |
262 | 60 | charm_config_file.flush() | 67 | charm_config_file.flush() |
263 | 61 | # The NamedTemporaryFile instance is returned instead of just the name | 68 | # The NamedTemporaryFile instance is returned instead of just the name |
264 | @@ -119,7 +126,7 @@ | |||
265 | 119 | # we're in LXC. | 126 | # we're in LXC. |
266 | 120 | machine_data = get_machine_data() | 127 | machine_data = get_machine_data() |
267 | 121 | non_zookeeper_machines = [ | 128 | non_zookeeper_machines = [ |
269 | 122 | machine_data[key] for key in machine_data.keys()[1:]] | 129 | machine_data[key] for key in list(machine_data.keys())[1:]] |
270 | 123 | if len(non_zookeeper_machines) >= num_machines: | 130 | if len(non_zookeeper_machines) >= num_machines: |
271 | 124 | all_machines_running = True | 131 | all_machines_running = True |
272 | 125 | for machine in non_zookeeper_machines: | 132 | for machine in non_zookeeper_machines: |
273 | @@ -170,8 +177,8 @@ | |||
274 | 170 | start_time = time.time() | 177 | start_time = time.time() |
275 | 171 | while True: | 178 | while True: |
276 | 172 | try: | 179 | try: |
279 | 173 | stream = urllib2.urlopen(url) | 180 | stream = urlopen(url) |
280 | 174 | except (urllib2.HTTPError, urllib2.URLError): | 181 | except (HTTPError, URLError): |
281 | 175 | pass | 182 | pass |
282 | 176 | else: | 183 | else: |
283 | 177 | page = stream.read() | 184 | page = stream.read() |
284 | 178 | 185 | ||
285 | === modified file 'charmhelpers/contrib/hahelpers/cluster.py' | |||
286 | --- charmhelpers/contrib/hahelpers/cluster.py 2014-11-25 14:35:22 +0000 | |||
287 | +++ charmhelpers/contrib/hahelpers/cluster.py 2014-11-25 15:09:14 +0000 | |||
288 | @@ -13,9 +13,10 @@ | |||
289 | 13 | 13 | ||
290 | 14 | import subprocess | 14 | import subprocess |
291 | 15 | import os | 15 | import os |
292 | 16 | |||
293 | 17 | from socket import gethostname as get_unit_hostname | 16 | from socket import gethostname as get_unit_hostname |
294 | 18 | 17 | ||
295 | 18 | import six | ||
296 | 19 | |||
297 | 19 | from charmhelpers.core.hookenv import ( | 20 | from charmhelpers.core.hookenv import ( |
298 | 20 | log, | 21 | log, |
299 | 21 | relation_ids, | 22 | relation_ids, |
300 | @@ -77,7 +78,7 @@ | |||
301 | 77 | "show", resource | 78 | "show", resource |
302 | 78 | ] | 79 | ] |
303 | 79 | try: | 80 | try: |
305 | 80 | status = subprocess.check_output(cmd) | 81 | status = subprocess.check_output(cmd).decode('UTF-8') |
306 | 81 | except subprocess.CalledProcessError: | 82 | except subprocess.CalledProcessError: |
307 | 82 | return False | 83 | return False |
308 | 83 | else: | 84 | else: |
309 | @@ -197,7 +198,7 @@ | |||
310 | 197 | for setting in settings: | 198 | for setting in settings: |
311 | 198 | conf[setting] = config_get(setting) | 199 | conf[setting] = config_get(setting) |
312 | 199 | missing = [] | 200 | missing = [] |
314 | 200 | [missing.append(s) for s, v in conf.iteritems() if v is None] | 201 | [missing.append(s) for s, v in six.iteritems(conf) if v is None] |
315 | 201 | if missing: | 202 | if missing: |
316 | 202 | log('Insufficient config data to configure hacluster.', level=ERROR) | 203 | log('Insufficient config data to configure hacluster.', level=ERROR) |
317 | 203 | raise HAIncompleteConfig | 204 | raise HAIncompleteConfig |
318 | 204 | 205 | ||
319 | === modified file 'charmhelpers/contrib/network/ip.py' | |||
320 | --- charmhelpers/contrib/network/ip.py 2014-11-25 14:35:22 +0000 | |||
321 | +++ charmhelpers/contrib/network/ip.py 2014-11-25 15:09:14 +0000 | |||
322 | @@ -228,7 +228,7 @@ | |||
323 | 228 | raise Exception("Interface '%s' doesn't have any %s addresses." % | 228 | raise Exception("Interface '%s' doesn't have any %s addresses." % |
324 | 229 | (iface, inet_type)) | 229 | (iface, inet_type)) |
325 | 230 | 230 | ||
327 | 231 | return addresses | 231 | return sorted(addresses) |
328 | 232 | 232 | ||
329 | 233 | 233 | ||
330 | 234 | get_ipv4_addr = partial(get_iface_addr, inet_type='AF_INET') | 234 | get_ipv4_addr = partial(get_iface_addr, inet_type='AF_INET') |
331 | @@ -302,7 +302,7 @@ | |||
332 | 302 | if global_addrs: | 302 | if global_addrs: |
333 | 303 | # Make sure any found global addresses are not temporary | 303 | # Make sure any found global addresses are not temporary |
334 | 304 | cmd = ['ip', 'addr', 'show', iface] | 304 | cmd = ['ip', 'addr', 'show', iface] |
336 | 305 | out = subprocess.check_output(cmd) | 305 | out = subprocess.check_output(cmd).decode('UTF-8') |
337 | 306 | if dynamic_only: | 306 | if dynamic_only: |
338 | 307 | key = re.compile("inet6 (.+)/[0-9]+ scope global dynamic.*") | 307 | key = re.compile("inet6 (.+)/[0-9]+ scope global dynamic.*") |
339 | 308 | else: | 308 | else: |
340 | 309 | 309 | ||
341 | === modified file 'charmhelpers/contrib/openstack/amulet/deployment.py' | |||
342 | --- charmhelpers/contrib/openstack/amulet/deployment.py 2014-11-25 14:35:22 +0000 | |||
343 | +++ charmhelpers/contrib/openstack/amulet/deployment.py 2014-11-25 15:09:14 +0000 | |||
344 | @@ -1,3 +1,4 @@ | |||
345 | 1 | import six | ||
346 | 1 | from charmhelpers.contrib.amulet.deployment import ( | 2 | from charmhelpers.contrib.amulet.deployment import ( |
347 | 2 | AmuletDeployment | 3 | AmuletDeployment |
348 | 3 | ) | 4 | ) |
349 | @@ -69,7 +70,7 @@ | |||
350 | 69 | 70 | ||
351 | 70 | def _configure_services(self, configs): | 71 | def _configure_services(self, configs): |
352 | 71 | """Configure all of the services.""" | 72 | """Configure all of the services.""" |
354 | 72 | for service, config in configs.iteritems(): | 73 | for service, config in six.iteritems(configs): |
355 | 73 | self.d.configure(service, config) | 74 | self.d.configure(service, config) |
356 | 74 | 75 | ||
357 | 75 | def _get_openstack_release(self): | 76 | def _get_openstack_release(self): |
358 | 76 | 77 | ||
359 | === modified file 'charmhelpers/contrib/openstack/amulet/utils.py' | |||
360 | --- charmhelpers/contrib/openstack/amulet/utils.py 2014-11-25 14:35:22 +0000 | |||
361 | +++ charmhelpers/contrib/openstack/amulet/utils.py 2014-11-25 15:09:14 +0000 | |||
362 | @@ -7,6 +7,8 @@ | |||
363 | 7 | import keystoneclient.v2_0 as keystone_client | 7 | import keystoneclient.v2_0 as keystone_client |
364 | 8 | import novaclient.v1_1.client as nova_client | 8 | import novaclient.v1_1.client as nova_client |
365 | 9 | 9 | ||
366 | 10 | import six | ||
367 | 11 | |||
368 | 10 | from charmhelpers.contrib.amulet.utils import ( | 12 | from charmhelpers.contrib.amulet.utils import ( |
369 | 11 | AmuletUtils | 13 | AmuletUtils |
370 | 12 | ) | 14 | ) |
371 | @@ -60,7 +62,7 @@ | |||
372 | 60 | expected service catalog endpoints. | 62 | expected service catalog endpoints. |
373 | 61 | """ | 63 | """ |
374 | 62 | self.log.debug('actual: {}'.format(repr(actual))) | 64 | self.log.debug('actual: {}'.format(repr(actual))) |
376 | 63 | for k, v in expected.iteritems(): | 65 | for k, v in six.iteritems(expected): |
377 | 64 | if k in actual: | 66 | if k in actual: |
378 | 65 | ret = self._validate_dict_data(expected[k][0], actual[k][0]) | 67 | ret = self._validate_dict_data(expected[k][0], actual[k][0]) |
379 | 66 | if ret: | 68 | if ret: |
380 | 67 | 69 | ||
381 | === modified file 'charmhelpers/contrib/openstack/context.py' | |||
382 | --- charmhelpers/contrib/openstack/context.py 2014-11-25 14:35:22 +0000 | |||
383 | +++ charmhelpers/contrib/openstack/context.py 2014-11-25 15:09:14 +0000 | |||
384 | @@ -1,10 +1,11 @@ | |||
385 | 1 | import json | 1 | import json |
386 | 2 | import os | 2 | import os |
387 | 3 | import time | 3 | import time |
388 | 4 | |||
389 | 5 | from base64 import b64decode | 4 | from base64 import b64decode |
390 | 6 | from subprocess import check_call | 5 | from subprocess import check_call |
391 | 7 | 6 | ||
392 | 7 | import six | ||
393 | 8 | |||
394 | 8 | from charmhelpers.fetch import ( | 9 | from charmhelpers.fetch import ( |
395 | 9 | apt_install, | 10 | apt_install, |
396 | 10 | filter_installed_packages, | 11 | filter_installed_packages, |
397 | @@ -69,7 +70,7 @@ | |||
398 | 69 | 70 | ||
399 | 70 | def context_complete(ctxt): | 71 | def context_complete(ctxt): |
400 | 71 | _missing = [] | 72 | _missing = [] |
402 | 72 | for k, v in ctxt.iteritems(): | 73 | for k, v in six.iteritems(ctxt): |
403 | 73 | if v is None or v == '': | 74 | if v is None or v == '': |
404 | 74 | _missing.append(k) | 75 | _missing.append(k) |
405 | 75 | 76 | ||
406 | @@ -97,7 +98,7 @@ | |||
407 | 97 | split = config_flags.strip(' =').split('=') | 98 | split = config_flags.strip(' =').split('=') |
408 | 98 | limit = len(split) | 99 | limit = len(split) |
409 | 99 | flags = {} | 100 | flags = {} |
411 | 100 | for i in xrange(0, limit - 1): | 101 | for i in range(0, limit - 1): |
412 | 101 | current = split[i] | 102 | current = split[i] |
413 | 102 | next = split[i + 1] | 103 | next = split[i + 1] |
414 | 103 | vindex = next.rfind(',') | 104 | vindex = next.rfind(',') |
415 | @@ -375,7 +376,7 @@ | |||
416 | 375 | host = format_ipv6_addr(host) or host | 376 | host = format_ipv6_addr(host) or host |
417 | 376 | rabbitmq_hosts.append(host) | 377 | rabbitmq_hosts.append(host) |
418 | 377 | 378 | ||
420 | 378 | ctxt['rabbitmq_hosts'] = ','.join(rabbitmq_hosts) | 379 | ctxt['rabbitmq_hosts'] = ','.join(sorted(rabbitmq_hosts)) |
421 | 379 | 380 | ||
422 | 380 | if not context_complete(ctxt): | 381 | if not context_complete(ctxt): |
423 | 381 | return {} | 382 | return {} |
424 | @@ -408,7 +409,7 @@ | |||
425 | 408 | ceph_addr = format_ipv6_addr(ceph_addr) or ceph_addr | 409 | ceph_addr = format_ipv6_addr(ceph_addr) or ceph_addr |
426 | 409 | mon_hosts.append(ceph_addr) | 410 | mon_hosts.append(ceph_addr) |
427 | 410 | 411 | ||
429 | 411 | ctxt = {'mon_hosts': ' '.join(mon_hosts), | 412 | ctxt = {'mon_hosts': ' '.join(sorted(mon_hosts)), |
430 | 412 | 'auth': auth, | 413 | 'auth': auth, |
431 | 413 | 'key': key, | 414 | 'key': key, |
432 | 414 | 'use_syslog': use_syslog} | 415 | 'use_syslog': use_syslog} |
433 | @@ -587,7 +588,7 @@ | |||
434 | 587 | if k.startswith('ssl_key_'): | 588 | if k.startswith('ssl_key_'): |
435 | 588 | cns.append(k.lstrip('ssl_key_')) | 589 | cns.append(k.lstrip('ssl_key_')) |
436 | 589 | 590 | ||
438 | 590 | return list(set(cns)) | 591 | return sorted(list(set(cns))) |
439 | 591 | 592 | ||
440 | 592 | def get_network_addresses(self): | 593 | def get_network_addresses(self): |
441 | 593 | """For each network configured, return corresponding address and vip | 594 | """For each network configured, return corresponding address and vip |
442 | @@ -631,10 +632,10 @@ | |||
443 | 631 | else: | 632 | else: |
444 | 632 | addresses.append((addr, addr)) | 633 | addresses.append((addr, addr)) |
445 | 633 | 634 | ||
447 | 634 | return addresses | 635 | return sorted(addresses) |
448 | 635 | 636 | ||
449 | 636 | def __call__(self): | 637 | def __call__(self): |
451 | 637 | if isinstance(self.external_ports, basestring): | 638 | if isinstance(self.external_ports, six.string_types): |
452 | 638 | self.external_ports = [self.external_ports] | 639 | self.external_ports = [self.external_ports] |
453 | 639 | 640 | ||
454 | 640 | if not self.external_ports or not https(): | 641 | if not self.external_ports or not https(): |
455 | @@ -651,7 +652,7 @@ | |||
456 | 651 | self.configure_cert(cn) | 652 | self.configure_cert(cn) |
457 | 652 | 653 | ||
458 | 653 | addresses = self.get_network_addresses() | 654 | addresses = self.get_network_addresses() |
460 | 654 | for address, endpoint in set(addresses): | 655 | for address, endpoint in sorted(set(addresses)): |
461 | 655 | for api_port in self.external_ports: | 656 | for api_port in self.external_ports: |
462 | 656 | ext_port = determine_apache_port(api_port) | 657 | ext_port = determine_apache_port(api_port) |
463 | 657 | int_port = determine_api_port(api_port) | 658 | int_port = determine_api_port(api_port) |
464 | @@ -659,7 +660,7 @@ | |||
465 | 659 | ctxt['endpoints'].append(portmap) | 660 | ctxt['endpoints'].append(portmap) |
466 | 660 | ctxt['ext_ports'].append(int(ext_port)) | 661 | ctxt['ext_ports'].append(int(ext_port)) |
467 | 661 | 662 | ||
469 | 662 | ctxt['ext_ports'] = list(set(ctxt['ext_ports'])) | 663 | ctxt['ext_ports'] = sorted(list(set(ctxt['ext_ports']))) |
470 | 663 | return ctxt | 664 | return ctxt |
471 | 664 | 665 | ||
472 | 665 | 666 | ||
473 | @@ -921,10 +922,10 @@ | |||
474 | 921 | continue | 922 | continue |
475 | 922 | 923 | ||
476 | 923 | sub_config = sub_config[self.config_file] | 924 | sub_config = sub_config[self.config_file] |
478 | 924 | for k, v in sub_config.iteritems(): | 925 | for k, v in six.iteritems(sub_config): |
479 | 925 | if k == 'sections': | 926 | if k == 'sections': |
482 | 926 | for section, config_dict in v.iteritems(): | 927 | for section, config_dict in six.iteritems(v): |
483 | 927 | log("Adding section '%s'" % (section), | 928 | log("adding section '%s'" % (section), |
484 | 928 | level=DEBUG) | 929 | level=DEBUG) |
485 | 929 | ctxt[k][section] = config_dict | 930 | ctxt[k][section] = config_dict |
486 | 930 | else: | 931 | else: |
487 | 931 | 932 | ||
488 | === modified file 'charmhelpers/contrib/openstack/neutron.py' | |||
489 | --- charmhelpers/contrib/openstack/neutron.py 2014-11-17 15:15:52 +0000 | |||
490 | +++ charmhelpers/contrib/openstack/neutron.py 2014-11-25 15:09:14 +0000 | |||
491 | @@ -14,7 +14,7 @@ | |||
492 | 14 | def headers_package(): | 14 | def headers_package(): |
493 | 15 | """Ensures correct linux-headers for running kernel are installed, | 15 | """Ensures correct linux-headers for running kernel are installed, |
494 | 16 | for building DKMS package""" | 16 | for building DKMS package""" |
496 | 17 | kver = check_output(['uname', '-r']).strip() | 17 | kver = check_output(['uname', '-r']).decode('UTF-8').strip() |
497 | 18 | return 'linux-headers-%s' % kver | 18 | return 'linux-headers-%s' % kver |
498 | 19 | 19 | ||
499 | 20 | QUANTUM_CONF_DIR = '/etc/quantum' | 20 | QUANTUM_CONF_DIR = '/etc/quantum' |
500 | @@ -22,7 +22,7 @@ | |||
501 | 22 | 22 | ||
502 | 23 | def kernel_version(): | 23 | def kernel_version(): |
503 | 24 | """ Retrieve the current major kernel version as a tuple e.g. (3, 13) """ | 24 | """ Retrieve the current major kernel version as a tuple e.g. (3, 13) """ |
505 | 25 | kver = check_output(['uname', '-r']).strip() | 25 | kver = check_output(['uname', '-r']).decode('UTF-8').strip() |
506 | 26 | kver = kver.split('.') | 26 | kver = kver.split('.') |
507 | 27 | return (int(kver[0]), int(kver[1])) | 27 | return (int(kver[0]), int(kver[1])) |
508 | 28 | 28 | ||
509 | 29 | 29 | ||
510 | === modified file 'charmhelpers/contrib/openstack/templates/haproxy.cfg' | |||
511 | --- charmhelpers/contrib/openstack/templates/haproxy.cfg 2014-11-25 14:35:22 +0000 | |||
512 | +++ charmhelpers/contrib/openstack/templates/haproxy.cfg 2014-11-25 15:09:14 +0000 | |||
513 | @@ -35,7 +35,7 @@ | |||
514 | 35 | stats auth admin:password | 35 | stats auth admin:password |
515 | 36 | 36 | ||
516 | 37 | {% if frontends -%} | 37 | {% if frontends -%} |
518 | 38 | {% for service, ports in service_ports.iteritems() -%} | 38 | {% for service, ports in service_ports.items() -%} |
519 | 39 | frontend tcp-in_{{ service }} | 39 | frontend tcp-in_{{ service }} |
520 | 40 | bind *:{{ ports[0] }} | 40 | bind *:{{ ports[0] }} |
521 | 41 | bind :::{{ ports[0] }} | 41 | bind :::{{ ports[0] }} |
522 | @@ -46,7 +46,7 @@ | |||
523 | 46 | {% for frontend in frontends -%} | 46 | {% for frontend in frontends -%} |
524 | 47 | backend {{ service }}_{{ frontend }} | 47 | backend {{ service }}_{{ frontend }} |
525 | 48 | balance leastconn | 48 | balance leastconn |
527 | 49 | {% for unit, address in frontends[frontend]['backends'].iteritems() -%} | 49 | {% for unit, address in frontends[frontend]['backends'].items() -%} |
528 | 50 | server {{ unit }} {{ address }}:{{ ports[1] }} check | 50 | server {{ unit }} {{ address }}:{{ ports[1] }} check |
529 | 51 | {% endfor %} | 51 | {% endfor %} |
530 | 52 | {% endfor -%} | 52 | {% endfor -%} |
531 | 53 | 53 | ||
532 | === modified file 'charmhelpers/contrib/openstack/templating.py' | |||
533 | --- charmhelpers/contrib/openstack/templating.py 2014-11-25 14:35:22 +0000 | |||
534 | +++ charmhelpers/contrib/openstack/templating.py 2014-11-25 15:09:14 +0000 | |||
535 | @@ -1,13 +1,13 @@ | |||
536 | 1 | import os | 1 | import os |
537 | 2 | 2 | ||
538 | 3 | import six | ||
539 | 4 | |||
540 | 3 | from charmhelpers.fetch import apt_install | 5 | from charmhelpers.fetch import apt_install |
541 | 4 | |||
542 | 5 | from charmhelpers.core.hookenv import ( | 6 | from charmhelpers.core.hookenv import ( |
543 | 6 | log, | 7 | log, |
544 | 7 | ERROR, | 8 | ERROR, |
545 | 8 | INFO | 9 | INFO |
546 | 9 | ) | 10 | ) |
547 | 10 | |||
548 | 11 | from charmhelpers.contrib.openstack.utils import OPENSTACK_CODENAMES | 11 | from charmhelpers.contrib.openstack.utils import OPENSTACK_CODENAMES |
549 | 12 | 12 | ||
550 | 13 | try: | 13 | try: |
551 | @@ -43,7 +43,7 @@ | |||
552 | 43 | order by OpenStack release. | 43 | order by OpenStack release. |
553 | 44 | """ | 44 | """ |
554 | 45 | tmpl_dirs = [(rel, os.path.join(templates_dir, rel)) | 45 | tmpl_dirs = [(rel, os.path.join(templates_dir, rel)) |
556 | 46 | for rel in OPENSTACK_CODENAMES.itervalues()] | 46 | for rel in six.itervalues(OPENSTACK_CODENAMES)] |
557 | 47 | 47 | ||
558 | 48 | if not os.path.isdir(templates_dir): | 48 | if not os.path.isdir(templates_dir): |
559 | 49 | log('Templates directory not found @ %s.' % templates_dir, | 49 | log('Templates directory not found @ %s.' % templates_dir, |
560 | @@ -258,7 +258,7 @@ | |||
561 | 258 | """ | 258 | """ |
562 | 259 | Write out all registered config files. | 259 | Write out all registered config files. |
563 | 260 | """ | 260 | """ |
565 | 261 | [self.write(k) for k in self.templates.iterkeys()] | 261 | [self.write(k) for k in six.iterkeys(self.templates)] |
566 | 262 | 262 | ||
567 | 263 | def set_release(self, openstack_release): | 263 | def set_release(self, openstack_release): |
568 | 264 | """ | 264 | """ |
569 | @@ -275,5 +275,5 @@ | |||
570 | 275 | ''' | 275 | ''' |
571 | 276 | interfaces = [] | 276 | interfaces = [] |
572 | 277 | [interfaces.extend(i.complete_contexts()) | 277 | [interfaces.extend(i.complete_contexts()) |
574 | 278 | for i in self.templates.itervalues()] | 278 | for i in six.itervalues(self.templates)] |
575 | 279 | return interfaces | 279 | return interfaces |
576 | 280 | 280 | ||
577 | === modified file 'charmhelpers/contrib/openstack/utils.py' | |||
578 | --- charmhelpers/contrib/openstack/utils.py 2014-11-25 14:35:22 +0000 | |||
579 | +++ charmhelpers/contrib/openstack/utils.py 2014-11-25 15:09:14 +0000 | |||
580 | @@ -10,6 +10,8 @@ | |||
581 | 10 | import socket | 10 | import socket |
582 | 11 | import sys | 11 | import sys |
583 | 12 | 12 | ||
584 | 13 | import six | ||
585 | 14 | |||
586 | 13 | from charmhelpers.core.hookenv import ( | 15 | from charmhelpers.core.hookenv import ( |
587 | 14 | config, | 16 | config, |
588 | 15 | log as juju_log, | 17 | log as juju_log, |
589 | @@ -113,7 +115,7 @@ | |||
590 | 113 | 115 | ||
591 | 114 | # Best guess match based on deb string provided | 116 | # Best guess match based on deb string provided |
592 | 115 | if src.startswith('deb') or src.startswith('ppa'): | 117 | if src.startswith('deb') or src.startswith('ppa'): |
594 | 116 | for k, v in OPENSTACK_CODENAMES.iteritems(): | 118 | for k, v in six.iteritems(OPENSTACK_CODENAMES): |
595 | 117 | if v in src: | 119 | if v in src: |
596 | 118 | return v | 120 | return v |
597 | 119 | 121 | ||
598 | @@ -134,7 +136,7 @@ | |||
599 | 134 | 136 | ||
600 | 135 | def get_os_version_codename(codename): | 137 | def get_os_version_codename(codename): |
601 | 136 | '''Determine OpenStack version number from codename.''' | 138 | '''Determine OpenStack version number from codename.''' |
603 | 137 | for k, v in OPENSTACK_CODENAMES.iteritems(): | 139 | for k, v in six.iteritems(OPENSTACK_CODENAMES): |
604 | 138 | if v == codename: | 140 | if v == codename: |
605 | 139 | return k | 141 | return k |
606 | 140 | e = 'Could not derive OpenStack version for '\ | 142 | e = 'Could not derive OpenStack version for '\ |
607 | @@ -194,7 +196,7 @@ | |||
608 | 194 | else: | 196 | else: |
609 | 195 | vers_map = OPENSTACK_CODENAMES | 197 | vers_map = OPENSTACK_CODENAMES |
610 | 196 | 198 | ||
612 | 197 | for version, cname in vers_map.iteritems(): | 199 | for version, cname in six.iteritems(vers_map): |
613 | 198 | if cname == codename: | 200 | if cname == codename: |
614 | 199 | return version | 201 | return version |
615 | 200 | # e = "Could not determine OpenStack version for package: %s" % pkg | 202 | # e = "Could not determine OpenStack version for package: %s" % pkg |
616 | @@ -318,7 +320,7 @@ | |||
617 | 318 | rc_script.write( | 320 | rc_script.write( |
618 | 319 | "#!/bin/bash\n") | 321 | "#!/bin/bash\n") |
619 | 320 | [rc_script.write('export %s=%s\n' % (u, p)) | 322 | [rc_script.write('export %s=%s\n' % (u, p)) |
621 | 321 | for u, p in env_vars.iteritems() if u != "script_path"] | 323 | for u, p in six.iteritems(env_vars) if u != "script_path"] |
622 | 322 | 324 | ||
623 | 323 | 325 | ||
624 | 324 | def openstack_upgrade_available(package): | 326 | def openstack_upgrade_available(package): |
625 | @@ -418,7 +420,7 @@ | |||
626 | 418 | 420 | ||
627 | 419 | if isinstance(address, dns.name.Name): | 421 | if isinstance(address, dns.name.Name): |
628 | 420 | rtype = 'PTR' | 422 | rtype = 'PTR' |
630 | 421 | elif isinstance(address, basestring): | 423 | elif isinstance(address, six.string_types): |
631 | 422 | rtype = 'A' | 424 | rtype = 'A' |
632 | 423 | else: | 425 | else: |
633 | 424 | return None | 426 | return None |
634 | @@ -486,8 +488,7 @@ | |||
635 | 486 | 'hostname': json.dumps(hosts)} | 488 | 'hostname': json.dumps(hosts)} |
636 | 487 | 489 | ||
637 | 488 | if relation_prefix: | 490 | if relation_prefix: |
640 | 489 | keys = kwargs.keys() | 491 | for key in list(kwargs.keys()): |
639 | 490 | for key in keys: | ||
641 | 491 | kwargs["%s_%s" % (relation_prefix, key)] = kwargs[key] | 492 | kwargs["%s_%s" % (relation_prefix, key)] = kwargs[key] |
642 | 492 | del kwargs[key] | 493 | del kwargs[key] |
643 | 493 | 494 | ||
644 | 494 | 495 | ||
645 | === modified file 'charmhelpers/contrib/peerstorage/__init__.py' | |||
646 | --- charmhelpers/contrib/peerstorage/__init__.py 2014-11-25 14:35:22 +0000 | |||
647 | +++ charmhelpers/contrib/peerstorage/__init__.py 2014-11-25 15:09:14 +0000 | |||
648 | @@ -1,3 +1,4 @@ | |||
649 | 1 | import six | ||
650 | 1 | from charmhelpers.core.hookenv import relation_id as current_relation_id | 2 | from charmhelpers.core.hookenv import relation_id as current_relation_id |
651 | 2 | from charmhelpers.core.hookenv import ( | 3 | from charmhelpers.core.hookenv import ( |
652 | 3 | is_relation_made, | 4 | is_relation_made, |
653 | @@ -93,7 +94,7 @@ | |||
654 | 93 | if ex in echo_data: | 94 | if ex in echo_data: |
655 | 94 | echo_data.pop(ex) | 95 | echo_data.pop(ex) |
656 | 95 | else: | 96 | else: |
658 | 96 | for attribute, value in rdata.iteritems(): | 97 | for attribute, value in six.iteritems(rdata): |
659 | 97 | for include in includes: | 98 | for include in includes: |
660 | 98 | if include in attribute: | 99 | if include in attribute: |
661 | 99 | echo_data[attribute] = value | 100 | echo_data[attribute] = value |
662 | @@ -119,8 +120,8 @@ | |||
663 | 119 | relation_settings=relation_settings, | 120 | relation_settings=relation_settings, |
664 | 120 | **kwargs) | 121 | **kwargs) |
665 | 121 | if is_relation_made(peer_relation_name): | 122 | if is_relation_made(peer_relation_name): |
668 | 122 | for key, value in dict(kwargs.items() + | 123 | for key, value in six.iteritems(dict(list(kwargs.items()) + |
669 | 123 | relation_settings.items()).iteritems(): | 124 | list(relation_settings.items()))): |
670 | 124 | key_prefix = relation_id or current_relation_id() | 125 | key_prefix = relation_id or current_relation_id() |
671 | 125 | peer_store(key_prefix + delimiter + key, | 126 | peer_store(key_prefix + delimiter + key, |
672 | 126 | value, | 127 | value, |
673 | 127 | 128 | ||
674 | === modified file 'charmhelpers/contrib/python/packages.py' | |||
675 | --- charmhelpers/contrib/python/packages.py 2014-11-25 14:35:22 +0000 | |||
676 | +++ charmhelpers/contrib/python/packages.py 2014-11-25 15:09:14 +0000 | |||
677 | @@ -15,7 +15,7 @@ | |||
678 | 15 | 15 | ||
679 | 16 | def parse_options(given, available): | 16 | def parse_options(given, available): |
680 | 17 | """Given a set of options, check if available""" | 17 | """Given a set of options, check if available""" |
682 | 18 | for key, value in given.items(): | 18 | for key, value in sorted(given.items()): |
683 | 19 | if key in available: | 19 | if key in available: |
684 | 20 | yield "--{0}={1}".format(key, value) | 20 | yield "--{0}={1}".format(key, value) |
685 | 21 | 21 | ||
686 | 22 | 22 | ||
687 | === modified file 'charmhelpers/contrib/ssl/__init__.py' | |||
688 | --- charmhelpers/contrib/ssl/__init__.py 2014-11-25 14:35:22 +0000 | |||
689 | +++ charmhelpers/contrib/ssl/__init__.py 2014-11-25 15:09:14 +0000 | |||
690 | @@ -74,5 +74,5 @@ | |||
691 | 74 | subprocess.check_call(cmd) | 74 | subprocess.check_call(cmd) |
692 | 75 | return True | 75 | return True |
693 | 76 | except Exception as e: | 76 | except Exception as e: |
695 | 77 | print "Execution of openssl command failed:\n{}".format(e) | 77 | print("Execution of openssl command failed:\n{}".format(e)) |
696 | 78 | return False | 78 | return False |
697 | 79 | 79 | ||
698 | === modified file 'charmhelpers/contrib/storage/linux/ceph.py' | |||
699 | --- charmhelpers/contrib/storage/linux/ceph.py 2014-11-25 14:35:22 +0000 | |||
700 | +++ charmhelpers/contrib/storage/linux/ceph.py 2014-11-25 15:09:14 +0000 | |||
701 | @@ -65,7 +65,8 @@ | |||
702 | 65 | def rbd_exists(service, pool, rbd_img): | 65 | def rbd_exists(service, pool, rbd_img): |
703 | 66 | """Check to see if a RADOS block device exists.""" | 66 | """Check to see if a RADOS block device exists.""" |
704 | 67 | try: | 67 | try: |
706 | 68 | out = check_output(['rbd', 'list', '--id', service, '--pool', pool]) | 68 | out = check_output(['rbd', 'list', '--id', |
707 | 69 | service, '--pool', pool]).decode('UTF-8') | ||
708 | 69 | except CalledProcessError: | 70 | except CalledProcessError: |
709 | 70 | return False | 71 | return False |
710 | 71 | 72 | ||
711 | @@ -82,7 +83,8 @@ | |||
712 | 82 | def pool_exists(service, name): | 83 | def pool_exists(service, name): |
713 | 83 | """Check to see if a RADOS pool already exists.""" | 84 | """Check to see if a RADOS pool already exists.""" |
714 | 84 | try: | 85 | try: |
716 | 85 | out = check_output(['rados', '--id', service, 'lspools']) | 86 | out = check_output(['rados', '--id', service, |
717 | 87 | 'lspools']).decode('UTF-8') | ||
718 | 86 | except CalledProcessError: | 88 | except CalledProcessError: |
719 | 87 | return False | 89 | return False |
720 | 88 | 90 | ||
721 | @@ -96,7 +98,8 @@ | |||
722 | 96 | version = ceph_version() | 98 | version = ceph_version() |
723 | 97 | if version and version >= '0.56': | 99 | if version and version >= '0.56': |
724 | 98 | return json.loads(check_output(['ceph', '--id', service, | 100 | return json.loads(check_output(['ceph', '--id', service, |
726 | 99 | 'osd', 'ls', '--format=json'])) | 101 | 'osd', 'ls', |
727 | 102 | '--format=json']).decode('UTF-8')) | ||
728 | 100 | 103 | ||
729 | 101 | return None | 104 | return None |
730 | 102 | 105 | ||
731 | @@ -112,7 +115,7 @@ | |||
732 | 112 | # on upstream recommended best practices. | 115 | # on upstream recommended best practices. |
733 | 113 | osds = get_osds(service) | 116 | osds = get_osds(service) |
734 | 114 | if osds: | 117 | if osds: |
736 | 115 | pgnum = (len(osds) * 100 / replicas) | 118 | pgnum = (len(osds) * 100 // replicas) |
737 | 116 | else: | 119 | else: |
738 | 117 | # NOTE(james-page): Default to 200 for older ceph versions | 120 | # NOTE(james-page): Default to 200 for older ceph versions |
739 | 118 | # which don't support OSD query from cli | 121 | # which don't support OSD query from cli |
740 | @@ -193,7 +196,7 @@ | |||
741 | 193 | def image_mapped(name): | 196 | def image_mapped(name): |
742 | 194 | """Determine whether a RADOS block device is mapped locally.""" | 197 | """Determine whether a RADOS block device is mapped locally.""" |
743 | 195 | try: | 198 | try: |
745 | 196 | out = check_output(['rbd', 'showmapped']) | 199 | out = check_output(['rbd', 'showmapped']).decode('UTF-8') |
746 | 197 | except CalledProcessError: | 200 | except CalledProcessError: |
747 | 198 | return False | 201 | return False |
748 | 199 | 202 | ||
749 | @@ -361,7 +364,7 @@ | |||
750 | 361 | """Retrieve the local version of ceph.""" | 364 | """Retrieve the local version of ceph.""" |
751 | 362 | if os.path.exists('/usr/bin/ceph'): | 365 | if os.path.exists('/usr/bin/ceph'): |
752 | 363 | cmd = ['ceph', '-v'] | 366 | cmd = ['ceph', '-v'] |
754 | 364 | output = check_output(cmd) | 367 | output = check_output(cmd).decode('US-ASCII') |
755 | 365 | output = output.split() | 368 | output = output.split() |
756 | 366 | if len(output) > 3: | 369 | if len(output) > 3: |
757 | 367 | return output[2] | 370 | return output[2] |
758 | 368 | 371 | ||
759 | === modified file 'charmhelpers/contrib/storage/linux/loopback.py' | |||
760 | --- charmhelpers/contrib/storage/linux/loopback.py 2014-11-25 14:35:22 +0000 | |||
761 | +++ charmhelpers/contrib/storage/linux/loopback.py 2014-11-25 15:09:14 +0000 | |||
762 | @@ -1,12 +1,12 @@ | |||
763 | 1 | |||
764 | 2 | import os | 1 | import os |
765 | 3 | import re | 2 | import re |
766 | 4 | |||
767 | 5 | from subprocess import ( | 3 | from subprocess import ( |
768 | 6 | check_call, | 4 | check_call, |
769 | 7 | check_output, | 5 | check_output, |
770 | 8 | ) | 6 | ) |
771 | 9 | 7 | ||
772 | 8 | import six | ||
773 | 9 | |||
774 | 10 | 10 | ||
775 | 11 | ################################################## | 11 | ################################################## |
776 | 12 | # loopback device helpers. | 12 | # loopback device helpers. |
777 | @@ -37,7 +37,7 @@ | |||
778 | 37 | ''' | 37 | ''' |
779 | 38 | file_path = os.path.abspath(file_path) | 38 | file_path = os.path.abspath(file_path) |
780 | 39 | check_call(['losetup', '--find', file_path]) | 39 | check_call(['losetup', '--find', file_path]) |
782 | 40 | for d, f in loopback_devices().iteritems(): | 40 | for d, f in six.iteritems(loopback_devices()): |
783 | 41 | if f == file_path: | 41 | if f == file_path: |
784 | 42 | return d | 42 | return d |
785 | 43 | 43 | ||
786 | @@ -51,7 +51,7 @@ | |||
787 | 51 | 51 | ||
788 | 52 | :returns: str: Full path to the ensured loopback device (eg, /dev/loop0) | 52 | :returns: str: Full path to the ensured loopback device (eg, /dev/loop0) |
789 | 53 | ''' | 53 | ''' |
791 | 54 | for d, f in loopback_devices().iteritems(): | 54 | for d, f in six.iteritems(loopback_devices()): |
792 | 55 | if f == path: | 55 | if f == path: |
793 | 56 | return d | 56 | return d |
794 | 57 | 57 | ||
795 | 58 | 58 | ||
796 | === modified file 'charmhelpers/contrib/storage/linux/lvm.py' | |||
797 | --- charmhelpers/contrib/storage/linux/lvm.py 2014-05-10 19:58:31 +0000 | |||
798 | +++ charmhelpers/contrib/storage/linux/lvm.py 2014-11-25 15:09:14 +0000 | |||
799 | @@ -61,6 +61,7 @@ | |||
800 | 61 | vg = None | 61 | vg = None |
801 | 62 | pvd = check_output(['pvdisplay', block_device]).splitlines() | 62 | pvd = check_output(['pvdisplay', block_device]).splitlines() |
802 | 63 | for l in pvd: | 63 | for l in pvd: |
803 | 64 | l = l.decode('UTF-8') | ||
804 | 64 | if l.strip().startswith('VG Name'): | 65 | if l.strip().startswith('VG Name'): |
805 | 65 | vg = ' '.join(l.strip().split()[2:]) | 66 | vg = ' '.join(l.strip().split()[2:]) |
806 | 66 | return vg | 67 | return vg |
807 | 67 | 68 | ||
808 | === modified file 'charmhelpers/contrib/storage/linux/utils.py' | |||
809 | --- charmhelpers/contrib/storage/linux/utils.py 2014-07-31 08:17:42 +0000 | |||
810 | +++ charmhelpers/contrib/storage/linux/utils.py 2014-11-25 15:09:14 +0000 | |||
811 | @@ -30,7 +30,8 @@ | |||
812 | 30 | # sometimes sgdisk exits non-zero; this is OK, dd will clean up | 30 | # sometimes sgdisk exits non-zero; this is OK, dd will clean up |
813 | 31 | call(['sgdisk', '--zap-all', '--mbrtogpt', | 31 | call(['sgdisk', '--zap-all', '--mbrtogpt', |
814 | 32 | '--clear', block_device]) | 32 | '--clear', block_device]) |
816 | 33 | dev_end = check_output(['blockdev', '--getsz', block_device]) | 33 | dev_end = check_output(['blockdev', '--getsz', |
817 | 34 | block_device]).decode('UTF-8') | ||
818 | 34 | gpt_end = int(dev_end.split()[0]) - 100 | 35 | gpt_end = int(dev_end.split()[0]) - 100 |
819 | 35 | check_call(['dd', 'if=/dev/zero', 'of=%s' % (block_device), | 36 | check_call(['dd', 'if=/dev/zero', 'of=%s' % (block_device), |
820 | 36 | 'bs=1M', 'count=1']) | 37 | 'bs=1M', 'count=1']) |
821 | @@ -47,7 +48,7 @@ | |||
822 | 47 | it doesn't. | 48 | it doesn't. |
823 | 48 | ''' | 49 | ''' |
824 | 49 | is_partition = bool(re.search(r".*[0-9]+\b", device)) | 50 | is_partition = bool(re.search(r".*[0-9]+\b", device)) |
826 | 50 | out = check_output(['mount']) | 51 | out = check_output(['mount']).decode('UTF-8') |
827 | 51 | if is_partition: | 52 | if is_partition: |
828 | 52 | return bool(re.search(device + r"\b", out)) | 53 | return bool(re.search(device + r"\b", out)) |
829 | 53 | return bool(re.search(device + r"[0-9]+\b", out)) | 54 | return bool(re.search(device + r"[0-9]+\b", out)) |
830 | 54 | 55 | ||
831 | === modified file 'charmhelpers/contrib/templating/contexts.py' | |||
832 | --- charmhelpers/contrib/templating/contexts.py 2014-11-25 14:35:22 +0000 | |||
833 | +++ charmhelpers/contrib/templating/contexts.py 2014-11-25 15:09:14 +0000 | |||
834 | @@ -6,6 +6,8 @@ | |||
835 | 6 | import os | 6 | import os |
836 | 7 | import yaml | 7 | import yaml |
837 | 8 | 8 | ||
838 | 9 | import six | ||
839 | 10 | |||
840 | 9 | import charmhelpers.core.hookenv | 11 | import charmhelpers.core.hookenv |
841 | 10 | 12 | ||
842 | 11 | 13 | ||
843 | @@ -92,9 +94,9 @@ | |||
844 | 92 | 94 | ||
845 | 93 | # Don't use non-standard tags for unicode which will not | 95 | # Don't use non-standard tags for unicode which will not |
846 | 94 | # work when salt uses yaml.load_safe. | 96 | # work when salt uses yaml.load_safe. |
850 | 95 | yaml.add_representer(unicode, lambda dumper, | 97 | yaml.add_representer(six.text_type, |
851 | 96 | value: dumper.represent_scalar( | 98 | lambda dumper, value: dumper.represent_scalar( |
852 | 97 | u'tag:yaml.org,2002:str', value)) | 99 | six.u('tag:yaml.org,2002:str'), value)) |
853 | 98 | 100 | ||
854 | 99 | yaml_dir = os.path.dirname(yaml_path) | 101 | yaml_dir = os.path.dirname(yaml_path) |
855 | 100 | if not os.path.exists(yaml_dir): | 102 | if not os.path.exists(yaml_dir): |
856 | 101 | 103 | ||
857 | === modified file 'charmhelpers/core/fstab.py' | |||
858 | --- charmhelpers/core/fstab.py 2014-11-25 14:35:22 +0000 | |||
859 | +++ charmhelpers/core/fstab.py 2014-11-25 15:09:14 +0000 | |||
860 | @@ -3,10 +3,11 @@ | |||
861 | 3 | 3 | ||
862 | 4 | __author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>' | 4 | __author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>' |
863 | 5 | 5 | ||
864 | 6 | import io | ||
865 | 6 | import os | 7 | import os |
866 | 7 | 8 | ||
867 | 8 | 9 | ||
869 | 9 | class Fstab(file): | 10 | class Fstab(io.FileIO): |
870 | 10 | """This class extends file in order to implement a file reader/writer | 11 | """This class extends file in order to implement a file reader/writer |
871 | 11 | for file `/etc/fstab` | 12 | for file `/etc/fstab` |
872 | 12 | """ | 13 | """ |
873 | @@ -24,8 +25,8 @@ | |||
874 | 24 | options = "defaults" | 25 | options = "defaults" |
875 | 25 | 26 | ||
876 | 26 | self.options = options | 27 | self.options = options |
879 | 27 | self.d = d | 28 | self.d = int(d) |
880 | 28 | self.p = p | 29 | self.p = int(p) |
881 | 29 | 30 | ||
882 | 30 | def __eq__(self, o): | 31 | def __eq__(self, o): |
883 | 31 | return str(self) == str(o) | 32 | return str(self) == str(o) |
884 | @@ -45,7 +46,7 @@ | |||
885 | 45 | self._path = path | 46 | self._path = path |
886 | 46 | else: | 47 | else: |
887 | 47 | self._path = self.DEFAULT_PATH | 48 | self._path = self.DEFAULT_PATH |
889 | 48 | file.__init__(self, self._path, 'r+') | 49 | super(Fstab, self).__init__(self._path, 'rb+') |
890 | 49 | 50 | ||
891 | 50 | def _hydrate_entry(self, line): | 51 | def _hydrate_entry(self, line): |
892 | 51 | # NOTE: use split with no arguments to split on any | 52 | # NOTE: use split with no arguments to split on any |
893 | @@ -58,8 +59,9 @@ | |||
894 | 58 | def entries(self): | 59 | def entries(self): |
895 | 59 | self.seek(0) | 60 | self.seek(0) |
896 | 60 | for line in self.readlines(): | 61 | for line in self.readlines(): |
897 | 62 | line = line.decode('us-ascii') | ||
898 | 61 | try: | 63 | try: |
900 | 62 | if not line.startswith("#"): | 64 | if line.strip() and not line.startswith("#"): |
901 | 63 | yield self._hydrate_entry(line) | 65 | yield self._hydrate_entry(line) |
902 | 64 | except ValueError: | 66 | except ValueError: |
903 | 65 | pass | 67 | pass |
904 | @@ -75,14 +77,14 @@ | |||
905 | 75 | if self.get_entry_by_attr('device', entry.device): | 77 | if self.get_entry_by_attr('device', entry.device): |
906 | 76 | return False | 78 | return False |
907 | 77 | 79 | ||
909 | 78 | self.write(str(entry) + '\n') | 80 | self.write((str(entry) + '\n').encode('us-ascii')) |
910 | 79 | self.truncate() | 81 | self.truncate() |
911 | 80 | return entry | 82 | return entry |
912 | 81 | 83 | ||
913 | 82 | def remove_entry(self, entry): | 84 | def remove_entry(self, entry): |
914 | 83 | self.seek(0) | 85 | self.seek(0) |
915 | 84 | 86 | ||
917 | 85 | lines = self.readlines() | 87 | lines = [l.decode('us-ascii') for l in self.readlines()] |
918 | 86 | 88 | ||
919 | 87 | found = False | 89 | found = False |
920 | 88 | for index, line in enumerate(lines): | 90 | for index, line in enumerate(lines): |
921 | @@ -97,7 +99,7 @@ | |||
922 | 97 | lines.remove(line) | 99 | lines.remove(line) |
923 | 98 | 100 | ||
924 | 99 | self.seek(0) | 101 | self.seek(0) |
926 | 100 | self.write(''.join(lines)) | 102 | self.write(''.join(lines).encode('us-ascii')) |
927 | 101 | self.truncate() | 103 | self.truncate() |
928 | 102 | return True | 104 | return True |
929 | 103 | 105 | ||
930 | 104 | 106 | ||
931 | === modified file 'charmhelpers/core/hookenv.py' | |||
932 | --- charmhelpers/core/hookenv.py 2014-11-25 14:35:22 +0000 | |||
933 | +++ charmhelpers/core/hookenv.py 2014-11-25 15:09:14 +0000 | |||
934 | @@ -9,9 +9,14 @@ | |||
935 | 9 | import yaml | 9 | import yaml |
936 | 10 | import subprocess | 10 | import subprocess |
937 | 11 | import sys | 11 | import sys |
938 | 12 | import UserDict | ||
939 | 13 | from subprocess import CalledProcessError | 12 | from subprocess import CalledProcessError |
940 | 14 | 13 | ||
941 | 14 | import six | ||
942 | 15 | if not six.PY3: | ||
943 | 16 | from UserDict import UserDict | ||
944 | 17 | else: | ||
945 | 18 | from collections import UserDict | ||
946 | 19 | |||
947 | 15 | CRITICAL = "CRITICAL" | 20 | CRITICAL = "CRITICAL" |
948 | 16 | ERROR = "ERROR" | 21 | ERROR = "ERROR" |
949 | 17 | WARNING = "WARNING" | 22 | WARNING = "WARNING" |
950 | @@ -67,12 +72,12 @@ | |||
951 | 67 | subprocess.call(command) | 72 | subprocess.call(command) |
952 | 68 | 73 | ||
953 | 69 | 74 | ||
955 | 70 | class Serializable(UserDict.IterableUserDict): | 75 | class Serializable(UserDict): |
956 | 71 | """Wrapper, an object that can be serialized to yaml or json""" | 76 | """Wrapper, an object that can be serialized to yaml or json""" |
957 | 72 | 77 | ||
958 | 73 | def __init__(self, obj): | 78 | def __init__(self, obj): |
959 | 74 | # wrap the object | 79 | # wrap the object |
961 | 75 | UserDict.IterableUserDict.__init__(self) | 80 | UserDict.__init__(self) |
962 | 76 | self.data = obj | 81 | self.data = obj |
963 | 77 | 82 | ||
964 | 78 | def __getattr__(self, attr): | 83 | def __getattr__(self, attr): |
965 | @@ -218,7 +223,7 @@ | |||
966 | 218 | prev_keys = [] | 223 | prev_keys = [] |
967 | 219 | if self._prev_dict is not None: | 224 | if self._prev_dict is not None: |
968 | 220 | prev_keys = self._prev_dict.keys() | 225 | prev_keys = self._prev_dict.keys() |
970 | 221 | return list(set(prev_keys + dict.keys(self))) | 226 | return list(set(prev_keys + list(dict.keys(self)))) |
971 | 222 | 227 | ||
972 | 223 | def load_previous(self, path=None): | 228 | def load_previous(self, path=None): |
973 | 224 | """Load previous copy of config from disk. | 229 | """Load previous copy of config from disk. |
974 | @@ -269,7 +274,7 @@ | |||
975 | 269 | 274 | ||
976 | 270 | """ | 275 | """ |
977 | 271 | if self._prev_dict: | 276 | if self._prev_dict: |
979 | 272 | for k, v in self._prev_dict.iteritems(): | 277 | for k, v in six.iteritems(self._prev_dict): |
980 | 273 | if k not in self: | 278 | if k not in self: |
981 | 274 | self[k] = v | 279 | self[k] = v |
982 | 275 | with open(self.path, 'w') as f: | 280 | with open(self.path, 'w') as f: |
983 | @@ -284,7 +289,8 @@ | |||
984 | 284 | config_cmd_line.append(scope) | 289 | config_cmd_line.append(scope) |
985 | 285 | config_cmd_line.append('--format=json') | 290 | config_cmd_line.append('--format=json') |
986 | 286 | try: | 291 | try: |
988 | 287 | config_data = json.loads(subprocess.check_output(config_cmd_line)) | 292 | config_data = json.loads( |
989 | 293 | subprocess.check_output(config_cmd_line).decode('UTF-8')) | ||
990 | 288 | if scope is not None: | 294 | if scope is not None: |
991 | 289 | return config_data | 295 | return config_data |
992 | 290 | return Config(config_data) | 296 | return Config(config_data) |
993 | @@ -303,10 +309,10 @@ | |||
994 | 303 | if unit: | 309 | if unit: |
995 | 304 | _args.append(unit) | 310 | _args.append(unit) |
996 | 305 | try: | 311 | try: |
998 | 306 | return json.loads(subprocess.check_output(_args)) | 312 | return json.loads(subprocess.check_output(_args).decode('UTF-8')) |
999 | 307 | except ValueError: | 313 | except ValueError: |
1000 | 308 | return None | 314 | return None |
1002 | 309 | except CalledProcessError, e: | 315 | except CalledProcessError as e: |
1003 | 310 | if e.returncode == 2: | 316 | if e.returncode == 2: |
1004 | 311 | return None | 317 | return None |
1005 | 312 | raise | 318 | raise |
1006 | @@ -318,7 +324,7 @@ | |||
1007 | 318 | relation_cmd_line = ['relation-set'] | 324 | relation_cmd_line = ['relation-set'] |
1008 | 319 | if relation_id is not None: | 325 | if relation_id is not None: |
1009 | 320 | relation_cmd_line.extend(('-r', relation_id)) | 326 | relation_cmd_line.extend(('-r', relation_id)) |
1011 | 321 | for k, v in (relation_settings.items() + kwargs.items()): | 327 | for k, v in (list(relation_settings.items()) + list(kwargs.items())): |
1012 | 322 | if v is None: | 328 | if v is None: |
1013 | 323 | relation_cmd_line.append('{}='.format(k)) | 329 | relation_cmd_line.append('{}='.format(k)) |
1014 | 324 | else: | 330 | else: |
1015 | @@ -335,7 +341,8 @@ | |||
1016 | 335 | relid_cmd_line = ['relation-ids', '--format=json'] | 341 | relid_cmd_line = ['relation-ids', '--format=json'] |
1017 | 336 | if reltype is not None: | 342 | if reltype is not None: |
1018 | 337 | relid_cmd_line.append(reltype) | 343 | relid_cmd_line.append(reltype) |
1020 | 338 | return json.loads(subprocess.check_output(relid_cmd_line)) or [] | 344 | return json.loads( |
1021 | 345 | subprocess.check_output(relid_cmd_line).decode('UTF-8')) or [] | ||
1022 | 339 | return [] | 346 | return [] |
1023 | 340 | 347 | ||
1024 | 341 | 348 | ||
1025 | @@ -346,7 +353,8 @@ | |||
1026 | 346 | units_cmd_line = ['relation-list', '--format=json'] | 353 | units_cmd_line = ['relation-list', '--format=json'] |
1027 | 347 | if relid is not None: | 354 | if relid is not None: |
1028 | 348 | units_cmd_line.extend(('-r', relid)) | 355 | units_cmd_line.extend(('-r', relid)) |
1030 | 349 | return json.loads(subprocess.check_output(units_cmd_line)) or [] | 356 | return json.loads( |
1031 | 357 | subprocess.check_output(units_cmd_line).decode('UTF-8')) or [] | ||
1032 | 350 | 358 | ||
1033 | 351 | 359 | ||
1034 | 352 | @cached | 360 | @cached |
1035 | @@ -455,7 +463,7 @@ | |||
1036 | 455 | """Get the unit ID for the remote unit""" | 463 | """Get the unit ID for the remote unit""" |
1037 | 456 | _args = ['unit-get', '--format=json', attribute] | 464 | _args = ['unit-get', '--format=json', attribute] |
1038 | 457 | try: | 465 | try: |
1040 | 458 | return json.loads(subprocess.check_output(_args)) | 466 | return json.loads(subprocess.check_output(_args).decode('UTF-8')) |
1041 | 459 | except ValueError: | 467 | except ValueError: |
1042 | 460 | return None | 468 | return None |
1043 | 461 | 469 | ||
1044 | 462 | 470 | ||
1045 | === modified file 'charmhelpers/core/host.py' | |||
1046 | --- charmhelpers/core/host.py 2014-11-25 14:35:22 +0000 | |||
1047 | +++ charmhelpers/core/host.py 2014-11-25 15:09:14 +0000 | |||
1048 | @@ -14,11 +14,12 @@ | |||
1049 | 14 | import subprocess | 14 | import subprocess |
1050 | 15 | import hashlib | 15 | import hashlib |
1051 | 16 | from contextlib import contextmanager | 16 | from contextlib import contextmanager |
1052 | 17 | |||
1053 | 18 | from collections import OrderedDict | 17 | from collections import OrderedDict |
1054 | 19 | 18 | ||
1057 | 20 | from hookenv import log | 19 | import six |
1058 | 21 | from fstab import Fstab | 20 | |
1059 | 21 | from .hookenv import log | ||
1060 | 22 | from .fstab import Fstab | ||
1061 | 22 | 23 | ||
1062 | 23 | 24 | ||
1063 | 24 | def service_start(service_name): | 25 | def service_start(service_name): |
1064 | @@ -54,7 +55,9 @@ | |||
1065 | 54 | def service_running(service): | 55 | def service_running(service): |
1066 | 55 | """Determine whether a system service is running""" | 56 | """Determine whether a system service is running""" |
1067 | 56 | try: | 57 | try: |
1069 | 57 | output = subprocess.check_output(['service', service, 'status'], stderr=subprocess.STDOUT) | 58 | output = subprocess.check_output( |
1070 | 59 | ['service', service, 'status'], | ||
1071 | 60 | stderr=subprocess.STDOUT).decode('UTF-8') | ||
1072 | 58 | except subprocess.CalledProcessError: | 61 | except subprocess.CalledProcessError: |
1073 | 59 | return False | 62 | return False |
1074 | 60 | else: | 63 | else: |
1075 | @@ -67,7 +70,9 @@ | |||
1076 | 67 | def service_available(service_name): | 70 | def service_available(service_name): |
1077 | 68 | """Determine whether a system service is available""" | 71 | """Determine whether a system service is available""" |
1078 | 69 | try: | 72 | try: |
1080 | 70 | subprocess.check_output(['service', service_name, 'status'], stderr=subprocess.STDOUT) | 73 | subprocess.check_output( |
1081 | 74 | ['service', service_name, 'status'], | ||
1082 | 75 | stderr=subprocess.STDOUT).decode('UTF-8') | ||
1083 | 71 | except subprocess.CalledProcessError as e: | 76 | except subprocess.CalledProcessError as e: |
1084 | 72 | return 'unrecognized service' not in e.output | 77 | return 'unrecognized service' not in e.output |
1085 | 73 | else: | 78 | else: |
1086 | @@ -115,7 +120,7 @@ | |||
1087 | 115 | cmd.append(from_path) | 120 | cmd.append(from_path) |
1088 | 116 | cmd.append(to_path) | 121 | cmd.append(to_path) |
1089 | 117 | log(" ".join(cmd)) | 122 | log(" ".join(cmd)) |
1091 | 118 | return subprocess.check_output(cmd).strip() | 123 | return subprocess.check_output(cmd).decode('UTF-8').strip() |
1092 | 119 | 124 | ||
1093 | 120 | 125 | ||
1094 | 121 | def symlink(source, destination): | 126 | def symlink(source, destination): |
1095 | @@ -130,7 +135,7 @@ | |||
1096 | 130 | subprocess.check_call(cmd) | 135 | subprocess.check_call(cmd) |
1097 | 131 | 136 | ||
1098 | 132 | 137 | ||
1100 | 133 | def mkdir(path, owner='root', group='root', perms=0555, force=False): | 138 | def mkdir(path, owner='root', group='root', perms=0o555, force=False): |
1101 | 134 | """Create a directory""" | 139 | """Create a directory""" |
1102 | 135 | log("Making dir {} {}:{} {:o}".format(path, owner, group, | 140 | log("Making dir {} {}:{} {:o}".format(path, owner, group, |
1103 | 136 | perms)) | 141 | perms)) |
1104 | @@ -146,7 +151,7 @@ | |||
1105 | 146 | os.chown(realpath, uid, gid) | 151 | os.chown(realpath, uid, gid) |
1106 | 147 | 152 | ||
1107 | 148 | 153 | ||
1109 | 149 | def write_file(path, content, owner='root', group='root', perms=0444): | 154 | def write_file(path, content, owner='root', group='root', perms=0o444): |
1110 | 150 | """Create or overwrite a file with the contents of a string""" | 155 | """Create or overwrite a file with the contents of a string""" |
1111 | 151 | log("Writing file {} {}:{} {:o}".format(path, owner, group, perms)) | 156 | log("Writing file {} {}:{} {:o}".format(path, owner, group, perms)) |
1112 | 152 | uid = pwd.getpwnam(owner).pw_uid | 157 | uid = pwd.getpwnam(owner).pw_uid |
1113 | @@ -177,7 +182,7 @@ | |||
1114 | 177 | cmd_args.extend([device, mountpoint]) | 182 | cmd_args.extend([device, mountpoint]) |
1115 | 178 | try: | 183 | try: |
1116 | 179 | subprocess.check_output(cmd_args) | 184 | subprocess.check_output(cmd_args) |
1118 | 180 | except subprocess.CalledProcessError, e: | 185 | except subprocess.CalledProcessError as e: |
1119 | 181 | log('Error mounting {} at {}\n{}'.format(device, mountpoint, e.output)) | 186 | log('Error mounting {} at {}\n{}'.format(device, mountpoint, e.output)) |
1120 | 182 | return False | 187 | return False |
1121 | 183 | 188 | ||
1122 | @@ -191,7 +196,7 @@ | |||
1123 | 191 | cmd_args = ['umount', mountpoint] | 196 | cmd_args = ['umount', mountpoint] |
1124 | 192 | try: | 197 | try: |
1125 | 193 | subprocess.check_output(cmd_args) | 198 | subprocess.check_output(cmd_args) |
1127 | 194 | except subprocess.CalledProcessError, e: | 199 | except subprocess.CalledProcessError as e: |
1128 | 195 | log('Error unmounting {}\n{}'.format(mountpoint, e.output)) | 200 | log('Error unmounting {}\n{}'.format(mountpoint, e.output)) |
1129 | 196 | return False | 201 | return False |
1130 | 197 | 202 | ||
1131 | @@ -218,8 +223,8 @@ | |||
1132 | 218 | """ | 223 | """ |
1133 | 219 | if os.path.exists(path): | 224 | if os.path.exists(path): |
1134 | 220 | h = getattr(hashlib, hash_type)() | 225 | h = getattr(hashlib, hash_type)() |
1137 | 221 | with open(path, 'r') as source: | 226 | with open(path, 'rb') as source: |
1138 | 222 | h.update(source.read()) # IGNORE:E1101 - it does have update | 227 | h.update(source.read()) |
1139 | 223 | return h.hexdigest() | 228 | return h.hexdigest() |
1140 | 224 | else: | 229 | else: |
1141 | 225 | return None | 230 | return None |
1142 | @@ -297,7 +302,7 @@ | |||
1143 | 297 | if length is None: | 302 | if length is None: |
1144 | 298 | length = random.choice(range(35, 45)) | 303 | length = random.choice(range(35, 45)) |
1145 | 299 | alphanumeric_chars = [ | 304 | alphanumeric_chars = [ |
1147 | 300 | l for l in (string.letters + string.digits) | 305 | l for l in (string.ascii_letters + string.digits) |
1148 | 301 | if l not in 'l0QD1vAEIOUaeiou'] | 306 | if l not in 'l0QD1vAEIOUaeiou'] |
1149 | 302 | random_chars = [ | 307 | random_chars = [ |
1150 | 303 | random.choice(alphanumeric_chars) for _ in range(length)] | 308 | random.choice(alphanumeric_chars) for _ in range(length)] |
1151 | @@ -306,14 +311,14 @@ | |||
1152 | 306 | 311 | ||
1153 | 307 | def list_nics(nic_type): | 312 | def list_nics(nic_type): |
1154 | 308 | '''Return a list of nics of given type(s)''' | 313 | '''Return a list of nics of given type(s)''' |
1156 | 309 | if isinstance(nic_type, basestring): | 314 | if isinstance(nic_type, six.string_types): |
1157 | 310 | int_types = [nic_type] | 315 | int_types = [nic_type] |
1158 | 311 | else: | 316 | else: |
1159 | 312 | int_types = nic_type | 317 | int_types = nic_type |
1160 | 313 | interfaces = [] | 318 | interfaces = [] |
1161 | 314 | for int_type in int_types: | 319 | for int_type in int_types: |
1162 | 315 | cmd = ['ip', 'addr', 'show', 'label', int_type + '*'] | 320 | cmd = ['ip', 'addr', 'show', 'label', int_type + '*'] |
1164 | 316 | ip_output = subprocess.check_output(cmd).split('\n') | 321 | ip_output = subprocess.check_output(cmd).decode('UTF-8').split('\n') |
1165 | 317 | ip_output = (line for line in ip_output if line) | 322 | ip_output = (line for line in ip_output if line) |
1166 | 318 | for line in ip_output: | 323 | for line in ip_output: |
1167 | 319 | if line.split()[1].startswith(int_type): | 324 | if line.split()[1].startswith(int_type): |
1168 | @@ -335,7 +340,7 @@ | |||
1169 | 335 | 340 | ||
1170 | 336 | def get_nic_mtu(nic): | 341 | def get_nic_mtu(nic): |
1171 | 337 | cmd = ['ip', 'addr', 'show', nic] | 342 | cmd = ['ip', 'addr', 'show', nic] |
1173 | 338 | ip_output = subprocess.check_output(cmd).split('\n') | 343 | ip_output = subprocess.check_output(cmd).decode('UTF-8').split('\n') |
1174 | 339 | mtu = "" | 344 | mtu = "" |
1175 | 340 | for line in ip_output: | 345 | for line in ip_output: |
1176 | 341 | words = line.split() | 346 | words = line.split() |
1177 | @@ -346,7 +351,7 @@ | |||
1178 | 346 | 351 | ||
1179 | 347 | def get_nic_hwaddr(nic): | 352 | def get_nic_hwaddr(nic): |
1180 | 348 | cmd = ['ip', '-o', '-0', 'addr', 'show', nic] | 353 | cmd = ['ip', '-o', '-0', 'addr', 'show', nic] |
1182 | 349 | ip_output = subprocess.check_output(cmd) | 354 | ip_output = subprocess.check_output(cmd).decode('UTF-8') |
1183 | 350 | hwaddr = "" | 355 | hwaddr = "" |
1184 | 351 | words = ip_output.split() | 356 | words = ip_output.split() |
1185 | 352 | if 'link/ether' in words: | 357 | if 'link/ether' in words: |
1186 | 353 | 358 | ||
1187 | === modified file 'charmhelpers/core/services/helpers.py' | |||
1188 | --- charmhelpers/core/services/helpers.py 2014-11-25 14:35:22 +0000 | |||
1189 | +++ charmhelpers/core/services/helpers.py 2014-11-25 15:09:14 +0000 | |||
1190 | @@ -196,7 +196,7 @@ | |||
1191 | 196 | if not os.path.isabs(file_name): | 196 | if not os.path.isabs(file_name): |
1192 | 197 | file_name = os.path.join(hookenv.charm_dir(), file_name) | 197 | file_name = os.path.join(hookenv.charm_dir(), file_name) |
1193 | 198 | with open(file_name, 'w') as file_stream: | 198 | with open(file_name, 'w') as file_stream: |
1195 | 199 | os.fchmod(file_stream.fileno(), 0600) | 199 | os.fchmod(file_stream.fileno(), 0o600) |
1196 | 200 | yaml.dump(config_data, file_stream) | 200 | yaml.dump(config_data, file_stream) |
1197 | 201 | 201 | ||
1198 | 202 | def read_context(self, file_name): | 202 | def read_context(self, file_name): |
1199 | @@ -211,15 +211,19 @@ | |||
1200 | 211 | 211 | ||
1201 | 212 | class TemplateCallback(ManagerCallback): | 212 | class TemplateCallback(ManagerCallback): |
1202 | 213 | """ | 213 | """ |
1206 | 214 | Callback class that will render a Jinja2 template, for use as a ready action. | 214 | Callback class that will render a Jinja2 template, for use as a ready |
1207 | 215 | 215 | action. | |
1208 | 216 | :param str source: The template source file, relative to `$CHARM_DIR/templates` | 216 | |
1209 | 217 | :param str source: The template source file, relative to | ||
1210 | 218 | `$CHARM_DIR/templates` | ||
1211 | 219 | |||
1212 | 217 | :param str target: The target to write the rendered template to | 220 | :param str target: The target to write the rendered template to |
1213 | 218 | :param str owner: The owner of the rendered file | 221 | :param str owner: The owner of the rendered file |
1214 | 219 | :param str group: The group of the rendered file | 222 | :param str group: The group of the rendered file |
1215 | 220 | :param int perms: The permissions of the rendered file | 223 | :param int perms: The permissions of the rendered file |
1216 | 221 | """ | 224 | """ |
1218 | 222 | def __init__(self, source, target, owner='root', group='root', perms=0444): | 225 | def __init__(self, source, target, |
1219 | 226 | owner='root', group='root', perms=0o444): | ||
1220 | 223 | self.source = source | 227 | self.source = source |
1221 | 224 | self.target = target | 228 | self.target = target |
1222 | 225 | self.owner = owner | 229 | self.owner = owner |
1223 | 226 | 230 | ||
1224 | === modified file 'charmhelpers/core/templating.py' | |||
1225 | --- charmhelpers/core/templating.py 2014-11-25 14:35:22 +0000 | |||
1226 | +++ charmhelpers/core/templating.py 2014-11-25 15:09:14 +0000 | |||
1227 | @@ -4,7 +4,8 @@ | |||
1228 | 4 | from charmhelpers.core import hookenv | 4 | from charmhelpers.core import hookenv |
1229 | 5 | 5 | ||
1230 | 6 | 6 | ||
1232 | 7 | def render(source, target, context, owner='root', group='root', perms=0444, templates_dir=None): | 7 | def render(source, target, context, owner='root', group='root', |
1233 | 8 | perms=0o444, templates_dir=None): | ||
1234 | 8 | """ | 9 | """ |
1235 | 9 | Render a template. | 10 | Render a template. |
1236 | 10 | 11 | ||
1237 | 11 | 12 | ||
1238 | === modified file 'charmhelpers/fetch/__init__.py' | |||
1239 | --- charmhelpers/fetch/__init__.py 2014-11-25 14:35:22 +0000 | |||
1240 | +++ charmhelpers/fetch/__init__.py 2014-11-25 15:09:14 +0000 | |||
1241 | @@ -5,10 +5,6 @@ | |||
1242 | 5 | from charmhelpers.core.host import ( | 5 | from charmhelpers.core.host import ( |
1243 | 6 | lsb_release | 6 | lsb_release |
1244 | 7 | ) | 7 | ) |
1245 | 8 | from urlparse import ( | ||
1246 | 9 | urlparse, | ||
1247 | 10 | urlunparse, | ||
1248 | 11 | ) | ||
1249 | 12 | import subprocess | 8 | import subprocess |
1250 | 13 | from charmhelpers.core.hookenv import ( | 9 | from charmhelpers.core.hookenv import ( |
1251 | 14 | config, | 10 | config, |
1252 | @@ -16,6 +12,12 @@ | |||
1253 | 16 | ) | 12 | ) |
1254 | 17 | import os | 13 | import os |
1255 | 18 | 14 | ||
1256 | 15 | import six | ||
1257 | 16 | if six.PY3: | ||
1258 | 17 | from urllib.parse import urlparse, urlunparse | ||
1259 | 18 | else: | ||
1260 | 19 | from urlparse import urlparse, urlunparse | ||
1261 | 20 | |||
1262 | 19 | 21 | ||
1263 | 20 | CLOUD_ARCHIVE = """# Ubuntu Cloud Archive | 22 | CLOUD_ARCHIVE = """# Ubuntu Cloud Archive |
1264 | 21 | deb http://ubuntu-cloud.archive.canonical.com/ubuntu {} main | 23 | deb http://ubuntu-cloud.archive.canonical.com/ubuntu {} main |
1265 | @@ -149,7 +151,7 @@ | |||
1266 | 149 | cmd = ['apt-get', '--assume-yes'] | 151 | cmd = ['apt-get', '--assume-yes'] |
1267 | 150 | cmd.extend(options) | 152 | cmd.extend(options) |
1268 | 151 | cmd.append('install') | 153 | cmd.append('install') |
1270 | 152 | if isinstance(packages, basestring): | 154 | if isinstance(packages, six.string_types): |
1271 | 153 | cmd.append(packages) | 155 | cmd.append(packages) |
1272 | 154 | else: | 156 | else: |
1273 | 155 | cmd.extend(packages) | 157 | cmd.extend(packages) |
1274 | @@ -182,7 +184,7 @@ | |||
1275 | 182 | def apt_purge(packages, fatal=False): | 184 | def apt_purge(packages, fatal=False): |
1276 | 183 | """Purge one or more packages""" | 185 | """Purge one or more packages""" |
1277 | 184 | cmd = ['apt-get', '--assume-yes', 'purge'] | 186 | cmd = ['apt-get', '--assume-yes', 'purge'] |
1279 | 185 | if isinstance(packages, basestring): | 187 | if isinstance(packages, six.string_types): |
1280 | 186 | cmd.append(packages) | 188 | cmd.append(packages) |
1281 | 187 | else: | 189 | else: |
1282 | 188 | cmd.extend(packages) | 190 | cmd.extend(packages) |
1283 | @@ -193,7 +195,7 @@ | |||
1284 | 193 | def apt_hold(packages, fatal=False): | 195 | def apt_hold(packages, fatal=False): |
1285 | 194 | """Hold one or more packages""" | 196 | """Hold one or more packages""" |
1286 | 195 | cmd = ['apt-mark', 'hold'] | 197 | cmd = ['apt-mark', 'hold'] |
1288 | 196 | if isinstance(packages, basestring): | 198 | if isinstance(packages, six.string_types): |
1289 | 197 | cmd.append(packages) | 199 | cmd.append(packages) |
1290 | 198 | else: | 200 | else: |
1291 | 199 | cmd.extend(packages) | 201 | cmd.extend(packages) |
1292 | @@ -260,7 +262,7 @@ | |||
1293 | 260 | 262 | ||
1294 | 261 | if key: | 263 | if key: |
1295 | 262 | if '-----BEGIN PGP PUBLIC KEY BLOCK-----' in key: | 264 | if '-----BEGIN PGP PUBLIC KEY BLOCK-----' in key: |
1297 | 263 | with NamedTemporaryFile() as key_file: | 265 | with NamedTemporaryFile('w+') as key_file: |
1298 | 264 | key_file.write(key) | 266 | key_file.write(key) |
1299 | 265 | key_file.flush() | 267 | key_file.flush() |
1300 | 266 | key_file.seek(0) | 268 | key_file.seek(0) |
1301 | @@ -297,14 +299,14 @@ | |||
1302 | 297 | sources = safe_load((config(sources_var) or '').strip()) or [] | 299 | sources = safe_load((config(sources_var) or '').strip()) or [] |
1303 | 298 | keys = safe_load((config(keys_var) or '').strip()) or None | 300 | keys = safe_load((config(keys_var) or '').strip()) or None |
1304 | 299 | 301 | ||
1306 | 300 | if isinstance(sources, basestring): | 302 | if isinstance(sources, six.string_types): |
1307 | 301 | sources = [sources] | 303 | sources = [sources] |
1308 | 302 | 304 | ||
1309 | 303 | if keys is None: | 305 | if keys is None: |
1310 | 304 | for source in sources: | 306 | for source in sources: |
1311 | 305 | add_source(source, None) | 307 | add_source(source, None) |
1312 | 306 | else: | 308 | else: |
1314 | 307 | if isinstance(keys, basestring): | 309 | if isinstance(keys, six.string_types): |
1315 | 308 | keys = [keys] | 310 | keys = [keys] |
1316 | 309 | 311 | ||
1317 | 310 | if len(sources) != len(keys): | 312 | if len(sources) != len(keys): |
1318 | @@ -401,7 +403,7 @@ | |||
1319 | 401 | while result is None or result == APT_NO_LOCK: | 403 | while result is None or result == APT_NO_LOCK: |
1320 | 402 | try: | 404 | try: |
1321 | 403 | result = subprocess.check_call(cmd, env=env) | 405 | result = subprocess.check_call(cmd, env=env) |
1323 | 404 | except subprocess.CalledProcessError, e: | 406 | except subprocess.CalledProcessError as e: |
1324 | 405 | retry_count = retry_count + 1 | 407 | retry_count = retry_count + 1 |
1325 | 406 | if retry_count > APT_NO_LOCK_RETRY_COUNT: | 408 | if retry_count > APT_NO_LOCK_RETRY_COUNT: |
1326 | 407 | raise | 409 | raise |
1327 | 408 | 410 | ||
1328 | === modified file 'charmhelpers/fetch/archiveurl.py' | |||
1329 | --- charmhelpers/fetch/archiveurl.py 2014-11-25 14:35:22 +0000 | |||
1330 | +++ charmhelpers/fetch/archiveurl.py 2014-11-25 15:09:14 +0000 | |||
1331 | @@ -1,8 +1,23 @@ | |||
1332 | 1 | import os | 1 | import os |
1333 | 2 | import urllib2 | ||
1334 | 3 | from urllib import urlretrieve | ||
1335 | 4 | import urlparse | ||
1336 | 5 | import hashlib | 2 | import hashlib |
1337 | 3 | import re | ||
1338 | 4 | |||
1339 | 5 | import six | ||
1340 | 6 | if six.PY3: | ||
1341 | 7 | from urllib.request import ( | ||
1342 | 8 | build_opener, install_opener, urlopen, urlretrieve, | ||
1343 | 9 | HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, | ||
1344 | 10 | ) | ||
1345 | 11 | from urllib.parse import urlparse, urlunparse, parse_qs | ||
1346 | 12 | from urllib.error import URLError | ||
1347 | 13 | else: | ||
1348 | 14 | from urllib import urlretrieve | ||
1349 | 15 | from urllib2 import ( | ||
1350 | 16 | build_opener, install_opener, urlopen, | ||
1351 | 17 | HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, | ||
1352 | 18 | URLError | ||
1353 | 19 | ) | ||
1354 | 20 | from urlparse import urlparse, urlunparse, parse_qs | ||
1355 | 6 | 21 | ||
1356 | 7 | from charmhelpers.fetch import ( | 22 | from charmhelpers.fetch import ( |
1357 | 8 | BaseFetchHandler, | 23 | BaseFetchHandler, |
1358 | @@ -15,6 +30,24 @@ | |||
1359 | 15 | from charmhelpers.core.host import mkdir, check_hash | 30 | from charmhelpers.core.host import mkdir, check_hash |
1360 | 16 | 31 | ||
1361 | 17 | 32 | ||
1362 | 33 | def splituser(host): | ||
1363 | 34 | '''urllib.splituser(), but six's support of this seems broken''' | ||
1364 | 35 | _userprog = re.compile('^(.*)@(.*)$') | ||
1365 | 36 | match = _userprog.match(host) | ||
1366 | 37 | if match: | ||
1367 | 38 | return match.group(1, 2) | ||
1368 | 39 | return None, host | ||
1369 | 40 | |||
1370 | 41 | |||
1371 | 42 | def splitpasswd(user): | ||
1372 | 43 | '''urllib.splitpasswd(), but six's support of this is missing''' | ||
1373 | 44 | _passwdprog = re.compile('^([^:]*):(.*)$', re.S) | ||
1374 | 45 | match = _passwdprog.match(user) | ||
1375 | 46 | if match: | ||
1376 | 47 | return match.group(1, 2) | ||
1377 | 48 | return user, None | ||
1378 | 49 | |||
1379 | 50 | |||
1380 | 18 | class ArchiveUrlFetchHandler(BaseFetchHandler): | 51 | class ArchiveUrlFetchHandler(BaseFetchHandler): |
1381 | 19 | """ | 52 | """ |
1382 | 20 | Handler to download archive files from arbitrary URLs. | 53 | Handler to download archive files from arbitrary URLs. |
1383 | @@ -42,20 +75,20 @@ | |||
1384 | 42 | """ | 75 | """ |
1385 | 43 | # propogate all exceptions | 76 | # propogate all exceptions |
1386 | 44 | # URLError, OSError, etc | 77 | # URLError, OSError, etc |
1388 | 45 | proto, netloc, path, params, query, fragment = urlparse.urlparse(source) | 78 | proto, netloc, path, params, query, fragment = urlparse(source) |
1389 | 46 | if proto in ('http', 'https'): | 79 | if proto in ('http', 'https'): |
1391 | 47 | auth, barehost = urllib2.splituser(netloc) | 80 | auth, barehost = splituser(netloc) |
1392 | 48 | if auth is not None: | 81 | if auth is not None: |
1396 | 49 | source = urlparse.urlunparse((proto, barehost, path, params, query, fragment)) | 82 | source = urlunparse((proto, barehost, path, params, query, fragment)) |
1397 | 50 | username, password = urllib2.splitpasswd(auth) | 83 | username, password = splitpasswd(auth) |
1398 | 51 | passman = urllib2.HTTPPasswordMgrWithDefaultRealm() | 84 | passman = HTTPPasswordMgrWithDefaultRealm() |
1399 | 52 | # Realm is set to None in add_password to force the username and password | 85 | # Realm is set to None in add_password to force the username and password |
1400 | 53 | # to be used whatever the realm | 86 | # to be used whatever the realm |
1401 | 54 | passman.add_password(None, source, username, password) | 87 | passman.add_password(None, source, username, password) |
1406 | 55 | authhandler = urllib2.HTTPBasicAuthHandler(passman) | 88 | authhandler = HTTPBasicAuthHandler(passman) |
1407 | 56 | opener = urllib2.build_opener(authhandler) | 89 | opener = build_opener(authhandler) |
1408 | 57 | urllib2.install_opener(opener) | 90 | install_opener(opener) |
1409 | 58 | response = urllib2.urlopen(source) | 91 | response = urlopen(source) |
1410 | 59 | try: | 92 | try: |
1411 | 60 | with open(dest, 'w') as dest_file: | 93 | with open(dest, 'w') as dest_file: |
1412 | 61 | dest_file.write(response.read()) | 94 | dest_file.write(response.read()) |
1413 | @@ -91,17 +124,21 @@ | |||
1414 | 91 | url_parts = self.parse_url(source) | 124 | url_parts = self.parse_url(source) |
1415 | 92 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), 'fetched') | 125 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), 'fetched') |
1416 | 93 | if not os.path.exists(dest_dir): | 126 | if not os.path.exists(dest_dir): |
1418 | 94 | mkdir(dest_dir, perms=0755) | 127 | mkdir(dest_dir, perms=0o755) |
1419 | 95 | dld_file = os.path.join(dest_dir, os.path.basename(url_parts.path)) | 128 | dld_file = os.path.join(dest_dir, os.path.basename(url_parts.path)) |
1420 | 96 | try: | 129 | try: |
1421 | 97 | self.download(source, dld_file) | 130 | self.download(source, dld_file) |
1423 | 98 | except urllib2.URLError as e: | 131 | except URLError as e: |
1424 | 99 | raise UnhandledSource(e.reason) | 132 | raise UnhandledSource(e.reason) |
1425 | 100 | except OSError as e: | 133 | except OSError as e: |
1426 | 101 | raise UnhandledSource(e.strerror) | 134 | raise UnhandledSource(e.strerror) |
1428 | 102 | options = urlparse.parse_qs(url_parts.fragment) | 135 | options = parse_qs(url_parts.fragment) |
1429 | 103 | for key, value in options.items(): | 136 | for key, value in options.items(): |
1431 | 104 | if key in hashlib.algorithms: | 137 | if not six.PY3: |
1432 | 138 | algorithms = hashlib.algorithms | ||
1433 | 139 | else: | ||
1434 | 140 | algorithms = hashlib.algorithms_available | ||
1435 | 141 | if key in algorithms: | ||
1436 | 105 | check_hash(dld_file, value, key) | 142 | check_hash(dld_file, value, key) |
1437 | 106 | if checksum: | 143 | if checksum: |
1438 | 107 | check_hash(dld_file, checksum, hash_type) | 144 | check_hash(dld_file, checksum, hash_type) |
1439 | 108 | 145 | ||
1440 | === modified file 'charmhelpers/fetch/bzrurl.py' | |||
1441 | --- charmhelpers/fetch/bzrurl.py 2014-11-25 14:35:22 +0000 | |||
1442 | +++ charmhelpers/fetch/bzrurl.py 2014-11-25 15:09:14 +0000 | |||
1443 | @@ -5,6 +5,10 @@ | |||
1444 | 5 | ) | 5 | ) |
1445 | 6 | from charmhelpers.core.host import mkdir | 6 | from charmhelpers.core.host import mkdir |
1446 | 7 | 7 | ||
1447 | 8 | import six | ||
1448 | 9 | if six.PY3: | ||
1449 | 10 | raise ImportError('bzrlib does not support Python3') | ||
1450 | 11 | |||
1451 | 8 | try: | 12 | try: |
1452 | 9 | from bzrlib.branch import Branch | 13 | from bzrlib.branch import Branch |
1453 | 10 | except ImportError: | 14 | except ImportError: |
1454 | @@ -42,7 +46,7 @@ | |||
1455 | 42 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", | 46 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", |
1456 | 43 | branch_name) | 47 | branch_name) |
1457 | 44 | if not os.path.exists(dest_dir): | 48 | if not os.path.exists(dest_dir): |
1459 | 45 | mkdir(dest_dir, perms=0755) | 49 | mkdir(dest_dir, perms=0o755) |
1460 | 46 | try: | 50 | try: |
1461 | 47 | self.branch(source, dest_dir) | 51 | self.branch(source, dest_dir) |
1462 | 48 | except OSError as e: | 52 | except OSError as e: |
1463 | 49 | 53 | ||
1464 | === modified file 'charmhelpers/fetch/giturl.py' | |||
1465 | --- charmhelpers/fetch/giturl.py 2014-11-25 14:35:22 +0000 | |||
1466 | +++ charmhelpers/fetch/giturl.py 2014-11-25 15:09:14 +0000 | |||
1467 | @@ -5,6 +5,10 @@ | |||
1468 | 5 | ) | 5 | ) |
1469 | 6 | from charmhelpers.core.host import mkdir | 6 | from charmhelpers.core.host import mkdir |
1470 | 7 | 7 | ||
1471 | 8 | import six | ||
1472 | 9 | if six.PY3: | ||
1473 | 10 | raise ImportError('GitPython does not support Python 3') | ||
1474 | 11 | |||
1475 | 8 | try: | 12 | try: |
1476 | 9 | from git import Repo | 13 | from git import Repo |
1477 | 10 | except ImportError: | 14 | except ImportError: |
1478 | @@ -17,7 +21,7 @@ | |||
1479 | 17 | """Handler for git branches via generic and github URLs""" | 21 | """Handler for git branches via generic and github URLs""" |
1480 | 18 | def can_handle(self, source): | 22 | def can_handle(self, source): |
1481 | 19 | url_parts = self.parse_url(source) | 23 | url_parts = self.parse_url(source) |
1483 | 20 | #TODO (mattyw) no support for ssh git@ yet | 24 | # TODO (mattyw) no support for ssh git@ yet |
1484 | 21 | if url_parts.scheme not in ('http', 'https', 'git'): | 25 | if url_parts.scheme not in ('http', 'https', 'git'): |
1485 | 22 | return False | 26 | return False |
1486 | 23 | else: | 27 | else: |
1487 | @@ -36,7 +40,7 @@ | |||
1488 | 36 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", | 40 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", |
1489 | 37 | branch_name) | 41 | branch_name) |
1490 | 38 | if not os.path.exists(dest_dir): | 42 | if not os.path.exists(dest_dir): |
1492 | 39 | mkdir(dest_dir, perms=0755) | 43 | mkdir(dest_dir, perms=0o755) |
1493 | 40 | try: | 44 | try: |
1494 | 41 | self.clone(source, dest_dir, branch) | 45 | self.clone(source, dest_dir, branch) |
1495 | 42 | except OSError as e: | 46 | except OSError as e: |
1496 | 43 | 47 | ||
1497 | === modified file 'test_requirements.txt' | |||
1498 | --- test_requirements.txt 2014-11-25 14:35:22 +0000 | |||
1499 | +++ test_requirements.txt 2014-11-25 15:09:14 +0000 | |||
1500 | @@ -1,18 +1,17 @@ | |||
1519 | 1 | coverage==3.6 | 1 | # Test-only dependencies are unpinned. |
1520 | 2 | launchpadlib==1.10.2 | 2 | # |
1521 | 3 | --allow-external launchpadlib | 3 | pip |
1522 | 4 | --allow-unverified launchpadlib | 4 | distribute |
1523 | 5 | mock==1.0.1 | 5 | coverage>=3.6 |
1524 | 6 | netaddr | 6 | mock>=1.0.1 |
1525 | 7 | nose==1.3.1 | 7 | nose>=1.3.1 |
1526 | 8 | PyYAML==3.10 | 8 | flake8 |
1527 | 9 | simplejson==3.3.0 | 9 | testtools==0.9.14 # Before dependent on modern 'six' |
1528 | 10 | testtools | 10 | # |
1529 | 11 | Tempita==0.5.1 | 11 | # Specify precise versions of runtime dependencies where possible. |
1530 | 12 | bzr+http://bazaar.launchpad.net/~yellow/python-shelltoolbox/trunk@17#egg=shelltoolbox | 12 | netaddr==0.7.10 # trusty. precise is 0.7.5, but not in pypi. |
1531 | 13 | http://alastairs-place.net/projects/netifaces/netifaces-0.6.tar.gz | 13 | PyYAML==3.10 # precise |
1532 | 14 | bzr==2.6.0 | 14 | Tempita==0.5.1 # precise |
1533 | 15 | GitPython>=0.3.2.RC1 | 15 | netifaces==0.10 # trusty is 0.8, but using py3 compatible version for tests. |
1534 | 16 | Jinja2==2.7.2 | 16 | Jinja2==2.6 # precise |
1535 | 17 | --allow-external lazr.authentication | 17 | six==1.1 # precise |
1518 | 18 | --allow-unverified lazr.authentication | ||
1536 | 19 | 18 | ||
1537 | === modified file 'tests/cli/test_cmdline.py' | |||
1538 | --- tests/cli/test_cmdline.py 2014-11-25 14:35:22 +0000 | |||
1539 | +++ tests/cli/test_cmdline.py 2014-11-25 15:09:14 +0000 | |||
1540 | @@ -6,15 +6,13 @@ | |||
1541 | 6 | patch, | 6 | patch, |
1542 | 7 | MagicMock, | 7 | MagicMock, |
1543 | 8 | ) | 8 | ) |
1544 | 9 | try: | ||
1545 | 10 | from cStringIO import StringIO | ||
1546 | 11 | except ImportError: | ||
1547 | 12 | from StringIO import StringIO | ||
1548 | 13 | import json | 9 | import json |
1549 | 14 | from pprint import pformat | 10 | from pprint import pformat |
1550 | 15 | import yaml | 11 | import yaml |
1551 | 16 | import csv | 12 | import csv |
1552 | 17 | 13 | ||
1553 | 14 | from six import StringIO | ||
1554 | 15 | |||
1555 | 18 | from charmhelpers import cli | 16 | from charmhelpers import cli |
1556 | 19 | 17 | ||
1557 | 20 | 18 | ||
1558 | @@ -116,7 +114,8 @@ | |||
1559 | 116 | self.output_data = {"this": "is", "some": 1, "data": dict()} | 114 | self.output_data = {"this": "is", "some": 1, "data": dict()} |
1560 | 117 | 115 | ||
1561 | 118 | def test_supports_formats(self): | 116 | def test_supports_formats(self): |
1563 | 119 | self.assertItemsEqual(self.expected_formats, self.of.supported_formats) | 117 | self.assertEqual(sorted(self.expected_formats), |
1564 | 118 | sorted(self.of.supported_formats)) | ||
1565 | 120 | 119 | ||
1566 | 121 | def test_adds_arguments(self): | 120 | def test_adds_arguments(self): |
1567 | 122 | ap = MagicMock() | 121 | ap = MagicMock() |
1568 | @@ -130,11 +129,12 @@ | |||
1569 | 130 | 129 | ||
1570 | 131 | for call_args in add_arg.call_args_list: | 130 | for call_args in add_arg.call_args_list: |
1571 | 132 | if "--format" in call_args[0]: | 131 | if "--format" in call_args[0]: |
1573 | 133 | self.assertItemsEqual(call_args[1]['choices'], self.expected_formats) | 132 | self.assertEqual(sorted(call_args[1]['choices']), |
1574 | 133 | sorted(self.expected_formats)) | ||
1575 | 134 | self.assertEqual(call_args[1]['default'], 'raw') | 134 | self.assertEqual(call_args[1]['default'], 'raw') |
1576 | 135 | break | 135 | break |
1577 | 136 | else: | 136 | else: |
1579 | 137 | print arg_group.call_args_list | 137 | print(arg_group.call_args_list) |
1580 | 138 | self.fail("No --format argument was created") | 138 | self.fail("No --format argument was created") |
1581 | 139 | 139 | ||
1582 | 140 | all_args = [c[0][0] for c in add_arg.call_args_list] | 140 | all_args = [c[0][0] for c in add_arg.call_args_list] |
1583 | 141 | 141 | ||
1584 | === modified file 'tests/cli/test_function_signature_analysis.py' | |||
1585 | --- tests/cli/test_function_signature_analysis.py 2013-08-21 21:40:07 +0000 | |||
1586 | +++ tests/cli/test_function_signature_analysis.py 2014-11-25 15:09:14 +0000 | |||
1587 | @@ -1,7 +1,7 @@ | |||
1588 | 1 | """Tests for the commandant code that analyzes a function signature to | 1 | """Tests for the commandant code that analyzes a function signature to |
1589 | 2 | determine the parameters to argparse.""" | 2 | determine the parameters to argparse.""" |
1590 | 3 | 3 | ||
1592 | 4 | from testtools import TestCase, matchers | 4 | from testtools import TestCase |
1593 | 5 | 5 | ||
1594 | 6 | from charmhelpers import cli | 6 | from charmhelpers import cli |
1595 | 7 | 7 | ||
1596 | @@ -42,5 +42,5 @@ | |||
1597 | 42 | args = cli.describe_arguments(lambda x, y=3, *z, **missing: False) | 42 | args = cli.describe_arguments(lambda x, y=3, *z, **missing: False) |
1598 | 43 | for opts, _ in args: | 43 | for opts, _ in args: |
1599 | 44 | # opts should be ('varname',) at this point | 44 | # opts should be ('varname',) at this point |
1601 | 45 | self.assertThat(opts, matchers.HasLength(1)) | 45 | self.assertTrue(len(opts) == 1) |
1602 | 46 | self.assertNotIn('missing', opts) | 46 | self.assertNotIn('missing', opts) |
1603 | 47 | 47 | ||
1604 | === modified file 'tests/contrib/charmhelpers/test_charmhelpers.py' | |||
1605 | --- tests/contrib/charmhelpers/test_charmhelpers.py 2014-11-25 14:35:22 +0000 | |||
1606 | +++ tests/contrib/charmhelpers/test_charmhelpers.py 2014-11-25 15:09:14 +0000 | |||
1607 | @@ -2,10 +2,10 @@ | |||
1608 | 2 | 2 | ||
1609 | 3 | import unittest | 3 | import unittest |
1610 | 4 | import yaml | 4 | import yaml |
1611 | 5 | |||
1612 | 6 | from StringIO import StringIO | ||
1613 | 7 | from testtools import TestCase | 5 | from testtools import TestCase |
1614 | 8 | 6 | ||
1615 | 7 | from six import StringIO | ||
1616 | 8 | |||
1617 | 9 | import sys | 9 | import sys |
1618 | 10 | # Path hack to ensure we test the local code, not a version installed in | 10 | # Path hack to ensure we test the local code, not a version installed in |
1619 | 11 | # /usr/local/lib. This is necessary since /usr/local/lib is prepended before | 11 | # /usr/local/lib. This is necessary since /usr/local/lib is prepended before |
1620 | @@ -265,11 +265,11 @@ | |||
1621 | 265 | # wait_for_page_contents() will wait until a given string is | 265 | # wait_for_page_contents() will wait until a given string is |
1622 | 266 | # contained within the results of a given url and will return | 266 | # contained within the results of a given url and will return |
1623 | 267 | # once it does. | 267 | # once it does. |
1625 | 268 | # We need to patch the charmhelpers instance of urllib2 so that | 268 | # We need to patch the charmhelpers instance of urlopen so that |
1626 | 269 | # it doesn't try to connect out. | 269 | # it doesn't try to connect out. |
1627 | 270 | test_content = "Hello, world." | 270 | test_content = "Hello, world." |
1628 | 271 | new_urlopen = lambda *args: StringIO(test_content) | 271 | new_urlopen = lambda *args: StringIO(test_content) |
1630 | 272 | self.patch(charmhelpers.urllib2, 'urlopen', new_urlopen) | 272 | self.patch(charmhelpers, 'urlopen', new_urlopen) |
1631 | 273 | charmhelpers.wait_for_page_contents( | 273 | charmhelpers.wait_for_page_contents( |
1632 | 274 | 'http://example.com', test_content, timeout=0) | 274 | 'http://example.com', test_content, timeout=0) |
1633 | 275 | 275 | ||
1634 | @@ -277,10 +277,10 @@ | |||
1635 | 277 | # If the desired contents do not appear within the page before | 277 | # If the desired contents do not appear within the page before |
1636 | 278 | # the specified timeout, wait_for_page_contents() will raise a | 278 | # the specified timeout, wait_for_page_contents() will raise a |
1637 | 279 | # RuntimeError. | 279 | # RuntimeError. |
1639 | 280 | # We need to patch the charmhelpers instance of urllib2 so that | 280 | # We need to patch the charmhelpers instance of urlopen so that |
1640 | 281 | # it doesn't try to connect out. | 281 | # it doesn't try to connect out. |
1641 | 282 | new_urlopen = lambda *args: StringIO("This won't work.") | 282 | new_urlopen = lambda *args: StringIO("This won't work.") |
1643 | 283 | self.patch(charmhelpers.urllib2, 'urlopen', new_urlopen) | 283 | self.patch(charmhelpers, 'urlopen', new_urlopen) |
1644 | 284 | self.assertRaises( | 284 | self.assertRaises( |
1645 | 285 | RuntimeError, charmhelpers.wait_for_page_contents, | 285 | RuntimeError, charmhelpers.wait_for_page_contents, |
1646 | 286 | 'http://example.com', "This will error", timeout=0) | 286 | 'http://example.com', "This will error", timeout=0) |
1647 | 287 | 287 | ||
1648 | === modified file 'tests/contrib/hahelpers/test_cluster_utils.py' | |||
1649 | --- tests/contrib/hahelpers/test_cluster_utils.py 2014-09-24 09:42:52 +0000 | |||
1650 | +++ tests/contrib/hahelpers/test_cluster_utils.py 2014-11-25 15:09:14 +0000 | |||
1651 | @@ -44,7 +44,7 @@ | |||
1652 | 44 | def test_is_crm_leader(self, check_output): | 44 | def test_is_crm_leader(self, check_output): |
1653 | 45 | '''It determines its unit is leader''' | 45 | '''It determines its unit is leader''' |
1654 | 46 | self.get_unit_hostname.return_value = 'node1' | 46 | self.get_unit_hostname.return_value = 'node1' |
1656 | 47 | crm = 'resource vip is running on: node1' | 47 | crm = b'resource vip is running on: node1' |
1657 | 48 | check_output.return_value = crm | 48 | check_output.return_value = crm |
1658 | 49 | self.assertTrue(cluster_utils.is_crm_leader('vip')) | 49 | self.assertTrue(cluster_utils.is_crm_leader('vip')) |
1659 | 50 | 50 | ||
1660 | @@ -52,7 +52,7 @@ | |||
1661 | 52 | def test_is_not_leader(self, check_output): | 52 | def test_is_not_leader(self, check_output): |
1662 | 53 | '''It determines its unit is not leader''' | 53 | '''It determines its unit is not leader''' |
1663 | 54 | self.get_unit_hostname.return_value = 'node1' | 54 | self.get_unit_hostname.return_value = 'node1' |
1665 | 55 | crm = 'resource vip is running on: node2' | 55 | crm = b'resource vip is running on: node2' |
1666 | 56 | check_output.return_value = crm | 56 | check_output.return_value = crm |
1667 | 57 | self.assertFalse(cluster_utils.is_crm_leader('some_resource')) | 57 | self.assertFalse(cluster_utils.is_crm_leader('some_resource')) |
1668 | 58 | 58 | ||
1669 | 59 | 59 | ||
1670 | === modified file 'tests/contrib/network/test_ip.py' | |||
1671 | --- tests/contrib/network/test_ip.py 2014-11-25 14:35:22 +0000 | |||
1672 | +++ tests/contrib/network/test_ip.py 2014-11-25 15:09:14 +0000 | |||
1673 | @@ -59,7 +59,7 @@ | |||
1674 | 59 | }, | 59 | }, |
1675 | 60 | } | 60 | } |
1676 | 61 | 61 | ||
1678 | 62 | IP_OUTPUT = """link/ether fa:16:3e:2a:cc:ce brd ff:ff:ff:ff:ff:ff | 62 | IP_OUTPUT = b"""link/ether fa:16:3e:2a:cc:ce brd ff:ff:ff:ff:ff:ff |
1679 | 63 | inet 10.5.16.93/16 brd 10.5.255.255 scope global eth0 | 63 | inet 10.5.16.93/16 brd 10.5.255.255 scope global eth0 |
1680 | 64 | valid_lft forever preferred_lft forever | 64 | valid_lft forever preferred_lft forever |
1681 | 65 | inet6 2001:db8:1:0:d0cf:528c:23eb:6000/64 scope global | 65 | inet6 2001:db8:1:0:d0cf:528c:23eb:6000/64 scope global |
1682 | @@ -72,7 +72,7 @@ | |||
1683 | 72 | valid_lft forever preferred_lft forever | 72 | valid_lft forever preferred_lft forever |
1684 | 73 | """ | 73 | """ |
1685 | 74 | 74 | ||
1687 | 75 | IP_OUTPUT_NO_VALID = """link/ether fa:16:3e:2a:cc:ce brd ff:ff:ff:ff:ff:ff | 75 | IP_OUTPUT_NO_VALID = b"""link/ether fa:16:3e:2a:cc:ce brd ff:ff:ff:ff:ff:ff |
1688 | 76 | inet 10.5.16.93/16 brd 10.5.255.255 scope global eth0 | 76 | inet 10.5.16.93/16 brd 10.5.255.255 scope global eth0 |
1689 | 77 | valid_lft forever preferred_lft forever | 77 | valid_lft forever preferred_lft forever |
1690 | 78 | inet6 2001:db8:1:0:2918:3444:852:5b8a/64 scope global temporary dynamic | 78 | inet6 2001:db8:1:0:2918:3444:852:5b8a/64 scope global temporary dynamic |
1691 | @@ -100,13 +100,14 @@ | |||
1692 | 100 | return DUMMY_ADDRESSES[iface] | 100 | return DUMMY_ADDRESSES[iface] |
1693 | 101 | 101 | ||
1694 | 102 | with mock.patch.object(netifaces, 'interfaces') as interfaces: | 102 | with mock.patch.object(netifaces, 'interfaces') as interfaces: |
1696 | 103 | interfaces.return_value = DUMMY_ADDRESSES.keys() | 103 | interfaces.return_value = sorted(DUMMY_ADDRESSES.keys()) |
1697 | 104 | with mock.patch.object(netifaces, 'ifaddresses') as ifaddresses: | 104 | with mock.patch.object(netifaces, 'ifaddresses') as ifaddresses: |
1698 | 105 | ifaddresses.side_effect = side_effect | 105 | ifaddresses.side_effect = side_effect |
1699 | 106 | if not fatal: | 106 | if not fatal: |
1700 | 107 | self.assertEqual(expect_ip_addr, | 107 | self.assertEqual(expect_ip_addr, |
1703 | 108 | net_ip.get_address_in_network( | 108 | net_ip.get_address_in_network(network, |
1704 | 109 | network, fallback, fatal)) | 109 | fallback, |
1705 | 110 | fatal)) | ||
1706 | 110 | else: | 111 | else: |
1707 | 111 | net_ip.get_address_in_network(network, fallback, fatal) | 112 | net_ip.get_address_in_network(network, fallback, fatal) |
1708 | 112 | 113 | ||
1709 | @@ -122,7 +123,7 @@ | |||
1710 | 122 | None, None, fatal=True) | 123 | None, None, fatal=True) |
1711 | 123 | 124 | ||
1712 | 124 | def test_get_address_in_network_ipv4(self): | 125 | def test_get_address_in_network_ipv4(self): |
1714 | 125 | self._test_get_address_in_network('192.168.1.56', '192.168.1.0/24') | 126 | self._test_get_address_in_network('192.168.1.55', '192.168.1.0/24') |
1715 | 126 | 127 | ||
1716 | 127 | def test_get_address_in_network_ipv6(self): | 128 | def test_get_address_in_network_ipv6(self): |
1717 | 128 | self._test_get_address_in_network('2a01:348:2f4:0:685e:5748:ae62:209f', | 129 | self._test_get_address_in_network('2a01:348:2f4:0:685e:5748:ae62:209f', |
1718 | @@ -260,7 +261,7 @@ | |||
1719 | 260 | mock_get_iface_from_addr): | 261 | mock_get_iface_from_addr): |
1720 | 261 | mock_get_iface_from_addr.return_value = 'eth0' | 262 | mock_get_iface_from_addr.return_value = 'eth0' |
1721 | 262 | mock_check_out.return_value = \ | 263 | mock_check_out.return_value = \ |
1723 | 263 | "inet6 2a01:348:2f4:0:685e:5748:ae62:209f/64 scope global dynamic" | 264 | b"inet6 2a01:348:2f4:0:685e:5748:ae62:209f/64 scope global dynamic" |
1724 | 264 | _interfaces.return_value = DUMMY_ADDRESSES.keys() | 265 | _interfaces.return_value = DUMMY_ADDRESSES.keys() |
1725 | 265 | _ifaddresses.side_effect = DUMMY_ADDRESSES.__getitem__ | 266 | _ifaddresses.side_effect = DUMMY_ADDRESSES.__getitem__ |
1726 | 266 | result = net_ip.get_ipv6_addr(dynamic_only=False) | 267 | result = net_ip.get_ipv6_addr(dynamic_only=False) |
1727 | @@ -275,7 +276,7 @@ | |||
1728 | 275 | mock_get_iface_from_addr): | 276 | mock_get_iface_from_addr): |
1729 | 276 | mock_get_iface_from_addr.return_value = 'eth0' | 277 | mock_get_iface_from_addr.return_value = 'eth0' |
1730 | 277 | mock_check_out.return_value = \ | 278 | mock_check_out.return_value = \ |
1732 | 278 | "inet6 2a01:348:2f4:0:685e:5748:ae62:209f/64 scope global dynamic" | 279 | b"inet6 2a01:348:2f4:0:685e:5748:ae62:209f/64 scope global dynamic" |
1733 | 279 | _interfaces.return_value = DUMMY_ADDRESSES.keys() | 280 | _interfaces.return_value = DUMMY_ADDRESSES.keys() |
1734 | 280 | _ifaddresses.side_effect = DUMMY_ADDRESSES.__getitem__ | 281 | _ifaddresses.side_effect = DUMMY_ADDRESSES.__getitem__ |
1735 | 281 | result = net_ip.get_ipv6_addr(dynamic_only=False) | 282 | result = net_ip.get_ipv6_addr(dynamic_only=False) |
1736 | @@ -494,9 +495,9 @@ | |||
1737 | 494 | def test_get_iface_from_addr(self, mock_log, mock_ifaddresses, | 495 | def test_get_iface_from_addr(self, mock_log, mock_ifaddresses, |
1738 | 495 | mock_interfaces): | 496 | mock_interfaces): |
1739 | 496 | mock_ifaddresses.side_effect = lambda iface: DUMMY_ADDRESSES[iface] | 497 | mock_ifaddresses.side_effect = lambda iface: DUMMY_ADDRESSES[iface] |
1741 | 497 | mock_interfaces.return_value = DUMMY_ADDRESSES.keys() | 498 | mock_interfaces.return_value = sorted(DUMMY_ADDRESSES.keys()) |
1742 | 498 | addr = 'fe80::3e97:eff:fe8b:1cf7' | 499 | addr = 'fe80::3e97:eff:fe8b:1cf7' |
1744 | 499 | self.assertEqual(net_ip.get_iface_from_addr(addr), 'eth1') | 500 | self.assertEqual(net_ip.get_iface_from_addr(addr), 'eth0') |
1745 | 500 | 501 | ||
1746 | 501 | with nose.tools.assert_raises(Exception): | 502 | with nose.tools.assert_raises(Exception): |
1747 | 502 | net_ip.get_iface_from_addr('1.2.3.4') | 503 | net_ip.get_iface_from_addr('1.2.3.4') |
1748 | 503 | 504 | ||
1749 | === modified file 'tests/contrib/openstack/test_neutron_utils.py' | |||
1750 | --- tests/contrib/openstack/test_neutron_utils.py 2014-11-07 09:54:33 +0000 | |||
1751 | +++ tests/contrib/openstack/test_neutron_utils.py 2014-11-25 15:09:14 +0000 | |||
1752 | @@ -23,12 +23,12 @@ | |||
1753 | 23 | return mock | 23 | return mock |
1754 | 24 | 24 | ||
1755 | 25 | def test_headers_package(self): | 25 | def test_headers_package(self): |
1757 | 26 | self.check_output.return_value = '3.13.0-19-generic' | 26 | self.check_output.return_value = b'3.13.0-19-generic' |
1758 | 27 | kname = neutron.headers_package() | 27 | kname = neutron.headers_package() |
1759 | 28 | self.assertEquals(kname, 'linux-headers-3.13.0-19-generic') | 28 | self.assertEquals(kname, 'linux-headers-3.13.0-19-generic') |
1760 | 29 | 29 | ||
1761 | 30 | def test_kernel_version(self): | 30 | def test_kernel_version(self): |
1763 | 31 | self.check_output.return_value = '3.13.0-19-generic' | 31 | self.check_output.return_value = b'3.13.0-19-generic' |
1764 | 32 | kver_maj, kver_min = neutron.kernel_version() | 32 | kver_maj, kver_min = neutron.kernel_version() |
1765 | 33 | self.assertEquals((kver_maj, kver_min), (3, 13)) | 33 | self.assertEquals((kver_maj, kver_min), (3, 13)) |
1766 | 34 | 34 | ||
1767 | 35 | 35 | ||
1768 | === modified file 'tests/contrib/openstack/test_openstack_utils.py' | |||
1769 | --- tests/contrib/openstack/test_openstack_utils.py 2014-11-25 14:35:22 +0000 | |||
1770 | +++ tests/contrib/openstack/test_openstack_utils.py 2014-11-25 15:09:14 +0000 | |||
1771 | @@ -1,13 +1,22 @@ | |||
1772 | 1 | import io | ||
1773 | 1 | import os | 2 | import os |
1774 | 2 | import subprocess | 3 | import subprocess |
1775 | 3 | import unittest | 4 | import unittest |
1776 | 4 | |||
1777 | 5 | from copy import copy | 5 | from copy import copy |
1778 | 6 | from testtools import TestCase | 6 | from testtools import TestCase |
1779 | 7 | from mock import MagicMock, patch, call | 7 | from mock import MagicMock, patch, call |
1780 | 8 | 8 | ||
1781 | 9 | import charmhelpers.contrib.openstack.utils as openstack | 9 | import charmhelpers.contrib.openstack.utils as openstack |
1782 | 10 | 10 | ||
1783 | 11 | import six | ||
1784 | 12 | |||
1785 | 13 | if not six.PY3: | ||
1786 | 14 | builtin_open = '__builtin__.open' | ||
1787 | 15 | builtin_import = '__builtin__.__import__' | ||
1788 | 16 | else: | ||
1789 | 17 | builtin_open = 'builtins.open' | ||
1790 | 18 | builtin_import = 'builtins.__import__' | ||
1791 | 19 | |||
1792 | 11 | # mocked return of openstack.lsb_release() | 20 | # mocked return of openstack.lsb_release() |
1793 | 12 | FAKE_RELEASE = { | 21 | FAKE_RELEASE = { |
1794 | 13 | 'DISTRIB_CODENAME': 'precise', | 22 | 'DISTRIB_CODENAME': 'precise', |
1795 | @@ -222,7 +231,7 @@ | |||
1796 | 222 | '''Test deriving OpenStack codename from an installed package''' | 231 | '''Test deriving OpenStack codename from an installed package''' |
1797 | 223 | with patch('apt_pkg.Cache') as cache: | 232 | with patch('apt_pkg.Cache') as cache: |
1798 | 224 | cache.return_value = self._apt_cache() | 233 | cache.return_value = self._apt_cache() |
1800 | 225 | for pkg, vers in FAKE_REPO.iteritems(): | 234 | for pkg, vers in six.iteritems(FAKE_REPO): |
1801 | 226 | # test fake repo for all "installed" packages | 235 | # test fake repo for all "installed" packages |
1802 | 227 | if pkg.startswith('bad-'): | 236 | if pkg.startswith('bad-'): |
1803 | 228 | continue | 237 | continue |
1804 | @@ -291,7 +300,7 @@ | |||
1805 | 291 | '''Test deriving OpenStack version from an installed package''' | 300 | '''Test deriving OpenStack version from an installed package''' |
1806 | 292 | with patch('apt_pkg.Cache') as cache: | 301 | with patch('apt_pkg.Cache') as cache: |
1807 | 293 | cache.return_value = self._apt_cache() | 302 | cache.return_value = self._apt_cache() |
1809 | 294 | for pkg, vers in FAKE_REPO.iteritems(): | 303 | for pkg, vers in six.iteritems(FAKE_REPO): |
1810 | 295 | if pkg.startswith('bad-'): | 304 | if pkg.startswith('bad-'): |
1811 | 296 | continue | 305 | continue |
1812 | 297 | if 'pkg_vers' not in vers: | 306 | if 'pkg_vers' not in vers: |
1813 | @@ -354,12 +363,12 @@ | |||
1814 | 354 | ex_cmd = ['add-apt-repository', '-y', 'ppa:gandelman-a/openstack'] | 363 | ex_cmd = ['add-apt-repository', '-y', 'ppa:gandelman-a/openstack'] |
1815 | 355 | mock.assert_called_with(ex_cmd) | 364 | mock.assert_called_with(ex_cmd) |
1816 | 356 | 365 | ||
1818 | 357 | @patch('__builtin__.open') | 366 | @patch(builtin_open) |
1819 | 358 | @patch('charmhelpers.contrib.openstack.utils.juju_log') | 367 | @patch('charmhelpers.contrib.openstack.utils.juju_log') |
1820 | 359 | @patch('charmhelpers.contrib.openstack.utils.import_key') | 368 | @patch('charmhelpers.contrib.openstack.utils.import_key') |
1821 | 360 | def test_configure_install_source_deb_url(self, _import, _log, _open): | 369 | def test_configure_install_source_deb_url(self, _import, _log, _open): |
1822 | 361 | '''Test configuring installation source from deb repo url''' | 370 | '''Test configuring installation source from deb repo url''' |
1824 | 362 | _file = MagicMock(spec=file) | 371 | _file = MagicMock(spec=io.FileIO) |
1825 | 363 | _open.return_value = _file | 372 | _open.return_value = _file |
1826 | 364 | src = ('deb http://ubuntu-cloud.archive.canonical.com/ubuntu ' | 373 | src = ('deb http://ubuntu-cloud.archive.canonical.com/ubuntu ' |
1827 | 365 | 'precise-havana main|KEYID') | 374 | 'precise-havana main|KEYID') |
1828 | @@ -372,12 +381,12 @@ | |||
1829 | 372 | _file.__enter__().write.assert_called_with(src) | 381 | _file.__enter__().write.assert_called_with(src) |
1830 | 373 | 382 | ||
1831 | 374 | @patch('charmhelpers.contrib.openstack.utils.lsb_release') | 383 | @patch('charmhelpers.contrib.openstack.utils.lsb_release') |
1833 | 375 | @patch('__builtin__.open') | 384 | @patch(builtin_open) |
1834 | 376 | @patch('charmhelpers.contrib.openstack.utils.juju_log') | 385 | @patch('charmhelpers.contrib.openstack.utils.juju_log') |
1835 | 377 | def test_configure_install_source_distro_proposed(self, _log, _open, _lsb): | 386 | def test_configure_install_source_distro_proposed(self, _log, _open, _lsb): |
1836 | 378 | '''Test configuring installation source from deb repo url''' | 387 | '''Test configuring installation source from deb repo url''' |
1837 | 379 | _lsb.return_value = FAKE_RELEASE | 388 | _lsb.return_value = FAKE_RELEASE |
1839 | 380 | _file = MagicMock(spec=file) | 389 | _file = MagicMock(spec=io.FileIO) |
1840 | 381 | _open.return_value = _file | 390 | _open.return_value = _file |
1841 | 382 | openstack.configure_installation_source('distro-proposed') | 391 | openstack.configure_installation_source('distro-proposed') |
1842 | 383 | src = ('deb http://archive.ubuntu.com/ubuntu/ precise-proposed ' | 392 | src = ('deb http://archive.ubuntu.com/ubuntu/ precise-proposed ' |
1843 | @@ -402,13 +411,13 @@ | |||
1844 | 402 | 'ppa:ubuntu-cloud-archive/folsom-staging'] | 411 | 'ppa:ubuntu-cloud-archive/folsom-staging'] |
1845 | 403 | _subp.assert_called_with(cmd) | 412 | _subp.assert_called_with(cmd) |
1846 | 404 | 413 | ||
1848 | 405 | @patch('__builtin__.open') | 414 | @patch(builtin_open) |
1849 | 406 | @patch('charmhelpers.contrib.openstack.utils.apt_install') | 415 | @patch('charmhelpers.contrib.openstack.utils.apt_install') |
1850 | 407 | @patch('charmhelpers.contrib.openstack.utils.lsb_release') | 416 | @patch('charmhelpers.contrib.openstack.utils.lsb_release') |
1851 | 408 | def test_configure_install_source_uca_repos(self, _lsb, _install, _open): | 417 | def test_configure_install_source_uca_repos(self, _lsb, _install, _open): |
1852 | 409 | '''Test configuring installation source from UCA sources''' | 418 | '''Test configuring installation source from UCA sources''' |
1853 | 410 | _lsb.return_value = FAKE_RELEASE | 419 | _lsb.return_value = FAKE_RELEASE |
1855 | 411 | _file = MagicMock(spec=file) | 420 | _file = MagicMock(spec=io.FileIO) |
1856 | 412 | _open.return_value = _file | 421 | _open.return_value = _file |
1857 | 413 | for src, url in UCA_SOURCES: | 422 | for src, url in UCA_SOURCES: |
1858 | 414 | openstack.configure_installation_source(src) | 423 | openstack.configure_installation_source(src) |
1859 | @@ -455,13 +464,13 @@ | |||
1860 | 455 | @patch('os.mkdir') | 464 | @patch('os.mkdir') |
1861 | 456 | @patch('os.path.exists') | 465 | @patch('os.path.exists') |
1862 | 457 | @patch('charmhelpers.contrib.openstack.utils.charm_dir') | 466 | @patch('charmhelpers.contrib.openstack.utils.charm_dir') |
1864 | 458 | @patch('__builtin__.open') | 467 | @patch(builtin_open) |
1865 | 459 | def test_save_scriptrc(self, _open, _charm_dir, _exists, _mkdir): | 468 | def test_save_scriptrc(self, _open, _charm_dir, _exists, _mkdir): |
1866 | 460 | '''Test generation of scriptrc from environment''' | 469 | '''Test generation of scriptrc from environment''' |
1867 | 461 | scriptrc = ['#!/bin/bash\n', | 470 | scriptrc = ['#!/bin/bash\n', |
1868 | 462 | 'export setting1=foo\n', | 471 | 'export setting1=foo\n', |
1869 | 463 | 'export setting2=bar\n'] | 472 | 'export setting2=bar\n'] |
1871 | 464 | _file = MagicMock(spec=file) | 473 | _file = MagicMock(spec=io.FileIO) |
1872 | 465 | _open.return_value = _file | 474 | _open.return_value = _file |
1873 | 466 | _charm_dir.return_value = '/var/lib/juju/units/testing-foo-0/charm' | 475 | _charm_dir.return_value = '/var/lib/juju/units/testing-foo-0/charm' |
1874 | 467 | _exists.return_value = False | 476 | _exists.return_value = False |
1875 | @@ -583,21 +592,21 @@ | |||
1876 | 583 | @patch.object(openstack, 'apt_install') | 592 | @patch.object(openstack, 'apt_install') |
1877 | 584 | def test_get_host_ip_with_hostname(self, apt_install): | 593 | def test_get_host_ip_with_hostname(self, apt_install): |
1878 | 585 | fake_dns = FakeDNS('10.0.0.1') | 594 | fake_dns = FakeDNS('10.0.0.1') |
1880 | 586 | with patch('__builtin__.__import__', side_effect=[fake_dns]): | 595 | with patch(builtin_import, side_effect=[fake_dns]): |
1881 | 587 | ip = openstack.get_host_ip('www.ubuntu.com') | 596 | ip = openstack.get_host_ip('www.ubuntu.com') |
1882 | 588 | self.assertEquals(ip, '10.0.0.1') | 597 | self.assertEquals(ip, '10.0.0.1') |
1883 | 589 | 598 | ||
1884 | 590 | @patch.object(openstack, 'apt_install') | 599 | @patch.object(openstack, 'apt_install') |
1885 | 591 | def test_get_host_ip_with_ip(self, apt_install): | 600 | def test_get_host_ip_with_ip(self, apt_install): |
1886 | 592 | fake_dns = FakeDNS('5.5.5.5') | 601 | fake_dns = FakeDNS('5.5.5.5') |
1888 | 593 | with patch('__builtin__.__import__', side_effect=[fake_dns]): | 602 | with patch(builtin_import, side_effect=[fake_dns]): |
1889 | 594 | ip = openstack.get_host_ip('4.2.2.1') | 603 | ip = openstack.get_host_ip('4.2.2.1') |
1890 | 595 | self.assertEquals(ip, '4.2.2.1') | 604 | self.assertEquals(ip, '4.2.2.1') |
1891 | 596 | 605 | ||
1892 | 597 | @patch.object(openstack, 'apt_install') | 606 | @patch.object(openstack, 'apt_install') |
1893 | 598 | def test_ns_query_trigger_apt_install(self, apt_install): | 607 | def test_ns_query_trigger_apt_install(self, apt_install): |
1894 | 599 | fake_dns = FakeDNS('5.5.5.5') | 608 | fake_dns = FakeDNS('5.5.5.5') |
1896 | 600 | with patch('__builtin__.__import__', side_effect=[ImportError, fake_dns]): | 609 | with patch(builtin_import, side_effect=[ImportError, fake_dns]): |
1897 | 601 | nsq = openstack.ns_query('5.5.5.5') | 610 | nsq = openstack.ns_query('5.5.5.5') |
1898 | 602 | apt_install.assert_called_with('python-dnspython') | 611 | apt_install.assert_called_with('python-dnspython') |
1899 | 603 | self.assertEquals(nsq, '5.5.5.5') | 612 | self.assertEquals(nsq, '5.5.5.5') |
1900 | @@ -605,7 +614,7 @@ | |||
1901 | 605 | @patch.object(openstack, 'apt_install') | 614 | @patch.object(openstack, 'apt_install') |
1902 | 606 | def test_ns_query_ptr_record(self, apt_install): | 615 | def test_ns_query_ptr_record(self, apt_install): |
1903 | 607 | fake_dns = FakeDNS('127.0.0.1') | 616 | fake_dns = FakeDNS('127.0.0.1') |
1905 | 608 | with patch('__builtin__.__import__', side_effect=[fake_dns]): | 617 | with patch(builtin_import, side_effect=[fake_dns]): |
1906 | 609 | nsq = openstack.ns_query('127.0.0.1') | 618 | nsq = openstack.ns_query('127.0.0.1') |
1907 | 610 | self.assertEquals(nsq, '127.0.0.1') | 619 | self.assertEquals(nsq, '127.0.0.1') |
1908 | 611 | 620 | ||
1909 | @@ -613,35 +622,35 @@ | |||
1910 | 613 | def test_ns_query_a_record(self, apt_install): | 622 | def test_ns_query_a_record(self, apt_install): |
1911 | 614 | fake_dns = FakeDNS('127.0.0.1') | 623 | fake_dns = FakeDNS('127.0.0.1') |
1912 | 615 | fake_dns_name = FakeDNSName('www.somedomain.tld') | 624 | fake_dns_name = FakeDNSName('www.somedomain.tld') |
1914 | 616 | with patch('__builtin__.__import__', side_effect=[fake_dns]): | 625 | with patch(builtin_import, side_effect=[fake_dns]): |
1915 | 617 | nsq = openstack.ns_query(fake_dns_name) | 626 | nsq = openstack.ns_query(fake_dns_name) |
1916 | 618 | self.assertEquals(nsq, '127.0.0.1') | 627 | self.assertEquals(nsq, '127.0.0.1') |
1917 | 619 | 628 | ||
1918 | 620 | @patch.object(openstack, 'apt_install') | 629 | @patch.object(openstack, 'apt_install') |
1919 | 621 | def test_ns_query_blank_record(self, apt_install): | 630 | def test_ns_query_blank_record(self, apt_install): |
1920 | 622 | fake_dns = FakeDNS(None) | 631 | fake_dns = FakeDNS(None) |
1922 | 623 | with patch('__builtin__.__import__', side_effect=[fake_dns, fake_dns]): | 632 | with patch(builtin_import, side_effect=[fake_dns, fake_dns]): |
1923 | 624 | nsq = openstack.ns_query(None) | 633 | nsq = openstack.ns_query(None) |
1924 | 625 | self.assertEquals(nsq, None) | 634 | self.assertEquals(nsq, None) |
1925 | 626 | 635 | ||
1926 | 627 | @patch.object(openstack, 'apt_install') | 636 | @patch.object(openstack, 'apt_install') |
1927 | 628 | def test_ns_query_lookup_fail(self, apt_install): | 637 | def test_ns_query_lookup_fail(self, apt_install): |
1928 | 629 | fake_dns = FakeDNS('') | 638 | fake_dns = FakeDNS('') |
1930 | 630 | with patch('__builtin__.__import__', side_effect=[fake_dns, fake_dns]): | 639 | with patch(builtin_import, side_effect=[fake_dns, fake_dns]): |
1931 | 631 | nsq = openstack.ns_query('nonexistant') | 640 | nsq = openstack.ns_query('nonexistant') |
1932 | 632 | self.assertEquals(nsq, None) | 641 | self.assertEquals(nsq, None) |
1933 | 633 | 642 | ||
1934 | 634 | @patch.object(openstack, 'apt_install') | 643 | @patch.object(openstack, 'apt_install') |
1935 | 635 | def test_get_hostname_with_ip(self, apt_install): | 644 | def test_get_hostname_with_ip(self, apt_install): |
1936 | 636 | fake_dns = FakeDNS('www.ubuntu.com') | 645 | fake_dns = FakeDNS('www.ubuntu.com') |
1938 | 637 | with patch('__builtin__.__import__', side_effect=[fake_dns, fake_dns]): | 646 | with patch(builtin_import, side_effect=[fake_dns, fake_dns]): |
1939 | 638 | hn = openstack.get_hostname('4.2.2.1') | 647 | hn = openstack.get_hostname('4.2.2.1') |
1940 | 639 | self.assertEquals(hn, 'www.ubuntu.com') | 648 | self.assertEquals(hn, 'www.ubuntu.com') |
1941 | 640 | 649 | ||
1942 | 641 | @patch.object(openstack, 'apt_install') | 650 | @patch.object(openstack, 'apt_install') |
1943 | 642 | def test_get_hostname_with_ip_not_fqdn(self, apt_install): | 651 | def test_get_hostname_with_ip_not_fqdn(self, apt_install): |
1944 | 643 | fake_dns = FakeDNS('packages.ubuntu.com') | 652 | fake_dns = FakeDNS('packages.ubuntu.com') |
1946 | 644 | with patch('__builtin__.__import__', side_effect=[fake_dns, fake_dns]): | 653 | with patch(builtin_import, side_effect=[fake_dns, fake_dns]): |
1947 | 645 | hn = openstack.get_hostname('4.2.2.1', fqdn=False) | 654 | hn = openstack.get_hostname('4.2.2.1', fqdn=False) |
1948 | 646 | self.assertEquals(hn, 'packages') | 655 | self.assertEquals(hn, 'packages') |
1949 | 647 | 656 | ||
1950 | @@ -663,7 +672,7 @@ | |||
1951 | 663 | @patch.object(openstack, 'apt_install') | 672 | @patch.object(openstack, 'apt_install') |
1952 | 664 | def test_get_hostname_trigger_apt_install(self, apt_install): | 673 | def test_get_hostname_trigger_apt_install(self, apt_install): |
1953 | 665 | fake_dns = FakeDNS('www.ubuntu.com') | 674 | fake_dns = FakeDNS('www.ubuntu.com') |
1955 | 666 | with patch('__builtin__.__import__', side_effect=[ImportError, fake_dns, fake_dns]): | 675 | with patch(builtin_import, side_effect=[ImportError, fake_dns, fake_dns]): |
1956 | 667 | hn = openstack.get_hostname('4.2.2.1') | 676 | hn = openstack.get_hostname('4.2.2.1') |
1957 | 668 | apt_install.assert_called_with('python-dnspython') | 677 | apt_install.assert_called_with('python-dnspython') |
1958 | 669 | self.assertEquals(hn, 'www.ubuntu.com') | 678 | self.assertEquals(hn, 'www.ubuntu.com') |
1959 | @@ -673,12 +682,12 @@ | |||
1960 | 673 | def test_get_hostname_lookup_fail(self, apt_install, ns_query): | 682 | def test_get_hostname_lookup_fail(self, apt_install, ns_query): |
1961 | 674 | fake_dns = FakeDNS('www.ubuntu.com') | 683 | fake_dns = FakeDNS('www.ubuntu.com') |
1962 | 675 | ns_query.return_value = [] | 684 | ns_query.return_value = [] |
1964 | 676 | with patch('__builtin__.__import__', side_effect=[fake_dns, fake_dns]): | 685 | with patch(builtin_import, side_effect=[fake_dns, fake_dns]): |
1965 | 677 | hn = openstack.get_hostname('4.2.2.1') | 686 | hn = openstack.get_hostname('4.2.2.1') |
1966 | 678 | self.assertEquals(hn, None) | 687 | self.assertEquals(hn, None) |
1967 | 679 | 688 | ||
1968 | 680 | @patch('os.path.isfile') | 689 | @patch('os.path.isfile') |
1970 | 681 | @patch('__builtin__.open') | 690 | @patch(builtin_open) |
1971 | 682 | def test_get_matchmaker_map(self, _open, _isfile): | 691 | def test_get_matchmaker_map(self, _open, _isfile): |
1972 | 683 | _isfile.return_value = True | 692 | _isfile.return_value = True |
1973 | 684 | mm_data = """ | 693 | mm_data = """ |
1974 | @@ -696,7 +705,7 @@ | |||
1975 | 696 | ) | 705 | ) |
1976 | 697 | 706 | ||
1977 | 698 | @patch('os.path.isfile') | 707 | @patch('os.path.isfile') |
1979 | 699 | @patch('__builtin__.open') | 708 | @patch(builtin_open) |
1980 | 700 | def test_get_matchmaker_map_nofile(self, _open, _isfile): | 709 | def test_get_matchmaker_map_nofile(self, _open, _isfile): |
1981 | 701 | _isfile.return_value = False | 710 | _isfile.return_value = False |
1982 | 702 | self.assertEqual( | 711 | self.assertEqual( |
1983 | 703 | 712 | ||
1984 | === modified file 'tests/contrib/openstack/test_os_contexts.py' | |||
1985 | --- tests/contrib/openstack/test_os_contexts.py 2014-11-25 14:35:22 +0000 | |||
1986 | +++ tests/contrib/openstack/test_os_contexts.py 2014-11-25 15:09:14 +0000 | |||
1987 | @@ -11,6 +11,13 @@ | |||
1988 | 11 | ) | 11 | ) |
1989 | 12 | from tests.helpers import patch_open | 12 | from tests.helpers import patch_open |
1990 | 13 | 13 | ||
1991 | 14 | import six | ||
1992 | 15 | |||
1993 | 16 | if not six.PY3: | ||
1994 | 17 | open_builtin = '__builtin__.open' | ||
1995 | 18 | else: | ||
1996 | 19 | open_builtin = 'builtins.open' | ||
1997 | 20 | |||
1998 | 14 | 21 | ||
1999 | 15 | class FakeRelation(object): | 22 | class FakeRelation(object): |
2000 | 16 | 23 | ||
2001 | @@ -472,7 +479,7 @@ | |||
2002 | 472 | self.assertEquals(result, expected) | 479 | self.assertEquals(result, expected) |
2003 | 473 | 480 | ||
2004 | 474 | @patch('os.path.exists') | 481 | @patch('os.path.exists') |
2006 | 475 | @patch('__builtin__.open') | 482 | @patch(open_builtin) |
2007 | 476 | def test_db_ssl(self, _open, osexists): | 483 | def test_db_ssl(self, _open, osexists): |
2008 | 477 | osexists.return_value = False | 484 | osexists.return_value = False |
2009 | 478 | ssl_dir = '/etc/dbssl' | 485 | ssl_dir = '/etc/dbssl' |
2010 | @@ -725,7 +732,7 @@ | |||
2011 | 725 | } | 732 | } |
2012 | 726 | self.assertEquals(result, expected) | 733 | self.assertEquals(result, expected) |
2013 | 727 | 734 | ||
2015 | 728 | @patch('__builtin__.open') | 735 | @patch(open_builtin) |
2016 | 729 | def test_amqp_context_with_data_ssl(self, _open): | 736 | def test_amqp_context_with_data_ssl(self, _open): |
2017 | 730 | '''Test amqp context with all required data and ssl''' | 737 | '''Test amqp context with all required data and ssl''' |
2018 | 731 | relation = FakeRelation(relation_data=AMQP_RELATION_WITH_SSL) | 738 | relation = FakeRelation(relation_data=AMQP_RELATION_WITH_SSL) |
2019 | @@ -799,7 +806,7 @@ | |||
2020 | 799 | 'rabbitmq_password': 'foobar', | 806 | 'rabbitmq_password': 'foobar', |
2021 | 800 | 'rabbitmq_user': 'adam', | 807 | 'rabbitmq_user': 'adam', |
2022 | 801 | 'rabbitmq_virtual_host': 'foo', | 808 | 'rabbitmq_virtual_host': 'foo', |
2024 | 802 | 'rabbitmq_hosts': 'rabbithost2,rabbithost1', | 809 | 'rabbitmq_hosts': 'rabbithost1,rabbithost2', |
2025 | 803 | } | 810 | } |
2026 | 804 | self.assertEquals(result, expected) | 811 | self.assertEquals(result, expected) |
2027 | 805 | 812 | ||
2028 | @@ -868,7 +875,7 @@ | |||
2029 | 868 | ceph = context.CephContext() | 875 | ceph = context.CephContext() |
2030 | 869 | result = ceph() | 876 | result = ceph() |
2031 | 870 | expected = { | 877 | expected = { |
2033 | 871 | 'mon_hosts': 'ceph_node2 ceph_node1', | 878 | 'mon_hosts': 'ceph_node1 ceph_node2', |
2034 | 872 | 'auth': 'foo', | 879 | 'auth': 'foo', |
2035 | 873 | 'key': 'bar', | 880 | 'key': 'bar', |
2036 | 874 | 'use_syslog': 'true' | 881 | 'use_syslog': 'true' |
2037 | @@ -882,8 +889,8 @@ | |||
2038 | 882 | def test_ceph_context_with_missing_data(self, ensure_packages, mkdir): | 889 | def test_ceph_context_with_missing_data(self, ensure_packages, mkdir): |
2039 | 883 | '''Test ceph context with missing relation data''' | 890 | '''Test ceph context with missing relation data''' |
2040 | 884 | relation = copy(CEPH_RELATION) | 891 | relation = copy(CEPH_RELATION) |
2043 | 885 | for k, v in relation.iteritems(): | 892 | for k, v in six.iteritems(relation): |
2044 | 886 | for u in v.iterkeys(): | 893 | for u in six.iterkeys(v): |
2045 | 887 | del relation[k][u]['auth'] | 894 | del relation[k][u]['auth'] |
2046 | 888 | relation = FakeRelation(relation_data=relation) | 895 | relation = FakeRelation(relation_data=relation) |
2047 | 889 | self.relation_get.side_effect = relation.get | 896 | self.relation_get.side_effect = relation.get |
2048 | @@ -911,7 +918,7 @@ | |||
2049 | 911 | ceph = context.CephContext() | 918 | ceph = context.CephContext() |
2050 | 912 | result = ceph() | 919 | result = ceph() |
2051 | 913 | expected = { | 920 | expected = { |
2053 | 914 | 'mon_hosts': '192.168.1.11 192.168.1.10', | 921 | 'mon_hosts': '192.168.1.10 192.168.1.11', |
2054 | 915 | 'auth': 'foo', | 922 | 'auth': 'foo', |
2055 | 916 | 'key': 'bar', | 923 | 'key': 'bar', |
2056 | 917 | 'use_syslog': 'true', | 924 | 'use_syslog': 'true', |
2057 | @@ -1264,12 +1271,9 @@ | |||
2058 | 1264 | if len(vips) > 1: | 1271 | if len(vips) > 1: |
2059 | 1265 | ex = { | 1272 | ex = { |
2060 | 1266 | 'namespace': 'cinder', | 1273 | 'namespace': 'cinder', |
2067 | 1267 | 'endpoints': [('10.5.1.100', '10.5.1.1', | 1274 | 'endpoints': [('10.5.1.100', '10.5.1.1', 8766, 8756), |
2068 | 1268 | 8766, 8756), | 1275 | ('10.5.2.100', '10.5.2.1', 8766, 8756), |
2069 | 1269 | ('10.5.2.100', '10.5.2.1', | 1276 | ('10.5.3.100', '10.5.3.1', 8766, 8756)], |
2064 | 1270 | 8766, 8756), | ||
2065 | 1271 | ('10.5.3.100', '10.5.3.1', | ||
2066 | 1272 | 8766, 8756)], | ||
2070 | 1273 | 'ext_ports': [8766] | 1277 | 'ext_ports': [8766] |
2071 | 1274 | } | 1278 | } |
2072 | 1275 | else: | 1279 | else: |
2073 | @@ -1283,12 +1287,10 @@ | |||
2074 | 1283 | if multinet: | 1287 | if multinet: |
2075 | 1284 | ex = { | 1288 | ex = { |
2076 | 1285 | 'namespace': 'cinder', | 1289 | 'namespace': 'cinder', |
2083 | 1286 | 'endpoints': [('10.5.3.100', '10.5.3.100', | 1290 | 'endpoints': sorted([ |
2084 | 1287 | 8776, 8766), | 1291 | ('10.5.3.100', '10.5.3.100', 8776, 8766), |
2085 | 1288 | ('10.5.2.100', '10.5.2.100', | 1292 | ('10.5.2.100', '10.5.2.100', 8776, 8766), |
2086 | 1289 | 8776, 8766), | 1293 | ('10.5.1.100', '10.5.1.100', 8776, 8766)]), |
2081 | 1290 | ('10.5.1.100', '10.5.1.100', | ||
2082 | 1291 | 8776, 8766)], | ||
2087 | 1292 | 'ext_ports': [8776] | 1294 | 'ext_ports': [8776] |
2088 | 1293 | } | 1295 | } |
2089 | 1294 | else: | 1296 | else: |
2090 | @@ -1391,9 +1393,10 @@ | |||
2091 | 1391 | apache = context.ApacheSSLContext() | 1393 | apache = context.ApacheSSLContext() |
2092 | 1392 | self.assertEquals(apache.canonical_names(), ['cinderhost1']) | 1394 | self.assertEquals(apache.canonical_names(), ['cinderhost1']) |
2093 | 1393 | rel.relation_data = IDENTITY_RELATION_MULTIPLE_CERT | 1395 | rel.relation_data = IDENTITY_RELATION_MULTIPLE_CERT |
2097 | 1394 | self.assertEquals(apache.canonical_names(), ['cinderhost1-adm-network', | 1396 | self.assertEquals(apache.canonical_names(), |
2098 | 1395 | 'cinderhost1-int-network', | 1397 | sorted(['cinderhost1-adm-network', |
2099 | 1396 | 'cinderhost1-pub-network']) | 1398 | 'cinderhost1-int-network', |
2100 | 1399 | 'cinderhost1-pub-network'])) | ||
2101 | 1397 | rel.relation_data = IDENTITY_RELATION_NO_CERT | 1400 | rel.relation_data = IDENTITY_RELATION_NO_CERT |
2102 | 1398 | self.assertEquals(apache.canonical_names(), []) | 1401 | self.assertEquals(apache.canonical_names(), []) |
2103 | 1399 | 1402 | ||
2104 | @@ -1903,17 +1906,15 @@ | |||
2105 | 1903 | 1906 | ||
2106 | 1904 | def test_workerconfig_context_noconfig(self): | 1907 | def test_workerconfig_context_noconfig(self): |
2107 | 1905 | self.config.return_value = None | 1908 | self.config.return_value = None |
2110 | 1906 | with patch.object(context.WorkerConfigContext, 'num_cpus') as cpus: | 1909 | with patch.object(context.WorkerConfigContext, 'num_cpus', 2): |
2109 | 1907 | cpus.__get__ = Mock(return_value=2) | ||
2111 | 1908 | worker = context.WorkerConfigContext() | 1910 | worker = context.WorkerConfigContext() |
2113 | 1909 | self.assertEqual({'workers': 2}, worker()) | 1911 | self.assertEqual({'workers': 0}, worker()) |
2114 | 1910 | 1912 | ||
2115 | 1911 | def test_workerconfig_context_withconfig(self): | 1913 | def test_workerconfig_context_withconfig(self): |
2116 | 1912 | self.config.side_effect = fake_config({ | 1914 | self.config.side_effect = fake_config({ |
2117 | 1913 | 'worker-multiplier': 4, | 1915 | 'worker-multiplier': 4, |
2118 | 1914 | }) | 1916 | }) |
2121 | 1915 | with patch.object(context.WorkerConfigContext, 'num_cpus') as cpus: | 1917 | with patch.object(context.WorkerConfigContext, 'num_cpus', 2): |
2120 | 1916 | cpus.__get__ = Mock(return_value=2) | ||
2122 | 1917 | worker = context.WorkerConfigContext() | 1918 | worker = context.WorkerConfigContext() |
2123 | 1918 | self.assertEqual({'workers': 8}, worker()) | 1919 | self.assertEqual({'workers': 8}, worker()) |
2124 | 1919 | 1920 | ||
2125 | 1920 | 1921 | ||
2126 | === modified file 'tests/contrib/openstack/test_os_templating.py' | |||
2127 | --- tests/contrib/openstack/test_os_templating.py 2014-11-25 14:35:22 +0000 | |||
2128 | +++ tests/contrib/openstack/test_os_templating.py 2014-11-25 15:09:14 +0000 | |||
2129 | @@ -1,7 +1,13 @@ | |||
2130 | 1 | 1 | ||
2131 | 2 | import os | 2 | import os |
2132 | 3 | |||
2133 | 4 | import unittest | 3 | import unittest |
2134 | 4 | |||
2135 | 5 | import six | ||
2136 | 6 | if not six.PY3: | ||
2137 | 7 | builtin_open = '__builtin__.open' | ||
2138 | 8 | else: | ||
2139 | 9 | builtin_open = 'builtins.open' | ||
2140 | 10 | |||
2141 | 5 | from mock import patch, call, MagicMock | 11 | from mock import patch, call, MagicMock |
2142 | 6 | 12 | ||
2143 | 7 | import charmhelpers.contrib.openstack.templating as templating | 13 | import charmhelpers.contrib.openstack.templating as templating |
2144 | @@ -160,7 +166,7 @@ | |||
2145 | 160 | def test_render_template_by_basename(self): | 166 | def test_render_template_by_basename(self): |
2146 | 161 | '''It renders template if it finds it by config file basename''' | 167 | '''It renders template if it finds it by config file basename''' |
2147 | 162 | 168 | ||
2149 | 163 | @patch('__builtin__.open') | 169 | @patch(builtin_open) |
2150 | 164 | @patch.object(templating, 'get_loader') | 170 | @patch.object(templating, 'get_loader') |
2151 | 165 | def test_write_out_config(self, loader, _open): | 171 | def test_write_out_config(self, loader, _open): |
2152 | 166 | '''It writes a templated config when provided a complete context''' | 172 | '''It writes a templated config when provided a complete context''' |
2153 | @@ -183,7 +189,7 @@ | |||
2154 | 183 | ] | 189 | ] |
2155 | 184 | with patch.object(self.renderer, 'write') as _write: | 190 | with patch.object(self.renderer, 'write') as _write: |
2156 | 185 | self.renderer.write_all() | 191 | self.renderer.write_all() |
2158 | 186 | self.assertEquals(ex_calls, _write.call_args_list) | 192 | self.assertEquals(sorted(ex_calls), sorted(_write.call_args_list)) |
2159 | 187 | pass | 193 | pass |
2160 | 188 | 194 | ||
2161 | 189 | @patch.object(templating, 'get_loader') | 195 | @patch.object(templating, 'get_loader') |
2162 | 190 | 196 | ||
2163 | === modified file 'tests/contrib/storage/test_linux_ceph.py' | |||
2164 | --- tests/contrib/storage/test_linux_ceph.py 2014-11-19 22:27:26 +0000 | |||
2165 | +++ tests/contrib/storage/test_linux_ceph.py 2014-11-25 15:09:14 +0000 | |||
2166 | @@ -14,19 +14,19 @@ | |||
2167 | 14 | import time | 14 | import time |
2168 | 15 | 15 | ||
2169 | 16 | 16 | ||
2171 | 17 | LS_POOLS = """ | 17 | LS_POOLS = b""" |
2172 | 18 | images | 18 | images |
2173 | 19 | volumes | 19 | volumes |
2174 | 20 | rbd | 20 | rbd |
2175 | 21 | """ | 21 | """ |
2176 | 22 | 22 | ||
2178 | 23 | LS_RBDS = """ | 23 | LS_RBDS = b""" |
2179 | 24 | rbd1 | 24 | rbd1 |
2180 | 25 | rbd2 | 25 | rbd2 |
2181 | 26 | rbd3 | 26 | rbd3 |
2182 | 27 | """ | 27 | """ |
2183 | 28 | 28 | ||
2185 | 29 | IMG_MAP = """ | 29 | IMG_MAP = b""" |
2186 | 30 | bar | 30 | bar |
2187 | 31 | baz | 31 | baz |
2188 | 32 | """ | 32 | """ |
2189 | @@ -93,7 +93,7 @@ | |||
2190 | 93 | @patch.object(ceph_utils, 'ceph_version') | 93 | @patch.object(ceph_utils, 'ceph_version') |
2191 | 94 | def test_get_osds(self, version): | 94 | def test_get_osds(self, version): |
2192 | 95 | version.return_value = '0.56.2' | 95 | version.return_value = '0.56.2' |
2194 | 96 | self.check_output.return_value = json.dumps([1, 2, 3]) | 96 | self.check_output.return_value = json.dumps([1, 2, 3]).encode('UTF-8') |
2195 | 97 | self.assertEquals(ceph_utils.get_osds('test'), [1, 2, 3]) | 97 | self.assertEquals(ceph_utils.get_osds('test'), [1, 2, 3]) |
2196 | 98 | 98 | ||
2197 | 99 | @patch.object(ceph_utils, 'ceph_version') | 99 | @patch.object(ceph_utils, 'ceph_version') |
2198 | @@ -104,7 +104,7 @@ | |||
2199 | 104 | @patch.object(ceph_utils, 'ceph_version') | 104 | @patch.object(ceph_utils, 'ceph_version') |
2200 | 105 | def test_get_osds_none(self, version): | 105 | def test_get_osds_none(self, version): |
2201 | 106 | version.return_value = '0.56.2' | 106 | version.return_value = '0.56.2' |
2203 | 107 | self.check_output.return_value = json.dumps(None) | 107 | self.check_output.return_value = json.dumps(None).encode('UTF-8') |
2204 | 108 | self.assertEquals(ceph_utils.get_osds('test'), None) | 108 | self.assertEquals(ceph_utils.get_osds('test'), None) |
2205 | 109 | 109 | ||
2206 | 110 | @patch.object(ceph_utils, 'get_osds') | 110 | @patch.object(ceph_utils, 'get_osds') |
2207 | @@ -534,13 +534,13 @@ | |||
2208 | 534 | @patch('os.path.exists') | 534 | @patch('os.path.exists') |
2209 | 535 | def test_ceph_version_error(self, path, output): | 535 | def test_ceph_version_error(self, path, output): |
2210 | 536 | path.return_value = True | 536 | path.return_value = True |
2212 | 537 | output.return_value = '' | 537 | output.return_value = b'' |
2213 | 538 | self.assertEquals(ceph_utils.ceph_version(), None) | 538 | self.assertEquals(ceph_utils.ceph_version(), None) |
2214 | 539 | 539 | ||
2215 | 540 | @patch.object(ceph_utils, 'check_output') | 540 | @patch.object(ceph_utils, 'check_output') |
2216 | 541 | @patch('os.path.exists') | 541 | @patch('os.path.exists') |
2217 | 542 | def test_ceph_version_ok(self, path, output): | 542 | def test_ceph_version_ok(self, path, output): |
2218 | 543 | path.return_value = True | 543 | path.return_value = True |
2221 | 544 | output.return_value = 'ceph version 0.67.4'\ | 544 | output.return_value = \ |
2222 | 545 | ' (ad85b8bfafea6232d64cb7ba76a8b6e8252fa0c7)' | 545 | b'ceph version 0.67.4 (ad85b8bfafea6232d64cb7ba76a8b6e8252fa0c7)' |
2223 | 546 | self.assertEquals(ceph_utils.ceph_version(), '0.67.4') | 546 | self.assertEquals(ceph_utils.ceph_version(), '0.67.4') |
2224 | 547 | 547 | ||
2225 | === modified file 'tests/contrib/storage/test_linux_storage_lvm.py' | |||
2226 | --- tests/contrib/storage/test_linux_storage_lvm.py 2014-07-03 12:36:50 +0000 | |||
2227 | +++ tests/contrib/storage/test_linux_storage_lvm.py 2014-11-25 15:09:14 +0000 | |||
2228 | @@ -5,7 +5,7 @@ | |||
2229 | 5 | 5 | ||
2230 | 6 | import charmhelpers.contrib.storage.linux.lvm as lvm | 6 | import charmhelpers.contrib.storage.linux.lvm as lvm |
2231 | 7 | 7 | ||
2233 | 8 | PVDISPLAY = """ | 8 | PVDISPLAY = b""" |
2234 | 9 | --- Physical volume --- | 9 | --- Physical volume --- |
2235 | 10 | PV Name /dev/loop0 | 10 | PV Name /dev/loop0 |
2236 | 11 | VG Name foo | 11 | VG Name foo |
2237 | @@ -19,7 +19,7 @@ | |||
2238 | 19 | 19 | ||
2239 | 20 | """ | 20 | """ |
2240 | 21 | 21 | ||
2242 | 22 | EMPTY_VG_IN_PVDISPLAY = """ | 22 | EMPTY_VG_IN_PVDISPLAY = b""" |
2243 | 23 | --- Physical volume --- | 23 | --- Physical volume --- |
2244 | 24 | PV Name /dev/loop0 | 24 | PV Name /dev/loop0 |
2245 | 25 | VG Name | 25 | VG Name |
2246 | 26 | 26 | ||
2247 | === modified file 'tests/contrib/storage/test_linux_storage_utils.py' | |||
2248 | --- tests/contrib/storage/test_linux_storage_utils.py 2014-07-31 08:55:15 +0000 | |||
2249 | +++ tests/contrib/storage/test_linux_storage_utils.py 2014-11-25 15:09:14 +0000 | |||
2250 | @@ -14,7 +14,7 @@ | |||
2251 | 14 | @patch(STORAGE_LINUX_UTILS + '.check_call') | 14 | @patch(STORAGE_LINUX_UTILS + '.check_call') |
2252 | 15 | def test_zap_disk(self, check_call, call, check_output): | 15 | def test_zap_disk(self, check_call, call, check_output): |
2253 | 16 | '''It calls sgdisk correctly to zap disk''' | 16 | '''It calls sgdisk correctly to zap disk''' |
2255 | 17 | check_output.return_value = '200\n' | 17 | check_output.return_value = b'200\n' |
2256 | 18 | storage_utils.zap_disk('/dev/foo') | 18 | storage_utils.zap_disk('/dev/foo') |
2257 | 19 | call.assert_any_call(['sgdisk', '--zap-all', '--mbrtogpt', | 19 | call.assert_any_call(['sgdisk', '--zap-all', '--mbrtogpt', |
2258 | 20 | '--clear', '/dev/foo']) | 20 | '--clear', '/dev/foo']) |
2259 | @@ -50,7 +50,7 @@ | |||
2260 | 50 | def test_is_device_mounted(self, check_output): | 50 | def test_is_device_mounted(self, check_output): |
2261 | 51 | '''It detects mounted devices as mounted.''' | 51 | '''It detects mounted devices as mounted.''' |
2262 | 52 | check_output.return_value = ( | 52 | check_output.return_value = ( |
2264 | 53 | "/dev/sda1 on / type ext4 (rw,errors=remount-ro)\n") | 53 | b"/dev/sda1 on / type ext4 (rw,errors=remount-ro)\n") |
2265 | 54 | result = storage_utils.is_device_mounted('/dev/sda') | 54 | result = storage_utils.is_device_mounted('/dev/sda') |
2266 | 55 | self.assertTrue(result) | 55 | self.assertTrue(result) |
2267 | 56 | 56 | ||
2268 | @@ -58,7 +58,7 @@ | |||
2269 | 58 | def test_is_device_mounted_partition(self, check_output): | 58 | def test_is_device_mounted_partition(self, check_output): |
2270 | 59 | '''It detects mounted partitions as mounted.''' | 59 | '''It detects mounted partitions as mounted.''' |
2271 | 60 | check_output.return_value = ( | 60 | check_output.return_value = ( |
2273 | 61 | "/dev/sda1 on / type ext4 (rw,errors=remount-ro)\n") | 61 | b"/dev/sda1 on / type ext4 (rw,errors=remount-ro)\n") |
2274 | 62 | result = storage_utils.is_device_mounted('/dev/sda1') | 62 | result = storage_utils.is_device_mounted('/dev/sda1') |
2275 | 63 | self.assertTrue(result) | 63 | self.assertTrue(result) |
2276 | 64 | 64 | ||
2277 | @@ -67,7 +67,7 @@ | |||
2278 | 67 | '''It detects mounted devices as mounted if "mount" shows only a | 67 | '''It detects mounted devices as mounted if "mount" shows only a |
2279 | 68 | partition as mounted.''' | 68 | partition as mounted.''' |
2280 | 69 | check_output.return_value = ( | 69 | check_output.return_value = ( |
2282 | 70 | "/dev/sda1 on / type ext4 (rw,errors=remount-ro)\n") | 70 | b"/dev/sda1 on / type ext4 (rw,errors=remount-ro)\n") |
2283 | 71 | result = storage_utils.is_device_mounted('/dev/sda') | 71 | result = storage_utils.is_device_mounted('/dev/sda') |
2284 | 72 | self.assertTrue(result) | 72 | self.assertTrue(result) |
2285 | 73 | 73 | ||
2286 | @@ -75,7 +75,7 @@ | |||
2287 | 75 | def test_is_device_mounted_not_mounted(self, check_output): | 75 | def test_is_device_mounted_not_mounted(self, check_output): |
2288 | 76 | '''It detects unmounted devices as not mounted.''' | 76 | '''It detects unmounted devices as not mounted.''' |
2289 | 77 | check_output.return_value = ( | 77 | check_output.return_value = ( |
2291 | 78 | "/dev/foo on / type ext4 (rw,errors=remount-ro)\n") | 78 | b"/dev/foo on / type ext4 (rw,errors=remount-ro)\n") |
2292 | 79 | result = storage_utils.is_device_mounted('/dev/sda') | 79 | result = storage_utils.is_device_mounted('/dev/sda') |
2293 | 80 | self.assertFalse(result) | 80 | self.assertFalse(result) |
2294 | 81 | 81 | ||
2295 | @@ -83,7 +83,7 @@ | |||
2296 | 83 | def test_is_device_mounted_not_mounted_partition(self, check_output): | 83 | def test_is_device_mounted_not_mounted_partition(self, check_output): |
2297 | 84 | '''It detects unmounted partitions as not mounted.''' | 84 | '''It detects unmounted partitions as not mounted.''' |
2298 | 85 | check_output.return_value = ( | 85 | check_output.return_value = ( |
2300 | 86 | "/dev/foo on / type ext4 (rw,errors=remount-ro)\n") | 86 | b"/dev/foo on / type ext4 (rw,errors=remount-ro)\n") |
2301 | 87 | result = storage_utils.is_device_mounted('/dev/sda1') | 87 | result = storage_utils.is_device_mounted('/dev/sda1') |
2302 | 88 | self.assertFalse(result) | 88 | self.assertFalse(result) |
2303 | 89 | 89 | ||
2304 | @@ -91,7 +91,7 @@ | |||
2305 | 91 | def test_is_device_mounted_cciss(self, check_output): | 91 | def test_is_device_mounted_cciss(self, check_output): |
2306 | 92 | '''It detects mounted cciss partitions as mounted.''' | 92 | '''It detects mounted cciss partitions as mounted.''' |
2307 | 93 | check_output.return_value = ( | 93 | check_output.return_value = ( |
2309 | 94 | "/dev/cciss/c0d0 on / type ext4 (rw,errors=remount-ro)\n") | 94 | b"/dev/cciss/c0d0 on / type ext4 (rw,errors=remount-ro)\n") |
2310 | 95 | result = storage_utils.is_device_mounted('/dev/cciss/c0d0') | 95 | result = storage_utils.is_device_mounted('/dev/cciss/c0d0') |
2311 | 96 | self.assertTrue(result) | 96 | self.assertTrue(result) |
2312 | 97 | 97 | ||
2313 | @@ -99,6 +99,6 @@ | |||
2314 | 99 | def test_is_device_mounted_cciss_not_mounted(self, check_output): | 99 | def test_is_device_mounted_cciss_not_mounted(self, check_output): |
2315 | 100 | '''It detects unmounted cciss partitions as not mounted.''' | 100 | '''It detects unmounted cciss partitions as not mounted.''' |
2316 | 101 | check_output.return_value = ( | 101 | check_output.return_value = ( |
2318 | 102 | "/dev/cciss/c0d1 on / type ext4 (rw,errors=remount-ro)\n") | 102 | b"/dev/cciss/c0d1 on / type ext4 (rw,errors=remount-ro)\n") |
2319 | 103 | result = storage_utils.is_device_mounted('/dev/cciss/c0d0') | 103 | result = storage_utils.is_device_mounted('/dev/cciss/c0d0') |
2320 | 104 | self.assertFalse(result) | 104 | self.assertFalse(result) |
2321 | 105 | 105 | ||
2322 | === modified file 'tests/contrib/templating/test_contexts.py' | |||
2323 | --- tests/contrib/templating/test_contexts.py 2014-08-13 20:52:09 +0000 | |||
2324 | +++ tests/contrib/templating/test_contexts.py 2014-11-25 15:09:14 +0000 | |||
2325 | @@ -9,6 +9,8 @@ | |||
2326 | 9 | import unittest | 9 | import unittest |
2327 | 10 | import yaml | 10 | import yaml |
2328 | 11 | 11 | ||
2329 | 12 | import six | ||
2330 | 13 | |||
2331 | 12 | import charmhelpers.contrib.templating.contexts | 14 | import charmhelpers.contrib.templating.contexts |
2332 | 13 | 15 | ||
2333 | 14 | 16 | ||
2334 | @@ -134,12 +136,12 @@ | |||
2335 | 134 | } | 136 | } |
2336 | 135 | self.mock_relations.return_value = { | 137 | self.mock_relations.return_value = { |
2337 | 136 | 'wsgi-file': { | 138 | 'wsgi-file': { |
2341 | 137 | u'wsgi-file:0': { | 139 | six.u('wsgi-file:0'): { |
2342 | 138 | u'gunicorn/1': { | 140 | six.u('gunicorn/1'): { |
2343 | 139 | u'private-address': u'10.0.3.99', | 141 | six.u('private-address'): six.u('10.0.3.99'), |
2344 | 140 | }, | 142 | }, |
2345 | 141 | 'click-index/3': { | 143 | 'click-index/3': { |
2347 | 142 | u'wsgi_group': u'ubunet', | 144 | six.u('wsgi_group'): six.u('ubunet'), |
2348 | 143 | }, | 145 | }, |
2349 | 144 | }, | 146 | }, |
2350 | 145 | }, | 147 | }, |
2351 | @@ -162,8 +164,9 @@ | |||
2352 | 162 | expected["wsgi_file:relation_key2"] = "relation_value2" | 164 | expected["wsgi_file:relation_key2"] = "relation_value2" |
2353 | 163 | expected["relations_full"]['wsgi-file'] = { | 165 | expected["relations_full"]['wsgi-file'] = { |
2354 | 164 | 'wsgi-file:0': { | 166 | 'wsgi-file:0': { |
2357 | 165 | 'gunicorn/1': {u'private-address': u'10.0.3.99'}, | 167 | 'gunicorn/1': { |
2358 | 166 | 'click-index/3': {u'wsgi_group': u'ubunet'}, | 168 | six.u('private-address'): six.u('10.0.3.99')}, |
2359 | 169 | 'click-index/3': {six.u('wsgi_group'): six.u('ubunet')}, | ||
2360 | 167 | }, | 170 | }, |
2361 | 168 | } | 171 | } |
2362 | 169 | expected["relations"]["wsgi-file"] = [ | 172 | expected["relations"]["wsgi-file"] = [ |
2363 | 170 | 173 | ||
2364 | === modified file 'tests/contrib/unison/test_unison.py' | |||
2365 | --- tests/contrib/unison/test_unison.py 2014-10-22 06:17:55 +0000 | |||
2366 | +++ tests/contrib/unison/test_unison.py 2014-11-25 15:09:14 +0000 | |||
2367 | @@ -110,13 +110,13 @@ | |||
2368 | 110 | 110 | ||
2369 | 111 | isfile.return_value = False | 111 | isfile.return_value = False |
2370 | 112 | with patch_open() as (_open, _file): | 112 | with patch_open() as (_open, _file): |
2372 | 113 | self.check_output.return_value = 'fookey' | 113 | self.check_output.return_value = b'fookey' |
2373 | 114 | unison.create_public_key( | 114 | unison.create_public_key( |
2374 | 115 | user='foo', priv_key_path='/home/foo/.ssh/id_rsa', | 115 | user='foo', priv_key_path='/home/foo/.ssh/id_rsa', |
2375 | 116 | pub_key_path='/home/foo/.ssh/id_rsa.pub') | 116 | pub_key_path='/home/foo/.ssh/id_rsa.pub') |
2376 | 117 | self.assertIn(call(create_cmd), self.check_output.call_args_list) | 117 | self.assertIn(call(create_cmd), self.check_output.call_args_list) |
2377 | 118 | _open.assert_called_with('/home/foo/.ssh/id_rsa.pub', 'wb') | 118 | _open.assert_called_with('/home/foo/.ssh/id_rsa.pub', 'wb') |
2379 | 119 | _file.write.assert_called_with('fookey') | 119 | _file.write.assert_called_with(b'fookey') |
2380 | 120 | 120 | ||
2381 | 121 | @patch('os.mkdir') | 121 | @patch('os.mkdir') |
2382 | 122 | @patch('os.path.isdir') | 122 | @patch('os.path.isdir') |
2383 | 123 | 123 | ||
2384 | === modified file 'tests/core/test_fstab.py' | |||
2385 | --- tests/core/test_fstab.py 2014-11-25 14:35:22 +0000 | |||
2386 | +++ tests/core/test_fstab.py 2014-11-25 15:09:14 +0000 | |||
2387 | @@ -24,7 +24,7 @@ | |||
2388 | 24 | class FstabTest(unittest.TestCase): | 24 | class FstabTest(unittest.TestCase): |
2389 | 25 | 25 | ||
2390 | 26 | def setUp(self): | 26 | def setUp(self): |
2392 | 27 | self.tempfile = tempfile.NamedTemporaryFile(delete=False) | 27 | self.tempfile = tempfile.NamedTemporaryFile('w+', delete=False) |
2393 | 28 | self.tempfile.write(DEFAULT_FSTAB_FILE) | 28 | self.tempfile.write(DEFAULT_FSTAB_FILE) |
2394 | 29 | self.tempfile.close() | 29 | self.tempfile.close() |
2395 | 30 | self.fstab = Fstab(path=self.tempfile.name) | 30 | self.fstab = Fstab(path=self.tempfile.name) |
2396 | 31 | 31 | ||
2397 | === modified file 'tests/core/test_hookenv.py' | |||
2398 | --- tests/core/test_hookenv.py 2014-11-25 14:35:22 +0000 | |||
2399 | +++ tests/core/test_hookenv.py 2014-11-25 15:09:14 +0000 | |||
2400 | @@ -3,14 +3,18 @@ | |||
2401 | 3 | from subprocess import CalledProcessError | 3 | from subprocess import CalledProcessError |
2402 | 4 | import shutil | 4 | import shutil |
2403 | 5 | import tempfile | 5 | import tempfile |
2404 | 6 | |||
2405 | 7 | import cPickle as pickle | ||
2406 | 8 | from mock import patch, call, mock_open | 6 | from mock import patch, call, mock_open |
2407 | 9 | from StringIO import StringIO | ||
2408 | 10 | from mock import MagicMock | 7 | from mock import MagicMock |
2409 | 11 | from testtools import TestCase | 8 | from testtools import TestCase |
2410 | 12 | import yaml | 9 | import yaml |
2411 | 13 | 10 | ||
2412 | 11 | import six | ||
2413 | 12 | from six.moves import StringIO | ||
2414 | 13 | if six.PY3: | ||
2415 | 14 | import pickle | ||
2416 | 15 | else: | ||
2417 | 16 | import cPickle as pickle | ||
2418 | 17 | |||
2419 | 14 | from charmhelpers.core import hookenv | 18 | from charmhelpers.core import hookenv |
2420 | 15 | 19 | ||
2421 | 16 | CHARM_METADATA = """name: testmock | 20 | CHARM_METADATA = """name: testmock |
2422 | @@ -125,7 +129,7 @@ | |||
2423 | 125 | def test_keys(self): | 129 | def test_keys(self): |
2424 | 126 | c = hookenv.Config(dict(foo='bar')) | 130 | c = hookenv.Config(dict(foo='bar')) |
2425 | 127 | c["baz"] = "bar" | 131 | c["baz"] = "bar" |
2427 | 128 | self.assertEqual([u"foo", "baz"], c.keys()) | 132 | self.assertEqual(sorted([six.u("foo"), "baz"]), sorted(c.keys())) |
2428 | 129 | 133 | ||
2429 | 130 | 134 | ||
2430 | 131 | class SerializableTest(TestCase): | 135 | class SerializableTest(TestCase): |
2431 | @@ -165,11 +169,9 @@ | |||
2432 | 165 | } | 169 | } |
2433 | 166 | wrapped = hookenv.Serializable(foo) | 170 | wrapped = hookenv.Serializable(foo) |
2434 | 167 | for meth in ('keys', 'values', 'items'): | 171 | for meth in ('keys', 'values', 'items'): |
2436 | 168 | self.assertEqual(getattr(wrapped, meth)(), getattr(foo, meth)()) | 172 | self.assertEqual(sorted(list(getattr(wrapped, meth)())), |
2437 | 173 | sorted(list(getattr(foo, meth)()))) | ||
2438 | 169 | 174 | ||
2439 | 170 | for meth in ('iterkeys', 'itervalues', 'iteritems'): | ||
2440 | 171 | self.assertEqual(list(getattr(wrapped, meth)()), | ||
2441 | 172 | list(getattr(foo, meth)())) | ||
2442 | 173 | self.assertEqual(wrapped.get('bar'), foo.get('bar')) | 175 | self.assertEqual(wrapped.get('bar'), foo.get('bar')) |
2443 | 174 | self.assertEqual(wrapped.get('baz', 42), foo.get('baz', 42)) | 176 | self.assertEqual(wrapped.get('baz', 42), foo.get('baz', 42)) |
2444 | 175 | self.assertIn('bar', wrapped) | 177 | self.assertIn('bar', wrapped) |
2445 | @@ -246,7 +248,7 @@ | |||
2446 | 246 | @patch('subprocess.check_output') | 248 | @patch('subprocess.check_output') |
2447 | 247 | def test_gets_charm_config_with_scope(self, check_output): | 249 | def test_gets_charm_config_with_scope(self, check_output): |
2448 | 248 | config_data = 'bar' | 250 | config_data = 'bar' |
2450 | 249 | check_output.return_value = json.dumps(config_data) | 251 | check_output.return_value = json.dumps(config_data).encode('UTF-8') |
2451 | 250 | 252 | ||
2452 | 251 | result = hookenv.config(scope='baz') | 253 | result = hookenv.config(scope='baz') |
2453 | 252 | 254 | ||
2454 | @@ -257,11 +259,11 @@ | |||
2455 | 257 | self.assertEqual(result[1], 'a') | 259 | self.assertEqual(result[1], 'a') |
2456 | 258 | 260 | ||
2457 | 259 | # ... because the result is actually a string | 261 | # ... because the result is actually a string |
2459 | 260 | self.assert_(isinstance(result, basestring)) | 262 | self.assert_(isinstance(result, six.string_types)) |
2460 | 261 | 263 | ||
2461 | 262 | @patch('subprocess.check_output') | 264 | @patch('subprocess.check_output') |
2462 | 263 | def test_gets_missing_charm_config_with_scope(self, check_output): | 265 | def test_gets_missing_charm_config_with_scope(self, check_output): |
2464 | 264 | check_output.return_value = '' | 266 | check_output.return_value = b'' |
2465 | 265 | 267 | ||
2466 | 266 | result = hookenv.config(scope='baz') | 268 | result = hookenv.config(scope='baz') |
2467 | 267 | 269 | ||
2468 | @@ -271,7 +273,7 @@ | |||
2469 | 271 | @patch('charmhelpers.core.hookenv.charm_dir') | 273 | @patch('charmhelpers.core.hookenv.charm_dir') |
2470 | 272 | @patch('subprocess.check_output') | 274 | @patch('subprocess.check_output') |
2471 | 273 | def test_gets_config_without_scope(self, check_output, charm_dir): | 275 | def test_gets_config_without_scope(self, check_output, charm_dir): |
2473 | 274 | check_output.return_value = json.dumps(dict(foo='bar')) | 276 | check_output.return_value = json.dumps(dict(foo='bar')).encode('UTF-8') |
2474 | 275 | charm_dir.side_effect = tempfile.mkdtemp | 277 | charm_dir.side_effect = tempfile.mkdtemp |
2475 | 276 | 278 | ||
2476 | 277 | result = hookenv.config() | 279 | result = hookenv.config() |
2477 | @@ -327,7 +329,7 @@ | |||
2478 | 327 | @patch('charmhelpers.core.hookenv.relation_type') | 329 | @patch('charmhelpers.core.hookenv.relation_type') |
2479 | 328 | def test_gets_relation_ids(self, relation_type, check_output): | 330 | def test_gets_relation_ids(self, relation_type, check_output): |
2480 | 329 | ids = [1, 2, 3] | 331 | ids = [1, 2, 3] |
2482 | 330 | check_output.return_value = json.dumps(ids) | 332 | check_output.return_value = json.dumps(ids).encode('UTF-8') |
2483 | 331 | reltype = 'foo' | 333 | reltype = 'foo' |
2484 | 332 | relation_type.return_value = reltype | 334 | relation_type.return_value = reltype |
2485 | 333 | 335 | ||
2486 | @@ -341,7 +343,7 @@ | |||
2487 | 341 | @patch('charmhelpers.core.hookenv.relation_type') | 343 | @patch('charmhelpers.core.hookenv.relation_type') |
2488 | 342 | def test_gets_relation_ids_empty_array(self, relation_type, check_output): | 344 | def test_gets_relation_ids_empty_array(self, relation_type, check_output): |
2489 | 343 | ids = [] | 345 | ids = [] |
2491 | 344 | check_output.return_value = json.dumps(None) | 346 | check_output.return_value = json.dumps(None).encode('UTF-8') |
2492 | 345 | reltype = 'foo' | 347 | reltype = 'foo' |
2493 | 346 | relation_type.return_value = reltype | 348 | relation_type.return_value = reltype |
2494 | 347 | 349 | ||
2495 | @@ -355,7 +357,7 @@ | |||
2496 | 355 | @patch('charmhelpers.core.hookenv.relation_type') | 357 | @patch('charmhelpers.core.hookenv.relation_type') |
2497 | 356 | def test_relation_ids_no_relation_type(self, relation_type, check_output): | 358 | def test_relation_ids_no_relation_type(self, relation_type, check_output): |
2498 | 357 | ids = [1, 2, 3] | 359 | ids = [1, 2, 3] |
2500 | 358 | check_output.return_value = json.dumps(ids) | 360 | check_output.return_value = json.dumps(ids).encode('UTF-8') |
2501 | 359 | relation_type.return_value = None | 361 | relation_type.return_value = None |
2502 | 360 | 362 | ||
2503 | 361 | result = hookenv.relation_ids() | 363 | result = hookenv.relation_ids() |
2504 | @@ -366,7 +368,7 @@ | |||
2505 | 366 | @patch('charmhelpers.core.hookenv.relation_type') | 368 | @patch('charmhelpers.core.hookenv.relation_type') |
2506 | 367 | def test_gets_relation_ids_for_type(self, relation_type, check_output): | 369 | def test_gets_relation_ids_for_type(self, relation_type, check_output): |
2507 | 368 | ids = [1, 2, 3] | 370 | ids = [1, 2, 3] |
2509 | 369 | check_output.return_value = json.dumps(ids) | 371 | check_output.return_value = json.dumps(ids).encode('UTF-8') |
2510 | 370 | reltype = 'foo' | 372 | reltype = 'foo' |
2511 | 371 | 373 | ||
2512 | 372 | result = hookenv.relation_ids(reltype) | 374 | result = hookenv.relation_ids(reltype) |
2513 | @@ -382,7 +384,7 @@ | |||
2514 | 382 | relid = 123 | 384 | relid = 123 |
2515 | 383 | units = ['foo', 'bar'] | 385 | units = ['foo', 'bar'] |
2516 | 384 | relation_id.return_value = relid | 386 | relation_id.return_value = relid |
2518 | 385 | check_output.return_value = json.dumps(units) | 387 | check_output.return_value = json.dumps(units).encode('UTF-8') |
2519 | 386 | 388 | ||
2520 | 387 | result = hookenv.related_units() | 389 | result = hookenv.related_units() |
2521 | 388 | 390 | ||
2522 | @@ -393,10 +395,10 @@ | |||
2523 | 393 | @patch('subprocess.check_output') | 395 | @patch('subprocess.check_output') |
2524 | 394 | @patch('charmhelpers.core.hookenv.relation_id') | 396 | @patch('charmhelpers.core.hookenv.relation_id') |
2525 | 395 | def test_gets_related_units_empty_array(self, relation_id, check_output): | 397 | def test_gets_related_units_empty_array(self, relation_id, check_output): |
2527 | 396 | relid = 123 | 398 | relid = str(123) |
2528 | 397 | units = [] | 399 | units = [] |
2529 | 398 | relation_id.return_value = relid | 400 | relation_id.return_value = relid |
2531 | 399 | check_output.return_value = json.dumps(None) | 401 | check_output.return_value = json.dumps(None).encode('UTF-8') |
2532 | 400 | 402 | ||
2533 | 401 | result = hookenv.related_units() | 403 | result = hookenv.related_units() |
2534 | 402 | 404 | ||
2535 | @@ -409,7 +411,7 @@ | |||
2536 | 409 | def test_related_units_no_relation(self, relation_id, check_output): | 411 | def test_related_units_no_relation(self, relation_id, check_output): |
2537 | 410 | units = ['foo', 'bar'] | 412 | units = ['foo', 'bar'] |
2538 | 411 | relation_id.return_value = None | 413 | relation_id.return_value = None |
2540 | 412 | check_output.return_value = json.dumps(units) | 414 | check_output.return_value = json.dumps(units).encode('UTF-8') |
2541 | 413 | 415 | ||
2542 | 414 | result = hookenv.related_units() | 416 | result = hookenv.related_units() |
2543 | 415 | 417 | ||
2544 | @@ -421,7 +423,7 @@ | |||
2545 | 421 | def test_gets_related_units_for_id(self, relation_id, check_output): | 423 | def test_gets_related_units_for_id(self, relation_id, check_output): |
2546 | 422 | relid = 123 | 424 | relid = 123 |
2547 | 423 | units = ['foo', 'bar'] | 425 | units = ['foo', 'bar'] |
2549 | 424 | check_output.return_value = json.dumps(units) | 426 | check_output.return_value = json.dumps(units).encode('UTF-8') |
2550 | 425 | 427 | ||
2551 | 426 | result = hookenv.related_units(relid) | 428 | result = hookenv.related_units(relid) |
2552 | 427 | 429 | ||
2553 | @@ -765,7 +767,7 @@ | |||
2554 | 765 | @patch('subprocess.check_output') | 767 | @patch('subprocess.check_output') |
2555 | 766 | def test_gets_relation(self, check_output): | 768 | def test_gets_relation(self, check_output): |
2556 | 767 | data = {"foo": "BAR"} | 769 | data = {"foo": "BAR"} |
2558 | 768 | check_output.return_value = json.dumps(data) | 770 | check_output.return_value = json.dumps(data).encode('UTF-8') |
2559 | 769 | result = hookenv.relation_get() | 771 | result = hookenv.relation_get() |
2560 | 770 | 772 | ||
2561 | 771 | self.assertEqual(result['foo'], 'BAR') | 773 | self.assertEqual(result['foo'], 'BAR') |
2562 | @@ -773,7 +775,7 @@ | |||
2563 | 773 | 775 | ||
2564 | 774 | @patch('charmhelpers.core.hookenv.subprocess') | 776 | @patch('charmhelpers.core.hookenv.subprocess') |
2565 | 775 | def test_relation_get_none(self, mock_subprocess): | 777 | def test_relation_get_none(self, mock_subprocess): |
2567 | 776 | mock_subprocess.check_output.return_value = 'null' | 778 | mock_subprocess.check_output.return_value = b'null' |
2568 | 777 | 779 | ||
2569 | 778 | result = hookenv.relation_get() | 780 | result = hookenv.relation_get() |
2570 | 779 | 781 | ||
2571 | @@ -801,7 +803,7 @@ | |||
2572 | 801 | 803 | ||
2573 | 802 | @patch('subprocess.check_output') | 804 | @patch('subprocess.check_output') |
2574 | 803 | def test_gets_relation_with_scope(self, check_output): | 805 | def test_gets_relation_with_scope(self, check_output): |
2576 | 804 | check_output.return_value = json.dumps('bar') | 806 | check_output.return_value = json.dumps('bar').encode('UTF-8') |
2577 | 805 | 807 | ||
2578 | 806 | result = hookenv.relation_get(attribute='baz-scope') | 808 | result = hookenv.relation_get(attribute='baz-scope') |
2579 | 807 | 809 | ||
2580 | @@ -811,7 +813,7 @@ | |||
2581 | 811 | 813 | ||
2582 | 812 | @patch('subprocess.check_output') | 814 | @patch('subprocess.check_output') |
2583 | 813 | def test_gets_missing_relation_with_scope(self, check_output): | 815 | def test_gets_missing_relation_with_scope(self, check_output): |
2585 | 814 | check_output.return_value = "" | 816 | check_output.return_value = b"" |
2586 | 815 | 817 | ||
2587 | 816 | result = hookenv.relation_get(attribute='baz-scope') | 818 | result = hookenv.relation_get(attribute='baz-scope') |
2588 | 817 | 819 | ||
2589 | @@ -821,7 +823,7 @@ | |||
2590 | 821 | 823 | ||
2591 | 822 | @patch('subprocess.check_output') | 824 | @patch('subprocess.check_output') |
2592 | 823 | def test_gets_relation_with_unit_name(self, check_output): | 825 | def test_gets_relation_with_unit_name(self, check_output): |
2594 | 824 | check_output.return_value = json.dumps('BAR') | 826 | check_output.return_value = json.dumps('BAR').encode('UTF-8') |
2595 | 825 | 827 | ||
2596 | 826 | result = hookenv.relation_get(attribute='baz-scope', unit='baz-unit') | 828 | result = hookenv.relation_get(attribute='baz-scope', unit='baz-unit') |
2597 | 827 | 829 | ||
2598 | @@ -834,7 +836,7 @@ | |||
2599 | 834 | @patch('subprocess.check_output') | 836 | @patch('subprocess.check_output') |
2600 | 835 | def test_relation_set_flushes_local_unit_cache(self, check_output, | 837 | def test_relation_set_flushes_local_unit_cache(self, check_output, |
2601 | 836 | check_call, local_unit): | 838 | check_call, local_unit): |
2603 | 837 | check_output.return_value = json.dumps('BAR') | 839 | check_output.return_value = json.dumps('BAR').encode('UTF-8') |
2604 | 838 | local_unit.return_value = 'baz_unit' | 840 | local_unit.return_value = 'baz_unit' |
2605 | 839 | hookenv.relation_get(attribute='baz_scope', unit='baz_unit') | 841 | hookenv.relation_get(attribute='baz_scope', unit='baz_unit') |
2606 | 840 | hookenv.relation_get(attribute='bar_scope') | 842 | hookenv.relation_get(attribute='bar_scope') |
2607 | @@ -845,7 +847,7 @@ | |||
2608 | 845 | 847 | ||
2609 | 846 | @patch('subprocess.check_output') | 848 | @patch('subprocess.check_output') |
2610 | 847 | def test_gets_relation_with_relation_id(self, check_output): | 849 | def test_gets_relation_with_relation_id(self, check_output): |
2612 | 848 | check_output.return_value = json.dumps('BAR') | 850 | check_output.return_value = json.dumps('BAR').encode('UTF-8') |
2613 | 849 | 851 | ||
2614 | 850 | result = hookenv.relation_get(attribute='baz-scope', unit='baz-unit', | 852 | result = hookenv.relation_get(attribute='baz-scope', unit='baz-unit', |
2615 | 851 | rid=123) | 853 | rid=123) |
2616 | @@ -910,13 +912,13 @@ | |||
2617 | 910 | 912 | ||
2618 | 911 | @patch('subprocess.check_output') | 913 | @patch('subprocess.check_output') |
2619 | 912 | def test_gets_unit_attribute(self, check_output_): | 914 | def test_gets_unit_attribute(self, check_output_): |
2621 | 913 | check_output_.return_value = json.dumps('bar') | 915 | check_output_.return_value = json.dumps('bar').encode('UTF-8') |
2622 | 914 | self.assertEqual(hookenv.unit_get('foo'), 'bar') | 916 | self.assertEqual(hookenv.unit_get('foo'), 'bar') |
2623 | 915 | check_output_.assert_called_with(['unit-get', '--format=json', 'foo']) | 917 | check_output_.assert_called_with(['unit-get', '--format=json', 'foo']) |
2624 | 916 | 918 | ||
2625 | 917 | @patch('subprocess.check_output') | 919 | @patch('subprocess.check_output') |
2626 | 918 | def test_gets_missing_unit_attribute(self, check_output_): | 920 | def test_gets_missing_unit_attribute(self, check_output_): |
2628 | 919 | check_output_.return_value = "" | 921 | check_output_.return_value = b"" |
2629 | 920 | self.assertEqual(hookenv.unit_get('foo'), None) | 922 | self.assertEqual(hookenv.unit_get('foo'), None) |
2630 | 921 | check_output_.assert_called_with(['unit-get', '--format=json', 'foo']) | 923 | check_output_.assert_called_with(['unit-get', '--format=json', 'foo']) |
2631 | 922 | 924 | ||
2632 | @@ -925,8 +927,8 @@ | |||
2633 | 925 | values = { | 927 | values = { |
2634 | 926 | 'hello': 'world', | 928 | 'hello': 'world', |
2635 | 927 | 'foo': 'bar', | 929 | 'foo': 'bar', |
2638 | 928 | 'baz': None | 930 | 'baz': None, |
2639 | 929 | } | 931 | } |
2640 | 930 | 932 | ||
2641 | 931 | @hookenv.cached | 933 | @hookenv.cached |
2642 | 932 | def cache_function(attribute): | 934 | def cache_function(attribute): |
2643 | 933 | 935 | ||
2644 | === modified file 'tests/core/test_host.py' | |||
2645 | --- tests/core/test_host.py 2014-11-25 14:35:22 +0000 | |||
2646 | +++ tests/core/test_host.py 2014-11-25 15:09:14 +0000 | |||
2647 | @@ -19,30 +19,30 @@ | |||
2648 | 19 | """rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 | 19 | """rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 |
2649 | 20 | """).strip().split('\n') | 20 | """).strip().split('\n') |
2650 | 21 | 21 | ||
2652 | 22 | LSB_RELEASE = u'''DISTRIB_ID=Ubuntu | 22 | LSB_RELEASE = '''DISTRIB_ID=Ubuntu |
2653 | 23 | DISTRIB_RELEASE=13.10 | 23 | DISTRIB_RELEASE=13.10 |
2654 | 24 | DISTRIB_CODENAME=saucy | 24 | DISTRIB_CODENAME=saucy |
2655 | 25 | DISTRIB_DESCRIPTION="Ubuntu Saucy Salamander (development branch)" | 25 | DISTRIB_DESCRIPTION="Ubuntu Saucy Salamander (development branch)" |
2656 | 26 | ''' | 26 | ''' |
2657 | 27 | 27 | ||
2659 | 28 | IP_LINE_ETH0 = (""" | 28 | IP_LINE_ETH0 = b""" |
2660 | 29 | 2: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP qlen 1000 | 29 | 2: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP qlen 1000 |
2661 | 30 | link/ether e4:11:5b:ab:a7:3c brd ff:ff:ff:ff:ff:ff | 30 | link/ether e4:11:5b:ab:a7:3c brd ff:ff:ff:ff:ff:ff |
2663 | 31 | """) | 31 | """ |
2664 | 32 | 32 | ||
2666 | 33 | IP_LINE_ETH1 = (""" | 33 | IP_LINE_ETH1 = b""" |
2667 | 34 | 3: eth1: <BROADCAST,MULTICAST> mtu 1546 qdisc noop state DOWN qlen 1000 | 34 | 3: eth1: <BROADCAST,MULTICAST> mtu 1546 qdisc noop state DOWN qlen 1000 |
2668 | 35 | link/ether e4:11:5b:ab:a7:3c brd ff:ff:ff:ff:ff:ff | 35 | link/ether e4:11:5b:ab:a7:3c brd ff:ff:ff:ff:ff:ff |
2670 | 36 | """) | 36 | """ |
2671 | 37 | 37 | ||
2673 | 38 | IP_LINE_HWADDR = ("""2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000\ link/ether e4:11:5b:ab:a7:3c brd ff:ff:ff:ff:ff:ff""") | 38 | IP_LINE_HWADDR = b"""2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000\ link/ether e4:11:5b:ab:a7:3c brd ff:ff:ff:ff:ff:ff""" |
2674 | 39 | 39 | ||
2675 | 40 | IP_LINES = IP_LINE_ETH0 + IP_LINE_ETH1 | 40 | IP_LINES = IP_LINE_ETH0 + IP_LINE_ETH1 |
2676 | 41 | 41 | ||
2678 | 42 | IP_LINE_BONDS = (""" | 42 | IP_LINE_BONDS = b""" |
2679 | 43 | 6: bond0.10@bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default | 43 | 6: bond0.10@bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default |
2680 | 44 | link/ether 08:00:27:16:b9:5f brd ff:ff:ff:ff:ff:ff | 44 | link/ether 08:00:27:16:b9:5f brd ff:ff:ff:ff:ff:ff |
2682 | 45 | """) | 45 | """ |
2683 | 46 | 46 | ||
2684 | 47 | 47 | ||
2685 | 48 | class HelpersTest(TestCase): | 48 | class HelpersTest(TestCase): |
2686 | @@ -166,12 +166,12 @@ | |||
2687 | 166 | 166 | ||
2688 | 167 | @patch('subprocess.check_output') | 167 | @patch('subprocess.check_output') |
2689 | 168 | def test_service_running_on_stopped_service(self, check_output): | 168 | def test_service_running_on_stopped_service(self, check_output): |
2691 | 169 | check_output.return_value = 'foo stop/waiting' | 169 | check_output.return_value = b'foo stop/waiting' |
2692 | 170 | self.assertFalse(host.service_running('foo')) | 170 | self.assertFalse(host.service_running('foo')) |
2693 | 171 | 171 | ||
2694 | 172 | @patch('subprocess.check_output') | 172 | @patch('subprocess.check_output') |
2695 | 173 | def test_service_running_on_running_service(self, check_output): | 173 | def test_service_running_on_running_service(self, check_output): |
2697 | 174 | check_output.return_value = 'foo start/running, process 23871' | 174 | check_output.return_value = b'foo start/running, process 23871' |
2698 | 175 | self.assertTrue(host.service_running('foo')) | 175 | self.assertTrue(host.service_running('foo')) |
2699 | 176 | 176 | ||
2700 | 177 | @patch('subprocess.check_output') | 177 | @patch('subprocess.check_output') |
2701 | @@ -284,7 +284,7 @@ | |||
2702 | 284 | def test_rsyncs_a_path(self, log, check_output): | 284 | def test_rsyncs_a_path(self, log, check_output): |
2703 | 285 | from_path = '/from/this/path/foo' | 285 | from_path = '/from/this/path/foo' |
2704 | 286 | to_path = '/to/this/path/bar' | 286 | to_path = '/to/this/path/bar' |
2706 | 287 | check_output.return_value = ' some output ' | 287 | check_output.return_value = b' some output ' # Spaces will be stripped |
2707 | 288 | 288 | ||
2708 | 289 | result = host.rsync(from_path, to_path) | 289 | result = host.rsync(from_path, to_path) |
2709 | 290 | 290 | ||
2710 | @@ -319,7 +319,7 @@ | |||
2711 | 319 | path = '/some/other/path/from/link' | 319 | path = '/some/other/path/from/link' |
2712 | 320 | realpath = '/some/path' | 320 | realpath = '/some/path' |
2713 | 321 | path_exists = False | 321 | path_exists = False |
2715 | 322 | perms = 0644 | 322 | perms = 0o644 |
2716 | 323 | 323 | ||
2717 | 324 | getpwnam.return_value.pw_uid = uid | 324 | getpwnam.return_value.pw_uid = uid |
2718 | 325 | getgrnam.return_value.gr_gid = gid | 325 | getgrnam.return_value.gr_gid = gid |
2719 | @@ -343,7 +343,7 @@ | |||
2720 | 343 | path = '/some/other/path/from/link' | 343 | path = '/some/other/path/from/link' |
2721 | 344 | realpath = '/some/path' | 344 | realpath = '/some/path' |
2722 | 345 | path_exists = False | 345 | path_exists = False |
2724 | 346 | perms = 0555 | 346 | perms = 0o555 |
2725 | 347 | 347 | ||
2726 | 348 | os_.path.abspath.return_value = realpath | 348 | os_.path.abspath.return_value = realpath |
2727 | 349 | os_.path.exists.return_value = path_exists | 349 | os_.path.exists.return_value = path_exists |
2728 | @@ -370,7 +370,7 @@ | |||
2729 | 370 | path_exists = True | 370 | path_exists = True |
2730 | 371 | force = True | 371 | force = True |
2731 | 372 | is_dir = False | 372 | is_dir = False |
2733 | 373 | perms = 0644 | 373 | perms = 0o644 |
2734 | 374 | 374 | ||
2735 | 375 | getpwnam.return_value.pw_uid = uid | 375 | getpwnam.return_value.pw_uid = uid |
2736 | 376 | getgrnam.return_value.gr_gid = gid | 376 | getgrnam.return_value.gr_gid = gid |
2737 | @@ -402,7 +402,7 @@ | |||
2738 | 402 | group = 'some-group-{bar}' | 402 | group = 'some-group-{bar}' |
2739 | 403 | path = '/some/path/{baz}' | 403 | path = '/some/path/{baz}' |
2740 | 404 | contents = 'what is {juju}' | 404 | contents = 'what is {juju}' |
2742 | 405 | perms = 0644 | 405 | perms = 0o644 |
2743 | 406 | fileno = 'some-fileno' | 406 | fileno = 'some-fileno' |
2744 | 407 | 407 | ||
2745 | 408 | getpwnam.return_value.pw_uid = uid | 408 | getpwnam.return_value.pw_uid = uid |
2746 | @@ -428,7 +428,7 @@ | |||
2747 | 428 | gid = 0 | 428 | gid = 0 |
2748 | 429 | path = '/some/path/{baz}' | 429 | path = '/some/path/{baz}' |
2749 | 430 | fmtstr = 'what is {juju}' | 430 | fmtstr = 'what is {juju}' |
2751 | 431 | perms = 0444 | 431 | perms = 0o444 |
2752 | 432 | fileno = 'some-fileno' | 432 | fileno = 'some-fileno' |
2753 | 433 | 433 | ||
2754 | 434 | with patch_open() as (mock_open, mock_file): | 434 | with patch_open() as (mock_open, mock_file): |
2755 | @@ -636,7 +636,7 @@ | |||
2756 | 636 | 636 | ||
2757 | 637 | @host.restart_on_change(restart_map) | 637 | @host.restart_on_change(restart_map) |
2758 | 638 | def make_some_changes(mock_file): | 638 | def make_some_changes(mock_file): |
2760 | 639 | mock_file.read.return_value = "newstuff" | 639 | mock_file.read.return_value = b"newstuff" |
2761 | 640 | 640 | ||
2762 | 641 | with patch_open() as (mock_open, mock_file): | 641 | with patch_open() as (mock_open, mock_file): |
2763 | 642 | make_some_changes(mock_file) | 642 | make_some_changes(mock_file) |
2764 | @@ -664,7 +664,7 @@ | |||
2765 | 664 | pass | 664 | pass |
2766 | 665 | 665 | ||
2767 | 666 | with patch_open() as (mock_open, mock_file): | 666 | with patch_open() as (mock_open, mock_file): |
2769 | 667 | mock_file.read.side_effect = ['exists', 'missing', 'exists2'] | 667 | mock_file.read.side_effect = [b'exists', b'missing', b'exists2'] |
2770 | 668 | make_some_changes() | 668 | make_some_changes() |
2771 | 669 | 669 | ||
2772 | 670 | # Restart should only happen once per service | 670 | # Restart should only happen once per service |
2773 | @@ -691,7 +691,7 @@ | |||
2774 | 691 | pass | 691 | pass |
2775 | 692 | 692 | ||
2776 | 693 | with patch_open() as (mock_open, mock_file): | 693 | with patch_open() as (mock_open, mock_file): |
2778 | 694 | mock_file.read.side_effect = ['exists', 'missing', 'exists2'] | 694 | mock_file.read.side_effect = [b'exists', b'missing', b'exists2'] |
2779 | 695 | make_some_changes() | 695 | make_some_changes() |
2780 | 696 | 696 | ||
2781 | 697 | # Restarts should happen in the order they are described in the | 697 | # Restarts should happen in the order they are described in the |
2782 | @@ -713,7 +713,6 @@ | |||
2783 | 713 | with mocked_open('/etc/lsb-release', LSB_RELEASE): | 713 | with mocked_open('/etc/lsb-release', LSB_RELEASE): |
2784 | 714 | lsb_release = host.lsb_release() | 714 | lsb_release = host.lsb_release() |
2785 | 715 | for key in result: | 715 | for key in result: |
2786 | 716 | print lsb_release | ||
2787 | 717 | self.assertEqual(result[key], lsb_release[key]) | 716 | self.assertEqual(result[key], lsb_release[key]) |
2788 | 718 | 717 | ||
2789 | 719 | def test_pwgen(self): | 718 | def test_pwgen(self): |
2790 | 720 | 719 | ||
2791 | === modified file 'tests/core/test_services.py' | |||
2792 | --- tests/core/test_services.py 2014-11-25 14:35:22 +0000 | |||
2793 | +++ tests/core/test_services.py 2014-11-25 15:09:14 +0000 | |||
2794 | @@ -573,7 +573,7 @@ | |||
2795 | 573 | with mock.patch.object(services.helpers, 'open', mopen, create=True): | 573 | with mock.patch.object(services.helpers, 'open', mopen, create=True): |
2796 | 574 | services.helpers.StoredContext('foo.yaml', {'key': 'val'}) | 574 | services.helpers.StoredContext('foo.yaml', {'key': 'val'}) |
2797 | 575 | mopen.assert_called_once_with('charm_dir/foo.yaml', 'w') | 575 | mopen.assert_called_once_with('charm_dir/foo.yaml', 'w') |
2799 | 576 | fchmod.assert_called_once_with(mopen.return_value.fileno(), 0600) | 576 | fchmod.assert_called_once_with(mopen.return_value.fileno(), 0o600) |
2800 | 577 | yaml.dump.assert_called_once_with({'key': 'val'}, mopen.return_value) | 577 | yaml.dump.assert_called_once_with({'key': 'val'}, mopen.return_value) |
2801 | 578 | 578 | ||
2802 | 579 | @mock.patch.object(hookenv, 'charm_dir', lambda: 'charm_dir') | 579 | @mock.patch.object(hookenv, 'charm_dir', lambda: 'charm_dir') |
2803 | @@ -637,7 +637,7 @@ | |||
2804 | 637 | callback(manager, 'test', 'event') | 637 | callback(manager, 'test', 'event') |
2805 | 638 | mtemplating.render.assert_called_once_with( | 638 | mtemplating.render.assert_called_once_with( |
2806 | 639 | 'foo.yml', 'bar.yml', {'foo': 'bar'}, | 639 | 'foo.yml', 'bar.yml', {'foo': 'bar'}, |
2808 | 640 | 'root', 'root', 0444) | 640 | 'root', 'root', 0o444) |
2809 | 641 | 641 | ||
2810 | 642 | @mock.patch.object(services.helpers, 'templating') | 642 | @mock.patch.object(services.helpers, 'templating') |
2811 | 643 | def test_template_explicit(self, mtemplating): | 643 | def test_template_explicit(self, mtemplating): |
2812 | @@ -645,14 +645,14 @@ | |||
2813 | 645 | 'required_data': [{'foo': 'bar'}]}}) | 645 | 'required_data': [{'foo': 'bar'}]}}) |
2814 | 646 | callback = services.template( | 646 | callback = services.template( |
2815 | 647 | source='foo.yml', target='bar.yml', | 647 | source='foo.yml', target='bar.yml', |
2817 | 648 | owner='user', group='group', perms=0555 | 648 | owner='user', group='group', perms=0o555 |
2818 | 649 | ) | 649 | ) |
2819 | 650 | assert isinstance(callback, services.ManagerCallback) | 650 | assert isinstance(callback, services.ManagerCallback) |
2820 | 651 | assert not mtemplating.render.called | 651 | assert not mtemplating.render.called |
2821 | 652 | callback(manager, 'test', 'event') | 652 | callback(manager, 'test', 'event') |
2822 | 653 | mtemplating.render.assert_called_once_with( | 653 | mtemplating.render.assert_called_once_with( |
2823 | 654 | 'foo.yml', 'bar.yml', {'foo': 'bar'}, | 654 | 'foo.yml', 'bar.yml', {'foo': 'bar'}, |
2825 | 655 | 'user', 'group', 0555) | 655 | 'user', 'group', 0o555) |
2826 | 656 | 656 | ||
2827 | 657 | 657 | ||
2828 | 658 | class TestPortsCallback(unittest.TestCase): | 658 | class TestPortsCallback(unittest.TestCase): |
2829 | 659 | 659 | ||
2830 | === modified file 'tests/core/test_sysctl.py' | |||
2831 | --- tests/core/test_sysctl.py 2014-11-25 14:35:22 +0000 | |||
2832 | +++ tests/core/test_sysctl.py 2014-11-25 15:09:14 +0000 | |||
2833 | @@ -4,11 +4,18 @@ | |||
2834 | 4 | __author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>' | 4 | __author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>' |
2835 | 5 | 5 | ||
2836 | 6 | from charmhelpers.core.sysctl import create | 6 | from charmhelpers.core.sysctl import create |
2837 | 7 | import io | ||
2838 | 7 | from mock import patch, MagicMock | 8 | from mock import patch, MagicMock |
2839 | 8 | |||
2840 | 9 | import unittest | 9 | import unittest |
2841 | 10 | import tempfile | 10 | import tempfile |
2842 | 11 | 11 | ||
2843 | 12 | import six | ||
2844 | 13 | if not six.PY3: | ||
2845 | 14 | builtin_open = '__builtin__.open' | ||
2846 | 15 | else: | ||
2847 | 16 | builtin_open = 'builtins.open' | ||
2848 | 17 | |||
2849 | 18 | |||
2850 | 12 | TO_PATCH = [ | 19 | TO_PATCH = [ |
2851 | 13 | 'log', | 20 | 'log', |
2852 | 14 | 'check_call', | 21 | 'check_call', |
2853 | @@ -27,10 +34,10 @@ | |||
2854 | 27 | self.addCleanup(_m.stop) | 34 | self.addCleanup(_m.stop) |
2855 | 28 | return mock | 35 | return mock |
2856 | 29 | 36 | ||
2858 | 30 | @patch('__builtin__.open') | 37 | @patch(builtin_open) |
2859 | 31 | def test_create(self, mock_open): | 38 | def test_create(self, mock_open): |
2860 | 32 | """Test create sysctl method""" | 39 | """Test create sysctl method""" |
2862 | 33 | _file = MagicMock(spec=file) | 40 | _file = MagicMock(spec=io.FileIO) |
2863 | 34 | mock_open.return_value = _file | 41 | mock_open.return_value = _file |
2864 | 35 | 42 | ||
2865 | 36 | create('{"kernel.max_pid": 1337}', "/etc/sysctl.d/test-sysctl.conf") | 43 | create('{"kernel.max_pid": 1337}', "/etc/sysctl.d/test-sysctl.conf") |
2866 | 37 | 44 | ||
2867 | === modified file 'tests/fetch/test_archiveurl.py' | |||
2868 | --- tests/fetch/test_archiveurl.py 2014-11-25 14:35:22 +0000 | |||
2869 | +++ tests/fetch/test_archiveurl.py 2014-11-25 15:09:14 +0000 | |||
2870 | @@ -1,6 +1,14 @@ | |||
2871 | 1 | import os | 1 | import os |
2874 | 2 | from testtools import TestCase | 2 | |
2875 | 3 | from urlparse import urlparse | 3 | import six |
2876 | 4 | if six.PY3: | ||
2877 | 5 | from urllib.parse import urlparse | ||
2878 | 6 | from urllib.error import URLError | ||
2879 | 7 | else: | ||
2880 | 8 | from urllib2 import URLError | ||
2881 | 9 | from urlparse import urlparse | ||
2882 | 10 | |||
2883 | 11 | from unittest import TestCase | ||
2884 | 4 | from mock import ( | 12 | from mock import ( |
2885 | 5 | MagicMock, | 13 | MagicMock, |
2886 | 6 | patch, | 14 | patch, |
2887 | @@ -11,7 +19,6 @@ | |||
2888 | 11 | archiveurl, | 19 | archiveurl, |
2889 | 12 | UnhandledSource, | 20 | UnhandledSource, |
2890 | 13 | ) | 21 | ) |
2891 | 14 | import urllib2 | ||
2892 | 15 | 22 | ||
2893 | 16 | 23 | ||
2894 | 17 | class ArchiveUrlFetchHandlerTest(TestCase): | 24 | class ArchiveUrlFetchHandlerTest(TestCase): |
2895 | @@ -50,7 +57,7 @@ | |||
2896 | 50 | result = self.fh.can_handle(url) | 57 | result = self.fh.can_handle(url) |
2897 | 51 | self.assertNotEqual(result, True, url) | 58 | self.assertNotEqual(result, True, url) |
2898 | 52 | 59 | ||
2900 | 53 | @patch('urllib2.urlopen') | 60 | @patch('charmhelpers.fetch.archiveurl.urlopen') |
2901 | 54 | def test_downloads(self, _urlopen): | 61 | def test_downloads(self, _urlopen): |
2902 | 55 | for url in self.valid_urls: | 62 | for url in self.valid_urls: |
2903 | 56 | response = MagicMock() | 63 | response = MagicMock() |
2904 | @@ -87,7 +94,7 @@ | |||
2905 | 87 | 94 | ||
2906 | 88 | url = "http://www.example.com/archive.tar.gz" | 95 | url = "http://www.example.com/archive.tar.gz" |
2907 | 89 | 96 | ||
2909 | 90 | self.fh.download.side_effect = urllib2.URLError('fail') | 97 | self.fh.download.side_effect = URLError('fail') |
2910 | 91 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): | 98 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): |
2911 | 92 | self.assertRaises(UnhandledSource, self.fh.install, url) | 99 | self.assertRaises(UnhandledSource, self.fh.install, url) |
2912 | 93 | 100 | ||
2913 | 94 | 101 | ||
2914 | === modified file 'tests/fetch/test_bzrurl.py' | |||
2915 | --- tests/fetch/test_bzrurl.py 2014-11-25 14:35:22 +0000 | |||
2916 | +++ tests/fetch/test_bzrurl.py 2014-11-25 15:09:14 +0000 | |||
2917 | @@ -1,20 +1,34 @@ | |||
2918 | 1 | import os | 1 | import os |
2919 | 2 | from testtools import TestCase | 2 | from testtools import TestCase |
2920 | 3 | from urlparse import urlparse | ||
2921 | 4 | from mock import ( | 3 | from mock import ( |
2922 | 5 | MagicMock, | 4 | MagicMock, |
2923 | 6 | patch, | 5 | patch, |
2924 | 7 | ) | 6 | ) |
2931 | 8 | from charmhelpers.fetch import ( | 7 | import unittest |
2932 | 9 | bzrurl, | 8 | |
2933 | 10 | UnhandledSource, | 9 | import six |
2934 | 11 | ) | 10 | if six.PY3: |
2935 | 12 | 11 | from urllib.parse import urlparse | |
2936 | 13 | 12 | else: | |
2937 | 13 | from urlparse import urlparse | ||
2938 | 14 | |||
2939 | 15 | try: | ||
2940 | 16 | from charmhelpers.fetch import ( | ||
2941 | 17 | bzrurl, | ||
2942 | 18 | UnhandledSource, | ||
2943 | 19 | ) | ||
2944 | 20 | except ImportError: | ||
2945 | 21 | bzrurl = None | ||
2946 | 22 | UnhandledSource = None | ||
2947 | 23 | |||
2948 | 24 | |||
2949 | 25 | @unittest.skipIf(six.PY3, 'bzr does not support Python 3') | ||
2950 | 14 | class BzrUrlFetchHandlerTest(TestCase): | 26 | class BzrUrlFetchHandlerTest(TestCase): |
2951 | 15 | 27 | ||
2952 | 16 | def setUp(self): | 28 | def setUp(self): |
2953 | 17 | super(BzrUrlFetchHandlerTest, self).setUp() | 29 | super(BzrUrlFetchHandlerTest, self).setUp() |
2954 | 30 | if six.PY3: | ||
2955 | 31 | return | ||
2956 | 18 | self.valid_urls = ( | 32 | self.valid_urls = ( |
2957 | 19 | "bzr+ssh://example.com/branch-name", | 33 | "bzr+ssh://example.com/branch-name", |
2958 | 20 | "bzr+ssh://example.com/branch-name/", | 34 | "bzr+ssh://example.com/branch-name/", |
2959 | @@ -41,6 +55,7 @@ | |||
2960 | 41 | ) | 55 | ) |
2961 | 42 | self.fh = bzrurl.BzrUrlFetchHandler() | 56 | self.fh = bzrurl.BzrUrlFetchHandler() |
2962 | 43 | 57 | ||
2963 | 58 | @unittest.skipIf(six.PY3, 'bzr does not support Python 3') | ||
2964 | 44 | def test_handles_bzr_urls(self): | 59 | def test_handles_bzr_urls(self): |
2965 | 45 | for url in self.valid_urls: | 60 | for url in self.valid_urls: |
2966 | 46 | result = self.fh.can_handle(url) | 61 | result = self.fh.can_handle(url) |
2967 | @@ -49,6 +64,7 @@ | |||
2968 | 49 | result = self.fh.can_handle(url) | 64 | result = self.fh.can_handle(url) |
2969 | 50 | self.assertNotEqual(result, True, url) | 65 | self.assertNotEqual(result, True, url) |
2970 | 51 | 66 | ||
2971 | 67 | @unittest.skipIf(six.PY3, 'bzr does not support Python 3') | ||
2972 | 52 | @patch('bzrlib.branch.Branch.open') | 68 | @patch('bzrlib.branch.Branch.open') |
2973 | 53 | def test_branch(self, _open): | 69 | def test_branch(self, _open): |
2974 | 54 | dest_path = "/destination/path" | 70 | dest_path = "/destination/path" |
2975 | @@ -63,6 +79,7 @@ | |||
2976 | 63 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): | 79 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): |
2977 | 64 | self.assertRaises(UnhandledSource, self.fh.branch, url, dest_path) | 80 | self.assertRaises(UnhandledSource, self.fh.branch, url, dest_path) |
2978 | 65 | 81 | ||
2979 | 82 | @unittest.skipIf(six.PY3, 'bzr does not support Python 3') | ||
2980 | 66 | @patch('charmhelpers.fetch.bzrurl.mkdir') | 83 | @patch('charmhelpers.fetch.bzrurl.mkdir') |
2981 | 67 | def test_installs(self, _mkdir): | 84 | def test_installs(self, _mkdir): |
2982 | 68 | self.fh.branch = MagicMock() | 85 | self.fh.branch = MagicMock() |
2983 | @@ -73,4 +90,4 @@ | |||
2984 | 73 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): | 90 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): |
2985 | 74 | where = self.fh.install(url) | 91 | where = self.fh.install(url) |
2986 | 75 | self.assertEqual(where, dest) | 92 | self.assertEqual(where, dest) |
2988 | 76 | _mkdir.assert_called_with(where, perms=0755) | 93 | _mkdir.assert_called_with(where, perms=0o755) |
2989 | 77 | 94 | ||
2990 | === modified file 'tests/fetch/test_fetch.py' | |||
2991 | --- tests/fetch/test_fetch.py 2014-11-25 14:35:22 +0000 | |||
2992 | +++ tests/fetch/test_fetch.py 2014-11-25 15:09:14 +0000 | |||
2993 | @@ -1,4 +1,3 @@ | |||
2994 | 1 | from cStringIO import StringIO | ||
2995 | 2 | import subprocess | 1 | import subprocess |
2996 | 3 | 2 | ||
2997 | 4 | from tests.helpers import patch_open | 3 | from tests.helpers import patch_open |
2998 | @@ -8,11 +7,18 @@ | |||
2999 | 8 | MagicMock, | 7 | MagicMock, |
3000 | 9 | call, | 8 | call, |
3001 | 10 | ) | 9 | ) |
3002 | 11 | from urlparse import urlparse | ||
3003 | 12 | from charmhelpers import fetch | 10 | from charmhelpers import fetch |
3004 | 13 | import os | 11 | import os |
3005 | 14 | import yaml | 12 | import yaml |
3006 | 15 | 13 | ||
3007 | 14 | import six | ||
3008 | 15 | from six.moves import StringIO | ||
3009 | 16 | if six.PY3: | ||
3010 | 17 | from urllib.parse import urlparse | ||
3011 | 18 | else: | ||
3012 | 19 | from urlparse import urlparse | ||
3013 | 20 | |||
3014 | 21 | |||
3015 | 16 | FAKE_APT_CACHE = { | 22 | FAKE_APT_CACHE = { |
3016 | 17 | # an installed package | 23 | # an installed package |
3017 | 18 | 'vim': { | 24 | 'vim': { |
3018 | @@ -404,7 +410,11 @@ | |||
3019 | 404 | @patch('charmhelpers.fetch.log') | 410 | @patch('charmhelpers.fetch.log') |
3020 | 405 | def test_plugins_are_valid(self, log_): | 411 | def test_plugins_are_valid(self, log_): |
3021 | 406 | plugins = fetch.plugins() | 412 | plugins = fetch.plugins() |
3023 | 407 | self.assertEqual(len(fetch.FETCH_HANDLERS), len(plugins)) | 413 | if not six.PY3: |
3024 | 414 | self.assertEqual(len(fetch.FETCH_HANDLERS), len(plugins)) | ||
3025 | 415 | else: | ||
3026 | 416 | # No bzr or git libraries for Python3. | ||
3027 | 417 | self.assertEqual(len(fetch.FETCH_HANDLERS) - 2, len(plugins)) | ||
3028 | 408 | 418 | ||
3029 | 409 | 419 | ||
3030 | 410 | class BaseFetchHandlerTest(TestCase): | 420 | class BaseFetchHandlerTest(TestCase): |
3031 | 411 | 421 | ||
3032 | === modified file 'tests/fetch/test_giturl.py' | |||
3033 | --- tests/fetch/test_giturl.py 2014-11-25 14:35:22 +0000 | |||
3034 | +++ tests/fetch/test_giturl.py 2014-11-25 15:09:14 +0000 | |||
3035 | @@ -1,18 +1,31 @@ | |||
3036 | 1 | import os | 1 | import os |
3037 | 2 | from testtools import TestCase | 2 | from testtools import TestCase |
3038 | 3 | from urlparse import urlparse | ||
3039 | 4 | from mock import ( | 3 | from mock import ( |
3040 | 5 | MagicMock, | 4 | MagicMock, |
3041 | 6 | patch, | 5 | patch, |
3042 | 7 | ) | 6 | ) |
3049 | 8 | from charmhelpers.fetch import ( | 7 | import unittest |
3050 | 9 | giturl, | 8 | |
3051 | 10 | UnhandledSource, | 9 | import six |
3052 | 11 | ) | 10 | if six.PY3: |
3053 | 12 | 11 | from urllib.parse import urlparse | |
3054 | 13 | 12 | else: | |
3055 | 13 | from urlparse import urlparse | ||
3056 | 14 | |||
3057 | 15 | try: | ||
3058 | 16 | from charmhelpers.fetch import ( | ||
3059 | 17 | giturl, | ||
3060 | 18 | UnhandledSource, | ||
3061 | 19 | ) | ||
3062 | 20 | except ImportError: | ||
3063 | 21 | giturl = None | ||
3064 | 22 | UnhandledSource = None | ||
3065 | 23 | |||
3066 | 24 | |||
3067 | 25 | @unittest.skipIf(six.PY3, 'git does not support Python 3') | ||
3068 | 14 | class GitUrlFetchHandlerTest(TestCase): | 26 | class GitUrlFetchHandlerTest(TestCase): |
3069 | 15 | 27 | ||
3070 | 28 | @unittest.skipIf(six.PY3, 'git does not support Python 3') | ||
3071 | 16 | def setUp(self): | 29 | def setUp(self): |
3072 | 17 | super(GitUrlFetchHandlerTest, self).setUp() | 30 | super(GitUrlFetchHandlerTest, self).setUp() |
3073 | 18 | self.valid_urls = ( | 31 | self.valid_urls = ( |
3074 | @@ -27,6 +40,7 @@ | |||
3075 | 27 | ) | 40 | ) |
3076 | 28 | self.fh = giturl.GitUrlFetchHandler() | 41 | self.fh = giturl.GitUrlFetchHandler() |
3077 | 29 | 42 | ||
3078 | 43 | @unittest.skipIf(six.PY3, 'git does not support Python 3') | ||
3079 | 30 | def test_handles_git_urls(self): | 44 | def test_handles_git_urls(self): |
3080 | 31 | for url in self.valid_urls: | 45 | for url in self.valid_urls: |
3081 | 32 | result = self.fh.can_handle(url) | 46 | result = self.fh.can_handle(url) |
3082 | @@ -35,6 +49,7 @@ | |||
3083 | 35 | result = self.fh.can_handle(url) | 49 | result = self.fh.can_handle(url) |
3084 | 36 | self.assertNotEqual(result, True, url) | 50 | self.assertNotEqual(result, True, url) |
3085 | 37 | 51 | ||
3086 | 52 | @unittest.skipIf(six.PY3, 'git does not support Python 3') | ||
3087 | 38 | @patch('git.Repo.clone_from') | 53 | @patch('git.Repo.clone_from') |
3088 | 39 | def test_branch(self, _clone_from): | 54 | def test_branch(self, _clone_from): |
3089 | 40 | dest_path = "/destination/path" | 55 | dest_path = "/destination/path" |
3090 | @@ -52,6 +67,7 @@ | |||
3091 | 52 | dest_path, | 67 | dest_path, |
3092 | 53 | branch) | 68 | branch) |
3093 | 54 | 69 | ||
3094 | 70 | @unittest.skipIf(six.PY3, 'git does not support Python 3') | ||
3095 | 55 | @patch('charmhelpers.fetch.giturl.mkdir') | 71 | @patch('charmhelpers.fetch.giturl.mkdir') |
3096 | 56 | def test_installs(self, _mkdir): | 72 | def test_installs(self, _mkdir): |
3097 | 57 | self.fh.clone = MagicMock() | 73 | self.fh.clone = MagicMock() |
3098 | @@ -63,4 +79,4 @@ | |||
3099 | 63 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): | 79 | with patch.dict('os.environ', {'CHARM_DIR': 'foo'}): |
3100 | 64 | where = self.fh.install(url) | 80 | where = self.fh.install(url) |
3101 | 65 | self.assertEqual(where, dest) | 81 | self.assertEqual(where, dest) |
3103 | 66 | _mkdir.assert_called_with(where, perms=0755) | 82 | _mkdir.assert_called_with(where, perms=0o755) |
3104 | 67 | 83 | ||
3105 | === modified file 'tests/helpers.py' | |||
3106 | --- tests/helpers.py 2014-11-25 14:35:22 +0000 | |||
3107 | +++ tests/helpers.py 2014-11-25 15:09:14 +0000 | |||
3108 | @@ -3,6 +3,12 @@ | |||
3109 | 3 | from mock import patch, MagicMock | 3 | from mock import patch, MagicMock |
3110 | 4 | import io | 4 | import io |
3111 | 5 | 5 | ||
3112 | 6 | import six | ||
3113 | 7 | if not six.PY3: | ||
3114 | 8 | builtin_open = '__builtin__.open' | ||
3115 | 9 | else: | ||
3116 | 10 | builtin_open = 'builtins.open' | ||
3117 | 11 | |||
3118 | 6 | 12 | ||
3119 | 7 | @contextmanager | 13 | @contextmanager |
3120 | 8 | def patch_open(): | 14 | def patch_open(): |
3121 | @@ -11,26 +17,29 @@ | |||
3122 | 11 | 17 | ||
3123 | 12 | Yields the mock for "open" and "file", respectively.''' | 18 | Yields the mock for "open" and "file", respectively.''' |
3124 | 13 | mock_open = MagicMock(spec=open) | 19 | mock_open = MagicMock(spec=open) |
3126 | 14 | mock_file = MagicMock(spec=file) | 20 | mock_file = MagicMock(spec=io.FileIO) |
3127 | 15 | 21 | ||
3128 | 16 | @contextmanager | 22 | @contextmanager |
3129 | 17 | def stub_open(*args, **kwargs): | 23 | def stub_open(*args, **kwargs): |
3130 | 18 | mock_open(*args, **kwargs) | 24 | mock_open(*args, **kwargs) |
3131 | 19 | yield mock_file | 25 | yield mock_file |
3132 | 20 | 26 | ||
3134 | 21 | with patch('__builtin__.open', stub_open): | 27 | with patch(builtin_open, stub_open): |
3135 | 22 | yield mock_open, mock_file | 28 | yield mock_open, mock_file |
3136 | 23 | 29 | ||
3137 | 24 | 30 | ||
3138 | 25 | @contextmanager | 31 | @contextmanager |
3139 | 26 | def mock_open(filename, contents=None): | 32 | def mock_open(filename, contents=None): |
3140 | 27 | ''' Slightly simpler mock of open to return contents for filename ''' | 33 | ''' Slightly simpler mock of open to return contents for filename ''' |
3143 | 28 | def mock_file(*args): | 34 | def mock_file(name, mode='r', buffering=-1): # Python 2 signature. |
3144 | 29 | if args[0] == filename: | 35 | if name == filename: |
3145 | 36 | if (not six.PY3) or 'b' in mode: | ||
3146 | 37 | return io.BytesIO(contents) | ||
3147 | 30 | return io.StringIO(contents) | 38 | return io.StringIO(contents) |
3148 | 31 | else: | 39 | else: |
3151 | 32 | return open(*args) | 40 | return open(name, mode, buffering) |
3152 | 33 | with patch('__builtin__.open', mock_file): | 41 | |
3153 | 42 | with patch(builtin_open, mock_file): | ||
3154 | 34 | yield | 43 | yield |
3155 | 35 | 44 | ||
3156 | 36 | 45 | ||
3157 | 37 | 46 | ||
3158 | === modified file 'tests/payload/test_archive.py' | |||
3159 | --- tests/payload/test_archive.py 2014-11-25 14:35:22 +0000 | |||
3160 | +++ tests/payload/test_archive.py 2014-11-25 15:09:14 +0000 | |||
3161 | @@ -84,7 +84,7 @@ | |||
3162 | 84 | self.addCleanup(rmtree, destdir) | 84 | self.addCleanup(rmtree, destdir) |
3163 | 85 | try: | 85 | try: |
3164 | 86 | zip_file, contents = self.create_archive("zip") | 86 | zip_file, contents = self.create_archive("zip") |
3166 | 87 | except subprocess.CalledProcessError, e: | 87 | except subprocess.CalledProcessError as e: |
3167 | 88 | if e.returncode == 127: | 88 | if e.returncode == 127: |
3168 | 89 | self.skip("Skipping - zip is not installed") | 89 | self.skip("Skipping - zip is not installed") |
3169 | 90 | else: | 90 | else: |
3170 | 91 | 91 | ||
3171 | === modified file 'tests/payload/test_execd.py' | |||
3172 | --- tests/payload/test_execd.py 2013-07-11 08:31:49 +0000 | |||
3173 | +++ tests/payload/test_execd.py 2014-11-25 15:09:14 +0000 | |||
3174 | @@ -111,7 +111,7 @@ | |||
3175 | 111 | 111 | ||
3176 | 112 | expected = [os.path.join(self.test_charm_dir, 'exec.d', mod, | 112 | expected = [os.path.join(self.test_charm_dir, 'exec.d', mod, |
3177 | 113 | 'charm-pre-install') for mod in modules] | 113 | 'charm-pre-install') for mod in modules] |
3179 | 114 | self.assertItemsEqual(submodules, expected) | 114 | self.assertEqual(sorted(submodules), sorted(expected)) |
3180 | 115 | 115 | ||
3181 | 116 | def test_execd_run(self): | 116 | def test_execd_run(self): |
3182 | 117 | modules = ['basenode', 'mod2', 'c'] | 117 | modules = ['basenode', 'mod2', 'c'] |
3183 | 118 | 118 | ||
3184 | === modified file 'tests/tools/test_charm_helper_sync.py' | |||
3185 | --- tests/tools/test_charm_helper_sync.py 2014-11-25 14:35:22 +0000 | |||
3186 | +++ tests/tools/test_charm_helper_sync.py 2014-11-25 15:09:14 +0000 | |||
3187 | @@ -2,6 +2,13 @@ | |||
3188 | 2 | from mock import call, patch | 2 | from mock import call, patch |
3189 | 3 | import yaml | 3 | import yaml |
3190 | 4 | 4 | ||
3191 | 5 | import six | ||
3192 | 6 | if not six.PY3: | ||
3193 | 7 | builtin_open = '__builtin__.open' | ||
3194 | 8 | else: | ||
3195 | 9 | builtin_open = 'builtins.open' | ||
3196 | 10 | |||
3197 | 11 | |||
3198 | 5 | import tools.charm_helpers_sync.charm_helpers_sync as sync | 12 | import tools.charm_helpers_sync.charm_helpers_sync as sync |
3199 | 6 | 13 | ||
3200 | 7 | INCLUDE = """ | 14 | INCLUDE = """ |
3201 | @@ -46,7 +53,7 @@ | |||
3202 | 46 | self.assertEquals('/tmp/mycharm/hooks/charmhelpers/contrib/openstack', | 53 | self.assertEquals('/tmp/mycharm/hooks/charmhelpers/contrib/openstack', |
3203 | 47 | path) | 54 | path) |
3204 | 48 | 55 | ||
3206 | 49 | @patch('__builtin__.open') | 56 | @patch(builtin_open) |
3207 | 50 | @patch('os.path.exists') | 57 | @patch('os.path.exists') |
3208 | 51 | @patch('os.walk') | 58 | @patch('os.walk') |
3209 | 52 | def test_ensure_init(self, walk, exists, _open): | 59 | def test_ensure_init(self, walk, exists, _open): |
3210 | @@ -114,7 +121,7 @@ | |||
3211 | 114 | isfile.side_effect = _isfile | 121 | isfile.side_effect = _isfile |
3212 | 115 | isdir.side_effect = _isdir | 122 | isdir.side_effect = _isdir |
3213 | 116 | result = sync.get_filter(opts)(dir='/tmp/charm-helpers/core', | 123 | result = sync.get_filter(opts)(dir='/tmp/charm-helpers/core', |
3215 | 117 | ls=files.iterkeys()) | 124 | ls=six.iterkeys(files)) |
3216 | 118 | return result | 125 | return result |
3217 | 119 | 126 | ||
3218 | 120 | @patch('os.path.isdir') | 127 | @patch('os.path.isdir') |
3219 | @@ -123,15 +130,15 @@ | |||
3220 | 123 | '''It filters out all non-py files by default''' | 130 | '''It filters out all non-py files by default''' |
3221 | 124 | result = self._test_filter_dir(opts=None, isfile=isfile, isdir=isdir) | 131 | result = self._test_filter_dir(opts=None, isfile=isfile, isdir=isdir) |
3222 | 125 | ex = ['bad_file.bin', 'bad_file.img', 'some_dir'] | 132 | ex = ['bad_file.bin', 'bad_file.img', 'some_dir'] |
3224 | 126 | self.assertEquals(ex, result) | 133 | self.assertEquals(sorted(ex), sorted(result)) |
3225 | 127 | 134 | ||
3226 | 128 | @patch('os.path.isdir') | 135 | @patch('os.path.isdir') |
3227 | 129 | @patch('os.path.isfile') | 136 | @patch('os.path.isfile') |
3228 | 130 | def test_filter_dir_with_include(self, isfile, isdir): | 137 | def test_filter_dir_with_include(self, isfile, isdir): |
3229 | 131 | '''It includes non-py files if specified as an include opt''' | 138 | '''It includes non-py files if specified as an include opt''' |
3233 | 132 | result = self._test_filter_dir(opts=['inc=*.img'], | 139 | result = sorted(self._test_filter_dir(opts=['inc=*.img'], |
3234 | 133 | isfile=isfile, isdir=isdir) | 140 | isfile=isfile, isdir=isdir)) |
3235 | 134 | ex = ['bad_file.bin', 'some_dir'] | 141 | ex = sorted(['bad_file.bin', 'some_dir']) |
3236 | 135 | self.assertEquals(ex, result) | 142 | self.assertEquals(ex, result) |
3237 | 136 | 143 | ||
3238 | 137 | @patch('os.path.isdir') | 144 | @patch('os.path.isdir') |
3239 | 138 | 145 | ||
3240 | === modified file 'tools/charm_helpers_sync/charm_helpers_sync.py' | |||
3241 | --- tools/charm_helpers_sync/charm_helpers_sync.py 2014-11-25 14:35:22 +0000 | |||
3242 | +++ tools/charm_helpers_sync/charm_helpers_sync.py 2014-11-25 15:09:14 +0000 | |||
3243 | @@ -14,9 +14,10 @@ | |||
3244 | 14 | import sys | 14 | import sys |
3245 | 15 | import tempfile | 15 | import tempfile |
3246 | 16 | import yaml | 16 | import yaml |
3247 | 17 | |||
3248 | 18 | from fnmatch import fnmatch | 17 | from fnmatch import fnmatch |
3249 | 19 | 18 | ||
3250 | 19 | import six | ||
3251 | 20 | |||
3252 | 20 | CHARM_HELPERS_BRANCH = 'lp:charm-helpers' | 21 | CHARM_HELPERS_BRANCH = 'lp:charm-helpers' |
3253 | 21 | 22 | ||
3254 | 22 | 23 | ||
3255 | @@ -139,7 +140,7 @@ | |||
3256 | 139 | 140 | ||
3257 | 140 | def extract_options(inc, global_options=None): | 141 | def extract_options(inc, global_options=None): |
3258 | 141 | global_options = global_options or [] | 142 | global_options = global_options or [] |
3260 | 142 | if global_options and isinstance(global_options, basestring): | 143 | if global_options and isinstance(global_options, six.string_types): |
3261 | 143 | global_options = [global_options] | 144 | global_options = [global_options] |
3262 | 144 | if '|' not in inc: | 145 | if '|' not in inc: |
3263 | 145 | return (inc, global_options) | 146 | return (inc, global_options) |
3264 | @@ -159,7 +160,7 @@ | |||
3265 | 159 | sync(src, dest, inc, opts) | 160 | sync(src, dest, inc, opts) |
3266 | 160 | elif isinstance(inc, dict): | 161 | elif isinstance(inc, dict): |
3267 | 161 | # could also do nested dicts here. | 162 | # could also do nested dicts here. |
3269 | 162 | for k, v in inc.iteritems(): | 163 | for k, v in six.iteritems(inc): |
3270 | 163 | if isinstance(v, list): | 164 | if isinstance(v, list): |
3271 | 164 | for m in v: | 165 | for m in v: |
3272 | 165 | inc, opts = extract_options(m, global_options) | 166 | inc, opts = extract_options(m, global_options) |
3273 | @@ -217,7 +218,7 @@ | |||
3274 | 217 | checkout = clone_helpers(tmpd, config['branch']) | 218 | checkout = clone_helpers(tmpd, config['branch']) |
3275 | 218 | sync_helpers(config['include'], checkout, config['destination'], | 219 | sync_helpers(config['include'], checkout, config['destination'], |
3276 | 219 | options=sync_options) | 220 | options=sync_options) |
3278 | 220 | except Exception, e: | 221 | except Exception as e: |
3279 | 221 | logging.error("Could not sync: %s" % e) | 222 | logging.error("Could not sync: %s" % e) |
3280 | 222 | raise e | 223 | raise e |
3281 | 223 | finally: | 224 | finally: |
Running make test in a clean precise lxc:
Checking for Python syntax... contrib/ templating/ contexts. py:99:54: E901 SyntaxError: invalid syntax templating/ test_contexts. py:137: 31: E901 SyntaxError: invalid syntax test_hookenv. py:132: 40: E901 SyntaxError: invalid syntax
Py2 OK
charmhelpers/
tests/contrib/
tests/core/
make: *** [lint] Error 1
Also, running apt-get as an import side-effect makes me grimace.