Merge lp:~harlowja/cloud-init/py2-3 into lp:~cloud-init-dev/cloud-init/trunk
- py2-3
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Scott Moser |
Proposed branch: | lp:~harlowja/cloud-init/py2-3 |
Merge into: | lp:~cloud-init-dev/cloud-init/trunk |
Diff against target: |
1969 lines (+317/-205) 59 files modified
cloudinit/config/cc_apt_configure.py (+3/-1) cloudinit/config/cc_debug.py (+4/-2) cloudinit/config/cc_landscape.py (+1/-1) cloudinit/config/cc_mcollective.py (+6/-5) cloudinit/config/cc_phone_home.py (+4/-2) cloudinit/config/cc_puppet.py (+4/-3) cloudinit/config/cc_resolv_conf.py (+3/-2) cloudinit/config/cc_seed_random.py (+2/-1) cloudinit/config/cc_ssh.py (+4/-2) cloudinit/config/cc_yum_add_repo.py (+4/-3) cloudinit/distros/__init__.py (+20/-19) cloudinit/distros/arch.py (+3/-1) cloudinit/distros/freebsd.py (+6/-4) cloudinit/distros/net_util.py (+4/-1) cloudinit/distros/parsers/hostname.py (+1/-1) cloudinit/distros/parsers/hosts.py (+1/-1) cloudinit/distros/parsers/resolv_conf.py (+1/-1) cloudinit/distros/parsers/sys_conf.py (+5/-5) cloudinit/distros/rhel.py (+3/-1) cloudinit/distros/sles.py (+3/-1) cloudinit/ec2_utils.py (+4/-5) cloudinit/handlers/__init__.py (+1/-1) cloudinit/handlers/boot_hook.py (+1/-1) cloudinit/handlers/cloud_config.py (+1/-1) cloudinit/handlers/shell_script.py (+1/-1) cloudinit/handlers/upstart_job.py (+1/-1) cloudinit/helpers.py (+7/-5) cloudinit/log.py (+4/-3) cloudinit/mergers/__init__.py (+3/-1) cloudinit/mergers/m_dict.py (+3/-1) cloudinit/mergers/m_list.py (+3/-1) cloudinit/mergers/m_str.py (+6/-4) cloudinit/netinfo.py (+5/-3) cloudinit/signal_handler.py (+1/-1) cloudinit/sources/DataSourceConfigDrive.py (+3/-1) cloudinit/sources/DataSourceEc2.py (+4/-2) cloudinit/sources/DataSourceMAAS.py (+5/-2) cloudinit/sources/DataSourceOVF.py (+5/-3) cloudinit/sources/DataSourceSmartOS.py (+7/-5) cloudinit/sources/__init__.py (+6/-4) cloudinit/sources/helpers/openstack.py (+4/-2) cloudinit/ssh_util.py (+3/-3) cloudinit/stages.py (+10/-9) cloudinit/type_utils.py (+25/-6) cloudinit/url_helper.py (+14/-7) cloudinit/user_data.py (+6/-4) cloudinit/util.py (+70/-45) packages/bddeb (+1/-0) packages/brpm (+2/-0) requirements.txt (+3/-0) tests/unittests/test_data.py (+7/-6) tests/unittests/test_datasource/test_nocloud.py (+1/-1) tests/unittests/test_datasource/test_openstack.py (+2/-3) tests/unittests/test_distros/test_netconfig.py (+2/-3) tests/unittests/test_handler/test_handler_locale.py (+3/-3) tests/unittests/test_handler/test_handler_seed_random.py (+1/-1) tests/unittests/test_handler/test_handler_set_hostname.py (+3/-3) tests/unittests/test_handler/test_handler_timezone.py (+3/-3) tests/unittests/test_handler/test_handler_yum_add_repo.py (+4/-3) |
To merge this branch: | bzr merge lp:~harlowja/cloud-init/py2-3 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
cloud-init Commiters | Pending | ||
Review via email: mp+225240@code.launchpad.net |
Commit message
Description of the change
Gets the basic integration of six usage going.
This change does the following:
- Moves to using the new locations of modules (using six as needed)
- urlparse moved, configparser moved, stringio...
- Fixes the octal usage that we had previously (0o644 is the new way that works)
- The utils load_file() now decodes the files by default from binary -> utf-8 (unless decode=False, decode=False seems needed for the configobj module to correctly work)
- The utils write_file() now decodes to binary before writing (from unicode) as needed
- Adjust tests to work correctly using the new way of load/writing files
- 986. By Joshua Harlow
-
Fix urllib.quote moving to a new location
- 987. By Joshua Harlow
-
Consistently return the unicode/text version of responses
- 988. By Joshua Harlow
-
Explicitly use response.contents instead of str(contents)
To avoid using a function that has different meaning in
python 2 and python 3 instead prefer the explict access
of the contents attribute instead (which will now always
be unicode) to avoid the subtle issues that will happen
if we continue to use str() instead. - 989. By Joshua Harlow
-
Fix the configparser being required to use stringio and not bytesio
- 990. By Joshua Harlow
-
Fix types that changed/moved
- 991. By Joshua Harlow
-
Remove another comparison for (str, basestring)
- 992. By Joshua Harlow
-
Fix all iteritems() usage and remove (str, basestring) usage
Bohuslav "Slavek" Kabrda (bkabrda) wrote : | # |
Joshua Harlow (harlowja) wrote : | # |
2.6 and higher, as for the dict stuff, meh.
Zane Bitter (zaneb) wrote : | # |
Looks good to me.
Minor point: "import pickle" in http://
Barry Warsaw (barry) wrote : | # |
Is this branch behind trunk? I had some merge conflicts which aren't showing up in this MP.
I'm working on a new branch, highly inspired by this one, which should be more current against trunk, and use tox to ensure py2/3 compatibility. Most of the code changes here I agree with (except the iteritems ones -- I'm with Bohuslav on that :).
We have to disable the cheetah test in py3 since that package is not compatible. The biggest problem will be with the use of mocker which isn't py3 compatible. Not sure how to deal with that yet.
Joshua Harlow (harlowja) wrote : | # |
Likely is behind (seeing that its not updated in a while); if you are working on a newer branch (derived from this one) that's cool and probably means we don't need this one at that point. Maybe time to slowly (or fastly) move to mock then...
Barry Warsaw (barry) wrote : | # |
Here's my WIP branch: lp:~barry/cloud-init/py2-3
This largely merges Joshua's branch here, albeit manually because of aforementioned problems. It adds tox support for bilingual test runs, and the Python 2.7 test suite passes fully for me (try `tox -e py27`).
My next steps will be to look at replacing mocker and then repairing the Python 3 test suite. I'll also need to scrounge up a Python 2.6 to make sure support for that version hasn't broken.
I'll create a MP for my branch and welcome all comments and contributions!
Scott Moser (smoser) wrote : | # |
dont know what the right way to do this is, but this is effectively merged. so no need for this review, so i rejected it.
Unmerged revisions
- 992. By Joshua Harlow
-
Fix all iteritems() usage and remove (str, basestring) usage
- 991. By Joshua Harlow
-
Remove another comparison for (str, basestring)
- 990. By Joshua Harlow
-
Fix types that changed/moved
- 989. By Joshua Harlow
-
Fix the configparser being required to use stringio and not bytesio
- 988. By Joshua Harlow
-
Explicitly use response.contents instead of str(contents)
To avoid using a function that has different meaning in
python 2 and python 3 instead prefer the explict access
of the contents attribute instead (which will now always
be unicode) to avoid the subtle issues that will happen
if we continue to use str() instead. - 987. By Joshua Harlow
-
Consistently return the unicode/text version of responses
- 986. By Joshua Harlow
-
Fix urllib.quote moving to a new location
- 985. By Joshua Harlow
-
Fix up the unittests due to new changes
- 984. By Joshua Harlow
-
Adjust a bunch of moved StringIO imports
- 983. By Joshua Harlow
-
Fix a bunch more octal changes and import moves
Preview Diff
1 | === modified file 'cloudinit/config/cc_apt_configure.py' | |||
2 | --- cloudinit/config/cc_apt_configure.py 2014-02-12 19:56:55 +0000 | |||
3 | +++ cloudinit/config/cc_apt_configure.py 2014-07-08 04:39:36 +0000 | |||
4 | @@ -22,6 +22,8 @@ | |||
5 | 22 | import os | 22 | import os |
6 | 23 | import re | 23 | import re |
7 | 24 | 24 | ||
8 | 25 | import six | ||
9 | 26 | |||
10 | 25 | from cloudinit import templater | 27 | from cloudinit import templater |
11 | 26 | from cloudinit import util | 28 | from cloudinit import util |
12 | 27 | 29 | ||
13 | @@ -126,7 +128,7 @@ | |||
14 | 126 | 128 | ||
15 | 127 | 129 | ||
16 | 128 | def rename_apt_lists(old_mirrors, new_mirrors, lists_d="/var/lib/apt/lists"): | 130 | def rename_apt_lists(old_mirrors, new_mirrors, lists_d="/var/lib/apt/lists"): |
18 | 129 | for (name, omirror) in old_mirrors.iteritems(): | 131 | for (name, omirror) in six.iteritems(old_mirrors): |
19 | 130 | nmirror = new_mirrors.get(name) | 132 | nmirror = new_mirrors.get(name) |
20 | 131 | if not nmirror: | 133 | if not nmirror: |
21 | 132 | continue | 134 | continue |
22 | 133 | 135 | ||
23 | === modified file 'cloudinit/config/cc_debug.py' | |||
24 | --- cloudinit/config/cc_debug.py 2014-01-23 19:28:59 +0000 | |||
25 | +++ cloudinit/config/cc_debug.py 2014-07-08 04:39:36 +0000 | |||
26 | @@ -14,10 +14,12 @@ | |||
27 | 14 | # You should have received a copy of the GNU General Public License | 14 | # You should have received a copy of the GNU General Public License |
28 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
29 | 16 | 16 | ||
30 | 17 | import copy | ||
31 | 18 | |||
32 | 19 | from six import StringIO | ||
33 | 20 | |||
34 | 17 | from cloudinit import type_utils | 21 | from cloudinit import type_utils |
35 | 18 | from cloudinit import util | 22 | from cloudinit import util |
36 | 19 | import copy | ||
37 | 20 | from StringIO import StringIO | ||
38 | 21 | 23 | ||
39 | 22 | 24 | ||
40 | 23 | def _make_header(text): | 25 | def _make_header(text): |
41 | 24 | 26 | ||
42 | === modified file 'cloudinit/config/cc_landscape.py' | |||
43 | --- cloudinit/config/cc_landscape.py 2014-01-27 22:34:35 +0000 | |||
44 | +++ cloudinit/config/cc_landscape.py 2014-07-08 04:39:36 +0000 | |||
45 | @@ -20,7 +20,7 @@ | |||
46 | 20 | 20 | ||
47 | 21 | import os | 21 | import os |
48 | 22 | 22 | ||
50 | 23 | from StringIO import StringIO | 23 | from six import StringIO |
51 | 24 | 24 | ||
52 | 25 | from configobj import ConfigObj | 25 | from configobj import ConfigObj |
53 | 26 | 26 | ||
54 | 27 | 27 | ||
55 | === modified file 'cloudinit/config/cc_mcollective.py' | |||
56 | --- cloudinit/config/cc_mcollective.py 2014-01-27 22:34:35 +0000 | |||
57 | +++ cloudinit/config/cc_mcollective.py 2014-07-08 04:39:36 +0000 | |||
58 | @@ -19,7 +19,8 @@ | |||
59 | 19 | # You should have received a copy of the GNU General Public License | 19 | # You should have received a copy of the GNU General Public License |
60 | 20 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 20 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
61 | 21 | 21 | ||
63 | 22 | from StringIO import StringIO | 22 | import six |
64 | 23 | from six import StringIO | ||
65 | 23 | 24 | ||
66 | 24 | # Used since this can maintain comments | 25 | # Used since this can maintain comments |
67 | 25 | # and doesn't need a top level section | 26 | # and doesn't need a top level section |
68 | @@ -51,7 +52,7 @@ | |||
69 | 51 | # original file in order to be able to mix the rest up | 52 | # original file in order to be able to mix the rest up |
70 | 52 | mcollective_config = ConfigObj(SERVER_CFG) | 53 | mcollective_config = ConfigObj(SERVER_CFG) |
71 | 53 | # See: http://tiny.cc/jh9agw | 54 | # See: http://tiny.cc/jh9agw |
73 | 54 | for (cfg_name, cfg) in mcollective_cfg['conf'].iteritems(): | 55 | for (cfg_name, cfg) in six.iteritems(mcollective_cfg['conf']): |
74 | 55 | if cfg_name == 'public-cert': | 56 | if cfg_name == 'public-cert': |
75 | 56 | util.write_file(PUBCERT_FILE, cfg, mode=0644) | 57 | util.write_file(PUBCERT_FILE, cfg, mode=0644) |
76 | 57 | mcollective_config['plugin.ssl_server_public'] = PUBCERT_FILE | 58 | mcollective_config['plugin.ssl_server_public'] = PUBCERT_FILE |
77 | @@ -61,7 +62,7 @@ | |||
78 | 61 | mcollective_config['plugin.ssl_server_private'] = PRICERT_FILE | 62 | mcollective_config['plugin.ssl_server_private'] = PRICERT_FILE |
79 | 62 | mcollective_config['securityprovider'] = 'ssl' | 63 | mcollective_config['securityprovider'] = 'ssl' |
80 | 63 | else: | 64 | else: |
82 | 64 | if isinstance(cfg, (basestring, str)): | 65 | if isinstance(cfg, six.string_types): |
83 | 65 | # Just set it in the 'main' section | 66 | # Just set it in the 'main' section |
84 | 66 | mcollective_config[cfg_name] = cfg | 67 | mcollective_config[cfg_name] = cfg |
85 | 67 | elif isinstance(cfg, (dict)): | 68 | elif isinstance(cfg, (dict)): |
86 | @@ -69,7 +70,7 @@ | |||
87 | 69 | # if it is needed and then add/or create items as needed | 70 | # if it is needed and then add/or create items as needed |
88 | 70 | if cfg_name not in mcollective_config.sections: | 71 | if cfg_name not in mcollective_config.sections: |
89 | 71 | mcollective_config[cfg_name] = {} | 72 | mcollective_config[cfg_name] = {} |
91 | 72 | for (o, v) in cfg.iteritems(): | 73 | for (o, v) in six.iteritems(cfg): |
92 | 73 | mcollective_config[cfg_name][o] = v | 74 | mcollective_config[cfg_name][o] = v |
93 | 74 | else: | 75 | else: |
94 | 75 | # Otherwise just try to convert it to a string | 76 | # Otherwise just try to convert it to a string |
95 | @@ -81,7 +82,7 @@ | |||
96 | 81 | contents = StringIO() | 82 | contents = StringIO() |
97 | 82 | mcollective_config.write(contents) | 83 | mcollective_config.write(contents) |
98 | 83 | contents = contents.getvalue() | 84 | contents = contents.getvalue() |
100 | 84 | util.write_file(SERVER_CFG, contents, mode=0644) | 85 | util.write_file(SERVER_CFG, contents, mode=0o644) |
101 | 85 | 86 | ||
102 | 86 | # Start mcollective | 87 | # Start mcollective |
103 | 87 | util.subp(['service', 'mcollective', 'start'], capture=False) | 88 | util.subp(['service', 'mcollective', 'start'], capture=False) |
104 | 88 | 89 | ||
105 | === modified file 'cloudinit/config/cc_phone_home.py' | |||
106 | --- cloudinit/config/cc_phone_home.py 2014-02-05 15:36:47 +0000 | |||
107 | +++ cloudinit/config/cc_phone_home.py 2014-07-08 04:39:36 +0000 | |||
108 | @@ -18,6 +18,8 @@ | |||
109 | 18 | # You should have received a copy of the GNU General Public License | 18 | # You should have received a copy of the GNU General Public License |
110 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
111 | 20 | 20 | ||
112 | 21 | import six | ||
113 | 22 | |||
114 | 21 | from cloudinit import templater | 23 | from cloudinit import templater |
115 | 22 | from cloudinit import util | 24 | from cloudinit import util |
116 | 23 | 25 | ||
117 | @@ -81,7 +83,7 @@ | |||
118 | 81 | 'pub_key_ecdsa': '/etc/ssh/ssh_host_ecdsa_key.pub', | 83 | 'pub_key_ecdsa': '/etc/ssh/ssh_host_ecdsa_key.pub', |
119 | 82 | } | 84 | } |
120 | 83 | 85 | ||
122 | 84 | for (n, path) in pubkeys.iteritems(): | 86 | for (n, path) in six.iteritems(pubkeys): |
123 | 85 | try: | 87 | try: |
124 | 86 | all_keys[n] = util.load_file(path) | 88 | all_keys[n] = util.load_file(path) |
125 | 87 | except: | 89 | except: |
126 | @@ -99,7 +101,7 @@ | |||
127 | 99 | 101 | ||
128 | 100 | # Get them read to be posted | 102 | # Get them read to be posted |
129 | 101 | real_submit_keys = {} | 103 | real_submit_keys = {} |
131 | 102 | for (k, v) in submit_keys.iteritems(): | 104 | for (k, v) in six.iteritems(submit_keys): |
132 | 103 | if v is None: | 105 | if v is None: |
133 | 104 | real_submit_keys[k] = 'N/A' | 106 | real_submit_keys[k] = 'N/A' |
134 | 105 | else: | 107 | else: |
135 | 106 | 108 | ||
136 | === modified file 'cloudinit/config/cc_puppet.py' | |||
137 | --- cloudinit/config/cc_puppet.py 2014-02-05 15:36:47 +0000 | |||
138 | +++ cloudinit/config/cc_puppet.py 2014-07-08 04:39:36 +0000 | |||
139 | @@ -18,7 +18,8 @@ | |||
140 | 18 | # You should have received a copy of the GNU General Public License | 18 | # You should have received a copy of the GNU General Public License |
141 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
142 | 20 | 20 | ||
144 | 21 | from StringIO import StringIO | 21 | import six |
145 | 22 | from six import StringIO | ||
146 | 22 | 23 | ||
147 | 23 | import os | 24 | import os |
148 | 24 | import socket | 25 | import socket |
149 | @@ -81,7 +82,7 @@ | |||
150 | 81 | cleaned_contents = '\n'.join(cleaned_lines) | 82 | cleaned_contents = '\n'.join(cleaned_lines) |
151 | 82 | puppet_config.readfp(StringIO(cleaned_contents), | 83 | puppet_config.readfp(StringIO(cleaned_contents), |
152 | 83 | filename=PUPPET_CONF_PATH) | 84 | filename=PUPPET_CONF_PATH) |
154 | 84 | for (cfg_name, cfg) in puppet_cfg['conf'].iteritems(): | 85 | for (cfg_name, cfg) in six.iteritems(puppet_cfg['conf']): |
155 | 85 | # Cert configuration is a special case | 86 | # Cert configuration is a special case |
156 | 86 | # Dump the puppet master ca certificate in the correct place | 87 | # Dump the puppet master ca certificate in the correct place |
157 | 87 | if cfg_name == 'ca_cert': | 88 | if cfg_name == 'ca_cert': |
158 | @@ -96,7 +97,7 @@ | |||
159 | 96 | else: | 97 | else: |
160 | 97 | # Iterate throug the config items, we'll use ConfigParser.set | 98 | # Iterate throug the config items, we'll use ConfigParser.set |
161 | 98 | # to overwrite or create new items as needed | 99 | # to overwrite or create new items as needed |
163 | 99 | for (o, v) in cfg.iteritems(): | 100 | for (o, v) in six.iteritems(cfg): |
164 | 100 | if o == 'certname': | 101 | if o == 'certname': |
165 | 101 | # Expand %f as the fqdn | 102 | # Expand %f as the fqdn |
166 | 102 | # TODO(harlowja) should this use the cloud fqdn?? | 103 | # TODO(harlowja) should this use the cloud fqdn?? |
167 | 103 | 104 | ||
168 | === modified file 'cloudinit/config/cc_resolv_conf.py' | |||
169 | --- cloudinit/config/cc_resolv_conf.py 2014-02-05 15:36:47 +0000 | |||
170 | +++ cloudinit/config/cc_resolv_conf.py 2014-07-08 04:39:36 +0000 | |||
171 | @@ -48,6 +48,7 @@ | |||
172 | 48 | # timeout: 1 | 48 | # timeout: 1 |
173 | 49 | # | 49 | # |
174 | 50 | 50 | ||
175 | 51 | import six | ||
176 | 51 | 52 | ||
177 | 52 | from cloudinit.settings import PER_INSTANCE | 53 | from cloudinit.settings import PER_INSTANCE |
178 | 53 | from cloudinit import templater | 54 | from cloudinit import templater |
179 | @@ -67,8 +68,8 @@ | |||
180 | 67 | flags = [] | 68 | flags = [] |
181 | 68 | false_flags = [] | 69 | false_flags = [] |
182 | 69 | if 'options' in params: | 70 | if 'options' in params: |
185 | 70 | for key, val in params['options'].iteritems(): | 71 | for key, val in six.iteritems(params['options']): |
186 | 71 | if type(val) == bool: | 72 | if isinstance(val, bool): |
187 | 72 | if val: | 73 | if val: |
188 | 73 | flags.append(key) | 74 | flags.append(key) |
189 | 74 | else: | 75 | else: |
190 | 75 | 76 | ||
191 | === modified file 'cloudinit/config/cc_seed_random.py' | |||
192 | --- cloudinit/config/cc_seed_random.py 2014-03-04 19:35:09 +0000 | |||
193 | +++ cloudinit/config/cc_seed_random.py 2014-07-08 04:39:36 +0000 | |||
194 | @@ -21,7 +21,8 @@ | |||
195 | 21 | 21 | ||
196 | 22 | import base64 | 22 | import base64 |
197 | 23 | import os | 23 | import os |
199 | 24 | from StringIO import StringIO | 24 | |
200 | 25 | from six import StringIO | ||
201 | 25 | 26 | ||
202 | 26 | from cloudinit.settings import PER_INSTANCE | 27 | from cloudinit.settings import PER_INSTANCE |
203 | 27 | from cloudinit import log as logging | 28 | from cloudinit import log as logging |
204 | 28 | 29 | ||
205 | === modified file 'cloudinit/config/cc_ssh.py' | |||
206 | --- cloudinit/config/cc_ssh.py 2014-01-28 14:48:47 +0000 | |||
207 | +++ cloudinit/config/cc_ssh.py 2014-07-08 04:39:36 +0000 | |||
208 | @@ -21,6 +21,8 @@ | |||
209 | 21 | import glob | 21 | import glob |
210 | 22 | import os | 22 | import os |
211 | 23 | 23 | ||
212 | 24 | import six | ||
213 | 25 | |||
214 | 24 | # Ensure this is aliased to a name not 'distros' | 26 | # Ensure this is aliased to a name not 'distros' |
215 | 25 | # since the module attribute 'distros' | 27 | # since the module attribute 'distros' |
216 | 26 | # is a list of distros that are supported, not a sub-module | 28 | # is a list of distros that are supported, not a sub-module |
217 | @@ -68,13 +70,13 @@ | |||
218 | 68 | 70 | ||
219 | 69 | if "ssh_keys" in cfg: | 71 | if "ssh_keys" in cfg: |
220 | 70 | # if there are keys in cloud-config, use them | 72 | # if there are keys in cloud-config, use them |
222 | 71 | for (key, val) in cfg["ssh_keys"].iteritems(): | 73 | for (key, val) in six.iteritems(cfg["ssh_keys"]): |
223 | 72 | if key in KEY_2_FILE: | 74 | if key in KEY_2_FILE: |
224 | 73 | tgt_fn = KEY_2_FILE[key][0] | 75 | tgt_fn = KEY_2_FILE[key][0] |
225 | 74 | tgt_perms = KEY_2_FILE[key][1] | 76 | tgt_perms = KEY_2_FILE[key][1] |
226 | 75 | util.write_file(tgt_fn, val, tgt_perms) | 77 | util.write_file(tgt_fn, val, tgt_perms) |
227 | 76 | 78 | ||
229 | 77 | for (priv, pub) in PRIV_2_PUB.iteritems(): | 79 | for (priv, pub) in six.iteritems(PRIV_2_PUB): |
230 | 78 | if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']: | 80 | if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']: |
231 | 79 | continue | 81 | continue |
232 | 80 | pair = (KEY_2_FILE[priv][0], KEY_2_FILE[pub][0]) | 82 | pair = (KEY_2_FILE[priv][0], KEY_2_FILE[pub][0]) |
233 | 81 | 83 | ||
234 | === modified file 'cloudinit/config/cc_yum_add_repo.py' | |||
235 | --- cloudinit/config/cc_yum_add_repo.py 2014-02-06 15:59:04 +0000 | |||
236 | +++ cloudinit/config/cc_yum_add_repo.py 2014-07-08 04:39:36 +0000 | |||
237 | @@ -18,10 +18,11 @@ | |||
238 | 18 | 18 | ||
239 | 19 | import os | 19 | import os |
240 | 20 | 20 | ||
241 | 21 | import configobj | ||
242 | 22 | import six | ||
243 | 23 | |||
244 | 21 | from cloudinit import util | 24 | from cloudinit import util |
245 | 22 | 25 | ||
246 | 23 | import configobj | ||
247 | 24 | |||
248 | 25 | 26 | ||
249 | 26 | def _canonicalize_id(repo_id): | 27 | def _canonicalize_id(repo_id): |
250 | 27 | repo_id = repo_id.lower().replace("-", "_") | 28 | repo_id = repo_id.lower().replace("-", "_") |
251 | @@ -37,7 +38,7 @@ | |||
252 | 37 | # Can handle 'lists' in certain cases | 38 | # Can handle 'lists' in certain cases |
253 | 38 | # See: http://bit.ly/Qqrf1t | 39 | # See: http://bit.ly/Qqrf1t |
254 | 39 | return "\n ".join([_format_repo_value(v) for v in val]) | 40 | return "\n ".join([_format_repo_value(v) for v in val]) |
256 | 40 | if not isinstance(val, (basestring, str)): | 41 | if not isinstance(val, six.string_types): |
257 | 41 | return str(val) | 42 | return str(val) |
258 | 42 | return val | 43 | return val |
259 | 43 | 44 | ||
260 | 44 | 45 | ||
261 | === modified file 'cloudinit/distros/__init__.py' | |||
262 | --- cloudinit/distros/__init__.py 2014-02-12 19:56:55 +0000 | |||
263 | +++ cloudinit/distros/__init__.py 2014-07-08 04:39:36 +0000 | |||
264 | @@ -21,7 +21,8 @@ | |||
265 | 21 | # You should have received a copy of the GNU General Public License | 21 | # You should have received a copy of the GNU General Public License |
266 | 22 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 22 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
267 | 23 | 23 | ||
269 | 24 | from StringIO import StringIO | 24 | import six |
270 | 25 | from six import StringIO | ||
271 | 25 | 26 | ||
272 | 26 | import abc | 27 | import abc |
273 | 27 | import itertools | 28 | import itertools |
274 | @@ -268,7 +269,7 @@ | |||
275 | 268 | if header: | 269 | if header: |
276 | 269 | contents.write("%s\n" % (header)) | 270 | contents.write("%s\n" % (header)) |
277 | 270 | contents.write("%s\n" % (eh)) | 271 | contents.write("%s\n" % (eh)) |
279 | 271 | util.write_file(self.hosts_fn, contents.getvalue(), mode=0644) | 272 | util.write_file(self.hosts_fn, contents.getvalue(), mode=0o644) |
280 | 272 | 273 | ||
281 | 273 | def _bring_up_interface(self, device_name): | 274 | def _bring_up_interface(self, device_name): |
282 | 274 | cmd = ['ifup', device_name] | 275 | cmd = ['ifup', device_name] |
283 | @@ -330,7 +331,7 @@ | |||
284 | 330 | redact_opts = ['passwd'] | 331 | redact_opts = ['passwd'] |
285 | 331 | 332 | ||
286 | 332 | # Check the values and create the command | 333 | # Check the values and create the command |
288 | 333 | for key, val in kwargs.iteritems(): | 334 | for key, val in six.iteritems(kwargs): |
289 | 334 | 335 | ||
290 | 335 | if key in adduser_opts and val and isinstance(val, str): | 336 | if key in adduser_opts and val and isinstance(val, str): |
291 | 336 | adduser_cmd.extend([adduser_opts[key], val]) | 337 | adduser_cmd.extend([adduser_opts[key], val]) |
292 | @@ -452,7 +453,7 @@ | |||
293 | 452 | util.make_header(base="added"), | 453 | util.make_header(base="added"), |
294 | 453 | "#includedir %s" % (path), ''] | 454 | "#includedir %s" % (path), ''] |
295 | 454 | sudoers_contents = "\n".join(lines) | 455 | sudoers_contents = "\n".join(lines) |
297 | 455 | util.write_file(sudo_base, sudoers_contents, 0440) | 456 | util.write_file(sudo_base, sudoers_contents, 0o440) |
298 | 456 | else: | 457 | else: |
299 | 457 | lines = ['', util.make_header(base="added"), | 458 | lines = ['', util.make_header(base="added"), |
300 | 458 | "#includedir %s" % (path), ''] | 459 | "#includedir %s" % (path), ''] |
301 | @@ -462,7 +463,7 @@ | |||
302 | 462 | except IOError as e: | 463 | except IOError as e: |
303 | 463 | util.logexc(LOG, "Failed to write %s", sudo_base) | 464 | util.logexc(LOG, "Failed to write %s", sudo_base) |
304 | 464 | raise e | 465 | raise e |
306 | 465 | util.ensure_dir(path, 0750) | 466 | util.ensure_dir(path, 0o750) |
307 | 466 | 467 | ||
308 | 467 | def write_sudo_rules(self, user, rules, sudo_file=None): | 468 | def write_sudo_rules(self, user, rules, sudo_file=None): |
309 | 468 | if not sudo_file: | 469 | if not sudo_file: |
310 | @@ -475,7 +476,7 @@ | |||
311 | 475 | if isinstance(rules, (list, tuple)): | 476 | if isinstance(rules, (list, tuple)): |
312 | 476 | for rule in rules: | 477 | for rule in rules: |
313 | 477 | lines.append("%s %s" % (user, rule)) | 478 | lines.append("%s %s" % (user, rule)) |
315 | 478 | elif isinstance(rules, (basestring, str)): | 479 | elif isinstance(rules, six.string_types): |
316 | 479 | lines.append("%s %s" % (user, rules)) | 480 | lines.append("%s %s" % (user, rules)) |
317 | 480 | else: | 481 | else: |
318 | 481 | msg = "Can not create sudoers rule addition with type %r" | 482 | msg = "Can not create sudoers rule addition with type %r" |
319 | @@ -490,7 +491,7 @@ | |||
320 | 490 | content, | 491 | content, |
321 | 491 | ] | 492 | ] |
322 | 492 | try: | 493 | try: |
324 | 493 | util.write_file(sudo_file, "\n".join(contents), 0440) | 494 | util.write_file(sudo_file, "\n".join(contents), 0o440) |
325 | 494 | except IOError as e: | 495 | except IOError as e: |
326 | 495 | util.logexc(LOG, "Failed to write sudoers file %s", sudo_file) | 496 | util.logexc(LOG, "Failed to write sudoers file %s", sudo_file) |
327 | 496 | raise e | 497 | raise e |
328 | @@ -545,10 +546,10 @@ | |||
329 | 545 | subst['ec2_region'] = "%s" % availability_zone[0:-1] | 546 | subst['ec2_region'] = "%s" % availability_zone[0:-1] |
330 | 546 | 547 | ||
331 | 547 | results = {} | 548 | results = {} |
333 | 548 | for (name, mirror) in mirror_info.get('failsafe', {}).iteritems(): | 549 | for (name, mirror) in six.iteritems(mirror_info.get('failsafe', {})): |
334 | 549 | results[name] = mirror | 550 | results[name] = mirror |
335 | 550 | 551 | ||
337 | 551 | for (name, searchlist) in mirror_info.get('search', {}).iteritems(): | 552 | for (name, searchlist) in six.iteritems(mirror_info.get('search', {})): |
338 | 552 | mirrors = [] | 553 | mirrors = [] |
339 | 553 | for tmpl in searchlist: | 554 | for tmpl in searchlist: |
340 | 554 | try: | 555 | try: |
341 | @@ -588,7 +589,7 @@ | |||
342 | 588 | # is the standard form used in the rest | 589 | # is the standard form used in the rest |
343 | 589 | # of cloud-init | 590 | # of cloud-init |
344 | 590 | def _normalize_groups(grp_cfg): | 591 | def _normalize_groups(grp_cfg): |
346 | 591 | if isinstance(grp_cfg, (str, basestring)): | 592 | if isinstance(grp_cfg, six.string_types): |
347 | 592 | grp_cfg = grp_cfg.strip().split(",") | 593 | grp_cfg = grp_cfg.strip().split(",") |
348 | 593 | if isinstance(grp_cfg, (list)): | 594 | if isinstance(grp_cfg, (list)): |
349 | 594 | c_grp_cfg = {} | 595 | c_grp_cfg = {} |
350 | @@ -598,7 +599,7 @@ | |||
351 | 598 | if k not in c_grp_cfg: | 599 | if k not in c_grp_cfg: |
352 | 599 | if isinstance(v, (list)): | 600 | if isinstance(v, (list)): |
353 | 600 | c_grp_cfg[k] = list(v) | 601 | c_grp_cfg[k] = list(v) |
355 | 601 | elif isinstance(v, (basestring, str)): | 602 | elif isinstance(v, six.string_types): |
356 | 602 | c_grp_cfg[k] = [v] | 603 | c_grp_cfg[k] = [v] |
357 | 603 | else: | 604 | else: |
358 | 604 | raise TypeError("Bad group member type %s" % | 605 | raise TypeError("Bad group member type %s" % |
359 | @@ -606,12 +607,12 @@ | |||
360 | 606 | else: | 607 | else: |
361 | 607 | if isinstance(v, (list)): | 608 | if isinstance(v, (list)): |
362 | 608 | c_grp_cfg[k].extend(v) | 609 | c_grp_cfg[k].extend(v) |
364 | 609 | elif isinstance(v, (basestring, str)): | 610 | elif isinstance(v, six.string_types): |
365 | 610 | c_grp_cfg[k].append(v) | 611 | c_grp_cfg[k].append(v) |
366 | 611 | else: | 612 | else: |
367 | 612 | raise TypeError("Bad group member type %s" % | 613 | raise TypeError("Bad group member type %s" % |
368 | 613 | type_utils.obj_name(v)) | 614 | type_utils.obj_name(v)) |
370 | 614 | elif isinstance(i, (str, basestring)): | 615 | elif isinstance(i, six.string_types): |
371 | 615 | if i not in c_grp_cfg: | 616 | if i not in c_grp_cfg: |
372 | 616 | c_grp_cfg[i] = [] | 617 | c_grp_cfg[i] = [] |
373 | 617 | else: | 618 | else: |
374 | @@ -648,7 +649,7 @@ | |||
375 | 648 | if isinstance(u_cfg, (dict)): | 649 | if isinstance(u_cfg, (dict)): |
376 | 649 | ad_ucfg = [] | 650 | ad_ucfg = [] |
377 | 650 | for (k, v) in u_cfg.items(): | 651 | for (k, v) in u_cfg.items(): |
379 | 651 | if isinstance(v, (bool, int, basestring, str, float)): | 652 | if isinstance(v, (bool, int, float) + six.string_types): |
380 | 652 | if util.is_true(v): | 653 | if util.is_true(v): |
381 | 653 | ad_ucfg.append(str(k)) | 654 | ad_ucfg.append(str(k)) |
382 | 654 | elif isinstance(v, (dict)): | 655 | elif isinstance(v, (dict)): |
383 | @@ -658,12 +659,12 @@ | |||
384 | 658 | raise TypeError(("Unmappable user value type %s" | 659 | raise TypeError(("Unmappable user value type %s" |
385 | 659 | " for key %s") % (type_utils.obj_name(v), k)) | 660 | " for key %s") % (type_utils.obj_name(v), k)) |
386 | 660 | u_cfg = ad_ucfg | 661 | u_cfg = ad_ucfg |
388 | 661 | elif isinstance(u_cfg, (str, basestring)): | 662 | elif isinstance(u_cfg, six.string_types): |
389 | 662 | u_cfg = util.uniq_merge_sorted(u_cfg) | 663 | u_cfg = util.uniq_merge_sorted(u_cfg) |
390 | 663 | 664 | ||
391 | 664 | users = {} | 665 | users = {} |
392 | 665 | for user_config in u_cfg: | 666 | for user_config in u_cfg: |
394 | 666 | if isinstance(user_config, (str, basestring, list)): | 667 | if isinstance(user_config, (list,) + six.string_types): |
395 | 667 | for u in util.uniq_merge(user_config): | 668 | for u in util.uniq_merge(user_config): |
396 | 668 | if u and u not in users: | 669 | if u and u not in users: |
397 | 669 | users[u] = {} | 670 | users[u] = {} |
398 | @@ -768,7 +769,7 @@ | |||
399 | 768 | old_user = cfg['user'] | 769 | old_user = cfg['user'] |
400 | 769 | # Translate it into the format that is more useful | 770 | # Translate it into the format that is more useful |
401 | 770 | # going forward | 771 | # going forward |
403 | 771 | if isinstance(old_user, (basestring, str)): | 772 | if isinstance(old_user, six.string_types): |
404 | 772 | old_user = { | 773 | old_user = { |
405 | 773 | 'name': old_user, | 774 | 'name': old_user, |
406 | 774 | } | 775 | } |
407 | @@ -797,7 +798,7 @@ | |||
408 | 797 | default_user_config = util.mergemanydict([old_user, distro_user_config]) | 798 | default_user_config = util.mergemanydict([old_user, distro_user_config]) |
409 | 798 | 799 | ||
410 | 799 | base_users = cfg.get('users', []) | 800 | base_users = cfg.get('users', []) |
412 | 800 | if not isinstance(base_users, (list, dict, str, basestring)): | 801 | if not isinstance(base_users, (list, dict) + six.string_types): |
413 | 801 | LOG.warn(("Format for 'users' key must be a comma separated string" | 802 | LOG.warn(("Format for 'users' key must be a comma separated string" |
414 | 802 | " or a dictionary or a list and not %s"), | 803 | " or a dictionary or a list and not %s"), |
415 | 803 | type_utils.obj_name(base_users)) | 804 | type_utils.obj_name(base_users)) |
416 | @@ -811,7 +812,7 @@ | |||
417 | 811 | base_users.append({'name': 'default'}) | 812 | base_users.append({'name': 'default'}) |
418 | 812 | elif isinstance(base_users, (dict)): | 813 | elif isinstance(base_users, (dict)): |
419 | 813 | base_users['default'] = dict(base_users).get('default', True) | 814 | base_users['default'] = dict(base_users).get('default', True) |
421 | 814 | elif isinstance(base_users, (str, basestring)): | 815 | elif isinstance(base_users, six.string_types): |
422 | 815 | # Just append it on to be re-parsed later | 816 | # Just append it on to be re-parsed later |
423 | 816 | base_users += ",default" | 817 | base_users += ",default" |
424 | 817 | 818 | ||
425 | 818 | 819 | ||
426 | === modified file 'cloudinit/distros/arch.py' | |||
427 | --- cloudinit/distros/arch.py 2014-02-12 19:56:55 +0000 | |||
428 | +++ cloudinit/distros/arch.py 2014-07-08 04:39:36 +0000 | |||
429 | @@ -16,6 +16,8 @@ | |||
430 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
431 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
432 | 18 | 18 | ||
433 | 19 | import six | ||
434 | 20 | |||
435 | 19 | from cloudinit import distros | 21 | from cloudinit import distros |
436 | 20 | from cloudinit import helpers | 22 | from cloudinit import helpers |
437 | 21 | from cloudinit import log as logging | 23 | from cloudinit import log as logging |
438 | @@ -68,7 +70,7 @@ | |||
439 | 68 | settings, entries) | 70 | settings, entries) |
440 | 69 | dev_names = entries.keys() | 71 | dev_names = entries.keys() |
441 | 70 | # Format for netctl | 72 | # Format for netctl |
443 | 71 | for (dev, info) in entries.iteritems(): | 73 | for (dev, info) in six.iteritems(entries): |
444 | 72 | nameservers = [] | 74 | nameservers = [] |
445 | 73 | net_fn = self.network_conf_dir + dev | 75 | net_fn = self.network_conf_dir + dev |
446 | 74 | net_cfg = { | 76 | net_cfg = { |
447 | 75 | 77 | ||
448 | === modified file 'cloudinit/distros/freebsd.py' | |||
449 | --- cloudinit/distros/freebsd.py 2014-02-28 21:40:08 +0000 | |||
450 | +++ cloudinit/distros/freebsd.py 2014-07-08 04:39:36 +0000 | |||
451 | @@ -16,10 +16,11 @@ | |||
452 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
453 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
454 | 18 | 18 | ||
455 | 19 | from StringIO import StringIO | ||
456 | 20 | |||
457 | 21 | import re | 19 | import re |
458 | 22 | 20 | ||
459 | 21 | import six | ||
460 | 22 | from six import StringIO | ||
461 | 23 | |||
462 | 23 | from cloudinit import distros | 24 | from cloudinit import distros |
463 | 24 | from cloudinit import helpers | 25 | from cloudinit import helpers |
464 | 25 | from cloudinit import log as logging | 26 | from cloudinit import log as logging |
465 | @@ -150,8 +151,9 @@ | |||
466 | 150 | 151 | ||
467 | 151 | redact_opts = ['passwd'] | 152 | redact_opts = ['passwd'] |
468 | 152 | 153 | ||
471 | 153 | for key, val in kwargs.iteritems(): | 154 | for key, val in six.iteritems(kwargs): |
472 | 154 | if key in adduser_opts and val and isinstance(val, basestring): | 155 | if key in adduser_opts and val \ |
473 | 156 | and isinstance(val, six.string_types): | ||
474 | 155 | adduser_cmd.extend([adduser_opts[key], val]) | 157 | adduser_cmd.extend([adduser_opts[key], val]) |
475 | 156 | 158 | ||
476 | 157 | # Redact certain fields from the logs | 159 | # Redact certain fields from the logs |
477 | 158 | 160 | ||
478 | === modified file 'cloudinit/distros/net_util.py' | |||
479 | --- cloudinit/distros/net_util.py 2014-01-24 21:20:54 +0000 | |||
480 | +++ cloudinit/distros/net_util.py 2014-07-08 04:39:36 +0000 | |||
481 | @@ -79,6 +79,9 @@ | |||
482 | 79 | # } | 79 | # } |
483 | 80 | # } | 80 | # } |
484 | 81 | 81 | ||
485 | 82 | import six | ||
486 | 83 | |||
487 | 84 | |||
488 | 82 | def translate_network(settings): | 85 | def translate_network(settings): |
489 | 83 | # Get the standard cmd, args from the ubuntu format | 86 | # Get the standard cmd, args from the ubuntu format |
490 | 84 | entries = [] | 87 | entries = [] |
491 | @@ -103,7 +106,7 @@ | |||
492 | 103 | consume[cmd] = args | 106 | consume[cmd] = args |
493 | 104 | # Check if anything left over to consume | 107 | # Check if anything left over to consume |
494 | 105 | absorb = False | 108 | absorb = False |
496 | 106 | for (cmd, args) in consume.iteritems(): | 109 | for (cmd, args) in six.iteritems(consume): |
497 | 107 | if cmd == 'iface': | 110 | if cmd == 'iface': |
498 | 108 | absorb = True | 111 | absorb = True |
499 | 109 | if absorb: | 112 | if absorb: |
500 | 110 | 113 | ||
501 | === modified file 'cloudinit/distros/parsers/hostname.py' | |||
502 | --- cloudinit/distros/parsers/hostname.py 2012-11-12 22:30:08 +0000 | |||
503 | +++ cloudinit/distros/parsers/hostname.py 2014-07-08 04:39:36 +0000 | |||
504 | @@ -16,7 +16,7 @@ | |||
505 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
506 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
507 | 18 | 18 | ||
509 | 19 | from StringIO import StringIO | 19 | from six import StringIO |
510 | 20 | 20 | ||
511 | 21 | from cloudinit.distros.parsers import chop_comment | 21 | from cloudinit.distros.parsers import chop_comment |
512 | 22 | 22 | ||
513 | 23 | 23 | ||
514 | === modified file 'cloudinit/distros/parsers/hosts.py' | |||
515 | --- cloudinit/distros/parsers/hosts.py 2012-11-13 06:14:31 +0000 | |||
516 | +++ cloudinit/distros/parsers/hosts.py 2014-07-08 04:39:36 +0000 | |||
517 | @@ -16,7 +16,7 @@ | |||
518 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
519 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
520 | 18 | 18 | ||
522 | 19 | from StringIO import StringIO | 19 | from six import StringIO |
523 | 20 | 20 | ||
524 | 21 | from cloudinit.distros.parsers import chop_comment | 21 | from cloudinit.distros.parsers import chop_comment |
525 | 22 | 22 | ||
526 | 23 | 23 | ||
527 | === modified file 'cloudinit/distros/parsers/resolv_conf.py' | |||
528 | --- cloudinit/distros/parsers/resolv_conf.py 2013-03-19 13:32:04 +0000 | |||
529 | +++ cloudinit/distros/parsers/resolv_conf.py 2014-07-08 04:39:36 +0000 | |||
530 | @@ -16,7 +16,7 @@ | |||
531 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
532 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
533 | 18 | 18 | ||
535 | 19 | from StringIO import StringIO | 19 | from six import StringIO |
536 | 20 | 20 | ||
537 | 21 | from cloudinit import util | 21 | from cloudinit import util |
538 | 22 | 22 | ||
539 | 23 | 23 | ||
540 | === modified file 'cloudinit/distros/parsers/sys_conf.py' | |||
541 | --- cloudinit/distros/parsers/sys_conf.py 2012-11-12 22:30:08 +0000 | |||
542 | +++ cloudinit/distros/parsers/sys_conf.py 2014-07-08 04:39:36 +0000 | |||
543 | @@ -16,11 +16,11 @@ | |||
544 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
545 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
546 | 18 | 18 | ||
547 | 19 | from StringIO import StringIO | ||
548 | 20 | |||
549 | 21 | import pipes | 19 | import pipes |
550 | 22 | import re | 20 | import re |
551 | 23 | 21 | ||
552 | 22 | import six | ||
553 | 23 | |||
554 | 24 | # This library is used to parse/write | 24 | # This library is used to parse/write |
555 | 25 | # out the various sysconfig files edited (best attempt effort) | 25 | # out the various sysconfig files edited (best attempt effort) |
556 | 26 | # | 26 | # |
557 | @@ -61,15 +61,15 @@ | |||
558 | 61 | 61 | ||
559 | 62 | def __str__(self): | 62 | def __str__(self): |
560 | 63 | contents = self.write() | 63 | contents = self.write() |
562 | 64 | out_contents = StringIO() | 64 | out_contents = six.StringIO() |
563 | 65 | if isinstance(contents, (list, tuple)): | 65 | if isinstance(contents, (list, tuple)): |
564 | 66 | out_contents.write("\n".join(contents)) | 66 | out_contents.write("\n".join(contents)) |
565 | 67 | else: | 67 | else: |
567 | 68 | out_contents.write(str(contents)) | 68 | out_contents.write(six.text_type(contents)) |
568 | 69 | return out_contents.getvalue() | 69 | return out_contents.getvalue() |
569 | 70 | 70 | ||
570 | 71 | def _quote(self, value, multiline=False): | 71 | def _quote(self, value, multiline=False): |
572 | 72 | if not isinstance(value, (str, basestring)): | 72 | if not isinstance(value, six.string_types): |
573 | 73 | raise ValueError('Value "%s" is not a string' % (value)) | 73 | raise ValueError('Value "%s" is not a string' % (value)) |
574 | 74 | if len(value) == 0: | 74 | if len(value) == 0: |
575 | 75 | return '' | 75 | return '' |
576 | 76 | 76 | ||
577 | === modified file 'cloudinit/distros/rhel.py' | |||
578 | --- cloudinit/distros/rhel.py 2014-02-03 22:03:14 +0000 | |||
579 | +++ cloudinit/distros/rhel.py 2014-07-08 04:39:36 +0000 | |||
580 | @@ -20,6 +20,8 @@ | |||
581 | 20 | # You should have received a copy of the GNU General Public License | 20 | # You should have received a copy of the GNU General Public License |
582 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
583 | 22 | 22 | ||
584 | 23 | import six | ||
585 | 24 | |||
586 | 23 | from cloudinit import distros | 25 | from cloudinit import distros |
587 | 24 | from cloudinit import helpers | 26 | from cloudinit import helpers |
588 | 25 | from cloudinit import log as logging | 27 | from cloudinit import log as logging |
589 | @@ -71,7 +73,7 @@ | |||
590 | 71 | nameservers = [] | 73 | nameservers = [] |
591 | 72 | searchservers = [] | 74 | searchservers = [] |
592 | 73 | dev_names = entries.keys() | 75 | dev_names = entries.keys() |
594 | 74 | for (dev, info) in entries.iteritems(): | 76 | for (dev, info) in six.iteritems(entries): |
595 | 75 | net_fn = self.network_script_tpl % (dev) | 77 | net_fn = self.network_script_tpl % (dev) |
596 | 76 | net_cfg = { | 78 | net_cfg = { |
597 | 77 | 'DEVICE': dev, | 79 | 'DEVICE': dev, |
598 | 78 | 80 | ||
599 | === modified file 'cloudinit/distros/sles.py' | |||
600 | --- cloudinit/distros/sles.py 2014-01-23 19:06:13 +0000 | |||
601 | +++ cloudinit/distros/sles.py 2014-07-08 04:39:36 +0000 | |||
602 | @@ -18,6 +18,8 @@ | |||
603 | 18 | # You should have received a copy of the GNU General Public License | 18 | # You should have received a copy of the GNU General Public License |
604 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
605 | 20 | 20 | ||
606 | 21 | import six | ||
607 | 22 | |||
608 | 21 | from cloudinit import distros | 23 | from cloudinit import distros |
609 | 22 | 24 | ||
610 | 23 | from cloudinit.distros.parsers.hostname import HostnameConf | 25 | from cloudinit.distros.parsers.hostname import HostnameConf |
611 | @@ -62,7 +64,7 @@ | |||
612 | 62 | nameservers = [] | 64 | nameservers = [] |
613 | 63 | searchservers = [] | 65 | searchservers = [] |
614 | 64 | dev_names = entries.keys() | 66 | dev_names = entries.keys() |
616 | 65 | for (dev, info) in entries.iteritems(): | 67 | for (dev, info) in six.iteritems(entries): |
617 | 66 | net_fn = self.network_script_tpl % (dev) | 68 | net_fn = self.network_script_tpl % (dev) |
618 | 67 | mode = info.get('auto') | 69 | mode = info.get('auto') |
619 | 68 | if mode and mode.lower() == 'true': | 70 | if mode and mode.lower() == 'true': |
620 | 69 | 71 | ||
621 | === modified file 'cloudinit/ec2_utils.py' | |||
622 | --- cloudinit/ec2_utils.py 2014-02-08 20:20:33 +0000 | |||
623 | +++ cloudinit/ec2_utils.py 2014-07-08 04:39:36 +0000 | |||
624 | @@ -17,7 +17,6 @@ | |||
625 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
626 | 18 | 18 | ||
627 | 19 | import functools | 19 | import functools |
628 | 20 | import httplib | ||
629 | 21 | import json | 20 | import json |
630 | 22 | 21 | ||
631 | 23 | from cloudinit import log as logging | 22 | from cloudinit import log as logging |
632 | @@ -25,7 +24,7 @@ | |||
633 | 25 | from cloudinit import util | 24 | from cloudinit import util |
634 | 26 | 25 | ||
635 | 27 | LOG = logging.getLogger(__name__) | 26 | LOG = logging.getLogger(__name__) |
637 | 28 | SKIP_USERDATA_CODES = frozenset([httplib.NOT_FOUND]) | 27 | SKIP_USERDATA_CODES = frozenset([url_helper.NOT_FOUND]) |
638 | 29 | 28 | ||
639 | 30 | 29 | ||
640 | 31 | def maybe_json_object(text): | 30 | def maybe_json_object(text): |
641 | @@ -116,7 +115,7 @@ | |||
642 | 116 | leaf_contents = {} | 115 | leaf_contents = {} |
643 | 117 | for (field, resource) in leaves.items(): | 116 | for (field, resource) in leaves.items(): |
644 | 118 | leaf_url = url_helper.combine_url(base_url, resource) | 117 | leaf_url = url_helper.combine_url(base_url, resource) |
646 | 119 | leaf_blob = str(self._caller(leaf_url)) | 118 | leaf_blob = self._caller(leaf_url).contents |
647 | 120 | leaf_contents[field] = self._decode_leaf_blob(field, leaf_blob) | 119 | leaf_contents[field] = self._decode_leaf_blob(field, leaf_blob) |
648 | 121 | joined = {} | 120 | joined = {} |
649 | 122 | joined.update(child_contents) | 121 | joined.update(child_contents) |
650 | @@ -153,7 +152,7 @@ | |||
651 | 153 | timeout=timeout, | 152 | timeout=timeout, |
652 | 154 | retries=retries, | 153 | retries=retries, |
653 | 155 | exception_cb=exception_cb) | 154 | exception_cb=exception_cb) |
655 | 156 | user_data = str(response) | 155 | user_data = response.contents |
656 | 157 | except url_helper.UrlError as e: | 156 | except url_helper.UrlError as e: |
657 | 158 | if e.code not in SKIP_USERDATA_CODES: | 157 | if e.code not in SKIP_USERDATA_CODES: |
658 | 159 | util.logexc(LOG, "Failed fetching userdata from url %s", ud_url) | 158 | util.logexc(LOG, "Failed fetching userdata from url %s", ud_url) |
659 | @@ -173,7 +172,7 @@ | |||
660 | 173 | 172 | ||
661 | 174 | try: | 173 | try: |
662 | 175 | response = caller(md_url) | 174 | response = caller(md_url) |
664 | 176 | materializer = MetadataMaterializer(str(response), md_url, caller) | 175 | materializer = MetadataMaterializer(response.contents, md_url, caller) |
665 | 177 | md = materializer.materialize() | 176 | md = materializer.materialize() |
666 | 178 | if not isinstance(md, (dict)): | 177 | if not isinstance(md, (dict)): |
667 | 179 | md = {} | 178 | md = {} |
668 | 180 | 179 | ||
669 | === modified file 'cloudinit/handlers/__init__.py' | |||
670 | --- cloudinit/handlers/__init__.py 2014-01-16 21:57:21 +0000 | |||
671 | +++ cloudinit/handlers/__init__.py 2014-07-08 04:39:36 +0000 | |||
672 | @@ -147,7 +147,7 @@ | |||
673 | 147 | if not modfname.endswith(".py"): | 147 | if not modfname.endswith(".py"): |
674 | 148 | modfname = "%s.py" % (modfname) | 148 | modfname = "%s.py" % (modfname) |
675 | 149 | # TODO(harlowja): Check if path exists?? | 149 | # TODO(harlowja): Check if path exists?? |
677 | 150 | util.write_file(modfname, payload, 0600) | 150 | util.write_file(modfname, payload, 0o600) |
678 | 151 | handlers = pdata['handlers'] | 151 | handlers = pdata['handlers'] |
679 | 152 | try: | 152 | try: |
680 | 153 | mod = fixup_handler(importer.import_module(modname)) | 153 | mod = fixup_handler(importer.import_module(modname)) |
681 | 154 | 154 | ||
682 | === modified file 'cloudinit/handlers/boot_hook.py' | |||
683 | --- cloudinit/handlers/boot_hook.py 2013-07-21 16:34:26 +0000 | |||
684 | +++ cloudinit/handlers/boot_hook.py 2014-07-08 04:39:36 +0000 | |||
685 | @@ -50,7 +50,7 @@ | |||
686 | 50 | filepath = os.path.join(self.boothook_dir, filename) | 50 | filepath = os.path.join(self.boothook_dir, filename) |
687 | 51 | contents = util.strip_prefix_suffix(util.dos2unix(payload), | 51 | contents = util.strip_prefix_suffix(util.dos2unix(payload), |
688 | 52 | prefix=BOOTHOOK_PREFIX) | 52 | prefix=BOOTHOOK_PREFIX) |
690 | 53 | util.write_file(filepath, contents.lstrip(), 0700) | 53 | util.write_file(filepath, contents.lstrip(), 0o700) |
691 | 54 | return filepath | 54 | return filepath |
692 | 55 | 55 | ||
693 | 56 | def handle_part(self, _data, ctype, filename, # pylint: disable=W0221 | 56 | def handle_part(self, _data, ctype, filename, # pylint: disable=W0221 |
694 | 57 | 57 | ||
695 | === modified file 'cloudinit/handlers/cloud_config.py' | |||
696 | --- cloudinit/handlers/cloud_config.py 2014-01-09 00:16:24 +0000 | |||
697 | +++ cloudinit/handlers/cloud_config.py 2014-07-08 04:39:36 +0000 | |||
698 | @@ -95,7 +95,7 @@ | |||
699 | 95 | lines.append(util.yaml_dumps(self.cloud_buf)) | 95 | lines.append(util.yaml_dumps(self.cloud_buf)) |
700 | 96 | else: | 96 | else: |
701 | 97 | lines = [] | 97 | lines = [] |
703 | 98 | util.write_file(self.cloud_fn, "\n".join(lines), 0600) | 98 | util.write_file(self.cloud_fn, "\n".join(lines), 0o600) |
704 | 99 | 99 | ||
705 | 100 | def _extract_mergers(self, payload, headers): | 100 | def _extract_mergers(self, payload, headers): |
706 | 101 | merge_header_headers = '' | 101 | merge_header_headers = '' |
707 | 102 | 102 | ||
708 | === modified file 'cloudinit/handlers/shell_script.py' | |||
709 | --- cloudinit/handlers/shell_script.py 2014-01-09 00:16:24 +0000 | |||
710 | +++ cloudinit/handlers/shell_script.py 2014-07-08 04:39:36 +0000 | |||
711 | @@ -53,4 +53,4 @@ | |||
712 | 53 | filename = util.clean_filename(filename) | 53 | filename = util.clean_filename(filename) |
713 | 54 | payload = util.dos2unix(payload) | 54 | payload = util.dos2unix(payload) |
714 | 55 | path = os.path.join(self.script_dir, filename) | 55 | path = os.path.join(self.script_dir, filename) |
716 | 56 | util.write_file(path, payload, 0700) | 56 | util.write_file(path, payload, 0o700) |
717 | 57 | 57 | ||
718 | === modified file 'cloudinit/handlers/upstart_job.py' | |||
719 | --- cloudinit/handlers/upstart_job.py 2013-07-21 16:26:44 +0000 | |||
720 | +++ cloudinit/handlers/upstart_job.py 2014-07-08 04:39:36 +0000 | |||
721 | @@ -66,7 +66,7 @@ | |||
722 | 66 | 66 | ||
723 | 67 | payload = util.dos2unix(payload) | 67 | payload = util.dos2unix(payload) |
724 | 68 | path = os.path.join(self.upstart_dir, filename) | 68 | path = os.path.join(self.upstart_dir, filename) |
726 | 69 | util.write_file(path, payload, 0644) | 69 | util.write_file(path, payload, 0o644) |
727 | 70 | 70 | ||
728 | 71 | if SUITABLE_UPSTART: | 71 | if SUITABLE_UPSTART: |
729 | 72 | util.subp(["initctl", "reload-configuration"], capture=False) | 72 | util.subp(["initctl", "reload-configuration"], capture=False) |
730 | 73 | 73 | ||
731 | === modified file 'cloudinit/helpers.py' | |||
732 | --- cloudinit/helpers.py 2014-01-17 20:12:31 +0000 | |||
733 | +++ cloudinit/helpers.py 2014-07-08 04:39:36 +0000 | |||
734 | @@ -23,10 +23,12 @@ | |||
735 | 23 | from time import time | 23 | from time import time |
736 | 24 | 24 | ||
737 | 25 | import contextlib | 25 | import contextlib |
738 | 26 | import io | ||
739 | 27 | import os | 26 | import os |
740 | 28 | 27 | ||
742 | 29 | from ConfigParser import (NoSectionError, NoOptionError, RawConfigParser) | 28 | import six |
743 | 29 | from six.moves.configparser import (NoSectionError, | ||
744 | 30 | NoOptionError, | ||
745 | 31 | RawConfigParser) | ||
746 | 30 | 32 | ||
747 | 31 | from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE, | 33 | from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE, |
748 | 32 | CFG_ENV_NAME) | 34 | CFG_ENV_NAME) |
749 | @@ -318,10 +320,10 @@ | |||
750 | 318 | return self.registered[content_type] | 320 | return self.registered[content_type] |
751 | 319 | 321 | ||
752 | 320 | def items(self): | 322 | def items(self): |
754 | 321 | return self.registered.items() | 323 | return list(self.iteritems()) |
755 | 322 | 324 | ||
756 | 323 | def iteritems(self): | 325 | def iteritems(self): |
758 | 324 | return self.registered.iteritems() | 326 | return six.iteritems(self.registered) |
759 | 325 | 327 | ||
760 | 326 | 328 | ||
761 | 327 | class Paths(object): | 329 | class Paths(object): |
762 | @@ -449,7 +451,7 @@ | |||
763 | 449 | 451 | ||
764 | 450 | def stringify(self, header=None): | 452 | def stringify(self, header=None): |
765 | 451 | contents = '' | 453 | contents = '' |
767 | 452 | with io.BytesIO() as outputstream: | 454 | with six.StringIO() as outputstream: |
768 | 453 | self.write(outputstream) | 455 | self.write(outputstream) |
769 | 454 | outputstream.flush() | 456 | outputstream.flush() |
770 | 455 | contents = outputstream.getvalue() | 457 | contents = outputstream.getvalue() |
771 | 456 | 458 | ||
772 | === modified file 'cloudinit/log.py' | |||
773 | --- cloudinit/log.py 2013-04-17 16:42:55 +0000 | |||
774 | +++ cloudinit/log.py 2014-07-08 04:39:36 +0000 | |||
775 | @@ -28,7 +28,8 @@ | |||
776 | 28 | import os | 28 | import os |
777 | 29 | import sys | 29 | import sys |
778 | 30 | 30 | ||
780 | 31 | from StringIO import StringIO | 31 | import six |
781 | 32 | from six import StringIO | ||
782 | 32 | 33 | ||
783 | 33 | # Logging levels for easy access | 34 | # Logging levels for easy access |
784 | 34 | CRITICAL = logging.CRITICAL | 35 | CRITICAL = logging.CRITICAL |
785 | @@ -72,13 +73,13 @@ | |||
786 | 72 | 73 | ||
787 | 73 | log_cfgs = [] | 74 | log_cfgs = [] |
788 | 74 | log_cfg = cfg.get('logcfg') | 75 | log_cfg = cfg.get('logcfg') |
790 | 75 | if log_cfg and isinstance(log_cfg, (str, basestring)): | 76 | if log_cfg and isinstance(log_cfg, six.string_types): |
791 | 76 | # If there is a 'logcfg' entry in the config, | 77 | # If there is a 'logcfg' entry in the config, |
792 | 77 | # respect it, it is the old keyname | 78 | # respect it, it is the old keyname |
793 | 78 | log_cfgs.append(str(log_cfg)) | 79 | log_cfgs.append(str(log_cfg)) |
794 | 79 | elif "log_cfgs" in cfg: | 80 | elif "log_cfgs" in cfg: |
795 | 80 | for a_cfg in cfg['log_cfgs']: | 81 | for a_cfg in cfg['log_cfgs']: |
797 | 81 | if isinstance(a_cfg, (basestring, str)): | 82 | if isinstance(a_cfg, six.string_types): |
798 | 82 | log_cfgs.append(a_cfg) | 83 | log_cfgs.append(a_cfg) |
799 | 83 | elif isinstance(a_cfg, (collections.Iterable)): | 84 | elif isinstance(a_cfg, (collections.Iterable)): |
800 | 84 | cfg_str = [str(c) for c in a_cfg] | 85 | cfg_str = [str(c) for c in a_cfg] |
801 | 85 | 86 | ||
802 | === modified file 'cloudinit/mergers/__init__.py' | |||
803 | --- cloudinit/mergers/__init__.py 2013-05-03 21:41:28 +0000 | |||
804 | +++ cloudinit/mergers/__init__.py 2014-07-08 04:39:36 +0000 | |||
805 | @@ -18,6 +18,8 @@ | |||
806 | 18 | 18 | ||
807 | 19 | import re | 19 | import re |
808 | 20 | 20 | ||
809 | 21 | import six | ||
810 | 22 | |||
811 | 21 | from cloudinit import importer | 23 | from cloudinit import importer |
812 | 22 | from cloudinit import log as logging | 24 | from cloudinit import log as logging |
813 | 23 | from cloudinit import type_utils | 25 | from cloudinit import type_utils |
814 | @@ -100,7 +102,7 @@ | |||
815 | 100 | raw_mergers = config.pop('merge_type', None) | 102 | raw_mergers = config.pop('merge_type', None) |
816 | 101 | if raw_mergers is None: | 103 | if raw_mergers is None: |
817 | 102 | return parsed_mergers | 104 | return parsed_mergers |
819 | 103 | if isinstance(raw_mergers, (str, basestring)): | 105 | if isinstance(raw_mergers, six.string_types): |
820 | 104 | return string_extract_mergers(raw_mergers) | 106 | return string_extract_mergers(raw_mergers) |
821 | 105 | for m in raw_mergers: | 107 | for m in raw_mergers: |
822 | 106 | if isinstance(m, (dict)): | 108 | if isinstance(m, (dict)): |
823 | 107 | 109 | ||
824 | === modified file 'cloudinit/mergers/m_dict.py' | |||
825 | --- cloudinit/mergers/m_dict.py 2013-05-03 22:05:45 +0000 | |||
826 | +++ cloudinit/mergers/m_dict.py 2014-07-08 04:39:36 +0000 | |||
827 | @@ -16,6 +16,8 @@ | |||
828 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
829 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
830 | 18 | 18 | ||
831 | 19 | import six | ||
832 | 20 | |||
833 | 19 | DEF_MERGE_TYPE = 'no_replace' | 21 | DEF_MERGE_TYPE = 'no_replace' |
834 | 20 | MERGE_TYPES = ('replace', DEF_MERGE_TYPE,) | 22 | MERGE_TYPES = ('replace', DEF_MERGE_TYPE,) |
835 | 21 | 23 | ||
836 | @@ -57,7 +59,7 @@ | |||
837 | 57 | return new_v | 59 | return new_v |
838 | 58 | if isinstance(new_v, (list, tuple)) and self._recurse_array: | 60 | if isinstance(new_v, (list, tuple)) and self._recurse_array: |
839 | 59 | return self._merger.merge(old_v, new_v) | 61 | return self._merger.merge(old_v, new_v) |
841 | 60 | if isinstance(new_v, (basestring)) and self._recurse_str: | 62 | if isinstance(new_v, six.string_types) and self._recurse_str: |
842 | 61 | return self._merger.merge(old_v, new_v) | 63 | return self._merger.merge(old_v, new_v) |
843 | 62 | if isinstance(new_v, (dict)) and self._recurse_dict: | 64 | if isinstance(new_v, (dict)) and self._recurse_dict: |
844 | 63 | return self._merger.merge(old_v, new_v) | 65 | return self._merger.merge(old_v, new_v) |
845 | 64 | 66 | ||
846 | === modified file 'cloudinit/mergers/m_list.py' | |||
847 | --- cloudinit/mergers/m_list.py 2013-06-19 06:46:54 +0000 | |||
848 | +++ cloudinit/mergers/m_list.py 2014-07-08 04:39:36 +0000 | |||
849 | @@ -16,6 +16,8 @@ | |||
850 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
851 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
852 | 18 | 18 | ||
853 | 19 | import six | ||
854 | 20 | |||
855 | 19 | DEF_MERGE_TYPE = 'replace' | 21 | DEF_MERGE_TYPE = 'replace' |
856 | 20 | MERGE_TYPES = ('append', 'prepend', DEF_MERGE_TYPE, 'no_replace') | 22 | MERGE_TYPES = ('append', 'prepend', DEF_MERGE_TYPE, 'no_replace') |
857 | 21 | 23 | ||
858 | @@ -73,7 +75,7 @@ | |||
859 | 73 | return old_v | 75 | return old_v |
860 | 74 | if isinstance(new_v, (list, tuple)) and self._recurse_array: | 76 | if isinstance(new_v, (list, tuple)) and self._recurse_array: |
861 | 75 | return self._merger.merge(old_v, new_v) | 77 | return self._merger.merge(old_v, new_v) |
863 | 76 | if isinstance(new_v, (str, basestring)) and self._recurse_str: | 78 | if isinstance(new_v, six.string_types) and self._recurse_str: |
864 | 77 | return self._merger.merge(old_v, new_v) | 79 | return self._merger.merge(old_v, new_v) |
865 | 78 | if isinstance(new_v, (dict)) and self._recurse_dict: | 80 | if isinstance(new_v, (dict)) and self._recurse_dict: |
866 | 79 | return self._merger.merge(old_v, new_v) | 81 | return self._merger.merge(old_v, new_v) |
867 | 80 | 82 | ||
868 | === modified file 'cloudinit/mergers/m_str.py' | |||
869 | --- cloudinit/mergers/m_str.py 2013-05-03 21:41:28 +0000 | |||
870 | +++ cloudinit/mergers/m_str.py 2014-07-08 04:39:36 +0000 | |||
871 | @@ -17,6 +17,8 @@ | |||
872 | 17 | # You should have received a copy of the GNU General Public License | 17 | # You should have received a copy of the GNU General Public License |
873 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
874 | 19 | 19 | ||
875 | 20 | import six | ||
876 | 21 | |||
877 | 20 | 22 | ||
878 | 21 | class Merger(object): | 23 | class Merger(object): |
879 | 22 | def __init__(self, _merger, opts): | 24 | def __init__(self, _merger, opts): |
880 | @@ -34,11 +36,11 @@ | |||
881 | 34 | # perform the following action, if appending we will | 36 | # perform the following action, if appending we will |
882 | 35 | # merge them together, otherwise we will just return value. | 37 | # merge them together, otherwise we will just return value. |
883 | 36 | def _on_str(self, value, merge_with): | 38 | def _on_str(self, value, merge_with): |
885 | 37 | if not isinstance(value, (basestring)): | 39 | if not isinstance(value, six.string_types): |
886 | 38 | return merge_with | 40 | return merge_with |
887 | 39 | if not self._append: | 41 | if not self._append: |
888 | 40 | return merge_with | 42 | return merge_with |
891 | 41 | if isinstance(value, unicode): | 43 | if isinstance(value, six.text_type): |
892 | 42 | return value + unicode(merge_with) | 44 | return value + six.text_type(merge_with) |
893 | 43 | else: | 45 | else: |
895 | 44 | return value + str(merge_with) | 46 | return value + six.binary_type(merge_with) |
896 | 45 | 47 | ||
897 | === modified file 'cloudinit/netinfo.py' | |||
898 | --- cloudinit/netinfo.py 2014-02-26 18:14:55 +0000 | |||
899 | +++ cloudinit/netinfo.py 2014-07-08 04:39:36 +0000 | |||
900 | @@ -20,10 +20,12 @@ | |||
901 | 20 | # You should have received a copy of the GNU General Public License | 20 | # You should have received a copy of the GNU General Public License |
902 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
903 | 22 | 22 | ||
904 | 23 | import cloudinit.util as util | ||
905 | 24 | import re | 23 | import re |
906 | 25 | 24 | ||
907 | 26 | from prettytable import PrettyTable | 25 | from prettytable import PrettyTable |
908 | 26 | import six | ||
909 | 27 | |||
910 | 28 | import cloudinit.util as util | ||
911 | 27 | 29 | ||
912 | 28 | 30 | ||
913 | 29 | def netdev_info(empty=""): | 31 | def netdev_info(empty=""): |
914 | @@ -83,7 +85,7 @@ | |||
915 | 83 | devs[curdev][target] = toks[i][len(field) + 1:] | 85 | devs[curdev][target] = toks[i][len(field) + 1:] |
916 | 84 | 86 | ||
917 | 85 | if empty != "": | 87 | if empty != "": |
919 | 86 | for (_devname, dev) in devs.iteritems(): | 88 | for (_devname, dev) in six.iteritems(devs): |
920 | 87 | for field in dev: | 89 | for field in dev: |
921 | 88 | if dev[field] == "": | 90 | if dev[field] == "": |
922 | 89 | dev[field] = empty | 91 | dev[field] = empty |
923 | @@ -155,7 +157,7 @@ | |||
924 | 155 | if netdev is not None: | 157 | if netdev is not None: |
925 | 156 | fields = ['Device', 'Up', 'Address', 'Mask', 'Hw-Address'] | 158 | fields = ['Device', 'Up', 'Address', 'Mask', 'Hw-Address'] |
926 | 157 | tbl = PrettyTable(fields) | 159 | tbl = PrettyTable(fields) |
928 | 158 | for (dev, d) in netdev.iteritems(): | 160 | for (dev, d) in six.iteritems(netdev): |
929 | 159 | tbl.add_row([dev, d["up"], d["addr"], d["mask"], d["hwaddr"]]) | 161 | tbl.add_row([dev, d["up"], d["addr"], d["mask"], d["hwaddr"]]) |
930 | 160 | netdev_s = tbl.get_string() | 162 | netdev_s = tbl.get_string() |
931 | 161 | max_len = len(max(netdev_s.splitlines(), key=len)) | 163 | max_len = len(max(netdev_s.splitlines(), key=len)) |
932 | 162 | 164 | ||
933 | === modified file 'cloudinit/signal_handler.py' | |||
934 | --- cloudinit/signal_handler.py 2012-09-19 20:33:56 +0000 | |||
935 | +++ cloudinit/signal_handler.py 2014-07-08 04:39:36 +0000 | |||
936 | @@ -22,7 +22,7 @@ | |||
937 | 22 | import signal | 22 | import signal |
938 | 23 | import sys | 23 | import sys |
939 | 24 | 24 | ||
941 | 25 | from StringIO import StringIO | 25 | from six import StringIO |
942 | 26 | 26 | ||
943 | 27 | from cloudinit import log as logging | 27 | from cloudinit import log as logging |
944 | 28 | from cloudinit import util | 28 | from cloudinit import util |
945 | 29 | 29 | ||
946 | === modified file 'cloudinit/sources/DataSourceConfigDrive.py' | |||
947 | --- cloudinit/sources/DataSourceConfigDrive.py 2014-02-25 01:17:07 +0000 | |||
948 | +++ cloudinit/sources/DataSourceConfigDrive.py 2014-07-08 04:39:36 +0000 | |||
949 | @@ -20,6 +20,8 @@ | |||
950 | 20 | 20 | ||
951 | 21 | import os | 21 | import os |
952 | 22 | 22 | ||
953 | 23 | import six | ||
954 | 24 | |||
955 | 23 | from cloudinit import log as logging | 25 | from cloudinit import log as logging |
956 | 24 | from cloudinit import sources | 26 | from cloudinit import sources |
957 | 25 | from cloudinit import util | 27 | from cloudinit import util |
958 | @@ -198,7 +200,7 @@ | |||
959 | 198 | files = data.get('files', {}) | 200 | files = data.get('files', {}) |
960 | 199 | if files: | 201 | if files: |
961 | 200 | LOG.debug("Writing %s injected files", len(files)) | 202 | LOG.debug("Writing %s injected files", len(files)) |
963 | 201 | for (filename, content) in files.iteritems(): | 203 | for (filename, content) in six.iteritems(files): |
964 | 202 | if not filename.startswith(os.sep): | 204 | if not filename.startswith(os.sep): |
965 | 203 | filename = os.sep + filename | 205 | filename = os.sep + filename |
966 | 204 | try: | 206 | try: |
967 | 205 | 207 | ||
968 | === modified file 'cloudinit/sources/DataSourceEc2.py' | |||
969 | --- cloudinit/sources/DataSourceEc2.py 2014-02-01 20:03:32 +0000 | |||
970 | +++ cloudinit/sources/DataSourceEc2.py 2014-07-08 04:39:36 +0000 | |||
971 | @@ -23,6 +23,8 @@ | |||
972 | 23 | import os | 23 | import os |
973 | 24 | import time | 24 | import time |
974 | 25 | 25 | ||
975 | 26 | import six | ||
976 | 27 | |||
977 | 26 | from cloudinit import ec2_utils as ec2 | 28 | from cloudinit import ec2_utils as ec2 |
978 | 27 | from cloudinit import log as logging | 29 | from cloudinit import log as logging |
979 | 28 | from cloudinit import sources | 30 | from cloudinit import sources |
980 | @@ -156,8 +158,8 @@ | |||
981 | 156 | # 'ephemeral0': '/dev/sdb', | 158 | # 'ephemeral0': '/dev/sdb', |
982 | 157 | # 'root': '/dev/sda1'} | 159 | # 'root': '/dev/sda1'} |
983 | 158 | found = None | 160 | found = None |
986 | 159 | bdm_items = self.metadata['block-device-mapping'].iteritems() | 161 | bdms = self.metadata['block-device-mapping'] |
987 | 160 | for (entname, device) in bdm_items: | 162 | for (entname, device) in six.iteritems(bdms): |
988 | 161 | if entname == name: | 163 | if entname == name: |
989 | 162 | found = device | 164 | found = device |
990 | 163 | break | 165 | break |
991 | 164 | 166 | ||
992 | === modified file 'cloudinit/sources/DataSourceMAAS.py' | |||
993 | --- cloudinit/sources/DataSourceMAAS.py 2013-04-25 15:58:38 +0000 | |||
994 | +++ cloudinit/sources/DataSourceMAAS.py 2014-07-08 04:39:36 +0000 | |||
995 | @@ -20,11 +20,14 @@ | |||
996 | 20 | 20 | ||
997 | 21 | from email.utils import parsedate | 21 | from email.utils import parsedate |
998 | 22 | import errno | 22 | import errno |
999 | 23 | import oauth.oauth as oauth | ||
1000 | 24 | import os | 23 | import os |
1001 | 25 | import time | 24 | import time |
1002 | 26 | import urllib2 | 25 | import urllib2 |
1003 | 27 | 26 | ||
1004 | 27 | import oauth.oauth as oauth | ||
1005 | 28 | |||
1006 | 29 | import six | ||
1007 | 30 | |||
1008 | 28 | from cloudinit import log as logging | 31 | from cloudinit import log as logging |
1009 | 29 | from cloudinit import sources | 32 | from cloudinit import sources |
1010 | 30 | from cloudinit import url_helper | 33 | from cloudinit import url_helper |
1011 | @@ -262,7 +265,7 @@ | |||
1012 | 262 | 265 | ||
1013 | 263 | userdata = content.get('user-data', "") | 266 | userdata = content.get('user-data', "") |
1014 | 264 | md = {} | 267 | md = {} |
1016 | 265 | for (key, val) in content.iteritems(): | 268 | for (key, val) in six.iteritems(content): |
1017 | 266 | if key == 'user-data': | 269 | if key == 'user-data': |
1018 | 267 | continue | 270 | continue |
1019 | 268 | md[key] = val | 271 | md[key] = val |
1020 | 269 | 272 | ||
1021 | === modified file 'cloudinit/sources/DataSourceOVF.py' | |||
1022 | --- cloudinit/sources/DataSourceOVF.py 2013-06-07 17:30:03 +0000 | |||
1023 | +++ cloudinit/sources/DataSourceOVF.py 2014-07-08 04:39:36 +0000 | |||
1024 | @@ -26,6 +26,8 @@ | |||
1025 | 26 | import os | 26 | import os |
1026 | 27 | import re | 27 | import re |
1027 | 28 | 28 | ||
1028 | 29 | import six | ||
1029 | 30 | |||
1030 | 29 | from cloudinit import log as logging | 31 | from cloudinit import log as logging |
1031 | 30 | from cloudinit import sources | 32 | from cloudinit import sources |
1032 | 31 | from cloudinit import util | 33 | from cloudinit import util |
1033 | @@ -66,7 +68,7 @@ | |||
1034 | 66 | np = {'iso': transport_iso9660, | 68 | np = {'iso': transport_iso9660, |
1035 | 67 | 'vmware-guestd': transport_vmware_guestd, } | 69 | 'vmware-guestd': transport_vmware_guestd, } |
1036 | 68 | name = None | 70 | name = None |
1038 | 69 | for (name, transfunc) in np.iteritems(): | 71 | for (name, transfunc) in six.iteritems(np): |
1039 | 70 | (contents, _dev, _fname) = transfunc() | 72 | (contents, _dev, _fname) = transfunc() |
1040 | 71 | if contents: | 73 | if contents: |
1041 | 72 | break | 74 | break |
1042 | @@ -138,7 +140,7 @@ | |||
1043 | 138 | ud = "" | 140 | ud = "" |
1044 | 139 | cfg_props = ['password'] | 141 | cfg_props = ['password'] |
1045 | 140 | md_props = ['seedfrom', 'local-hostname', 'public-keys', 'instance-id'] | 142 | md_props = ['seedfrom', 'local-hostname', 'public-keys', 'instance-id'] |
1047 | 141 | for (prop, val) in props.iteritems(): | 143 | for (prop, val) in six.iteritems(props): |
1048 | 142 | if prop == 'hostname': | 144 | if prop == 'hostname': |
1049 | 143 | prop = "local-hostname" | 145 | prop = "local-hostname" |
1050 | 144 | if prop in md_props: | 146 | if prop in md_props: |
1051 | @@ -183,7 +185,7 @@ | |||
1052 | 183 | 185 | ||
1053 | 184 | # Go through mounts to see if it was already mounted | 186 | # Go through mounts to see if it was already mounted |
1054 | 185 | mounts = util.mounts() | 187 | mounts = util.mounts() |
1056 | 186 | for (dev, info) in mounts.iteritems(): | 188 | for (dev, info) in six.iteritems(mounts): |
1057 | 187 | fstype = info['fstype'] | 189 | fstype = info['fstype'] |
1058 | 188 | if fstype != "iso9660" and require_iso: | 190 | if fstype != "iso9660" and require_iso: |
1059 | 189 | continue | 191 | continue |
1060 | 190 | 192 | ||
1061 | === modified file 'cloudinit/sources/DataSourceSmartOS.py' | |||
1062 | --- cloudinit/sources/DataSourceSmartOS.py 2014-06-02 20:56:31 +0000 | |||
1063 | +++ cloudinit/sources/DataSourceSmartOS.py 2014-07-08 04:39:36 +0000 | |||
1064 | @@ -30,13 +30,15 @@ | |||
1065 | 30 | # Comments with "@datadictionary" are snippets of the definition | 30 | # Comments with "@datadictionary" are snippets of the definition |
1066 | 31 | 31 | ||
1067 | 32 | import base64 | 32 | import base64 |
1068 | 33 | import os | ||
1069 | 34 | import os.path | ||
1070 | 35 | |||
1071 | 36 | import serial | ||
1072 | 37 | import six | ||
1073 | 38 | |||
1074 | 33 | from cloudinit import log as logging | 39 | from cloudinit import log as logging |
1075 | 34 | from cloudinit import sources | 40 | from cloudinit import sources |
1076 | 35 | from cloudinit import util | 41 | from cloudinit import util |
1077 | 36 | import os | ||
1078 | 37 | import os.path | ||
1079 | 38 | import serial | ||
1080 | 39 | |||
1081 | 40 | 42 | ||
1082 | 41 | LOG = logging.getLogger(__name__) | 43 | LOG = logging.getLogger(__name__) |
1083 | 42 | 44 | ||
1084 | @@ -201,7 +203,7 @@ | |||
1085 | 201 | if b64_all is not None: | 203 | if b64_all is not None: |
1086 | 202 | self.b64_all = util.is_true(b64_all) | 204 | self.b64_all = util.is_true(b64_all) |
1087 | 203 | 205 | ||
1089 | 204 | for ci_noun, attribute in SMARTOS_ATTRIB_MAP.iteritems(): | 206 | for ci_noun, attribute in six.iteritems(SMARTOS_ATTRIB_MAP): |
1090 | 205 | smartos_noun, strip = attribute | 207 | smartos_noun, strip = attribute |
1091 | 206 | md[ci_noun] = self.query(smartos_noun, strip=strip) | 208 | md[ci_noun] = self.query(smartos_noun, strip=strip) |
1092 | 207 | 209 | ||
1093 | 208 | 210 | ||
1094 | === modified file 'cloudinit/sources/__init__.py' | |||
1095 | --- cloudinit/sources/__init__.py 2014-01-23 20:17:17 +0000 | |||
1096 | +++ cloudinit/sources/__init__.py 2014-07-08 04:39:36 +0000 | |||
1097 | @@ -23,6 +23,8 @@ | |||
1098 | 23 | import abc | 23 | import abc |
1099 | 24 | import os | 24 | import os |
1100 | 25 | 25 | ||
1101 | 26 | import six | ||
1102 | 27 | |||
1103 | 26 | from cloudinit import importer | 28 | from cloudinit import importer |
1104 | 27 | from cloudinit import log as logging | 29 | from cloudinit import log as logging |
1105 | 28 | from cloudinit import type_utils | 30 | from cloudinit import type_utils |
1106 | @@ -130,7 +132,7 @@ | |||
1107 | 130 | # we want to return the correct value for what will actually | 132 | # we want to return the correct value for what will actually |
1108 | 131 | # exist in this instance | 133 | # exist in this instance |
1109 | 132 | mappings = {"sd": ("vd", "xvd", "vtb")} | 134 | mappings = {"sd": ("vd", "xvd", "vtb")} |
1111 | 133 | for (nfrom, tlist) in mappings.iteritems(): | 135 | for (nfrom, tlist) in six.iteritems(mappings): |
1112 | 134 | if not short_name.startswith(nfrom): | 136 | if not short_name.startswith(nfrom): |
1113 | 135 | continue | 137 | continue |
1114 | 136 | for nto in tlist: | 138 | for nto in tlist: |
1115 | @@ -218,18 +220,18 @@ | |||
1116 | 218 | if not pubkey_data: | 220 | if not pubkey_data: |
1117 | 219 | return keys | 221 | return keys |
1118 | 220 | 222 | ||
1120 | 221 | if isinstance(pubkey_data, (basestring, str)): | 223 | if isinstance(pubkey_data, six.string_types): |
1121 | 222 | return str(pubkey_data).splitlines() | 224 | return str(pubkey_data).splitlines() |
1122 | 223 | 225 | ||
1123 | 224 | if isinstance(pubkey_data, (list, set)): | 226 | if isinstance(pubkey_data, (list, set)): |
1124 | 225 | return list(pubkey_data) | 227 | return list(pubkey_data) |
1125 | 226 | 228 | ||
1126 | 227 | if isinstance(pubkey_data, (dict)): | 229 | if isinstance(pubkey_data, (dict)): |
1128 | 228 | for (_keyname, klist) in pubkey_data.iteritems(): | 230 | for (_keyname, klist) in six.iteritems(pubkey_data): |
1129 | 229 | # lp:506332 uec metadata service responds with | 231 | # lp:506332 uec metadata service responds with |
1130 | 230 | # data that makes boto populate a string for 'klist' rather | 232 | # data that makes boto populate a string for 'klist' rather |
1131 | 231 | # than a list. | 233 | # than a list. |
1133 | 232 | if isinstance(klist, (str, basestring)): | 234 | if isinstance(klist, six.string_types): |
1134 | 233 | klist = [klist] | 235 | klist = [klist] |
1135 | 234 | if isinstance(klist, (list, set)): | 236 | if isinstance(klist, (list, set)): |
1136 | 235 | for pkey in klist: | 237 | for pkey in klist: |
1137 | 236 | 238 | ||
1138 | === modified file 'cloudinit/sources/helpers/openstack.py' | |||
1139 | --- cloudinit/sources/helpers/openstack.py 2014-02-24 22:41:42 +0000 | |||
1140 | +++ cloudinit/sources/helpers/openstack.py 2014-07-08 04:39:36 +0000 | |||
1141 | @@ -23,6 +23,8 @@ | |||
1142 | 23 | import copy | 23 | import copy |
1143 | 24 | import os | 24 | import os |
1144 | 25 | 25 | ||
1145 | 26 | import six | ||
1146 | 27 | |||
1147 | 26 | from cloudinit import ec2_utils | 28 | from cloudinit import ec2_utils |
1148 | 27 | from cloudinit import log as logging | 29 | from cloudinit import log as logging |
1149 | 28 | from cloudinit import sources | 30 | from cloudinit import sources |
1150 | @@ -224,7 +226,7 @@ | |||
1151 | 224 | 'version': 2, | 226 | 'version': 2, |
1152 | 225 | } | 227 | } |
1153 | 226 | data = datafiles(version) | 228 | data = datafiles(version) |
1155 | 227 | for (name, (path, required, translator)) in data.iteritems(): | 229 | for (name, (path, required, translator)) in six.iteritems(data): |
1156 | 228 | path = self._path_join(self.base_path, path) | 230 | path = self._path_join(self.base_path, path) |
1157 | 229 | data = None | 231 | data = None |
1158 | 230 | found = False | 232 | found = False |
1159 | @@ -344,7 +346,7 @@ | |||
1160 | 344 | raise NonReadable("%s: no files found" % (self.base_path)) | 346 | raise NonReadable("%s: no files found" % (self.base_path)) |
1161 | 345 | 347 | ||
1162 | 346 | md = {} | 348 | md = {} |
1164 | 347 | for (name, (key, translator, default)) in FILES_V1.iteritems(): | 349 | for (name, (key, translator, default)) in six.iteritems(FILES_V1): |
1165 | 348 | if name in found: | 350 | if name in found: |
1166 | 349 | path = found[name] | 351 | path = found[name] |
1167 | 350 | try: | 352 | try: |
1168 | 351 | 353 | ||
1169 | === modified file 'cloudinit/ssh_util.py' | |||
1170 | --- cloudinit/ssh_util.py 2013-06-19 06:44:00 +0000 | |||
1171 | +++ cloudinit/ssh_util.py 2014-07-08 04:39:36 +0000 | |||
1172 | @@ -239,7 +239,7 @@ | |||
1173 | 239 | # Make sure the users .ssh dir is setup accordingly | 239 | # Make sure the users .ssh dir is setup accordingly |
1174 | 240 | (ssh_dir, pwent) = users_ssh_info(username) | 240 | (ssh_dir, pwent) = users_ssh_info(username) |
1175 | 241 | if not os.path.isdir(ssh_dir): | 241 | if not os.path.isdir(ssh_dir): |
1177 | 242 | util.ensure_dir(ssh_dir, mode=0700) | 242 | util.ensure_dir(ssh_dir, mode=0o700) |
1178 | 243 | util.chownbyid(ssh_dir, pwent.pw_uid, pwent.pw_gid) | 243 | util.chownbyid(ssh_dir, pwent.pw_uid, pwent.pw_gid) |
1179 | 244 | 244 | ||
1180 | 245 | # Turn the 'update' keys given into actual entries | 245 | # Turn the 'update' keys given into actual entries |
1181 | @@ -252,8 +252,8 @@ | |||
1182 | 252 | (auth_key_fn, auth_key_entries) = extract_authorized_keys(username) | 252 | (auth_key_fn, auth_key_entries) = extract_authorized_keys(username) |
1183 | 253 | with util.SeLinuxGuard(ssh_dir, recursive=True): | 253 | with util.SeLinuxGuard(ssh_dir, recursive=True): |
1184 | 254 | content = update_authorized_keys(auth_key_entries, key_entries) | 254 | content = update_authorized_keys(auth_key_entries, key_entries) |
1187 | 255 | util.ensure_dir(os.path.dirname(auth_key_fn), mode=0700) | 255 | util.ensure_dir(os.path.dirname(auth_key_fn), mode=0o700) |
1188 | 256 | util.write_file(auth_key_fn, content, mode=0600) | 256 | util.write_file(auth_key_fn, content, mode=0o600) |
1189 | 257 | util.chownbyid(auth_key_fn, pwent.pw_uid, pwent.pw_gid) | 257 | util.chownbyid(auth_key_fn, pwent.pw_uid, pwent.pw_gid) |
1190 | 258 | 258 | ||
1191 | 259 | 259 | ||
1192 | 260 | 260 | ||
1193 | === modified file 'cloudinit/stages.py' | |||
1194 | --- cloudinit/stages.py 2014-02-13 18:53:08 +0000 | |||
1195 | +++ cloudinit/stages.py 2014-07-08 04:39:36 +0000 | |||
1196 | @@ -20,12 +20,13 @@ | |||
1197 | 20 | # You should have received a copy of the GNU General Public License | 20 | # You should have received a copy of the GNU General Public License |
1198 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1199 | 22 | 22 | ||
1200 | 23 | import cPickle as pickle | ||
1201 | 24 | |||
1202 | 25 | import copy | 23 | import copy |
1203 | 26 | import os | 24 | import os |
1204 | 25 | import pickle | ||
1205 | 27 | import sys | 26 | import sys |
1206 | 28 | 27 | ||
1207 | 28 | import six | ||
1208 | 29 | |||
1209 | 29 | from cloudinit.settings import (PER_INSTANCE, FREQUENCIES, CLOUD_CONFIG) | 30 | from cloudinit.settings import (PER_INSTANCE, FREQUENCIES, CLOUD_CONFIG) |
1210 | 30 | 31 | ||
1211 | 31 | from cloudinit import handlers | 32 | from cloudinit import handlers |
1212 | @@ -202,7 +203,7 @@ | |||
1213 | 202 | util.logexc(LOG, "Failed pickling datasource %s", self.datasource) | 203 | util.logexc(LOG, "Failed pickling datasource %s", self.datasource) |
1214 | 203 | return False | 204 | return False |
1215 | 204 | try: | 205 | try: |
1217 | 205 | util.write_file(pickled_fn, pk_contents, mode=0400) | 206 | util.write_file(pickled_fn, pk_contents, mode=0o400) |
1218 | 206 | except Exception: | 207 | except Exception: |
1219 | 207 | util.logexc(LOG, "Failed pickling datasource to %s", pickled_fn) | 208 | util.logexc(LOG, "Failed pickling datasource to %s", pickled_fn) |
1220 | 208 | return False | 209 | return False |
1221 | @@ -324,15 +325,15 @@ | |||
1222 | 324 | 325 | ||
1223 | 325 | def _store_userdata(self): | 326 | def _store_userdata(self): |
1224 | 326 | raw_ud = "%s" % (self.datasource.get_userdata_raw()) | 327 | raw_ud = "%s" % (self.datasource.get_userdata_raw()) |
1226 | 327 | util.write_file(self._get_ipath('userdata_raw'), raw_ud, 0600) | 328 | util.write_file(self._get_ipath('userdata_raw'), raw_ud, 0o600) |
1227 | 328 | processed_ud = "%s" % (self.datasource.get_userdata()) | 329 | processed_ud = "%s" % (self.datasource.get_userdata()) |
1229 | 329 | util.write_file(self._get_ipath('userdata'), processed_ud, 0600) | 330 | util.write_file(self._get_ipath('userdata'), processed_ud, 0o600) |
1230 | 330 | 331 | ||
1231 | 331 | def _store_vendordata(self): | 332 | def _store_vendordata(self): |
1232 | 332 | raw_vd = "%s" % (self.datasource.get_vendordata_raw()) | 333 | raw_vd = "%s" % (self.datasource.get_vendordata_raw()) |
1234 | 333 | util.write_file(self._get_ipath('vendordata_raw'), raw_vd, 0600) | 334 | util.write_file(self._get_ipath('vendordata_raw'), raw_vd, 0o600) |
1235 | 334 | processed_vd = "%s" % (self.datasource.get_vendordata()) | 335 | processed_vd = "%s" % (self.datasource.get_vendordata()) |
1237 | 335 | util.write_file(self._get_ipath('vendordata'), processed_vd, 0600) | 336 | util.write_file(self._get_ipath('vendordata'), processed_vd, 0o600) |
1238 | 336 | 337 | ||
1239 | 337 | def _default_handlers(self, opts=None): | 338 | def _default_handlers(self, opts=None): |
1240 | 338 | if opts is None: | 339 | if opts is None: |
1241 | @@ -384,7 +385,7 @@ | |||
1242 | 384 | if not path or not os.path.isdir(path): | 385 | if not path or not os.path.isdir(path): |
1243 | 385 | return | 386 | return |
1244 | 386 | potential_handlers = util.find_modules(path) | 387 | potential_handlers = util.find_modules(path) |
1246 | 387 | for (fname, mod_name) in potential_handlers.iteritems(): | 388 | for (fname, mod_name) in six.iteritems(potential_handlers): |
1247 | 388 | try: | 389 | try: |
1248 | 389 | mod_locs = importer.find_module(mod_name, [''], | 390 | mod_locs = importer.find_module(mod_name, [''], |
1249 | 390 | ['list_types', | 391 | ['list_types', |
1250 | @@ -574,7 +575,7 @@ | |||
1251 | 574 | for item in cfg_mods: | 575 | for item in cfg_mods: |
1252 | 575 | if not item: | 576 | if not item: |
1253 | 576 | continue | 577 | continue |
1255 | 577 | if isinstance(item, (str, basestring)): | 578 | if isinstance(item, six.string_types): |
1256 | 578 | module_list.append({ | 579 | module_list.append({ |
1257 | 579 | 'mod': item.strip(), | 580 | 'mod': item.strip(), |
1258 | 580 | }) | 581 | }) |
1259 | 581 | 582 | ||
1260 | === modified file 'cloudinit/type_utils.py' | |||
1261 | --- cloudinit/type_utils.py 2013-03-07 03:24:05 +0000 | |||
1262 | +++ cloudinit/type_utils.py 2014-07-08 04:39:36 +0000 | |||
1263 | @@ -24,11 +24,30 @@ | |||
1264 | 24 | 24 | ||
1265 | 25 | import types | 25 | import types |
1266 | 26 | 26 | ||
1267 | 27 | import six | ||
1268 | 28 | |||
1269 | 29 | if six.PY3: | ||
1270 | 30 | _NAME_TYPES = ( | ||
1271 | 31 | types.ModuleType, | ||
1272 | 32 | types.FunctionType, | ||
1273 | 33 | types.LambdaType, | ||
1274 | 34 | type, | ||
1275 | 35 | ) | ||
1276 | 36 | else: | ||
1277 | 37 | _NAME_TYPES = ( | ||
1278 | 38 | types.TypeType, | ||
1279 | 39 | types.ModuleType, | ||
1280 | 40 | types.FunctionType, | ||
1281 | 41 | types.LambdaType, | ||
1282 | 42 | types.ClassType, | ||
1283 | 43 | ) | ||
1284 | 44 | |||
1285 | 27 | 45 | ||
1286 | 28 | def obj_name(obj): | 46 | def obj_name(obj): |
1293 | 29 | if isinstance(obj, (types.TypeType, | 47 | if isinstance(obj, _NAME_TYPES): |
1294 | 30 | types.ModuleType, | 48 | return six.text_type(obj.__name__) |
1295 | 31 | types.FunctionType, | 49 | else: |
1296 | 32 | types.LambdaType)): | 50 | if not hasattr(obj, '__class__'): |
1297 | 33 | return str(obj.__name__) | 51 | return repr(obj) |
1298 | 34 | return obj_name(obj.__class__) | 52 | else: |
1299 | 53 | return obj_name(obj.__class__) | ||
1300 | 35 | 54 | ||
1301 | === modified file 'cloudinit/url_helper.py' | |||
1302 | --- cloudinit/url_helper.py 2014-02-13 17:13:42 +0000 | |||
1303 | +++ cloudinit/url_helper.py 2014-07-08 04:39:36 +0000 | |||
1304 | @@ -20,21 +20,28 @@ | |||
1305 | 20 | # You should have received a copy of the GNU General Public License | 20 | # You should have received a copy of the GNU General Public License |
1306 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1307 | 22 | 22 | ||
1309 | 23 | import httplib | 23 | import six |
1310 | 24 | |||
1311 | 24 | import time | 25 | import time |
1312 | 25 | import urllib | ||
1313 | 26 | 26 | ||
1314 | 27 | import requests | 27 | import requests |
1315 | 28 | from requests import exceptions | 28 | from requests import exceptions |
1316 | 29 | 29 | ||
1318 | 30 | from urlparse import (urlparse, urlunparse) | 30 | from six.moves.urllib.parse import (urlparse, urlunparse) |
1319 | 31 | from six.moves.urllib.parse import quote as urlquote | ||
1320 | 31 | 32 | ||
1321 | 32 | from cloudinit import log as logging | 33 | from cloudinit import log as logging |
1322 | 33 | from cloudinit import version | 34 | from cloudinit import version |
1323 | 34 | 35 | ||
1324 | 35 | LOG = logging.getLogger(__name__) | 36 | LOG = logging.getLogger(__name__) |
1325 | 36 | 37 | ||
1327 | 37 | NOT_FOUND = httplib.NOT_FOUND | 38 | if six.PY2: |
1328 | 39 | import httplib | ||
1329 | 40 | NOT_FOUND = httplib.NOT_FOUND | ||
1330 | 41 | else: | ||
1331 | 42 | import http.client | ||
1332 | 43 | NOT_FOUND = http.client.NOT_FOUND | ||
1333 | 44 | |||
1334 | 38 | 45 | ||
1335 | 39 | # Check if requests has ssl support (added in requests >= 0.8.8) | 46 | # Check if requests has ssl support (added in requests >= 0.8.8) |
1336 | 40 | SSL_ENABLED = False | 47 | SSL_ENABLED = False |
1337 | @@ -70,7 +77,7 @@ | |||
1338 | 70 | path = url_parsed[2] | 77 | path = url_parsed[2] |
1339 | 71 | if path and not path.endswith("/"): | 78 | if path and not path.endswith("/"): |
1340 | 72 | path += "/" | 79 | path += "/" |
1342 | 73 | path += urllib.quote(str(add_on), safe="/:") | 80 | path += urlquote(str(add_on), safe="/:") |
1343 | 74 | url_parsed[2] = path | 81 | url_parsed[2] = path |
1344 | 75 | return urlunparse(url_parsed) | 82 | return urlunparse(url_parsed) |
1345 | 76 | 83 | ||
1346 | @@ -111,7 +118,7 @@ | |||
1347 | 111 | 118 | ||
1348 | 112 | @property | 119 | @property |
1349 | 113 | def contents(self): | 120 | def contents(self): |
1351 | 114 | return self._response.content | 121 | return self._response.text |
1352 | 115 | 122 | ||
1353 | 116 | @property | 123 | @property |
1354 | 117 | def url(self): | 124 | def url(self): |
1355 | @@ -135,7 +142,7 @@ | |||
1356 | 135 | return self._response.status_code | 142 | return self._response.status_code |
1357 | 136 | 143 | ||
1358 | 137 | def __str__(self): | 144 | def __str__(self): |
1360 | 138 | return self.contents | 145 | return self._response.text |
1361 | 139 | 146 | ||
1362 | 140 | 147 | ||
1363 | 141 | class UrlError(IOError): | 148 | class UrlError(IOError): |
1364 | 142 | 149 | ||
1365 | === modified file 'cloudinit/user_data.py' | |||
1366 | --- cloudinit/user_data.py 2014-01-24 20:29:09 +0000 | |||
1367 | +++ cloudinit/user_data.py 2014-07-08 04:39:36 +0000 | |||
1368 | @@ -29,6 +29,8 @@ | |||
1369 | 29 | from email.mime.nonmultipart import MIMENonMultipart | 29 | from email.mime.nonmultipart import MIMENonMultipart |
1370 | 30 | from email.mime.text import MIMEText | 30 | from email.mime.text import MIMEText |
1371 | 31 | 31 | ||
1372 | 32 | import six | ||
1373 | 33 | |||
1374 | 32 | from cloudinit import handlers | 34 | from cloudinit import handlers |
1375 | 33 | from cloudinit import log as logging | 35 | from cloudinit import log as logging |
1376 | 34 | from cloudinit import util | 36 | from cloudinit import util |
1377 | @@ -235,9 +237,9 @@ | |||
1378 | 235 | resp = util.read_file_or_url(include_url, | 237 | resp = util.read_file_or_url(include_url, |
1379 | 236 | ssl_details=self.ssl_details) | 238 | ssl_details=self.ssl_details) |
1380 | 237 | if include_once_on and resp.ok(): | 239 | if include_once_on and resp.ok(): |
1382 | 238 | util.write_file(include_once_fn, str(resp), mode=0600) | 240 | util.write_file(include_once_fn, resp.contents, mode=0o600) |
1383 | 239 | if resp.ok(): | 241 | if resp.ok(): |
1385 | 240 | content = str(resp) | 242 | content = resp.contents |
1386 | 241 | else: | 243 | else: |
1387 | 242 | LOG.warn(("Fetching from %s resulted in" | 244 | LOG.warn(("Fetching from %s resulted in" |
1388 | 243 | " a invalid http code of %s"), | 245 | " a invalid http code of %s"), |
1389 | @@ -256,7 +258,7 @@ | |||
1390 | 256 | # filename and type not be present | 258 | # filename and type not be present |
1391 | 257 | # or | 259 | # or |
1392 | 258 | # scalar(payload) | 260 | # scalar(payload) |
1394 | 259 | if isinstance(ent, (str, basestring)): | 261 | if isinstance(ent, six.string_types): |
1395 | 260 | ent = {'content': ent} | 262 | ent = {'content': ent} |
1396 | 261 | if not isinstance(ent, (dict)): | 263 | if not isinstance(ent, (dict)): |
1397 | 262 | # TODO(harlowja) raise? | 264 | # TODO(harlowja) raise? |
1398 | @@ -337,7 +339,7 @@ | |||
1399 | 337 | data = util.decomp_gzip(raw_data) | 339 | data = util.decomp_gzip(raw_data) |
1400 | 338 | if "mime-version:" in data[0:4096].lower(): | 340 | if "mime-version:" in data[0:4096].lower(): |
1401 | 339 | msg = email.message_from_string(data) | 341 | msg = email.message_from_string(data) |
1403 | 340 | for (key, val) in headers.iteritems(): | 342 | for (key, val) in six.iteritems(headers): |
1404 | 341 | _replace_header(msg, key, val) | 343 | _replace_header(msg, key, val) |
1405 | 342 | else: | 344 | else: |
1406 | 343 | mtype = headers.get(CONTENT_TYPE, NOT_MULTIPART_TYPE) | 345 | mtype = headers.get(CONTENT_TYPE, NOT_MULTIPART_TYPE) |
1407 | 344 | 346 | ||
1408 | === modified file 'cloudinit/util.py' | |||
1409 | --- cloudinit/util.py 2014-02-24 22:20:12 +0000 | |||
1410 | +++ cloudinit/util.py 2014-07-08 04:39:36 +0000 | |||
1411 | @@ -22,8 +22,6 @@ | |||
1412 | 22 | # | 22 | # |
1413 | 23 | # pylint: disable=C0302 | 23 | # pylint: disable=C0302 |
1414 | 24 | 24 | ||
1415 | 25 | from StringIO import StringIO | ||
1416 | 26 | |||
1417 | 27 | import contextlib | 25 | import contextlib |
1418 | 28 | import copy as obj_copy | 26 | import copy as obj_copy |
1419 | 29 | import ctypes | 27 | import ctypes |
1420 | @@ -47,8 +45,10 @@ | |||
1421 | 47 | import sys | 45 | import sys |
1422 | 48 | import tempfile | 46 | import tempfile |
1423 | 49 | import time | 47 | import time |
1426 | 50 | import urlparse | 48 | |
1427 | 51 | 49 | from six.moves.urllib import parse as urlparse | |
1428 | 50 | |||
1429 | 51 | import six | ||
1430 | 52 | import yaml | 52 | import yaml |
1431 | 53 | 53 | ||
1432 | 54 | from cloudinit import importer | 54 | from cloudinit import importer |
1433 | @@ -71,8 +71,25 @@ | |||
1434 | 71 | } | 71 | } |
1435 | 72 | FN_ALLOWED = ('_-.()' + string.digits + string.ascii_letters) | 72 | FN_ALLOWED = ('_-.()' + string.digits + string.ascii_letters) |
1436 | 73 | 73 | ||
1437 | 74 | TRUE_STRINGS = ('true', '1', 'on', 'yes') | ||
1438 | 75 | FALSE_STRINGS = ('off', '0', 'no', 'false') | ||
1439 | 76 | |||
1440 | 74 | # Helper utils to see if running in a container | 77 | # Helper utils to see if running in a container |
1442 | 75 | CONTAINER_TESTS = ['running-in-container', 'lxc-is-container'] | 78 | CONTAINER_TESTS = ('running-in-container', 'lxc-is-container') |
1443 | 79 | |||
1444 | 80 | |||
1445 | 81 | def decode_binary(blob, encoding='utf-8'): | ||
1446 | 82 | # Converts a binary type into a text type using given encoding. | ||
1447 | 83 | if isinstance(blob, six.text_type): | ||
1448 | 84 | return blob | ||
1449 | 85 | return blob.decode(encoding) | ||
1450 | 86 | |||
1451 | 87 | |||
1452 | 88 | def encode_text(text, encoding='utf-8'): | ||
1453 | 89 | # Converts a text string into a binary type using given encoding. | ||
1454 | 90 | if isinstance(text, six.binary_type): | ||
1455 | 91 | return text | ||
1456 | 92 | return text.encode(encoding) | ||
1457 | 76 | 93 | ||
1458 | 77 | 94 | ||
1459 | 78 | class ProcessExecutionError(IOError): | 95 | class ProcessExecutionError(IOError): |
1460 | @@ -149,7 +166,8 @@ | |||
1461 | 149 | if self.selinux and self.selinux.is_selinux_enabled(): | 166 | if self.selinux and self.selinux.is_selinux_enabled(): |
1462 | 150 | path = os.path.realpath(os.path.expanduser(self.path)) | 167 | path = os.path.realpath(os.path.expanduser(self.path)) |
1463 | 151 | # path should be a string, not unicode | 168 | # path should be a string, not unicode |
1465 | 152 | path = str(path) | 169 | if six.PY2: |
1466 | 170 | path = str(path) | ||
1467 | 153 | do_restore = False | 171 | do_restore = False |
1468 | 154 | try: | 172 | try: |
1469 | 155 | # See if even worth restoring?? | 173 | # See if even worth restoring?? |
1470 | @@ -211,10 +229,10 @@ | |||
1471 | 211 | def is_true(val, addons=None): | 229 | def is_true(val, addons=None): |
1472 | 212 | if isinstance(val, (bool)): | 230 | if isinstance(val, (bool)): |
1473 | 213 | return val is True | 231 | return val is True |
1475 | 214 | check_set = ['true', '1', 'on', 'yes'] | 232 | check_set = TRUE_STRINGS |
1476 | 215 | if addons: | 233 | if addons: |
1479 | 216 | check_set = check_set + addons | 234 | check_set = list(check_set) + addons |
1480 | 217 | if str(val).lower().strip() in check_set: | 235 | if six.text_type(val).lower().strip() in check_set: |
1481 | 218 | return True | 236 | return True |
1482 | 219 | return False | 237 | return False |
1483 | 220 | 238 | ||
1484 | @@ -222,10 +240,10 @@ | |||
1485 | 222 | def is_false(val, addons=None): | 240 | def is_false(val, addons=None): |
1486 | 223 | if isinstance(val, (bool)): | 241 | if isinstance(val, (bool)): |
1487 | 224 | return val is False | 242 | return val is False |
1489 | 225 | check_set = ['off', '0', 'no', 'false'] | 243 | check_set = FALSE_STRINGS |
1490 | 226 | if addons: | 244 | if addons: |
1493 | 227 | check_set = check_set + addons | 245 | check_set = list(check_set) + addons |
1494 | 228 | if str(val).lower().strip() in check_set: | 246 | if six.text_type(val).lower().strip() in check_set: |
1495 | 229 | return True | 247 | return True |
1496 | 230 | return False | 248 | return False |
1497 | 231 | 249 | ||
1498 | @@ -275,7 +293,7 @@ | |||
1499 | 275 | def uniq_merge(*lists): | 293 | def uniq_merge(*lists): |
1500 | 276 | combined_list = [] | 294 | combined_list = [] |
1501 | 277 | for a_list in lists: | 295 | for a_list in lists: |
1503 | 278 | if isinstance(a_list, (str, basestring)): | 296 | if isinstance(a_list, six.string_types): |
1504 | 279 | a_list = a_list.strip().split(",") | 297 | a_list = a_list.strip().split(",") |
1505 | 280 | # Kickout the empty ones | 298 | # Kickout the empty ones |
1506 | 281 | a_list = [a for a in a_list if len(a)] | 299 | a_list = [a for a in a_list if len(a)] |
1507 | @@ -284,7 +302,7 @@ | |||
1508 | 284 | 302 | ||
1509 | 285 | 303 | ||
1510 | 286 | def clean_filename(fn): | 304 | def clean_filename(fn): |
1512 | 287 | for (k, v) in FN_REPLACEMENTS.iteritems(): | 305 | for (k, v) in six.iteritems(FN_REPLACEMENTS): |
1513 | 288 | fn = fn.replace(k, v) | 306 | fn = fn.replace(k, v) |
1514 | 289 | removals = [] | 307 | removals = [] |
1515 | 290 | for k in fn: | 308 | for k in fn: |
1516 | @@ -298,14 +316,14 @@ | |||
1517 | 298 | 316 | ||
1518 | 299 | def decomp_gzip(data, quiet=True): | 317 | def decomp_gzip(data, quiet=True): |
1519 | 300 | try: | 318 | try: |
1521 | 301 | buf = StringIO(str(data)) | 319 | buf = six.BytesIO(encode_text(data)) |
1522 | 302 | with contextlib.closing(gzip.GzipFile(None, "rb", 1, buf)) as gh: | 320 | with contextlib.closing(gzip.GzipFile(None, "rb", 1, buf)) as gh: |
1524 | 303 | return gh.read() | 321 | return decode_binary(gh.read()) |
1525 | 304 | except Exception as e: | 322 | except Exception as e: |
1526 | 305 | if quiet: | 323 | if quiet: |
1527 | 306 | return data | 324 | return data |
1528 | 307 | else: | 325 | else: |
1530 | 308 | raise DecompressionError(str(e)) | 326 | raise DecompressionError(six.text_type(e)) |
1531 | 309 | 327 | ||
1532 | 310 | 328 | ||
1533 | 311 | def extract_usergroup(ug_pair): | 329 | def extract_usergroup(ug_pair): |
1534 | @@ -364,7 +382,7 @@ | |||
1535 | 364 | 382 | ||
1536 | 365 | 383 | ||
1537 | 366 | def load_json(text, root_types=(dict,)): | 384 | def load_json(text, root_types=(dict,)): |
1539 | 367 | decoded = json.loads(text) | 385 | decoded = json.loads(decode_binary(text)) |
1540 | 368 | if not isinstance(decoded, tuple(root_types)): | 386 | if not isinstance(decoded, tuple(root_types)): |
1541 | 369 | expected_types = ", ".join([str(t) for t in root_types]) | 387 | expected_types = ", ".join([str(t) for t in root_types]) |
1542 | 370 | raise TypeError("(%s) root types expected, got %s instead" | 388 | raise TypeError("(%s) root types expected, got %s instead" |
1543 | @@ -396,7 +414,7 @@ | |||
1544 | 396 | if key not in yobj: | 414 | if key not in yobj: |
1545 | 397 | return default | 415 | return default |
1546 | 398 | val = yobj[key] | 416 | val = yobj[key] |
1548 | 399 | if not isinstance(val, (str, basestring)): | 417 | if not isinstance(val, six.string_types): |
1549 | 400 | val = str(val) | 418 | val = str(val) |
1550 | 401 | return val | 419 | return val |
1551 | 402 | 420 | ||
1552 | @@ -431,7 +449,7 @@ | |||
1553 | 431 | if isinstance(val, (list)): | 449 | if isinstance(val, (list)): |
1554 | 432 | cval = [v for v in val] | 450 | cval = [v for v in val] |
1555 | 433 | return cval | 451 | return cval |
1557 | 434 | if not isinstance(val, (basestring)): | 452 | if not isinstance(val, six.string_types): |
1558 | 435 | val = str(val) | 453 | val = str(val) |
1559 | 436 | return [val] | 454 | return [val] |
1560 | 437 | 455 | ||
1561 | @@ -706,11 +724,11 @@ | |||
1562 | 706 | 724 | ||
1563 | 707 | def load_yaml(blob, default=None, allowed=(dict,)): | 725 | def load_yaml(blob, default=None, allowed=(dict,)): |
1564 | 708 | loaded = default | 726 | loaded = default |
1565 | 727 | blob = decode_binary(blob) | ||
1566 | 709 | try: | 728 | try: |
1571 | 710 | blob = str(blob) | 729 | LOG.debug("Attempting to load yaml from string " |
1572 | 711 | LOG.debug(("Attempting to load yaml from string " | 730 | "of length %s with allowed root types %s", |
1573 | 712 | "of length %s with allowed root types %s"), | 731 | len(blob), allowed) |
1570 | 713 | len(blob), allowed) | ||
1574 | 714 | converted = safeyaml.load(blob) | 732 | converted = safeyaml.load(blob) |
1575 | 715 | if not isinstance(converted, allowed): | 733 | if not isinstance(converted, allowed): |
1576 | 716 | # Yes this will just be caught, but thats ok for now... | 734 | # Yes this will just be caught, but thats ok for now... |
1577 | @@ -744,14 +762,12 @@ | |||
1578 | 744 | md_resp = read_file_or_url(md_url, timeout, retries, file_retries) | 762 | md_resp = read_file_or_url(md_url, timeout, retries, file_retries) |
1579 | 745 | md = None | 763 | md = None |
1580 | 746 | if md_resp.ok(): | 764 | if md_resp.ok(): |
1583 | 747 | md_str = str(md_resp) | 765 | md = load_yaml(md_resp.contents, default={}) |
1582 | 748 | md = load_yaml(md_str, default={}) | ||
1584 | 749 | 766 | ||
1585 | 750 | ud_resp = read_file_or_url(ud_url, timeout, retries, file_retries) | 767 | ud_resp = read_file_or_url(ud_url, timeout, retries, file_retries) |
1586 | 751 | ud = None | 768 | ud = None |
1587 | 752 | if ud_resp.ok(): | 769 | if ud_resp.ok(): |
1590 | 753 | ud_str = str(ud_resp) | 770 | ud = ud_resp.contents |
1589 | 754 | ud = ud_str | ||
1591 | 755 | 771 | ||
1592 | 756 | return (md, ud) | 772 | return (md, ud) |
1593 | 757 | 773 | ||
1594 | @@ -782,7 +798,7 @@ | |||
1595 | 782 | if "conf_d" in cfg: | 798 | if "conf_d" in cfg: |
1596 | 783 | confd = cfg['conf_d'] | 799 | confd = cfg['conf_d'] |
1597 | 784 | if confd: | 800 | if confd: |
1599 | 785 | if not isinstance(confd, (str, basestring)): | 801 | if not isinstance(confd, six.string_types): |
1600 | 786 | raise TypeError(("Config file %s contains 'conf_d' " | 802 | raise TypeError(("Config file %s contains 'conf_d' " |
1601 | 787 | "with non-string type %s") % | 803 | "with non-string type %s") % |
1602 | 788 | (cfgfile, type_utils.obj_name(confd))) | 804 | (cfgfile, type_utils.obj_name(confd))) |
1603 | @@ -919,8 +935,8 @@ | |||
1604 | 919 | return (None, None, None) | 935 | return (None, None, None) |
1605 | 920 | 936 | ||
1606 | 921 | resp = read_file_or_url(url) | 937 | resp = read_file_or_url(url) |
1609 | 922 | if resp.contents.startswith(starts) and resp.ok(): | 938 | if resp.ok() and resp.contents.startswith(starts): |
1610 | 923 | return (key, url, str(resp)) | 939 | return (key, url, resp.contents) |
1611 | 924 | 940 | ||
1612 | 925 | return (key, url, None) | 941 | return (key, url, None) |
1613 | 926 | 942 | ||
1614 | @@ -1074,9 +1090,9 @@ | |||
1615 | 1074 | return out_list | 1090 | return out_list |
1616 | 1075 | 1091 | ||
1617 | 1076 | 1092 | ||
1619 | 1077 | def load_file(fname, read_cb=None, quiet=False): | 1093 | def load_file(fname, read_cb=None, quiet=False, decode=True): |
1620 | 1078 | LOG.debug("Reading from %s (quiet=%s)", fname, quiet) | 1094 | LOG.debug("Reading from %s (quiet=%s)", fname, quiet) |
1622 | 1079 | ofh = StringIO() | 1095 | ofh = six.BytesIO() |
1623 | 1080 | try: | 1096 | try: |
1624 | 1081 | with open(fname, 'rb') as ifh: | 1097 | with open(fname, 'rb') as ifh: |
1625 | 1082 | pipe_in_out(ifh, ofh, chunk_cb=read_cb) | 1098 | pipe_in_out(ifh, ofh, chunk_cb=read_cb) |
1626 | @@ -1087,7 +1103,10 @@ | |||
1627 | 1087 | raise | 1103 | raise |
1628 | 1088 | contents = ofh.getvalue() | 1104 | contents = ofh.getvalue() |
1629 | 1089 | LOG.debug("Read %s bytes from %s", len(contents), fname) | 1105 | LOG.debug("Read %s bytes from %s", len(contents), fname) |
1631 | 1090 | return contents | 1106 | if decode: |
1632 | 1107 | return decode_binary(contents) | ||
1633 | 1108 | else: | ||
1634 | 1109 | return contents | ||
1635 | 1091 | 1110 | ||
1636 | 1092 | 1111 | ||
1637 | 1093 | def get_cmdline(): | 1112 | def get_cmdline(): |
1638 | @@ -1217,7 +1236,7 @@ | |||
1639 | 1217 | 1236 | ||
1640 | 1218 | def hash_blob(blob, routine, mlen=None): | 1237 | def hash_blob(blob, routine, mlen=None): |
1641 | 1219 | hasher = hashlib.new(routine) | 1238 | hasher = hashlib.new(routine) |
1643 | 1220 | hasher.update(blob) | 1239 | hasher.update(encode_text(blob)) |
1644 | 1221 | digest = hasher.hexdigest() | 1240 | digest = hasher.hexdigest() |
1645 | 1222 | # Don't get to long now | 1241 | # Don't get to long now |
1646 | 1223 | if mlen is not None: | 1242 | if mlen is not None: |
1647 | @@ -1248,7 +1267,7 @@ | |||
1648 | 1248 | os.rename(src, dest) | 1267 | os.rename(src, dest) |
1649 | 1249 | 1268 | ||
1650 | 1250 | 1269 | ||
1652 | 1251 | def ensure_dirs(dirlist, mode=0755): | 1270 | def ensure_dirs(dirlist, mode=0o755): |
1653 | 1252 | for d in dirlist: | 1271 | for d in dirlist: |
1654 | 1253 | ensure_dir(d, mode) | 1272 | ensure_dir(d, mode) |
1655 | 1254 | 1273 | ||
1656 | @@ -1262,7 +1281,7 @@ | |||
1657 | 1262 | return | 1281 | return |
1658 | 1263 | try: | 1282 | try: |
1659 | 1264 | if key and content: | 1283 | if key and content: |
1661 | 1265 | write_file(target_fn, content, mode=0600) | 1284 | write_file(target_fn, content, mode=0o600) |
1662 | 1266 | LOG.debug(("Wrote to %s with contents of command line" | 1285 | LOG.debug(("Wrote to %s with contents of command line" |
1663 | 1267 | " url %s (len=%s)"), target_fn, url, len(content)) | 1286 | " url %s (len=%s)"), target_fn, url, len(content)) |
1664 | 1268 | elif key and not content: | 1287 | elif key and not content: |
1665 | @@ -1454,7 +1473,7 @@ | |||
1666 | 1454 | write_file(path, content, omode="ab", mode=None) | 1473 | write_file(path, content, omode="ab", mode=None) |
1667 | 1455 | 1474 | ||
1668 | 1456 | 1475 | ||
1670 | 1457 | def ensure_file(path, mode=0644): | 1476 | def ensure_file(path, mode=0o644): |
1671 | 1458 | write_file(path, content='', omode="ab", mode=mode) | 1477 | write_file(path, content='', omode="ab", mode=mode) |
1672 | 1459 | 1478 | ||
1673 | 1460 | 1479 | ||
1674 | @@ -1472,7 +1491,7 @@ | |||
1675 | 1472 | os.chmod(path, real_mode) | 1491 | os.chmod(path, real_mode) |
1676 | 1473 | 1492 | ||
1677 | 1474 | 1493 | ||
1679 | 1475 | def write_file(filename, content, mode=0644, omode="wb"): | 1494 | def write_file(filename, content, mode=0o644, omode="wb"): |
1680 | 1476 | """ | 1495 | """ |
1681 | 1477 | Writes a file with the given content and sets the file mode as specified. | 1496 | Writes a file with the given content and sets the file mode as specified. |
1682 | 1478 | Resotres the SELinux context if possible. | 1497 | Resotres the SELinux context if possible. |
1683 | @@ -1480,11 +1499,17 @@ | |||
1684 | 1480 | @param filename: The full path of the file to write. | 1499 | @param filename: The full path of the file to write. |
1685 | 1481 | @param content: The content to write to the file. | 1500 | @param content: The content to write to the file. |
1686 | 1482 | @param mode: The filesystem mode to set on the file. | 1501 | @param mode: The filesystem mode to set on the file. |
1688 | 1483 | @param omode: The open mode used when opening the file (r, rb, a, etc.) | 1502 | @param omode: The open mode used when opening the file (w, wb, a, etc.) |
1689 | 1484 | """ | 1503 | """ |
1690 | 1485 | ensure_dir(os.path.dirname(filename)) | 1504 | ensure_dir(os.path.dirname(filename)) |
1693 | 1486 | LOG.debug("Writing to %s - %s: [%s] %s bytes", | 1505 | if 'b' in omode.lower(): |
1694 | 1487 | filename, omode, mode, len(content)) | 1506 | content = encode_text(content) |
1695 | 1507 | write_type = 'bytes' | ||
1696 | 1508 | else: | ||
1697 | 1509 | content = decode_binary(content) | ||
1698 | 1510 | write_type = 'characters' | ||
1699 | 1511 | LOG.debug("Writing to %s - %s: [%s] %s %s", | ||
1700 | 1512 | filename, omode, mode, len(content), write_type) | ||
1701 | 1488 | with SeLinuxGuard(path=filename): | 1513 | with SeLinuxGuard(path=filename): |
1702 | 1489 | with open(filename, omode) as fh: | 1514 | with open(filename, omode) as fh: |
1703 | 1490 | fh.write(content) | 1515 | fh.write(content) |
1704 | @@ -1573,10 +1598,10 @@ | |||
1705 | 1573 | if isinstance(args, list): | 1598 | if isinstance(args, list): |
1706 | 1574 | fixed = [] | 1599 | fixed = [] |
1707 | 1575 | for f in args: | 1600 | for f in args: |
1709 | 1576 | fixed.append("'%s'" % (str(f).replace("'", escaped))) | 1601 | fixed.append("'%s'" % (six.text_type(f).replace("'", escaped))) |
1710 | 1577 | content = "%s%s\n" % (content, ' '.join(fixed)) | 1602 | content = "%s%s\n" % (content, ' '.join(fixed)) |
1711 | 1578 | cmds_made += 1 | 1603 | cmds_made += 1 |
1713 | 1579 | elif isinstance(args, (str, basestring)): | 1604 | elif isinstance(args, six.string_types): |
1714 | 1580 | content = "%s%s\n" % (content, args) | 1605 | content = "%s%s\n" % (content, args) |
1715 | 1581 | cmds_made += 1 | 1606 | cmds_made += 1 |
1716 | 1582 | else: | 1607 | else: |
1717 | @@ -1687,7 +1712,7 @@ | |||
1718 | 1687 | 1712 | ||
1719 | 1688 | pkglist = [] | 1713 | pkglist = [] |
1720 | 1689 | for pkg in pkgs: | 1714 | for pkg in pkgs: |
1722 | 1690 | if isinstance(pkg, basestring): | 1715 | if isinstance(pkg, six.string_types): |
1723 | 1691 | pkglist.append(pkg) | 1716 | pkglist.append(pkg) |
1724 | 1692 | continue | 1717 | continue |
1725 | 1693 | 1718 | ||
1726 | 1694 | 1719 | ||
1727 | === modified file 'packages/bddeb' | |||
1728 | --- packages/bddeb 2014-01-17 22:08:58 +0000 | |||
1729 | +++ packages/bddeb 2014-07-08 04:39:36 +0000 | |||
1730 | @@ -37,6 +37,7 @@ | |||
1731 | 37 | 'pyserial': 'python-serial', | 37 | 'pyserial': 'python-serial', |
1732 | 38 | 'pyyaml': 'python-yaml', | 38 | 'pyyaml': 'python-yaml', |
1733 | 39 | 'requests': 'python-requests', | 39 | 'requests': 'python-requests', |
1734 | 40 | 'six': 'python-six', | ||
1735 | 40 | } | 41 | } |
1736 | 41 | DEBUILD_ARGS = ["-us", "-S", "-uc", "-d"] | 42 | DEBUILD_ARGS = ["-us", "-S", "-uc", "-d"] |
1737 | 42 | 43 | ||
1738 | 43 | 44 | ||
1739 | === modified file 'packages/brpm' | |||
1740 | --- packages/brpm 2014-01-17 22:08:58 +0000 | |||
1741 | +++ packages/brpm 2014-07-08 04:39:36 +0000 | |||
1742 | @@ -44,6 +44,7 @@ | |||
1743 | 44 | 'pyserial': 'pyserial', | 44 | 'pyserial': 'pyserial', |
1744 | 45 | 'pyyaml': 'PyYAML', | 45 | 'pyyaml': 'PyYAML', |
1745 | 46 | 'requests': 'python-requests', | 46 | 'requests': 'python-requests', |
1746 | 47 | 'six': 'python-six', | ||
1747 | 47 | }, | 48 | }, |
1748 | 48 | 'suse': { | 49 | 'suse': { |
1749 | 49 | 'argparse': 'python-argparse', | 50 | 'argparse': 'python-argparse', |
1750 | @@ -55,6 +56,7 @@ | |||
1751 | 55 | 'pyserial': 'python-pyserial', | 56 | 'pyserial': 'python-pyserial', |
1752 | 56 | 'pyyaml': 'python-yaml', | 57 | 'pyyaml': 'python-yaml', |
1753 | 57 | 'requests': 'python-requests', | 58 | 'requests': 'python-requests', |
1754 | 59 | 'six': 'python-six', | ||
1755 | 58 | } | 60 | } |
1756 | 59 | } | 61 | } |
1757 | 60 | 62 | ||
1758 | 61 | 63 | ||
1759 | === modified file 'requirements.txt' | |||
1760 | --- requirements.txt 2014-02-12 10:14:49 +0000 | |||
1761 | +++ requirements.txt 2014-07-08 04:39:36 +0000 | |||
1762 | @@ -31,3 +31,6 @@ | |||
1763 | 31 | 31 | ||
1764 | 32 | # For patching pieces of cloud-config together | 32 | # For patching pieces of cloud-config together |
1765 | 33 | jsonpatch | 33 | jsonpatch |
1766 | 34 | |||
1767 | 35 | # For py2/3 simultaneous compatibility | ||
1768 | 36 | six | ||
1769 | 34 | 37 | ||
1770 | === modified file 'tests/unittests/test_data.py' | |||
1771 | --- tests/unittests/test_data.py 2014-01-17 15:27:09 +0000 | |||
1772 | +++ tests/unittests/test_data.py 2014-07-08 04:39:36 +0000 | |||
1773 | @@ -1,11 +1,12 @@ | |||
1774 | 1 | """Tests for handling of userdata within cloud init.""" | 1 | """Tests for handling of userdata within cloud init.""" |
1775 | 2 | 2 | ||
1776 | 3 | import StringIO | ||
1777 | 4 | |||
1778 | 5 | import gzip | 3 | import gzip |
1779 | 6 | import logging | 4 | import logging |
1780 | 7 | import os | 5 | import os |
1781 | 8 | 6 | ||
1782 | 7 | from six import BytesIO | ||
1783 | 8 | from six import StringIO | ||
1784 | 9 | |||
1785 | 9 | from email.mime.application import MIMEApplication | 10 | from email.mime.application import MIMEApplication |
1786 | 10 | from email.mime.base import MIMEBase | 11 | from email.mime.base import MIMEBase |
1787 | 11 | from email.mime.multipart import MIMEMultipart | 12 | from email.mime.multipart import MIMEMultipart |
1788 | @@ -53,7 +54,7 @@ | |||
1789 | 53 | self.patchUtils(root) | 54 | self.patchUtils(root) |
1790 | 54 | 55 | ||
1791 | 55 | def capture_log(self, lvl=logging.DEBUG): | 56 | def capture_log(self, lvl=logging.DEBUG): |
1793 | 56 | log_file = StringIO.StringIO() | 57 | log_file = StringIO() |
1794 | 57 | self._log_handler = logging.StreamHandler(log_file) | 58 | self._log_handler = logging.StreamHandler(log_file) |
1795 | 58 | self._log_handler.setLevel(lvl) | 59 | self._log_handler.setLevel(lvl) |
1796 | 59 | self._log = log.getLogger() | 60 | self._log = log.getLogger() |
1797 | @@ -352,9 +353,9 @@ | |||
1798 | 352 | """Tests that individual message gzip encoding works.""" | 353 | """Tests that individual message gzip encoding works.""" |
1799 | 353 | 354 | ||
1800 | 354 | def gzip_part(text): | 355 | def gzip_part(text): |
1804 | 355 | contents = StringIO.StringIO() | 356 | contents = BytesIO() |
1805 | 356 | f = gzip.GzipFile(fileobj=contents, mode='w') | 357 | f = gzip.GzipFile(fileobj=contents, mode='wb') |
1806 | 357 | f.write(str(text)) | 358 | f.write(util.encode_text(text)) |
1807 | 358 | f.flush() | 359 | f.flush() |
1808 | 359 | f.close() | 360 | f.close() |
1809 | 360 | return MIMEApplication(contents.getvalue(), 'gzip') | 361 | return MIMEApplication(contents.getvalue(), 'gzip') |
1810 | 361 | 362 | ||
1811 | === modified file 'tests/unittests/test_datasource/test_nocloud.py' | |||
1812 | --- tests/unittests/test_datasource/test_nocloud.py 2014-02-26 19:28:46 +0000 | |||
1813 | +++ tests/unittests/test_datasource/test_nocloud.py 2014-07-08 04:39:36 +0000 | |||
1814 | @@ -86,7 +86,7 @@ | |||
1815 | 86 | 86 | ||
1816 | 87 | data = { | 87 | data = { |
1817 | 88 | 'fs_label': None, | 88 | 'fs_label': None, |
1819 | 89 | 'meta-data': {'instance-id': 'IID'}, | 89 | 'meta-data': yaml.safe_dump({'instance-id': 'IID'}), |
1820 | 90 | 'user-data': "USER_DATA_RAW", | 90 | 'user-data': "USER_DATA_RAW", |
1821 | 91 | } | 91 | } |
1822 | 92 | 92 | ||
1823 | 93 | 93 | ||
1824 | === modified file 'tests/unittests/test_datasource/test_openstack.py' | |||
1825 | --- tests/unittests/test_datasource/test_openstack.py 2014-02-08 20:20:33 +0000 | |||
1826 | +++ tests/unittests/test_datasource/test_openstack.py 2014-07-08 04:39:36 +0000 | |||
1827 | @@ -20,9 +20,8 @@ | |||
1828 | 20 | import json | 20 | import json |
1829 | 21 | import re | 21 | import re |
1830 | 22 | 22 | ||
1834 | 23 | from StringIO import StringIO | 23 | from six import StringIO |
1835 | 24 | 24 | from six.moves.urllib.parse import urlparse | |
1833 | 25 | from urlparse import urlparse | ||
1836 | 26 | 25 | ||
1837 | 27 | from tests.unittests import helpers as test_helpers | 26 | from tests.unittests import helpers as test_helpers |
1838 | 28 | 27 | ||
1839 | 29 | 28 | ||
1840 | === modified file 'tests/unittests/test_distros/test_netconfig.py' | |||
1841 | --- tests/unittests/test_distros/test_netconfig.py 2012-10-11 19:49:45 +0000 | |||
1842 | +++ tests/unittests/test_distros/test_netconfig.py 2014-07-08 04:39:36 +0000 | |||
1843 | @@ -4,6 +4,8 @@ | |||
1844 | 4 | 4 | ||
1845 | 5 | import os | 5 | import os |
1846 | 6 | 6 | ||
1847 | 7 | from six import StringIO | ||
1848 | 8 | |||
1849 | 7 | from cloudinit import distros | 9 | from cloudinit import distros |
1850 | 8 | from cloudinit import helpers | 10 | from cloudinit import helpers |
1851 | 9 | from cloudinit import settings | 11 | from cloudinit import settings |
1852 | @@ -11,9 +13,6 @@ | |||
1853 | 11 | 13 | ||
1854 | 12 | from cloudinit.distros.parsers.sys_conf import SysConf | 14 | from cloudinit.distros.parsers.sys_conf import SysConf |
1855 | 13 | 15 | ||
1856 | 14 | from StringIO import StringIO | ||
1857 | 15 | |||
1858 | 16 | |||
1859 | 17 | BASE_NET_CFG = ''' | 16 | BASE_NET_CFG = ''' |
1860 | 18 | auto lo | 17 | auto lo |
1861 | 19 | iface lo inet loopback | 18 | iface lo inet loopback |
1862 | 20 | 19 | ||
1863 | === modified file 'tests/unittests/test_handler/test_handler_locale.py' | |||
1864 | --- tests/unittests/test_handler/test_handler_locale.py 2013-06-25 06:57:27 +0000 | |||
1865 | +++ tests/unittests/test_handler/test_handler_locale.py 2014-07-08 04:39:36 +0000 | |||
1866 | @@ -29,7 +29,7 @@ | |||
1867 | 29 | 29 | ||
1868 | 30 | from configobj import ConfigObj | 30 | from configobj import ConfigObj |
1869 | 31 | 31 | ||
1871 | 32 | from StringIO import StringIO | 32 | from six import BytesIO |
1872 | 33 | 33 | ||
1873 | 34 | import logging | 34 | import logging |
1874 | 35 | 35 | ||
1875 | @@ -59,6 +59,6 @@ | |||
1876 | 59 | cc = self._get_cloud('sles') | 59 | cc = self._get_cloud('sles') |
1877 | 60 | cc_locale.handle('cc_locale', cfg, cc, LOG, []) | 60 | cc_locale.handle('cc_locale', cfg, cc, LOG, []) |
1878 | 61 | 61 | ||
1881 | 62 | contents = util.load_file('/etc/sysconfig/language') | 62 | contents = util.load_file('/etc/sysconfig/language', decode=False) |
1882 | 63 | n_cfg = ConfigObj(StringIO(contents)) | 63 | n_cfg = ConfigObj(BytesIO(contents)) |
1883 | 64 | self.assertEquals({'RC_LANG': cfg['locale']}, dict(n_cfg)) | 64 | self.assertEquals({'RC_LANG': cfg['locale']}, dict(n_cfg)) |
1884 | 65 | 65 | ||
1885 | === modified file 'tests/unittests/test_handler/test_handler_seed_random.py' | |||
1886 | --- tests/unittests/test_handler/test_handler_seed_random.py 2014-03-04 19:35:09 +0000 | |||
1887 | +++ tests/unittests/test_handler/test_handler_seed_random.py 2014-07-08 04:39:36 +0000 | |||
1888 | @@ -22,7 +22,7 @@ | |||
1889 | 22 | import gzip | 22 | import gzip |
1890 | 23 | import tempfile | 23 | import tempfile |
1891 | 24 | 24 | ||
1893 | 25 | from StringIO import StringIO | 25 | from six import StringIO |
1894 | 26 | 26 | ||
1895 | 27 | from cloudinit import cloud | 27 | from cloudinit import cloud |
1896 | 28 | from cloudinit import distros | 28 | from cloudinit import distros |
1897 | 29 | 29 | ||
1898 | === modified file 'tests/unittests/test_handler/test_handler_set_hostname.py' | |||
1899 | --- tests/unittests/test_handler/test_handler_set_hostname.py 2013-06-25 06:57:27 +0000 | |||
1900 | +++ tests/unittests/test_handler/test_handler_set_hostname.py 2014-07-08 04:39:36 +0000 | |||
1901 | @@ -9,7 +9,7 @@ | |||
1902 | 9 | 9 | ||
1903 | 10 | import logging | 10 | import logging |
1904 | 11 | 11 | ||
1906 | 12 | from StringIO import StringIO | 12 | from six import BytesIO |
1907 | 13 | 13 | ||
1908 | 14 | from configobj import ConfigObj | 14 | from configobj import ConfigObj |
1909 | 15 | 15 | ||
1910 | @@ -37,8 +37,8 @@ | |||
1911 | 37 | self.patchUtils(self.tmp) | 37 | self.patchUtils(self.tmp) |
1912 | 38 | cc_set_hostname.handle('cc_set_hostname', | 38 | cc_set_hostname.handle('cc_set_hostname', |
1913 | 39 | cfg, cc, LOG, []) | 39 | cfg, cc, LOG, []) |
1916 | 40 | contents = util.load_file("/etc/sysconfig/network") | 40 | contents = util.load_file("/etc/sysconfig/network", decode=False) |
1917 | 41 | n_cfg = ConfigObj(StringIO(contents)) | 41 | n_cfg = ConfigObj(BytesIO(contents)) |
1918 | 42 | self.assertEquals({'HOSTNAME': 'blah.blah.blah.yahoo.com'}, | 42 | self.assertEquals({'HOSTNAME': 'blah.blah.blah.yahoo.com'}, |
1919 | 43 | dict(n_cfg)) | 43 | dict(n_cfg)) |
1920 | 44 | 44 | ||
1921 | 45 | 45 | ||
1922 | === modified file 'tests/unittests/test_handler/test_handler_timezone.py' | |||
1923 | --- tests/unittests/test_handler/test_handler_timezone.py 2013-06-25 06:57:27 +0000 | |||
1924 | +++ tests/unittests/test_handler/test_handler_timezone.py 2014-07-08 04:39:36 +0000 | |||
1925 | @@ -29,7 +29,7 @@ | |||
1926 | 29 | 29 | ||
1927 | 30 | from configobj import ConfigObj | 30 | from configobj import ConfigObj |
1928 | 31 | 31 | ||
1930 | 32 | from StringIO import StringIO | 32 | from six import BytesIO |
1931 | 33 | 33 | ||
1932 | 34 | import logging | 34 | import logging |
1933 | 35 | 35 | ||
1934 | @@ -67,8 +67,8 @@ | |||
1935 | 67 | 67 | ||
1936 | 68 | cc_timezone.handle('cc_timezone', cfg, cc, LOG, []) | 68 | cc_timezone.handle('cc_timezone', cfg, cc, LOG, []) |
1937 | 69 | 69 | ||
1940 | 70 | contents = util.load_file('/etc/sysconfig/clock') | 70 | contents = util.load_file('/etc/sysconfig/clock', decode=False) |
1941 | 71 | n_cfg = ConfigObj(StringIO(contents)) | 71 | n_cfg = ConfigObj(BytesIO(contents)) |
1942 | 72 | self.assertEquals({'TIMEZONE': cfg['timezone']}, dict(n_cfg)) | 72 | self.assertEquals({'TIMEZONE': cfg['timezone']}, dict(n_cfg)) |
1943 | 73 | 73 | ||
1944 | 74 | contents = util.load_file('/etc/localtime') | 74 | contents = util.load_file('/etc/localtime') |
1945 | 75 | 75 | ||
1946 | === modified file 'tests/unittests/test_handler/test_handler_yum_add_repo.py' | |||
1947 | --- tests/unittests/test_handler/test_handler_yum_add_repo.py 2014-04-01 18:20:57 +0000 | |||
1948 | +++ tests/unittests/test_handler/test_handler_yum_add_repo.py 2014-07-08 04:39:36 +0000 | |||
1949 | @@ -6,7 +6,7 @@ | |||
1950 | 6 | 6 | ||
1951 | 7 | import logging | 7 | import logging |
1952 | 8 | 8 | ||
1954 | 9 | from StringIO import StringIO | 9 | from six import BytesIO |
1955 | 10 | 10 | ||
1956 | 11 | import configobj | 11 | import configobj |
1957 | 12 | 12 | ||
1958 | @@ -52,8 +52,9 @@ | |||
1959 | 52 | } | 52 | } |
1960 | 53 | self.patchUtils(self.tmp) | 53 | self.patchUtils(self.tmp) |
1961 | 54 | cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, []) | 54 | cc_yum_add_repo.handle('yum_add_repo', cfg, None, LOG, []) |
1964 | 55 | contents = util.load_file("/etc/yum.repos.d/epel_testing.repo") | 55 | contents = util.load_file("/etc/yum.repos.d/epel_testing.repo", |
1965 | 56 | contents = configobj.ConfigObj(StringIO(contents)) | 56 | decode=False) |
1966 | 57 | contents = configobj.ConfigObj(BytesIO(contents)) | ||
1967 | 57 | expected = { | 58 | expected = { |
1968 | 58 | 'epel_testing': { | 59 | 'epel_testing': { |
1969 | 59 | 'name': 'Extra Packages for Enterprise Linux 5 - Testing', | 60 | 'name': 'Extra Packages for Enterprise Linux 5 - Testing', |
I'm also interested in cloud-init being compatible with Python 3. I don't understand cloud-init codebase that much, but the patch looks fine. My question is, what minimal Python version are you targeting? I'm assuming 2.6 and higher? If so, I'd recommend using dict.{items, keys,values} instead of six.iter{ items,keys, values} (dict) - it's more readable (but really just a nitpick).