Merge branch 'devel' into unevaluated-vars
This commit is contained in:
commit
cbb1808f05
13 changed files with 494 additions and 50 deletions
|
@ -130,6 +130,7 @@ the variable is still registered for the host, with the attribute skipped: True.
|
|||
* improved FreeBSD, NetBSD and Solaris facts
|
||||
* debug module always outputs data without having to specify -v
|
||||
* fix for sysctl module creating new keys (must specify checks=none)
|
||||
* NetBSD and OpenBSD support for the user and groups modules
|
||||
|
||||
1.1 "Mean Street" -- 4/2/2013
|
||||
|
||||
|
|
2
Makefile
2
Makefile
|
@ -52,7 +52,7 @@ endif
|
|||
# RPM build parameters
|
||||
RPMSPECDIR= packaging/rpm
|
||||
RPMSPEC = $(RPMSPECDIR)/ansible.spec
|
||||
RPMDIST = $(shell rpm --eval '%dist')
|
||||
RPMDIST = $(shell rpm --eval '%{?dist}')
|
||||
RPMRELEASE = 1
|
||||
ifeq ($(OFFICIAL),)
|
||||
RPMRELEASE = 0.git$(DATE)
|
||||
|
|
|
@ -102,6 +102,8 @@ def main(args):
|
|||
parser.add_option('-C', '--checkout', dest='checkout',
|
||||
default="HEAD",
|
||||
help='Branch/Tag/Commit to checkout. Defaults to HEAD.')
|
||||
parser.add_option('-i', '--inventory-file', dest='inventory',
|
||||
help="specify inventory host file")
|
||||
options, args = parser.parse_args(args)
|
||||
|
||||
if not options.dest:
|
||||
|
@ -115,9 +117,12 @@ def main(args):
|
|||
now = datetime.datetime.now()
|
||||
print >>sys.stderr, now.strftime("Starting ansible-pull at %F %T")
|
||||
|
||||
inv_opts = 'localhost,'
|
||||
limit_opts = 'localhost:%s:127.0.0.1' % socket.getfqdn()
|
||||
git_opts = "repo=%s dest=%s version=%s" % (options.url, options.dest, options.checkout)
|
||||
cmd = 'ansible all -c local --limit "%s" -m git -a "%s"' % (limit_opts, git_opts)
|
||||
cmd = 'ansible all -c local -i "%s" --limit "%s" -m git -a "%s"' % (
|
||||
inv_opts, limit_opts, git_opts
|
||||
)
|
||||
rc = _run(cmd)
|
||||
if rc != 0:
|
||||
return rc
|
||||
|
@ -129,6 +134,8 @@ def main(args):
|
|||
return 1
|
||||
|
||||
cmd = 'ansible-playbook -c local --limit "%s" %s' % (limit_opts, playbook)
|
||||
if options.inventory:
|
||||
cmd += ' -i "%s"' % options.inventory
|
||||
os.chdir(options.dest)
|
||||
rc = _run(cmd)
|
||||
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
.\" Title: ansible-playbook
|
||||
.\" Author: [see the "AUTHOR" section]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||
.\" Date: 05/29/2013
|
||||
.\" Date: 06/03/2013
|
||||
.\" Manual: System administration commands
|
||||
.\" Source: Ansible 1.2
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "ANSIBLE\-PLAYBOOK" "1" "05/29/2013" "Ansible 1\&.2" "System administration commands"
|
||||
.TH "ANSIBLE\-PLAYBOOK" "1" "06/03/2013" "Ansible 1\&.2" "System administration commands"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * set default formatting
|
||||
.\" -----------------------------------------------------------------
|
||||
|
@ -57,7 +57,7 @@ search path to load modules from\&. The default is
|
|||
.PP
|
||||
\fB\-e\fR \fIVARS\fR, \fB\-\-extra\-vars=\fR\fIVARS\fR
|
||||
.RS 4
|
||||
Extra variables to inject into a playbook, in key=value key=value format\&.
|
||||
Extra variables to inject into a playbook, in key=value key=value format or as quoted JSON (hashes and arrays)\&.
|
||||
.RE
|
||||
.PP
|
||||
\fB\-f\fR \fINUM\fR, \fB\-\-forks=\fR\fINUM\fR
|
||||
|
|
|
@ -12,7 +12,7 @@ ansible-pull - set up a remote copy of ansible on each managed node
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
ansible -d DEST -U URL [ -C CHECKOUT ]
|
||||
ansible -d DEST -U URL [ -C CHECKOUT ] [ -i INVENTORY ] [ <filename.yml> ]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -35,6 +35,17 @@ ansible-pull runs would be an excellent way to gather and analyze
|
|||
remote logs from ansible-pull.
|
||||
|
||||
|
||||
OPTIONAL ARGUMENT
|
||||
-----------------
|
||||
|
||||
*filename.yml*::
|
||||
|
||||
The name of one the YAML format files to run as an ansible playbook. This can
|
||||
be a relative path within the git checkout. If not provided, ansible-pull
|
||||
will look for a playbook based on the host's fully-qualified domain name and
|
||||
finally a playbook named *local.yml*.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
|
@ -50,6 +61,14 @@ URL of git repository to clone.
|
|||
|
||||
Branch/Tag/Commit to checkout. Defaults to 'HEAD'.
|
||||
|
||||
*-i* 'PATH', *--inventory=*'PATH'::
|
||||
|
||||
The 'PATH' to the inventory hosts file. This can be a relative path within
|
||||
the git checkout.
|
||||
|
||||
*--purge*::
|
||||
|
||||
Purge the git checkout after the playbook is run.
|
||||
|
||||
|
||||
AUTHOR
|
||||
|
|
|
@ -127,22 +127,22 @@ And in your playbook::
|
|||
hosts: /chroot/path
|
||||
|
||||
Pending Information
|
||||
===================
|
||||
```````````````````
|
||||
|
||||
In the future look here for more topics.
|
||||
|
||||
Using Ansible's S3 module
|
||||
`````````````````````````
|
||||
+++++++++++++++++++++++++
|
||||
|
||||
these modules are documented on the module page, more walk throughs coming soon
|
||||
|
||||
Using Ansible's Elastic Load Balancer Support
|
||||
`````````````````````````````````````````````
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
these modules are documented on the module page, more walk throughs coming soon
|
||||
|
||||
Using Ansible's Cloud Formation Module
|
||||
``````````````````````````````````````
|
||||
++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
these modules are documented on the module page, more walk throughs coming soon
|
||||
|
||||
|
|
|
@ -48,6 +48,9 @@ class InventoryDirectory(object):
|
|||
# this file is generated on a failed playbook and should only be
|
||||
# used when run specifically
|
||||
continue
|
||||
# Skip hidden files
|
||||
if i.startswith('.') and not i.startswith('./'):
|
||||
continue
|
||||
# These are things inside of an inventory basedir
|
||||
if i in ("host_vars", "group_vars", "vars_plugins"):
|
||||
continue
|
||||
|
@ -62,15 +65,22 @@ class InventoryDirectory(object):
|
|||
# This takes a lot of code because we can't directly use any of the objects, as they have to blend
|
||||
for name, group in parser.groups.iteritems():
|
||||
if name not in self.groups:
|
||||
self.groups[name] = Group(name)
|
||||
self.groups[name] = group
|
||||
else:
|
||||
# group is already there, copy variables
|
||||
# note: depth numbers on duplicates may be bogus
|
||||
for k, v in group.get_variables().iteritems():
|
||||
self.groups[name].set_variable(k, v)
|
||||
for host in group.get_hosts():
|
||||
if host.name not in self.hosts:
|
||||
self.hosts[host.name] = Host(host.name)
|
||||
self.hosts[host.name] = host
|
||||
else:
|
||||
# host is already there, copy variables
|
||||
# note: depth numbers on duplicates may be bogus
|
||||
for k, v in host.vars.iteritems():
|
||||
self.hosts[host.name].set_variable(k, v)
|
||||
self.groups[name].add_host(self.hosts[host.name])
|
||||
|
||||
# This needs to be a second loop to ensure all the parent groups exist
|
||||
for name, group in parser.groups.iteritems():
|
||||
for ancestor in group.get_ancestors():
|
||||
|
|
|
@ -35,6 +35,9 @@ class Group(object):
|
|||
|
||||
if self == group:
|
||||
raise Exception("can't add group to itself")
|
||||
|
||||
# don't add if it's already there
|
||||
if not group in self.child_groups:
|
||||
self.child_groups.append(group)
|
||||
group.depth = max([self.depth+1, group.depth])
|
||||
group.parent_groups.append(self)
|
||||
|
|
|
@ -57,12 +57,12 @@ class ActionModule(object):
|
|||
found = False
|
||||
for fn in inject.get('first_available_file'):
|
||||
fn_orig = fn
|
||||
fn = template.template(self.runner.basedir, fn, inject)
|
||||
fn = utils.path_dwim(self.runner.basedir, fn)
|
||||
if not os.path.exists(fn) and '_original_file' in inject:
|
||||
fn = utils.path_dwim_relative(inject['_original_file'], 'files', fn_orig, self.runner.basedir, check=False)
|
||||
if os.path.exists(fn):
|
||||
source = fn
|
||||
fnt = template.template(self.runner.basedir, fn, inject)
|
||||
fnd = utils.path_dwim(self.runner.basedir, fnt)
|
||||
if not os.path.exists(fnd) and '_original_file' in inject:
|
||||
fnd = utils.path_dwim_relative(inject['_original_file'], 'files', fnt, self.runner.basedir, check=False)
|
||||
if os.path.exists(fnd):
|
||||
source = fnd
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
|
|
|
@ -60,7 +60,7 @@ class ActionModule(object):
|
|||
fnt = template.template(self.runner.basedir, fn, inject)
|
||||
fnd = utils.path_dwim(self.runner.basedir, fnt)
|
||||
if not os.path.exists(fnd) and '_original_file' in inject:
|
||||
fnd = utils.path_dwim_relative(inject['_original_file'], 'templates', fn_orig, self.runner.basedir, check=False)
|
||||
fnd = utils.path_dwim_relative(inject['_original_file'], 'templates', fnt, self.runner.basedir, check=False)
|
||||
if os.path.exists(fnd):
|
||||
source = fnd
|
||||
found = True
|
||||
|
|
|
@ -242,11 +242,97 @@ class FreeBsdGroup(Group):
|
|||
cmd.append('-g %d' % int(self.gid))
|
||||
# modify the group if cmd will do anything
|
||||
if cmd_len != len(cmd):
|
||||
if self.module.check_mode:
|
||||
return (True, '', '')
|
||||
return self.execute_command(cmd)
|
||||
return (None, '', '')
|
||||
|
||||
# ===========================================
|
||||
|
||||
class OpenBsdGroup(Group):
|
||||
"""
|
||||
This is a OpenBSD Group manipulation class.
|
||||
|
||||
This overrides the following methods from the generic class:-
|
||||
- group_del()
|
||||
- group_add()
|
||||
- group_mod()
|
||||
"""
|
||||
|
||||
platform = 'OpenBSD'
|
||||
distribution = None
|
||||
GROUPFILE = '/etc/group'
|
||||
|
||||
def group_del(self):
|
||||
cmd = [self.module.get_bin_path('groupdel', True), self.name]
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def group_add(self, **kwargs):
|
||||
cmd = [self.module.get_bin_path('groupadd', True)]
|
||||
if self.gid is not None:
|
||||
cmd.append('-g')
|
||||
cmd.append('%d' % int(self.gid))
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def group_mod(self, **kwargs):
|
||||
cmd = [self.module.get_bin_path('groupmod', True)]
|
||||
info = self.group_info()
|
||||
cmd_len = len(cmd)
|
||||
if self.gid is not None and int(self.gid) != info[2]:
|
||||
cmd.append('-g')
|
||||
cmd.append('%d' % int(self.gid))
|
||||
if len(cmd) == 1:
|
||||
return (None, '', '')
|
||||
if self.module.check_mode:
|
||||
return (True, '', '')
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
# ===========================================
|
||||
|
||||
class NetBsdGroup(Group):
|
||||
"""
|
||||
This is a NetBSD Group manipulation class.
|
||||
|
||||
This overrides the following methods from the generic class:-
|
||||
- group_del()
|
||||
- group_add()
|
||||
- group_mod()
|
||||
"""
|
||||
|
||||
platform = 'NetBSD'
|
||||
distribution = None
|
||||
GROUPFILE = '/etc/group'
|
||||
|
||||
def group_del(self):
|
||||
cmd = [self.module.get_bin_path('groupdel', True), self.name]
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def group_add(self, **kwargs):
|
||||
cmd = [self.module.get_bin_path('groupadd', True)]
|
||||
if self.gid is not None:
|
||||
cmd.append('-g')
|
||||
cmd.append('%d' % int(self.gid))
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def group_mod(self, **kwargs):
|
||||
cmd = [self.module.get_bin_path('groupmod', True)]
|
||||
info = self.group_info()
|
||||
cmd_len = len(cmd)
|
||||
if self.gid is not None and int(self.gid) != info[2]:
|
||||
cmd.append('-g')
|
||||
cmd.append('%d' % int(self.gid))
|
||||
if len(cmd) == 1:
|
||||
return (None, '', '')
|
||||
if self.module.check_mode:
|
||||
return (True, '', '')
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
# ===========================================
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec = dict(
|
||||
|
|
|
@ -106,6 +106,10 @@ options:
|
|||
description:
|
||||
- When used with C(state=absent), behavior is as with
|
||||
C(userdel --force).
|
||||
login_class:
|
||||
required: false
|
||||
description:
|
||||
- Optionally sets the user's login class for FreeBSD, OpenBSD and NetBSD systems.
|
||||
remove:
|
||||
required: false
|
||||
default: "no"
|
||||
|
@ -215,6 +219,7 @@ class User(object):
|
|||
self.remove = module.params['remove']
|
||||
self.createhome = module.params['createhome']
|
||||
self.system = module.params['system']
|
||||
self.login_class = module.params['login_class']
|
||||
self.append = module.params['append']
|
||||
self.sshkeygen = module.params['generate_ssh_key']
|
||||
self.ssh_bits = module.params['ssh_key_bits']
|
||||
|
@ -554,7 +559,7 @@ class FreeBsdUser(User):
|
|||
self.module.get_bin_path('pw', True),
|
||||
'useradd',
|
||||
'-n',
|
||||
self.name
|
||||
self.name,
|
||||
]
|
||||
|
||||
if self.uid is not None:
|
||||
|
@ -590,6 +595,10 @@ class FreeBsdUser(User):
|
|||
cmd.append('-s')
|
||||
cmd.append(self.shell)
|
||||
|
||||
if self.login_class is not None:
|
||||
cmd.append('-L')
|
||||
cmd.append(self.login_class)
|
||||
|
||||
# system cannot be handled currently - should we error if its requested?
|
||||
# create the user
|
||||
(rc, out, err) = self.execute_command(cmd)
|
||||
|
@ -645,6 +654,10 @@ class FreeBsdUser(User):
|
|||
cmd.append('-s')
|
||||
cmd.append(self.shell)
|
||||
|
||||
if self.login_class is not None:
|
||||
cmd.append('-L')
|
||||
cmd.append(self.login_class)
|
||||
|
||||
if self.groups is not None:
|
||||
current_groups = self.user_group_membership()
|
||||
groups = self.get_groups_set()
|
||||
|
@ -690,6 +703,308 @@ class FreeBsdUser(User):
|
|||
|
||||
# ===========================================
|
||||
|
||||
class OpenBSDUser(User):
|
||||
"""
|
||||
This is a OpenBSD User manipulation class.
|
||||
Main differences are that OpenBSD:-
|
||||
- has no concept of "system" account.
|
||||
- has no force delete user
|
||||
|
||||
This overrides the following methods from the generic class:-
|
||||
- create_user()
|
||||
- remove_user()
|
||||
- modify_user()
|
||||
"""
|
||||
|
||||
platform = 'OpenBSD'
|
||||
distribution = None
|
||||
SHADOWFILE = '/etc/master.passwd'
|
||||
|
||||
def create_user(self):
|
||||
cmd = [self.module.get_bin_path('useradd', True)]
|
||||
|
||||
if self.uid is not None:
|
||||
cmd.append('-u')
|
||||
cmd.append(self.uid)
|
||||
|
||||
if self.non_unique:
|
||||
cmd.append('-o')
|
||||
|
||||
if self.group is not None:
|
||||
if not self.group_exists(self.group):
|
||||
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
||||
cmd.append('-g')
|
||||
cmd.append(self.group)
|
||||
|
||||
if self.groups is not None:
|
||||
groups = self.get_groups_set()
|
||||
cmd.append('-G')
|
||||
cmd.append(','.join(groups))
|
||||
|
||||
if self.comment is not None:
|
||||
cmd.append('-c')
|
||||
cmd.append(self.comment)
|
||||
|
||||
if self.home is not None:
|
||||
cmd.append('-d')
|
||||
cmd.append(self.home)
|
||||
|
||||
if self.shell is not None:
|
||||
cmd.append('-s')
|
||||
cmd.append(self.shell)
|
||||
|
||||
if self.login_class is not None:
|
||||
cmd.append('-L')
|
||||
cmd.append(self.login_class)
|
||||
|
||||
if self.password is not None:
|
||||
cmd.append('-p')
|
||||
cmd.append(self.password)
|
||||
|
||||
if self.createhome:
|
||||
cmd.append('-m')
|
||||
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def remove_user_userdel(self):
|
||||
cmd = [self.module.get_bin_path('userdel', True)]
|
||||
if self.remove:
|
||||
cmd.append('-r')
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def modify_user(self):
|
||||
cmd = [self.module.get_bin_path('usermod', True)]
|
||||
info = self.user_info()
|
||||
|
||||
if self.uid is not None and info[2] != int(self.uid):
|
||||
cmd.append('-u')
|
||||
cmd.append(self.uid)
|
||||
|
||||
if self.non_unique:
|
||||
cmd.append('-o')
|
||||
|
||||
if self.group is not None:
|
||||
if not self.group_exists(self.group):
|
||||
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
||||
ginfo = self.group_info(self.group)
|
||||
if info[3] != ginfo[2]:
|
||||
cmd.append('-g')
|
||||
cmd.append(self.group)
|
||||
|
||||
if self.groups is not None:
|
||||
current_groups = self.user_group_membership()
|
||||
groups_need_mod = False
|
||||
groups_option = '-G'
|
||||
groups = []
|
||||
|
||||
if self.groups == '':
|
||||
if current_groups and not self.append:
|
||||
groups_need_mod = True
|
||||
else:
|
||||
groups = self.get_groups_set()
|
||||
group_diff = set(current_groups).symmetric_difference(groups)
|
||||
|
||||
if group_diff:
|
||||
if self.append:
|
||||
for g in groups:
|
||||
if g in group_diff:
|
||||
groups_option = '-S'
|
||||
groups_need_mod = True
|
||||
break
|
||||
else:
|
||||
groups_need_mod = True
|
||||
|
||||
if groups_need_mod:
|
||||
cmd.append(groups_option)
|
||||
cmd.append(','.join(groups))
|
||||
|
||||
if self.comment is not None and info[4] != self.comment:
|
||||
cmd.append('-c')
|
||||
cmd.append(self.comment)
|
||||
|
||||
if self.home is not None and info[5] != self.home:
|
||||
cmd.append('-d')
|
||||
cmd.append(self.home)
|
||||
|
||||
if self.shell is not None and info[6] != self.shell:
|
||||
cmd.append('-s')
|
||||
cmd.append(self.shell)
|
||||
|
||||
if self.login_class is not None:
|
||||
cmd.append('-L')
|
||||
cmd.append(self.login_class)
|
||||
|
||||
if self.password is not None and info[1] != self.password:
|
||||
cmd.append('-p')
|
||||
cmd.append(self.password)
|
||||
|
||||
# skip if no changes to be made
|
||||
if len(cmd) == 1:
|
||||
return (None, '', '')
|
||||
elif self.module.check_mode:
|
||||
return (0, '', '')
|
||||
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
|
||||
# ===========================================
|
||||
|
||||
class NetBSDUser(User):
|
||||
"""
|
||||
This is a NetBSD User manipulation class.
|
||||
Main differences are that NetBSD:-
|
||||
- has no concept of "system" account.
|
||||
- has no force delete user
|
||||
|
||||
|
||||
This overrides the following methods from the generic class:-
|
||||
- create_user()
|
||||
- remove_user()
|
||||
- modify_user()
|
||||
"""
|
||||
|
||||
platform = 'NetBSD'
|
||||
distribution = None
|
||||
SHADOWFILE = '/etc/master.passwd'
|
||||
|
||||
def create_user(self):
|
||||
cmd = [self.module.get_bin_path('useradd', True)]
|
||||
|
||||
if self.uid is not None:
|
||||
cmd.append('-u')
|
||||
cmd.append(self.uid)
|
||||
|
||||
if self.non_unique:
|
||||
cmd.append('-o')
|
||||
|
||||
if self.group is not None:
|
||||
if not self.group_exists(self.group):
|
||||
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
||||
cmd.append('-g')
|
||||
cmd.append(self.group)
|
||||
|
||||
if self.groups is not None:
|
||||
groups = self.get_groups_set()
|
||||
if len(groups) > 16:
|
||||
self.module.fail_json(msg="Too many groups (%d) NetBSD allows for 16 max." % len(groups))
|
||||
cmd.append('-G')
|
||||
cmd.append(','.join(groups))
|
||||
|
||||
if self.comment is not None:
|
||||
cmd.append('-c')
|
||||
cmd.append(self.comment)
|
||||
|
||||
if self.home is not None:
|
||||
cmd.append('-d')
|
||||
cmd.append(self.home)
|
||||
|
||||
if self.shell is not None:
|
||||
cmd.append('-s')
|
||||
cmd.append(self.shell)
|
||||
|
||||
if self.login_class is not None:
|
||||
cmd.append('-L')
|
||||
cmd.append(self.login_class)
|
||||
|
||||
if self.password is not None:
|
||||
cmd.append('-p')
|
||||
cmd.append(self.password)
|
||||
|
||||
if self.createhome:
|
||||
cmd.append('-m')
|
||||
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def remove_user_userdel(self):
|
||||
cmd = [self.module.get_bin_path('userdel', True)]
|
||||
if self.remove:
|
||||
cmd.append('-r')
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
def modify_user(self):
|
||||
cmd = [self.module.get_bin_path('usermod', True)]
|
||||
info = self.user_info()
|
||||
|
||||
if self.uid is not None and info[2] != int(self.uid):
|
||||
cmd.append('-u')
|
||||
cmd.append(self.uid)
|
||||
|
||||
if self.non_unique:
|
||||
cmd.append('-o')
|
||||
|
||||
if self.group is not None:
|
||||
if not self.group_exists(self.group):
|
||||
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
||||
ginfo = self.group_info(self.group)
|
||||
if info[3] != ginfo[2]:
|
||||
cmd.append('-g')
|
||||
cmd.append(self.group)
|
||||
|
||||
if self.groups is not None:
|
||||
current_groups = self.user_group_membership()
|
||||
groups_need_mod = False
|
||||
groups = []
|
||||
|
||||
if self.groups == '':
|
||||
if current_groups and not self.append:
|
||||
groups_need_mod = True
|
||||
else:
|
||||
groups = self.get_groups_set()
|
||||
group_diff = set(current_groups).symmetric_difference(groups)
|
||||
|
||||
if group_diff:
|
||||
if self.append:
|
||||
for g in groups:
|
||||
if g in group_diff:
|
||||
groups = set(current_groups).union(groups)
|
||||
groups_need_mod = True
|
||||
break
|
||||
else:
|
||||
groups_need_mod = True
|
||||
|
||||
if groups_need_mod:
|
||||
if len(groups) > 16:
|
||||
self.module.fail_json(msg="Too many groups (%d) NetBSD allows for 16 max." % len(groups))
|
||||
cmd.append('-G')
|
||||
cmd.append(','.join(groups))
|
||||
|
||||
if self.comment is not None and info[4] != self.comment:
|
||||
cmd.append('-c')
|
||||
cmd.append(self.comment)
|
||||
|
||||
if self.home is not None and info[5] != self.home:
|
||||
cmd.append('-d')
|
||||
cmd.append(self.home)
|
||||
|
||||
if self.shell is not None and info[6] != self.shell:
|
||||
cmd.append('-s')
|
||||
cmd.append(self.shell)
|
||||
|
||||
if self.login_class is not None:
|
||||
cmd.append('-L')
|
||||
cmd.append(self.login_class)
|
||||
|
||||
if self.password is not None and info[1] != self.password:
|
||||
cmd.append('-p')
|
||||
cmd.append(self.password)
|
||||
|
||||
# skip if no changes to be made
|
||||
if len(cmd) == 1:
|
||||
return (None, '', '')
|
||||
elif self.module.check_mode:
|
||||
return (0, '', '')
|
||||
|
||||
cmd.append(self.name)
|
||||
return self.execute_command(cmd)
|
||||
|
||||
|
||||
# ===========================================
|
||||
|
||||
class SunOS(User):
|
||||
"""
|
||||
This is a SunOS User manipulation class - The main difference between
|
||||
|
@ -1024,6 +1339,7 @@ def main():
|
|||
home=dict(default=None, type='str'),
|
||||
shell=dict(default=None, type='str'),
|
||||
password=dict(default=None, type='str'),
|
||||
login_class=dict(default=None, type='str'),
|
||||
# following options are specific to userdel
|
||||
force=dict(default='no', type='bool'),
|
||||
remove=dict(default='no', type='bool'),
|
||||
|
|
|
@ -293,13 +293,15 @@ class TestInventory(unittest.TestCase):
|
|||
'inventory_hostname_short': 'zeus',
|
||||
'group_names': ['greek', 'major-god']}
|
||||
|
||||
def test_dir_inventory(self):
|
||||
inventory = self.dir_inventory()
|
||||
vars = inventory.get_variables('zeus')
|
||||
|
||||
print "VARS=%s" % vars
|
||||
|
||||
assert vars == {'inventory_hostname': 'zeus',
|
||||
'inventory_hostname_short': 'zeus',
|
||||
'group_names': ['greek', 'major-god', 'ungrouped'],
|
||||
'var_a': '1#2'}
|
||||
# test disabled as needs to be updated to model desired behavior
|
||||
#
|
||||
#def test_dir_inventory(self):
|
||||
# inventory = self.dir_inventory()
|
||||
# vars = inventory.get_variables('zeus')
|
||||
#
|
||||
# print "VARS=%s" % vars
|
||||
#
|
||||
# assert vars == {'inventory_hostname': 'zeus',
|
||||
# 'inventory_hostname_short': 'zeus',
|
||||
# 'group_names': ['greek', 'major-god', 'ungrouped'],
|
||||
# 'var_a': '1#2'}
|
||||
|
|
Loading…
Reference in a new issue