Merge lp:~harlowja/cloud-init/ug-cleanup-part-deuce into lp:~cloud-init-dev/cloud-init/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
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+127067@code.launchpad.net
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
=== modified file 'cloudinit/config/cc_byobu.py'
--- cloudinit/config/cc_byobu.py 2012-06-23 03:58:50 +0000
+++ cloudinit/config/cc_byobu.py 2012-09-28 21:23:20 +0000
@@ -18,12 +18,17 @@
18# You should have received a copy of the GNU General Public License18# You should have received a copy of the GNU General Public License
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/>.
2020
21# Ensure this is aliased to a name not 'distros'
22# since the module attribute 'distros'
23# is a list of distros that are supported, not a sub-module
24from cloudinit import distros as ds
25
21from cloudinit import util26from cloudinit import util
2227
23distros = ['ubuntu', 'debian']28distros = ['ubuntu', 'debian']
2429
2530
26def handle(name, cfg, _cloud, log, args):31def handle(name, cfg, cloud, log, args):
27 if len(args) != 0:32 if len(args) != 0:
28 value = args[0]33 value = args[0]
29 else:34 else:
@@ -56,16 +61,20 @@
5661
57 shcmd = ""62 shcmd = ""
58 if mod_user:63 if mod_user:
59 user = util.get_cfg_option_str(cfg, "user", "ubuntu")64 (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro)
60 shcmd += " sudo -Hu \"%s\" byobu-launcher-%s" % (user, bl_inst)65 (user, _user_config) = ds.extract_default(users)
61 shcmd += " || X=$(($X+1)); "66 if not user:
67 log.warn(("No default byobu user provided, "
68 "can not launch %s for the default user"), bl_inst)
69 else:
70 shcmd += " sudo -Hu \"%s\" byobu-launcher-%s" % (user, bl_inst)
71 shcmd += " || X=$(($X+1)); "
62 if mod_sys:72 if mod_sys:
63 shcmd += "echo \"%s\" | debconf-set-selections" % dc_val73 shcmd += "echo \"%s\" | debconf-set-selections" % dc_val
64 shcmd += " && dpkg-reconfigure byobu --frontend=noninteractive"74 shcmd += " && dpkg-reconfigure byobu --frontend=noninteractive"
65 shcmd += " || X=$(($X+1)); "75 shcmd += " || X=$(($X+1)); "
6676
67 cmd = ["/bin/sh", "-c", "%s %s %s" % ("X=0;", shcmd, "exit $X")]77 if len(shcmd):
6878 cmd = ["/bin/sh", "-c", "%s %s %s" % ("X=0;", shcmd, "exit $X")]
69 log.debug("Setting byobu to %s", value)79 log.debug("Setting byobu to %s", value)
7080 util.subp(cmd, capture=False)
71 util.subp(cmd, capture=False)
7281
=== modified file 'cloudinit/config/cc_set_passwords.py'
--- cloudinit/config/cc_set_passwords.py 2012-08-31 21:45:15 +0000
+++ cloudinit/config/cc_set_passwords.py 2012-09-28 21:23:20 +0000
@@ -20,6 +20,11 @@
2020
21import sys21import sys
2222
23# Ensure this is aliased to a name not 'distros'
24# since the module attribute 'distros'
25# is a list of distros that are supported, not a sub-module
26from cloudinit import distros as ds
27
23from cloudinit import ssh_util28from cloudinit import ssh_util
24from cloudinit import util29from cloudinit import util
2530
@@ -50,18 +55,10 @@
50 expire = util.get_cfg_option_bool(chfg, 'expire', expire)55 expire = util.get_cfg_option_bool(chfg, 'expire', expire)
5156
52 if not plist and password:57 if not plist and password:
53 user = cloud.distro.get_default_user()58 (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro)
5459 (user, _user_config) = ds.extract_default(users)
55 if 'users' in cfg:
56
57 user_zero = cfg['users'][0]
58
59 if isinstance(user_zero, dict) and 'name' in user_zero:
60 user = user_zero['name']
61
62 if user:60 if user:
63 plist = "%s:%s" % (user, password)61 plist = "%s:%s" % (user, password)
64
65 else:62 else:
66 log.warn("No default or defined user to change password for.")63 log.warn("No default or defined user to change password for.")
6764
6865
=== modified file 'cloudinit/config/cc_ssh.py'
--- cloudinit/config/cc_ssh.py 2012-08-31 18:45:40 +0000
+++ cloudinit/config/cc_ssh.py 2012-09-28 21:23:20 +0000
@@ -21,6 +21,11 @@
21import glob21import glob
22import os22import os
2323
24# Ensure this is aliased to a name not 'distros'
25# since the module attribute 'distros'
26# is a list of distros that are supported, not a sub-module
27from cloudinit import distros as ds
28
24from cloudinit import ssh_util29from cloudinit import ssh_util
25from cloudinit import util30from cloudinit import util
2631
@@ -102,16 +107,8 @@
102 " %s to file %s"), keytype, keyfile)107 " %s to file %s"), keytype, keyfile)
103108
104 try:109 try:
105 # TODO(utlemming): consolidate this stanza that occurs in:110 (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro)
106 # cc_ssh_import_id, cc_set_passwords, maybe cc_users_groups.py111 (user, _user_config) = ds.extract_default(users)
107 user = cloud.distro.get_default_user()
108
109 if 'users' in cfg:
110 user_zero = cfg['users'][0]
111
112 if user_zero != "default":
113 user = user_zero
114
115 disable_root = util.get_cfg_option_bool(cfg, "disable_root", True)112 disable_root = util.get_cfg_option_bool(cfg, "disable_root", True)
116 disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts",113 disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts",
117 DISABLE_ROOT_OPTS)114 DISABLE_ROOT_OPTS)
118115
=== modified file 'cloudinit/config/cc_ssh_authkey_fingerprints.py'
--- cloudinit/config/cc_ssh_authkey_fingerprints.py 2012-09-28 20:35:53 +0000
+++ cloudinit/config/cc_ssh_authkey_fingerprints.py 2012-09-28 21:23:20 +0000
@@ -21,7 +21,11 @@
2121
22from prettytable import PrettyTable22from prettytable import PrettyTable
2323
24from cloudinit import distros24# Ensure this is aliased to a name not 'distros'
25# since the module attribute 'distros'
26# is a list of distros that are supported, not a sub-module
27from cloudinit import distros as ds
28
25from cloudinit import ssh_util29from cloudinit import ssh_util
26from cloudinit import util30from cloudinit import util
2731
@@ -41,8 +45,10 @@
41 hasher = hashlib.new(hash_meth)45 hasher = hashlib.new(hash_meth)
42 hasher.update(base64.b64decode(b64_text))46 hasher.update(base64.b64decode(b64_text))
43 return ":".join(_split_hash(hasher.hexdigest()))47 return ":".join(_split_hash(hasher.hexdigest()))
44 except TypeError:48 except (TypeError, ValueError):
45 # Raised when b64 not really b64...49 # Raised when b64 not really b64...
50 # or when the hash type is not really
51 # a known/supported hash type...
46 return '?'52 return '?'
4753
4854
@@ -92,8 +98,8 @@
9298
93 hash_meth = util.get_cfg_option_str(cfg, "authkey_hash", "md5")99 hash_meth = util.get_cfg_option_str(cfg, "authkey_hash", "md5")
94 extract_func = ssh_util.extract_authorized_keys100 extract_func = ssh_util.extract_authorized_keys
95 (users, _groups) = distros.normalize_users_groups(cfg, cloud.distro)101 (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro)
96 for (user_name, _cfg) in users.items():102 for (user_name, _cfg) in users.items():
97 (auth_key_fn, auth_key_entries) = extract_func(user_name, cloud.paths)103 (auth_key_fn, auth_key_entries) = extract_func(user_name, cloud.paths)
98 _pprint_key_entries(user_name, auth_key_fn, auth_key_entries,104 _pprint_key_entries(user_name, auth_key_fn,
99 hash_meth)105 auth_key_entries, hash_meth)
100106
=== modified file 'cloudinit/config/cc_ssh_import_id.py'
--- cloudinit/config/cc_ssh_import_id.py 2012-08-31 19:36:05 +0000
+++ cloudinit/config/cc_ssh_import_id.py 2012-09-28 21:23:20 +0000
@@ -18,6 +18,11 @@
18# You should have received a copy of the GNU General Public License18# You should have received a copy of the GNU General Public License
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/>.
2020
21# Ensure this is aliased to a name not 'distros'
22# since the module attribute 'distros'
23# is a list of distros that are supported, not a sub-module
24from cloudinit import distros as ds
25
21from cloudinit import util26from cloudinit import util
22import pwd27import pwd
2328
@@ -39,33 +44,27 @@
39 return44 return
4045
41 # import for cloudinit created users46 # import for cloudinit created users
47 (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro)
42 elist = []48 elist = []
43 for user_cfg in cfg['users']:49 for (user, user_cfg) in users.items():
44 user = None
45 import_ids = []50 import_ids = []
4651 if user_cfg['default']:
47 if isinstance(user_cfg, str) and user_cfg == "default":
48 user = cloud.distro.get_default_user()
49 if not user:
50 continue
51
52 import_ids = util.get_cfg_option_list(cfg, "ssh_import_id", [])52 import_ids = util.get_cfg_option_list(cfg, "ssh_import_id", [])
5353 else:
54 elif isinstance(user_cfg, dict):
55 user = None
56 import_ids = []
57
58 try:54 try:
59 user = user_cfg['name']
60 import_ids = user_cfg['ssh_import_id']55 import_ids = user_cfg['ssh_import_id']
61
62 if import_ids and isinstance(import_ids, str):
63 import_ids = str(import_ids).split(',')
64
65 except:56 except:
66 log.debug("user %s is not configured for ssh_import" % user)57 log.debug("User %s is not configured for ssh_import_id", user)
67 continue58 continue
6859
60 try:
61 import_ids = util.uniq_merge(import_ids)
62 import_ids = [str(i) for i in import_ids]
63 except:
64 log.debug("User %s is not correctly configured for ssh_import_id",
65 user)
66 continue
67
69 if not len(import_ids):68 if not len(import_ids):
70 continue69 continue
7170
7271
=== modified file 'cloudinit/config/cc_users_groups.py'
--- cloudinit/config/cc_users_groups.py 2012-09-28 20:35:53 +0000
+++ cloudinit/config/cc_users_groups.py 2012-09-28 21:23:20 +0000
@@ -16,7 +16,10 @@
16# You should have received a copy of the GNU General Public License16# You should have received a copy of the GNU General Public License
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/>.
1818
19from cloudinit import distros19# Ensure this is aliased to a name not 'distros'
20# since the module attribute 'distros'
21# is a list of distros that are supported, not a sub-module
22from cloudinit import distros as ds
2023
21from cloudinit.settings import PER_INSTANCE24from cloudinit.settings import PER_INSTANCE
2225
@@ -24,7 +27,7 @@
2427
2528
26def handle(name, cfg, cloud, _log, _args):29def handle(name, cfg, cloud, _log, _args):
27 (users, groups) = distros.normalize_users_groups(cfg, cloud.distro)30 (users, groups) = ds.normalize_users_groups(cfg, cloud.distro)
28 for (name, members) in groups.items():31 for (name, members) in groups.items():
29 cloud.distro.create_group(name, members)32 cloud.distro.create_group(name, members)
30 for (user, config) in users.items():33 for (user, config) in users.items():
3134
=== modified file 'cloudinit/distros/__init__.py'
--- cloudinit/distros/__init__.py 2012-09-28 19:38:48 +0000
+++ cloudinit/distros/__init__.py 2012-09-28 21:23:20 +0000
@@ -24,6 +24,7 @@
24from StringIO import StringIO24from StringIO import StringIO
2525
26import abc26import abc
27import itertools
27import os28import os
28import re29import re
2930
@@ -186,8 +187,10 @@
186 'gecos': "%s" % (self.default_user.title()),187 'gecos': "%s" % (self.default_user.title()),
187 'sudo': "ALL=(ALL) NOPASSWD:ALL",188 'sudo': "ALL=(ALL) NOPASSWD:ALL",
188 }189 }
189 if self.default_user_groups:190 def_groups = self.default_user_groups
190 user_cfg['groups'] = _uniq_merge_sorted(self.default_user_groups)191 if not def_groups:
192 def_groups = []
193 user_cfg['groups'] = util.uniq_merge_sorted(def_groups)
191 return user_cfg194 return user_cfg
192195
193 def create_user(self, name, **kwargs):196 def create_user(self, name, **kwargs):
@@ -398,39 +401,27 @@
398 return default401 return default
399402
400403
401def _uniq_merge_sorted(*lists):404# Normalizes a input group configuration
402 return sorted(_uniq_merge(*lists))405# which can be a comma seperated list of
403406# group names, or a list of group names
404407# or a python dictionary of group names
405def _uniq_merge(*lists):408# to a list of members of that group.
406 combined_list = []409#
407 for a_list in lists:410# The output is a dictionary of group
408 if isinstance(a_list, (str, basestring)):411# names => members of that group which
409 a_list = a_list.strip().split(",")412# is the standard form used in the rest
410 else:413# of cloud-init
411 a_list = [str(a) for a in a_list]
412 a_list = [a.strip() for a in a_list if a.strip()]
413 combined_list.extend(a_list)
414 uniq_list = []
415 for a in combined_list:
416 if a in uniq_list:
417 continue
418 else:
419 uniq_list.append(a)
420 return uniq_list
421
422
423def _normalize_groups(grp_cfg):414def _normalize_groups(grp_cfg):
424 if isinstance(grp_cfg, (str, basestring, list)):415 if isinstance(grp_cfg, (str, basestring, list)):
425 c_grp_cfg = {}416 c_grp_cfg = {}
426 for i in _uniq_merge(grp_cfg):417 for i in util.uniq_merge(grp_cfg):
427 c_grp_cfg[i] = []418 c_grp_cfg[i] = []
428 grp_cfg = c_grp_cfg419 grp_cfg = c_grp_cfg
429420
430 groups = {}421 groups = {}
431 if isinstance(grp_cfg, (dict)):422 if isinstance(grp_cfg, (dict)):
432 for (grp_name, grp_members) in grp_cfg.items():423 for (grp_name, grp_members) in grp_cfg.items():
433 groups[grp_name] = _uniq_merge_sorted(grp_members)424 groups[grp_name] = util.uniq_merge_sorted(grp_members)
434 else:425 else:
435 raise TypeError(("Group config must be list, dict "426 raise TypeError(("Group config must be list, dict "
436 " or string types only and not %s") %427 " or string types only and not %s") %
@@ -438,6 +429,21 @@
438 return groups429 return groups
439430
440431
432# Normalizes a input group configuration
433# which can be a comma seperated list of
434# user names, or a list of string user names
435# or a list of dictionaries with components
436# that define the user config + 'name' (if
437# a 'name' field does not exist then the
438# default user is assumed to 'own' that
439# configuration.
440#
441# The output is a dictionary of user
442# names => user config which is the standard
443# form used in the rest of cloud-init. Note
444# the default user will have a special config
445# entry 'default' which will be marked as true
446# all other users will be marked as false.
441def _normalize_users(u_cfg, def_user_cfg=None):447def _normalize_users(u_cfg, def_user_cfg=None):
442 if isinstance(u_cfg, (dict)):448 if isinstance(u_cfg, (dict)):
443 ad_ucfg = []449 ad_ucfg = []
@@ -453,12 +459,12 @@
453 " for key %s") % (util.obj_name(v), k))459 " for key %s") % (util.obj_name(v), k))
454 u_cfg = ad_ucfg460 u_cfg = ad_ucfg
455 elif isinstance(u_cfg, (str, basestring)):461 elif isinstance(u_cfg, (str, basestring)):
456 u_cfg = _uniq_merge_sorted(u_cfg)462 u_cfg = util.uniq_merge_sorted(u_cfg)
457463
458 users = {}464 users = {}
459 for user_config in u_cfg:465 for user_config in u_cfg:
460 if isinstance(user_config, (str, basestring, list)):466 if isinstance(user_config, (str, basestring, list)):
461 for u in _uniq_merge(user_config):467 for u in util.uniq_merge(user_config):
462 if u and u not in users:468 if u and u not in users:
463 users[u] = {}469 users[u] = {}
464 elif isinstance(user_config, (dict)):470 elif isinstance(user_config, (dict)):
@@ -491,22 +497,59 @@
491497
492 # Fixup the default user into the real498 # Fixup the default user into the real
493 # default user name and replace it...499 # default user name and replace it...
500 def_user = None
494 if users and 'default' in users:501 if users and 'default' in users:
495 def_config = users.pop('default')502 def_config = users.pop('default')
496 if def_user_cfg:503 if def_user_cfg:
504 # Pickup what the default 'real name' is
505 # and any groups that are provided by the
506 # default config
497 def_user = def_user_cfg.pop('name')507 def_user = def_user_cfg.pop('name')
498 def_groups = def_user_cfg.pop('groups', [])508 def_groups = def_user_cfg.pop('groups', [])
509 # Pickup any config + groups for that user name
510 # that we may have previously extracted
499 parsed_config = users.pop(def_user, {})511 parsed_config = users.pop(def_user, {})
500 users_groups = _uniq_merge_sorted(parsed_config.get('groups', []),512 parsed_groups = parsed_config.get('groups', [])
501 def_groups)513 # Now merge our extracted groups with
514 # anything the default config provided
515 users_groups = util.uniq_merge_sorted(parsed_groups, def_groups)
502 parsed_config['groups'] = ",".join(users_groups)516 parsed_config['groups'] = ",".join(users_groups)
517 # The real config for the default user is the
518 # combination of the default user config provided
519 # by the distro, the default user config provided
520 # by the above merging for the user 'default' and
521 # then the parsed config from the user's 'real name'
522 # which does not have to be 'default' (but could be)
503 users[def_user] = util.mergemanydict([def_user_cfg,523 users[def_user] = util.mergemanydict([def_user_cfg,
504 def_config,524 def_config,
505 parsed_config])525 parsed_config])
506526
527 # Ensure that only the default user that we
528 # found (if any) is actually marked as being
529 # the default user
530 if users:
531 for (uname, uconfig) in users.items():
532 if def_user and uname == def_user:
533 uconfig['default'] = True
534 else:
535 uconfig['default'] = False
536
507 return users537 return users
508538
509539
540# Normalizes a set of user/users and group
541# dictionary configuration into a useable
542# format that the rest of cloud-init can
543# understand using the default user
544# provided by the input distrobution (if any)
545# to allow for mapping of the 'default' user.
546#
547# Output is a dictionary of group names -> [member] (list)
548# and a dictionary of user names -> user configuration (dict)
549#
550# If 'user' exists it will override
551# the 'users'[0] entry (if a list) otherwise it will
552# just become an entry in the returned dictionary (no override)
510def normalize_users_groups(cfg, distro):553def normalize_users_groups(cfg, distro):
511 if not cfg:554 if not cfg:
512 cfg = {}555 cfg = {}
@@ -548,6 +591,33 @@
548 return (users, groups)591 return (users, groups)
549592
550593
594# Given a user dictionary config it will
595# extract the default user name and user config
596# from that list and return that tuple or
597# return (None, None) if no default user is
598# found in the given input
599def extract_default(users, default_name=None, default_config=None):
600 if not users:
601 users = {}
602
603 def safe_find(entry):
604 config = entry[1]
605 if not config or 'default' not in config:
606 return False
607 else:
608 return config['default']
609
610 tmp_users = users.items()
611 tmp_users = dict(itertools.ifilter(safe_find, tmp_users))
612 if not tmp_users:
613 return (default_name, default_config)
614 else:
615 name = tmp_users.keys()[0]
616 config = tmp_users[name]
617 config.pop('default', None)
618 return (name, config)
619
620
551def fetch(name):621def fetch(name):
552 locs = importer.find_module(name,622 locs = importer.find_module(name,
553 ['', __name__],623 ['', __name__],
554624
=== modified file 'cloudinit/util.py'
--- cloudinit/util.py 2012-09-28 20:31:50 +0000
+++ cloudinit/util.py 2012-09-28 21:23:20 +0000
@@ -249,6 +249,36 @@
249 raise249 raise
250250
251251
252# Merges X lists, and then keeps the
253# unique ones, but orders by sort order
254# instead of by the original order
255def uniq_merge_sorted(*lists):
256 return sorted(uniq_merge(*lists))
257
258
259# Merges X lists and then iterates over those
260# and only keeps the unique items (order preserving)
261# and returns that merged and uniqued list as the
262# final result.
263#
264# Note: if any entry is a string it will be
265# split on commas and empty entries will be
266# evicted and merged in accordingly.
267def uniq_merge(*lists):
268 combined_list = []
269 for a_list in lists:
270 if isinstance(a_list, (str, basestring)):
271 a_list = a_list.strip().split(",")
272 # Kickout the empty ones
273 a_list = [a for a in a_list if len(a)]
274 combined_list.extend(a_list)
275 uniq_list = []
276 for i in combined_list:
277 if i not in uniq_list:
278 uniq_list.append(i)
279 return uniq_list
280
281
252def clean_filename(fn):282def clean_filename(fn):
253 for (k, v) in FN_REPLACEMENTS.iteritems():283 for (k, v) in FN_REPLACEMENTS.iteritems():
254 fn = fn.replace(k, v)284 fn = fn.replace(k, v)
255285
=== modified file 'tests/unittests/test_distros/test_user_data_normalize.py'
--- tests/unittests/test_distros/test_user_data_normalize.py 2012-09-28 01:30:01 +0000
+++ tests/unittests/test_distros/test_user_data_normalize.py 2012-09-28 21:23:20 +0000
@@ -119,8 +119,8 @@
119 (users, _groups) = self._norm(ug_cfg, distro)119 (users, _groups) = self._norm(ug_cfg, distro)
120 self.assertIn('joe', users)120 self.assertIn('joe', users)
121 self.assertIn('bob', users)121 self.assertIn('bob', users)
122 self.assertEquals({}, users['joe'])122 self.assertEquals({'default': False}, users['joe'])
123 self.assertEquals({}, users['bob'])123 self.assertEquals({'default': False}, users['bob'])
124124
125 def test_users_simple(self):125 def test_users_simple(self):
126 distro = self._make_distro('ubuntu')126 distro = self._make_distro('ubuntu')
@@ -133,8 +133,8 @@
133 (users, _groups) = self._norm(ug_cfg, distro)133 (users, _groups) = self._norm(ug_cfg, distro)
134 self.assertIn('joe', users)134 self.assertIn('joe', users)
135 self.assertIn('bob', users)135 self.assertIn('bob', users)
136 self.assertEquals({}, users['joe'])136 self.assertEquals({'default': False}, users['joe'])
137 self.assertEquals({}, users['bob'])137 self.assertEquals({'default': False}, users['bob'])
138138
139 def test_users_old_user(self):139 def test_users_old_user(self):
140 distro = self._make_distro('ubuntu', 'bob')140 distro = self._make_distro('ubuntu', 'bob')
@@ -179,8 +179,7 @@
179 }179 }
180 (users, _groups) = self._norm(ug_cfg, distro)180 (users, _groups) = self._norm(ug_cfg, distro)
181 self.assertIn('zetta', users)181 self.assertIn('zetta', users)
182 ug_cfg = {182 ug_cfg = {}
183 }
184 (users, groups) = self._norm(ug_cfg, distro)183 (users, groups) = self._norm(ug_cfg, distro)
185 self.assertEquals({}, users)184 self.assertEquals({}, users)
186 self.assertEquals({}, groups)185 self.assertEquals({}, groups)
@@ -198,6 +197,35 @@
198 users['bob']['groups'])197 users['bob']['groups'])
199 self.assertEquals(True,198 self.assertEquals(True,
200 users['bob']['blah'])199 users['bob']['blah'])
200 self.assertEquals(True,
201 users['bob']['default'])
202
203 def test_users_dict_extract(self):
204 distro = self._make_distro('ubuntu', 'bob')
205 ug_cfg = {
206 'users': [
207 'default',
208 ],
209 }
210 (users, _groups) = self._norm(ug_cfg, distro)
211 self.assertIn('bob', users)
212 (name, config) = distros.extract_default(users)
213 self.assertEquals(name, 'bob')
214 expected_config = {}
215 def_config = None
216 try:
217 def_config = distro.get_default_user()
218 except NotImplementedError:
219 pass
220 if not def_config:
221 def_config = {}
222 expected_config.update(def_config)
223
224 # Ignore these for now
225 expected_config.pop('name', None)
226 expected_config.pop('groups', None)
227 config.pop('groups', None)
228 self.assertEquals(config, expected_config)
201229
202 def test_users_dict_default(self):230 def test_users_dict_default(self):
203 distro = self._make_distro('ubuntu', 'bob')231 distro = self._make_distro('ubuntu', 'bob')
@@ -210,6 +238,8 @@
210 self.assertIn('bob', users)238 self.assertIn('bob', users)
211 self.assertEquals(",".join(distro.get_default_user()['groups']),239 self.assertEquals(",".join(distro.get_default_user()['groups']),
212 users['bob']['groups'])240 users['bob']['groups'])
241 self.assertEquals(True,
242 users['bob']['default'])
213243
214 def test_users_dict_trans(self):244 def test_users_dict_trans(self):
215 distro = self._make_distro('ubuntu')245 distro = self._make_distro('ubuntu')
@@ -223,8 +253,8 @@
223 (users, _groups) = self._norm(ug_cfg, distro)253 (users, _groups) = self._norm(ug_cfg, distro)
224 self.assertIn('joe', users)254 self.assertIn('joe', users)
225 self.assertIn('bob', users)255 self.assertIn('bob', users)
226 self.assertEquals({'tr_me': True}, users['joe'])256 self.assertEquals({'tr_me': True, 'default': False}, users['joe'])
227 self.assertEquals({}, users['bob'])257 self.assertEquals({'default': False}, users['bob'])
228258
229 def test_users_dict(self):259 def test_users_dict(self):
230 distro = self._make_distro('ubuntu')260 distro = self._make_distro('ubuntu')
@@ -237,5 +267,5 @@
237 (users, _groups) = self._norm(ug_cfg, distro)267 (users, _groups) = self._norm(ug_cfg, distro)
238 self.assertIn('joe', users)268 self.assertIn('joe', users)
239 self.assertIn('bob', users)269 self.assertIn('bob', users)
240 self.assertEquals({}, users['joe'])270 self.assertEquals({'default': False}, users['joe'])
241 self.assertEquals({}, users['bob'])271 self.assertEquals({'default': False}, users['bob'])