Merge lp:~harlowja/cloud-init/ug-cleanup-part-deuce into lp:~cloud-init-dev/cloud-init/trunk
- ug-cleanup-part-deuce
- Merge into trunk
Proposed by
Joshua Harlow
Status: | Merged |
---|---|
Merged at revision: | 677 |
Proposed branch: | lp:~harlowja/cloud-init/ug-cleanup-part-deuce |
Merge into: | lp:~cloud-init-dev/cloud-init/trunk |
Diff against target: |
603 lines (+236/-95) 9 files modified
cloudinit/config/cc_byobu.py (+18/-9) cloudinit/config/cc_set_passwords.py (+7/-10) cloudinit/config/cc_ssh.py (+7/-10) cloudinit/config/cc_ssh_authkey_fingerprints.py (+11/-5) cloudinit/config/cc_ssh_import_id.py (+18/-19) cloudinit/config/cc_users_groups.py (+5/-2) cloudinit/distros/__init__.py (+100/-30) cloudinit/util.py (+30/-0) tests/unittests/test_distros/test_user_data_normalize.py (+40/-10) |
To merge this branch: | bzr merge lp:~harlowja/cloud-init/ug-cleanup-part-deuce |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
cloud-init Commiters | Pending | ||
Review via email: mp+127067@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 673. By Joshua Harlow
-
Add a comment as to why distros can't be
imported without being renamed due to
previous usage of the attribute 'distros' - 674. By Joshua Harlow
-
Make byobu more tolerant of the user not being
located and warn when it is not found + only
run the shell command when actual contents
exist to run. - 675. By Joshua Harlow
-
Sync with head and fix conflicts.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'cloudinit/config/cc_byobu.py' |
2 | --- cloudinit/config/cc_byobu.py 2012-06-23 03:58:50 +0000 |
3 | +++ cloudinit/config/cc_byobu.py 2012-09-28 21:23:20 +0000 |
4 | @@ -18,12 +18,17 @@ |
5 | # You should have received a copy of the GNU General Public License |
6 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
7 | |
8 | +# Ensure this is aliased to a name not 'distros' |
9 | +# since the module attribute 'distros' |
10 | +# is a list of distros that are supported, not a sub-module |
11 | +from cloudinit import distros as ds |
12 | + |
13 | from cloudinit import util |
14 | |
15 | distros = ['ubuntu', 'debian'] |
16 | |
17 | |
18 | -def handle(name, cfg, _cloud, log, args): |
19 | +def handle(name, cfg, cloud, log, args): |
20 | if len(args) != 0: |
21 | value = args[0] |
22 | else: |
23 | @@ -56,16 +61,20 @@ |
24 | |
25 | shcmd = "" |
26 | if mod_user: |
27 | - user = util.get_cfg_option_str(cfg, "user", "ubuntu") |
28 | - shcmd += " sudo -Hu \"%s\" byobu-launcher-%s" % (user, bl_inst) |
29 | - shcmd += " || X=$(($X+1)); " |
30 | + (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) |
31 | + (user, _user_config) = ds.extract_default(users) |
32 | + if not user: |
33 | + log.warn(("No default byobu user provided, " |
34 | + "can not launch %s for the default user"), bl_inst) |
35 | + else: |
36 | + shcmd += " sudo -Hu \"%s\" byobu-launcher-%s" % (user, bl_inst) |
37 | + shcmd += " || X=$(($X+1)); " |
38 | if mod_sys: |
39 | shcmd += "echo \"%s\" | debconf-set-selections" % dc_val |
40 | shcmd += " && dpkg-reconfigure byobu --frontend=noninteractive" |
41 | shcmd += " || X=$(($X+1)); " |
42 | |
43 | - cmd = ["/bin/sh", "-c", "%s %s %s" % ("X=0;", shcmd, "exit $X")] |
44 | - |
45 | - log.debug("Setting byobu to %s", value) |
46 | - |
47 | - util.subp(cmd, capture=False) |
48 | + if len(shcmd): |
49 | + cmd = ["/bin/sh", "-c", "%s %s %s" % ("X=0;", shcmd, "exit $X")] |
50 | + log.debug("Setting byobu to %s", value) |
51 | + util.subp(cmd, capture=False) |
52 | |
53 | === modified file 'cloudinit/config/cc_set_passwords.py' |
54 | --- cloudinit/config/cc_set_passwords.py 2012-08-31 21:45:15 +0000 |
55 | +++ cloudinit/config/cc_set_passwords.py 2012-09-28 21:23:20 +0000 |
56 | @@ -20,6 +20,11 @@ |
57 | |
58 | import sys |
59 | |
60 | +# Ensure this is aliased to a name not 'distros' |
61 | +# since the module attribute 'distros' |
62 | +# is a list of distros that are supported, not a sub-module |
63 | +from cloudinit import distros as ds |
64 | + |
65 | from cloudinit import ssh_util |
66 | from cloudinit import util |
67 | |
68 | @@ -50,18 +55,10 @@ |
69 | expire = util.get_cfg_option_bool(chfg, 'expire', expire) |
70 | |
71 | if not plist and password: |
72 | - user = cloud.distro.get_default_user() |
73 | - |
74 | - if 'users' in cfg: |
75 | - |
76 | - user_zero = cfg['users'][0] |
77 | - |
78 | - if isinstance(user_zero, dict) and 'name' in user_zero: |
79 | - user = user_zero['name'] |
80 | - |
81 | + (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) |
82 | + (user, _user_config) = ds.extract_default(users) |
83 | if user: |
84 | plist = "%s:%s" % (user, password) |
85 | - |
86 | else: |
87 | log.warn("No default or defined user to change password for.") |
88 | |
89 | |
90 | === modified file 'cloudinit/config/cc_ssh.py' |
91 | --- cloudinit/config/cc_ssh.py 2012-08-31 18:45:40 +0000 |
92 | +++ cloudinit/config/cc_ssh.py 2012-09-28 21:23:20 +0000 |
93 | @@ -21,6 +21,11 @@ |
94 | import glob |
95 | import os |
96 | |
97 | +# Ensure this is aliased to a name not 'distros' |
98 | +# since the module attribute 'distros' |
99 | +# is a list of distros that are supported, not a sub-module |
100 | +from cloudinit import distros as ds |
101 | + |
102 | from cloudinit import ssh_util |
103 | from cloudinit import util |
104 | |
105 | @@ -102,16 +107,8 @@ |
106 | " %s to file %s"), keytype, keyfile) |
107 | |
108 | try: |
109 | - # TODO(utlemming): consolidate this stanza that occurs in: |
110 | - # cc_ssh_import_id, cc_set_passwords, maybe cc_users_groups.py |
111 | - user = cloud.distro.get_default_user() |
112 | - |
113 | - if 'users' in cfg: |
114 | - user_zero = cfg['users'][0] |
115 | - |
116 | - if user_zero != "default": |
117 | - user = user_zero |
118 | - |
119 | + (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) |
120 | + (user, _user_config) = ds.extract_default(users) |
121 | disable_root = util.get_cfg_option_bool(cfg, "disable_root", True) |
122 | disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts", |
123 | DISABLE_ROOT_OPTS) |
124 | |
125 | === modified file 'cloudinit/config/cc_ssh_authkey_fingerprints.py' |
126 | --- cloudinit/config/cc_ssh_authkey_fingerprints.py 2012-09-28 20:35:53 +0000 |
127 | +++ cloudinit/config/cc_ssh_authkey_fingerprints.py 2012-09-28 21:23:20 +0000 |
128 | @@ -21,7 +21,11 @@ |
129 | |
130 | from prettytable import PrettyTable |
131 | |
132 | -from cloudinit import distros |
133 | +# Ensure this is aliased to a name not 'distros' |
134 | +# since the module attribute 'distros' |
135 | +# is a list of distros that are supported, not a sub-module |
136 | +from cloudinit import distros as ds |
137 | + |
138 | from cloudinit import ssh_util |
139 | from cloudinit import util |
140 | |
141 | @@ -41,8 +45,10 @@ |
142 | hasher = hashlib.new(hash_meth) |
143 | hasher.update(base64.b64decode(b64_text)) |
144 | return ":".join(_split_hash(hasher.hexdigest())) |
145 | - except TypeError: |
146 | + except (TypeError, ValueError): |
147 | # Raised when b64 not really b64... |
148 | + # or when the hash type is not really |
149 | + # a known/supported hash type... |
150 | return '?' |
151 | |
152 | |
153 | @@ -92,8 +98,8 @@ |
154 | |
155 | hash_meth = util.get_cfg_option_str(cfg, "authkey_hash", "md5") |
156 | extract_func = ssh_util.extract_authorized_keys |
157 | - (users, _groups) = distros.normalize_users_groups(cfg, cloud.distro) |
158 | + (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) |
159 | for (user_name, _cfg) in users.items(): |
160 | (auth_key_fn, auth_key_entries) = extract_func(user_name, cloud.paths) |
161 | - _pprint_key_entries(user_name, auth_key_fn, auth_key_entries, |
162 | - hash_meth) |
163 | + _pprint_key_entries(user_name, auth_key_fn, |
164 | + auth_key_entries, hash_meth) |
165 | |
166 | === modified file 'cloudinit/config/cc_ssh_import_id.py' |
167 | --- cloudinit/config/cc_ssh_import_id.py 2012-08-31 19:36:05 +0000 |
168 | +++ cloudinit/config/cc_ssh_import_id.py 2012-09-28 21:23:20 +0000 |
169 | @@ -18,6 +18,11 @@ |
170 | # You should have received a copy of the GNU General Public License |
171 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
172 | |
173 | +# Ensure this is aliased to a name not 'distros' |
174 | +# since the module attribute 'distros' |
175 | +# is a list of distros that are supported, not a sub-module |
176 | +from cloudinit import distros as ds |
177 | + |
178 | from cloudinit import util |
179 | import pwd |
180 | |
181 | @@ -39,33 +44,27 @@ |
182 | return |
183 | |
184 | # import for cloudinit created users |
185 | + (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) |
186 | elist = [] |
187 | - for user_cfg in cfg['users']: |
188 | - user = None |
189 | + for (user, user_cfg) in users.items(): |
190 | import_ids = [] |
191 | - |
192 | - if isinstance(user_cfg, str) and user_cfg == "default": |
193 | - user = cloud.distro.get_default_user() |
194 | - if not user: |
195 | - continue |
196 | - |
197 | + if user_cfg['default']: |
198 | import_ids = util.get_cfg_option_list(cfg, "ssh_import_id", []) |
199 | - |
200 | - elif isinstance(user_cfg, dict): |
201 | - user = None |
202 | - import_ids = [] |
203 | - |
204 | + else: |
205 | try: |
206 | - user = user_cfg['name'] |
207 | import_ids = user_cfg['ssh_import_id'] |
208 | - |
209 | - if import_ids and isinstance(import_ids, str): |
210 | - import_ids = str(import_ids).split(',') |
211 | - |
212 | except: |
213 | - log.debug("user %s is not configured for ssh_import" % user) |
214 | + log.debug("User %s is not configured for ssh_import_id", user) |
215 | continue |
216 | |
217 | + try: |
218 | + import_ids = util.uniq_merge(import_ids) |
219 | + import_ids = [str(i) for i in import_ids] |
220 | + except: |
221 | + log.debug("User %s is not correctly configured for ssh_import_id", |
222 | + user) |
223 | + continue |
224 | + |
225 | if not len(import_ids): |
226 | continue |
227 | |
228 | |
229 | === modified file 'cloudinit/config/cc_users_groups.py' |
230 | --- cloudinit/config/cc_users_groups.py 2012-09-28 20:35:53 +0000 |
231 | +++ cloudinit/config/cc_users_groups.py 2012-09-28 21:23:20 +0000 |
232 | @@ -16,7 +16,10 @@ |
233 | # You should have received a copy of the GNU General Public License |
234 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
235 | |
236 | -from cloudinit import distros |
237 | +# Ensure this is aliased to a name not 'distros' |
238 | +# since the module attribute 'distros' |
239 | +# is a list of distros that are supported, not a sub-module |
240 | +from cloudinit import distros as ds |
241 | |
242 | from cloudinit.settings import PER_INSTANCE |
243 | |
244 | @@ -24,7 +27,7 @@ |
245 | |
246 | |
247 | def handle(name, cfg, cloud, _log, _args): |
248 | - (users, groups) = distros.normalize_users_groups(cfg, cloud.distro) |
249 | + (users, groups) = ds.normalize_users_groups(cfg, cloud.distro) |
250 | for (name, members) in groups.items(): |
251 | cloud.distro.create_group(name, members) |
252 | for (user, config) in users.items(): |
253 | |
254 | === modified file 'cloudinit/distros/__init__.py' |
255 | --- cloudinit/distros/__init__.py 2012-09-28 19:38:48 +0000 |
256 | +++ cloudinit/distros/__init__.py 2012-09-28 21:23:20 +0000 |
257 | @@ -24,6 +24,7 @@ |
258 | from StringIO import StringIO |
259 | |
260 | import abc |
261 | +import itertools |
262 | import os |
263 | import re |
264 | |
265 | @@ -186,8 +187,10 @@ |
266 | 'gecos': "%s" % (self.default_user.title()), |
267 | 'sudo': "ALL=(ALL) NOPASSWD:ALL", |
268 | } |
269 | - if self.default_user_groups: |
270 | - user_cfg['groups'] = _uniq_merge_sorted(self.default_user_groups) |
271 | + def_groups = self.default_user_groups |
272 | + if not def_groups: |
273 | + def_groups = [] |
274 | + user_cfg['groups'] = util.uniq_merge_sorted(def_groups) |
275 | return user_cfg |
276 | |
277 | def create_user(self, name, **kwargs): |
278 | @@ -398,39 +401,27 @@ |
279 | return default |
280 | |
281 | |
282 | -def _uniq_merge_sorted(*lists): |
283 | - return sorted(_uniq_merge(*lists)) |
284 | - |
285 | - |
286 | -def _uniq_merge(*lists): |
287 | - combined_list = [] |
288 | - for a_list in lists: |
289 | - if isinstance(a_list, (str, basestring)): |
290 | - a_list = a_list.strip().split(",") |
291 | - else: |
292 | - a_list = [str(a) for a in a_list] |
293 | - a_list = [a.strip() for a in a_list if a.strip()] |
294 | - combined_list.extend(a_list) |
295 | - uniq_list = [] |
296 | - for a in combined_list: |
297 | - if a in uniq_list: |
298 | - continue |
299 | - else: |
300 | - uniq_list.append(a) |
301 | - return uniq_list |
302 | - |
303 | - |
304 | +# Normalizes a input group configuration |
305 | +# which can be a comma seperated list of |
306 | +# group names, or a list of group names |
307 | +# or a python dictionary of group names |
308 | +# to a list of members of that group. |
309 | +# |
310 | +# The output is a dictionary of group |
311 | +# names => members of that group which |
312 | +# is the standard form used in the rest |
313 | +# of cloud-init |
314 | def _normalize_groups(grp_cfg): |
315 | if isinstance(grp_cfg, (str, basestring, list)): |
316 | c_grp_cfg = {} |
317 | - for i in _uniq_merge(grp_cfg): |
318 | + for i in util.uniq_merge(grp_cfg): |
319 | c_grp_cfg[i] = [] |
320 | grp_cfg = c_grp_cfg |
321 | |
322 | groups = {} |
323 | if isinstance(grp_cfg, (dict)): |
324 | for (grp_name, grp_members) in grp_cfg.items(): |
325 | - groups[grp_name] = _uniq_merge_sorted(grp_members) |
326 | + groups[grp_name] = util.uniq_merge_sorted(grp_members) |
327 | else: |
328 | raise TypeError(("Group config must be list, dict " |
329 | " or string types only and not %s") % |
330 | @@ -438,6 +429,21 @@ |
331 | return groups |
332 | |
333 | |
334 | +# Normalizes a input group configuration |
335 | +# which can be a comma seperated list of |
336 | +# user names, or a list of string user names |
337 | +# or a list of dictionaries with components |
338 | +# that define the user config + 'name' (if |
339 | +# a 'name' field does not exist then the |
340 | +# default user is assumed to 'own' that |
341 | +# configuration. |
342 | +# |
343 | +# The output is a dictionary of user |
344 | +# names => user config which is the standard |
345 | +# form used in the rest of cloud-init. Note |
346 | +# the default user will have a special config |
347 | +# entry 'default' which will be marked as true |
348 | +# all other users will be marked as false. |
349 | def _normalize_users(u_cfg, def_user_cfg=None): |
350 | if isinstance(u_cfg, (dict)): |
351 | ad_ucfg = [] |
352 | @@ -453,12 +459,12 @@ |
353 | " for key %s") % (util.obj_name(v), k)) |
354 | u_cfg = ad_ucfg |
355 | elif isinstance(u_cfg, (str, basestring)): |
356 | - u_cfg = _uniq_merge_sorted(u_cfg) |
357 | + u_cfg = util.uniq_merge_sorted(u_cfg) |
358 | |
359 | users = {} |
360 | for user_config in u_cfg: |
361 | if isinstance(user_config, (str, basestring, list)): |
362 | - for u in _uniq_merge(user_config): |
363 | + for u in util.uniq_merge(user_config): |
364 | if u and u not in users: |
365 | users[u] = {} |
366 | elif isinstance(user_config, (dict)): |
367 | @@ -491,22 +497,59 @@ |
368 | |
369 | # Fixup the default user into the real |
370 | # default user name and replace it... |
371 | + def_user = None |
372 | if users and 'default' in users: |
373 | def_config = users.pop('default') |
374 | if def_user_cfg: |
375 | + # Pickup what the default 'real name' is |
376 | + # and any groups that are provided by the |
377 | + # default config |
378 | def_user = def_user_cfg.pop('name') |
379 | def_groups = def_user_cfg.pop('groups', []) |
380 | + # Pickup any config + groups for that user name |
381 | + # that we may have previously extracted |
382 | parsed_config = users.pop(def_user, {}) |
383 | - users_groups = _uniq_merge_sorted(parsed_config.get('groups', []), |
384 | - def_groups) |
385 | + parsed_groups = parsed_config.get('groups', []) |
386 | + # Now merge our extracted groups with |
387 | + # anything the default config provided |
388 | + users_groups = util.uniq_merge_sorted(parsed_groups, def_groups) |
389 | parsed_config['groups'] = ",".join(users_groups) |
390 | + # The real config for the default user is the |
391 | + # combination of the default user config provided |
392 | + # by the distro, the default user config provided |
393 | + # by the above merging for the user 'default' and |
394 | + # then the parsed config from the user's 'real name' |
395 | + # which does not have to be 'default' (but could be) |
396 | users[def_user] = util.mergemanydict([def_user_cfg, |
397 | def_config, |
398 | parsed_config]) |
399 | |
400 | + # Ensure that only the default user that we |
401 | + # found (if any) is actually marked as being |
402 | + # the default user |
403 | + if users: |
404 | + for (uname, uconfig) in users.items(): |
405 | + if def_user and uname == def_user: |
406 | + uconfig['default'] = True |
407 | + else: |
408 | + uconfig['default'] = False |
409 | + |
410 | return users |
411 | |
412 | |
413 | +# Normalizes a set of user/users and group |
414 | +# dictionary configuration into a useable |
415 | +# format that the rest of cloud-init can |
416 | +# understand using the default user |
417 | +# provided by the input distrobution (if any) |
418 | +# to allow for mapping of the 'default' user. |
419 | +# |
420 | +# Output is a dictionary of group names -> [member] (list) |
421 | +# and a dictionary of user names -> user configuration (dict) |
422 | +# |
423 | +# If 'user' exists it will override |
424 | +# the 'users'[0] entry (if a list) otherwise it will |
425 | +# just become an entry in the returned dictionary (no override) |
426 | def normalize_users_groups(cfg, distro): |
427 | if not cfg: |
428 | cfg = {} |
429 | @@ -548,6 +591,33 @@ |
430 | return (users, groups) |
431 | |
432 | |
433 | +# Given a user dictionary config it will |
434 | +# extract the default user name and user config |
435 | +# from that list and return that tuple or |
436 | +# return (None, None) if no default user is |
437 | +# found in the given input |
438 | +def extract_default(users, default_name=None, default_config=None): |
439 | + if not users: |
440 | + users = {} |
441 | + |
442 | + def safe_find(entry): |
443 | + config = entry[1] |
444 | + if not config or 'default' not in config: |
445 | + return False |
446 | + else: |
447 | + return config['default'] |
448 | + |
449 | + tmp_users = users.items() |
450 | + tmp_users = dict(itertools.ifilter(safe_find, tmp_users)) |
451 | + if not tmp_users: |
452 | + return (default_name, default_config) |
453 | + else: |
454 | + name = tmp_users.keys()[0] |
455 | + config = tmp_users[name] |
456 | + config.pop('default', None) |
457 | + return (name, config) |
458 | + |
459 | + |
460 | def fetch(name): |
461 | locs = importer.find_module(name, |
462 | ['', __name__], |
463 | |
464 | === modified file 'cloudinit/util.py' |
465 | --- cloudinit/util.py 2012-09-28 20:31:50 +0000 |
466 | +++ cloudinit/util.py 2012-09-28 21:23:20 +0000 |
467 | @@ -249,6 +249,36 @@ |
468 | raise |
469 | |
470 | |
471 | +# Merges X lists, and then keeps the |
472 | +# unique ones, but orders by sort order |
473 | +# instead of by the original order |
474 | +def uniq_merge_sorted(*lists): |
475 | + return sorted(uniq_merge(*lists)) |
476 | + |
477 | + |
478 | +# Merges X lists and then iterates over those |
479 | +# and only keeps the unique items (order preserving) |
480 | +# and returns that merged and uniqued list as the |
481 | +# final result. |
482 | +# |
483 | +# Note: if any entry is a string it will be |
484 | +# split on commas and empty entries will be |
485 | +# evicted and merged in accordingly. |
486 | +def uniq_merge(*lists): |
487 | + combined_list = [] |
488 | + for a_list in lists: |
489 | + if isinstance(a_list, (str, basestring)): |
490 | + a_list = a_list.strip().split(",") |
491 | + # Kickout the empty ones |
492 | + a_list = [a for a in a_list if len(a)] |
493 | + combined_list.extend(a_list) |
494 | + uniq_list = [] |
495 | + for i in combined_list: |
496 | + if i not in uniq_list: |
497 | + uniq_list.append(i) |
498 | + return uniq_list |
499 | + |
500 | + |
501 | def clean_filename(fn): |
502 | for (k, v) in FN_REPLACEMENTS.iteritems(): |
503 | fn = fn.replace(k, v) |
504 | |
505 | === modified file 'tests/unittests/test_distros/test_user_data_normalize.py' |
506 | --- tests/unittests/test_distros/test_user_data_normalize.py 2012-09-28 01:30:01 +0000 |
507 | +++ tests/unittests/test_distros/test_user_data_normalize.py 2012-09-28 21:23:20 +0000 |
508 | @@ -119,8 +119,8 @@ |
509 | (users, _groups) = self._norm(ug_cfg, distro) |
510 | self.assertIn('joe', users) |
511 | self.assertIn('bob', users) |
512 | - self.assertEquals({}, users['joe']) |
513 | - self.assertEquals({}, users['bob']) |
514 | + self.assertEquals({'default': False}, users['joe']) |
515 | + self.assertEquals({'default': False}, users['bob']) |
516 | |
517 | def test_users_simple(self): |
518 | distro = self._make_distro('ubuntu') |
519 | @@ -133,8 +133,8 @@ |
520 | (users, _groups) = self._norm(ug_cfg, distro) |
521 | self.assertIn('joe', users) |
522 | self.assertIn('bob', users) |
523 | - self.assertEquals({}, users['joe']) |
524 | - self.assertEquals({}, users['bob']) |
525 | + self.assertEquals({'default': False}, users['joe']) |
526 | + self.assertEquals({'default': False}, users['bob']) |
527 | |
528 | def test_users_old_user(self): |
529 | distro = self._make_distro('ubuntu', 'bob') |
530 | @@ -179,8 +179,7 @@ |
531 | } |
532 | (users, _groups) = self._norm(ug_cfg, distro) |
533 | self.assertIn('zetta', users) |
534 | - ug_cfg = { |
535 | - } |
536 | + ug_cfg = {} |
537 | (users, groups) = self._norm(ug_cfg, distro) |
538 | self.assertEquals({}, users) |
539 | self.assertEquals({}, groups) |
540 | @@ -198,6 +197,35 @@ |
541 | users['bob']['groups']) |
542 | self.assertEquals(True, |
543 | users['bob']['blah']) |
544 | + self.assertEquals(True, |
545 | + users['bob']['default']) |
546 | + |
547 | + def test_users_dict_extract(self): |
548 | + distro = self._make_distro('ubuntu', 'bob') |
549 | + ug_cfg = { |
550 | + 'users': [ |
551 | + 'default', |
552 | + ], |
553 | + } |
554 | + (users, _groups) = self._norm(ug_cfg, distro) |
555 | + self.assertIn('bob', users) |
556 | + (name, config) = distros.extract_default(users) |
557 | + self.assertEquals(name, 'bob') |
558 | + expected_config = {} |
559 | + def_config = None |
560 | + try: |
561 | + def_config = distro.get_default_user() |
562 | + except NotImplementedError: |
563 | + pass |
564 | + if not def_config: |
565 | + def_config = {} |
566 | + expected_config.update(def_config) |
567 | + |
568 | + # Ignore these for now |
569 | + expected_config.pop('name', None) |
570 | + expected_config.pop('groups', None) |
571 | + config.pop('groups', None) |
572 | + self.assertEquals(config, expected_config) |
573 | |
574 | def test_users_dict_default(self): |
575 | distro = self._make_distro('ubuntu', 'bob') |
576 | @@ -210,6 +238,8 @@ |
577 | self.assertIn('bob', users) |
578 | self.assertEquals(",".join(distro.get_default_user()['groups']), |
579 | users['bob']['groups']) |
580 | + self.assertEquals(True, |
581 | + users['bob']['default']) |
582 | |
583 | def test_users_dict_trans(self): |
584 | distro = self._make_distro('ubuntu') |
585 | @@ -223,8 +253,8 @@ |
586 | (users, _groups) = self._norm(ug_cfg, distro) |
587 | self.assertIn('joe', users) |
588 | self.assertIn('bob', users) |
589 | - self.assertEquals({'tr_me': True}, users['joe']) |
590 | - self.assertEquals({}, users['bob']) |
591 | + self.assertEquals({'tr_me': True, 'default': False}, users['joe']) |
592 | + self.assertEquals({'default': False}, users['bob']) |
593 | |
594 | def test_users_dict(self): |
595 | distro = self._make_distro('ubuntu') |
596 | @@ -237,5 +267,5 @@ |
597 | (users, _groups) = self._norm(ug_cfg, distro) |
598 | self.assertIn('joe', users) |
599 | self.assertIn('bob', users) |
600 | - self.assertEquals({}, users['joe']) |
601 | - self.assertEquals({}, users['bob']) |
602 | + self.assertEquals({'default': False}, users['joe']) |
603 | + self.assertEquals({'default': False}, users['bob']) |