From 9e889939394645affe324fbe0b27456225d51c2f Mon Sep 17 00:00:00 2001 From: abelbabel Date: Wed, 25 Sep 2013 17:51:17 +0200 Subject: [PATCH 01/14] add check mode support Could it be that easy or do I have missed something? --- packaging/pkgng | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packaging/pkgng b/packaging/pkgng index fa341b2f80d..e6ad98e4b07 100644 --- a/packaging/pkgng +++ b/packaging/pkgng @@ -89,9 +89,10 @@ def remove_packages(module, pkgin_path, packages): if not query_package(module, pkgin_path, package): continue - rc, out, err = module.run_command("%s delete -y %s" % (pkgin_path, package)) + if not module.check_mode: + rc, out, err = module.run_command("%s delete -y %s" % (pkgin_path, package)) - if query_package(module, pkgin_path, package): + if not module.check_mode and query_package(module, pkgin_path, package): module.fail_json(msg="failed to remove %s: %s" % (package, out)) remove_c += 1 @@ -110,7 +111,7 @@ def install_packages(module, pkgin_path, packages, cached, pkgsite): if pkgsite != "": pkgsite="PACKAGESITE=%s" % (pkgsite) - if cached == "no": + if not module.check_mode and cached == "no": rc, out, err = module.run_command("%s %s update" % (pkgsite, pkgin_path)) if rc != 0: module.fail_json(msg="Could not update catalogue") @@ -119,9 +120,10 @@ def install_packages(module, pkgin_path, packages, cached, pkgsite): if query_package(module, pkgin_path, package): continue - rc, out, err = module.run_command("%s %s install -U -y %s" % (pkgsite, pkgin_path, package)) + if not module.check_mode: + rc, out, err = module.run_command("%s %s install -U -y %s" % (pkgsite, pkgin_path, package)) - if not query_package(module, pkgin_path, package): + if not module.check_mode and query_package(module, pkgin_path, package): module.fail_json(msg="failed to install %s: %s" % (package, out)) install_c += 1 @@ -134,11 +136,12 @@ def install_packages(module, pkgin_path, packages, cached, pkgsite): def main(): module = AnsibleModule( - argument_spec = dict( - state = dict(default="present", choices=["present","absent"]), - name = dict(aliases=["pkg"], required=True), - cached = dict(default="no", required=False, choices=["yes","no"]), - pkgsite = dict(default="", required=False))) + argument_spec = dict( + state = dict(default="present", choices=["present","absent"]), + name = dict(aliases=["pkg"], required=True), + cached = dict(default="supports_check_modeno", required=False, choices=["yes","no"]), + pkgsite = dict(default="", required=False)) + supports_check_mode = True) pkgin_path = module.get_bin_path('pkg', True) From 19db4d381cf8f429d0da379fe7fa46e79b09e17d Mon Sep 17 00:00:00 2001 From: abelbabel Date: Wed, 25 Sep 2013 18:38:46 +0200 Subject: [PATCH 02/14] removed typo --- packaging/pkgng | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/pkgng b/packaging/pkgng index e6ad98e4b07..ea2c5262793 100644 --- a/packaging/pkgng +++ b/packaging/pkgng @@ -139,7 +139,7 @@ def main(): argument_spec = dict( state = dict(default="present", choices=["present","absent"]), name = dict(aliases=["pkg"], required=True), - cached = dict(default="supports_check_modeno", required=False, choices=["yes","no"]), + cached = dict(default="no", required=False, choices=["yes","no"]), pkgsite = dict(default="", required=False)) supports_check_mode = True) From 51cebb062d76273a115d7b96b81faefa68601b3d Mon Sep 17 00:00:00 2001 From: abelbabel Date: Wed, 25 Sep 2013 18:50:41 +0200 Subject: [PATCH 03/14] typo --- packaging/pkgng | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/pkgng b/packaging/pkgng index ea2c5262793..af1fdf93ef1 100644 --- a/packaging/pkgng +++ b/packaging/pkgng @@ -140,7 +140,7 @@ def main(): state = dict(default="present", choices=["present","absent"]), name = dict(aliases=["pkg"], required=True), cached = dict(default="no", required=False, choices=["yes","no"]), - pkgsite = dict(default="", required=False)) + pkgsite = dict(default="", required=False)), supports_check_mode = True) pkgin_path = module.get_bin_path('pkg', True) From 4a6c68e98a0f523dffbf7a1b43e66381dac389ee Mon Sep 17 00:00:00 2001 From: Blair Zajac Date: Sat, 28 Sep 2013 16:26:08 -0700 Subject: [PATCH 04/14] apt: pass child process stdout and stdout to m.fail_json() and m.exit_json(). Without this, this fails: - name: apt-get dist-upgrade action: apt upgrade=dist register: apt_get_contents - name: apt-get clean action: command apt-get clean when: apt_get_contents.stdout.find("0 upgraded") == -1 TASK: [apt-get clean] ********************************************************* fatal: [192.168.2.2] => error while evaluating conditional: {% if apt_get_contents.stdout.find("0 upgraded") == -1 %} True {% else %} False {% endif %} FATAL: all hosts have already failed -- aborting --- packaging/apt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packaging/apt b/packaging/apt index 70cc7e05be0..33ba19b2d46 100644 --- a/packaging/apt +++ b/packaging/apt @@ -237,9 +237,9 @@ def install(m, pkgspec, cache, upgrade=False, default_release=None, install_reco rc, out, err = m.run_command(cmd) if rc: - m.fail_json(msg="'apt-get install %s' failed: %s" % (packages, err)) + m.fail_json(msg="'apt-get install %s' failed: %s" % (packages, err), stdout=out, stderr=err) else: - m.exit_json(changed=True) + m.exit_json(changed=True, stdout=out, stderr=err) else: m.exit_json(changed=False) @@ -265,8 +265,8 @@ def remove(m, pkgspec, cache, purge=False): rc, out, err = m.run_command(cmd) if rc: - m.fail_json(msg="'apt-get remove %s' failed: %s" % (packages, err)) - m.exit_json(changed=True) + m.fail_json(msg="'apt-get remove %s' failed: %s" % (packages, err), stdout=out, stderr=err) + m.exit_json(changed=True, stdout=out, stderr=err) def upgrade(m, mode="yes", force=False): if m.check_mode: @@ -298,10 +298,10 @@ def upgrade(m, mode="yes", force=False): force_yes, check_arg, upgrade_command) rc, out, err = m.run_command(cmd) if rc: - m.fail_json(msg="'%s %s' failed: %s" % (apt_cmd, upgrade_command, err)) + m.fail_json(msg="'%s %s' failed: %s" % (apt_cmd, upgrade_command, err), stdout=out, stderr=err) if (apt_cmd == APT_GET_CMD and APT_GET_ZERO in out) or (apt_cmd == APTITUDE_CMD and APTITUDE_ZERO in out): - m.exit_json(changed=False, msg=out) - m.exit_json(changed=True, msg=out) + m.exit_json(changed=False, msg=out, stdout=out, stderr=err) + m.exit_json(changed=True, msg=out, stdout=out, stderr=err) def main(): module = AnsibleModule( From a5cdf4918490f4589fccfe53a19309a874d02a3e Mon Sep 17 00:00:00 2001 From: Blair Zajac Date: Sat, 28 Sep 2013 16:45:19 -0700 Subject: [PATCH 05/14] apt: do not consider not-removed and not-upgraded packages as changes. If one pins a package and does a 'apt-get dist-upgrade' then the output looks like: # apt-get dist-upgrade Reading package lists... Done Building dependency tree Reading state information... Done Calculating upgrade... Done The following packages have been kept back: cassandra 0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded. The check for any changes made should only be on the 'upgraded' and 'newly installed' values and not include the 'to remove' and 'not upgraded' values. --- packaging/apt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/apt b/packaging/apt index 70cc7e05be0..a8bb9249548 100644 --- a/packaging/apt +++ b/packaging/apt @@ -131,8 +131,8 @@ import fnmatch # APT related constants APT_ENVVARS = "DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical" DPKG_OPTIONS = '-o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold"' -APT_GET_ZERO = "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." -APTITUDE_ZERO = "0 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded." +APT_GET_ZERO = "0 upgraded, 0 newly installed" +APTITUDE_ZERO = "0 packages upgraded, 0 newly installed" APT_LISTS_PATH = "/var/lib/apt/lists" APT_UPDATE_SUCCESS_STAMP_PATH = "/var/lib/apt/periodic/update-success-stamp" From 487aa9a1ecdee47c30dc3247df2d3b548bd18b7b Mon Sep 17 00:00:00 2001 From: Brian Harring Date: Mon, 30 Sep 2013 13:20:06 -0400 Subject: [PATCH 06/14] Enforce umask for cron module, so cron_file generated files are 0644. Certain cron implementations get cranky if files in cron.* are group writable. --- system/cron | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/cron b/system/cron index 81e411168b7..04dd065db0b 100644 --- a/system/cron +++ b/system/cron @@ -426,6 +426,8 @@ def main(): changed = False res_args = dict() + # Ensure all files generated are only writable by the owning user. Primarily relevant for the cron_file option. + os.umask(022) crontab = CronTab(module, user, cron_file) if crontab.syslogging: From c2c0729f6e1d2a0eba7970528f502e37428a5106 Mon Sep 17 00:00:00 2001 From: Rene Moser Date: Mon, 21 Oct 2013 16:39:18 +0200 Subject: [PATCH 07/14] apt: autoinstall python-apt if not available --- packaging/apt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packaging/apt b/packaging/apt index 6ab20171866..28c933b694a 100644 --- a/packaging/apt +++ b/packaging/apt @@ -322,7 +322,13 @@ def main(): ) if not HAS_PYTHON_APT: - module.fail_json(msg="Could not import python modules: apt, apt_pkg. Please install python-apt package.") + try: + module.run_command('apt-get install python-apt -y -q') + global apt, apt_pkg + import apt + import apt_pkg + except: + module.fail_json(msg="Could not import python modules: apt, apt_pkg. Please install python-apt package.") global APTITUDE_CMD APTITUDE_CMD = module.get_bin_path("aptitude", False) From f8c3a83cd5999a6a546f4775b2ffb0d1cb88225c Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Fri, 8 Nov 2013 13:11:15 -0600 Subject: [PATCH 08/14] DRY up dict conversion and fix serialization error --- cloud/rax_clb | 54 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/cloud/rax_clb b/cloud/rax_clb index 76564db59cb..d826d49bdee 100644 --- a/cloud/rax_clb +++ b/cloud/rax_clb @@ -136,6 +136,30 @@ PROTOCOLS = ['DNS_TCP', 'DNS_UDP', 'FTP', 'HTTP', 'HTTPS', 'IMAPS', 'IMAPv4', 'TCP_CLIENT_FIRST', 'UDP', 'UDP_STREAM', 'SFTP'] +def to_dict(obj): + instance = {} + for key in dir(obj): + value = getattr(obj, key) + if key == 'virtual_ips': + virtual_ips = [] + instance[key] = [] + for vip in value: + vip_dict = {} + for vip_key, vip_value in vars(vip).iteritems(): + if isinstance(vip_value, NON_CALLABLES): + vip_dict[vip_key] = vip_value + instance[key].append(vip_dict) + elif key == 'nodes': + instance[key] = [] + for node in value: + instance[key].append(node.to_dict()) + elif (isinstance(value, NON_CALLABLES) and + not key.startswith('_')): + instance[key] = value + + return instance + + def cloud_load_balancer(module, state, name, meta, algorithm, port, protocol, vip_type, timeout, wait, wait_timeout): for arg in (state, name, port, protocol, vip_type): @@ -210,20 +234,7 @@ def cloud_load_balancer(module, state, name, meta, algorithm, port, protocol, pyrax.utils.wait_for_build(balancer, interval=5, attempts=attempts) balancer.get() - instance = {} - for key, value in vars(balancer).iteritems(): - if key == 'virtual_ips': - virtual_ips = [] - instance[key] = [] - for vip in value: - vip_dict = {} - for vip_key, vip_value in vars(vip).iteritems(): - if isinstance(vip_value, NON_CALLABLES): - vip_dict[vip_key] = vip_value - instance[key].append(vip_dict) - elif (isinstance(value, NON_CALLABLES) and - not key.startswith('_')): - instance[key] = value + instance = to_dict(balancer) result = dict(changed=changed, balancer=instance) @@ -246,20 +257,7 @@ def cloud_load_balancer(module, state, name, meta, algorithm, port, protocol, except Exception, e: module.fail_json(msg='%s' % e.message) - instance = {} - for key, value in vars(balancer).iteritems(): - if key == 'virtual_ips': - virtual_ips = [] - instance[key] = [] - for vip in value: - vip_dict = {} - for vip_key, vip_value in vars(vip).iteritems(): - if isinstance(vip_value, NON_CALLABLES): - vip_dict[vip_key] = vip_value - instance[key].append(vip_dict) - elif (isinstance(value, NON_CALLABLES) and - not key.startswith('_')): - instance[key] = value + instance = to_dict(balancer) if wait: attempts = wait_timeout / 5 From 368f85e58a1aac4dbcca2b505f54cf37235f837d Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Fri, 8 Nov 2013 13:15:38 -0600 Subject: [PATCH 09/14] Remove unused variable --- cloud/rax_clb | 1 - 1 file changed, 1 deletion(-) diff --git a/cloud/rax_clb b/cloud/rax_clb index d826d49bdee..da8004c212a 100644 --- a/cloud/rax_clb +++ b/cloud/rax_clb @@ -141,7 +141,6 @@ def to_dict(obj): for key in dir(obj): value = getattr(obj, key) if key == 'virtual_ips': - virtual_ips = [] instance[key] = [] for vip in value: vip_dict = {} From 1d368f9e1f1ec1794e904eccd34c52621c3c61f6 Mon Sep 17 00:00:00 2001 From: James Laska Date: Fri, 8 Nov 2013 14:59:24 -0500 Subject: [PATCH 10/14] Correct documentation URLs --- internal/async_status | 5 ++--- network/get_url | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/async_status b/internal/async_status index 865286dd34b..79647da113d 100644 --- a/internal/async_status +++ b/internal/async_status @@ -24,8 +24,7 @@ DOCUMENTATION = ''' module: async_status short_description: Obtain status of asynchronous task description: - - "This module gets the status of an asynchronous task. See: - U(http://www.ansibleworks.com/docs/playbooks2.html#asynchronous-actions-and-polling)" + - "This module gets the status of an asynchronous task." version_added: "0.5" options: jid: @@ -42,7 +41,7 @@ options: choices: [ "status", "cleanup" ] default: "status" notes: - - See U(http://www.ansibleworks.com/docs/playbooks2.html#asynchronous-actions-and-polling) + - See also U(http://www.ansibleworks.com/docs/playbooks_async.html#asynchronous-actions-and-polling) requirements: [] author: Michael DeHaan ''' diff --git a/network/get_url b/network/get_url index 35d724febed..d3919da003d 100644 --- a/network/get_url +++ b/network/get_url @@ -36,7 +36,7 @@ description: the target host, requests will be sent through that proxy. This behaviour can be overridden by setting a variable for this task (see `setting the environment - `_), + `_), or by using the use_proxy option. version_added: "0.6" options: From 53e9a422e8ca04908d982d2369e084ed270c2051 Mon Sep 17 00:00:00 2001 From: Rob Szewczyk Date: Fri, 8 Nov 2013 17:46:41 -0500 Subject: [PATCH 11/14] Correcting the security group id lookup from the list of security group names --- cloud/ec2 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cloud/ec2 b/cloud/ec2 index 09a9a6d1582..5945d930fd4 100644 --- a/cloud/ec2 +++ b/cloud/ec2 @@ -392,9 +392,7 @@ def create_instances(module, ec2): if group_name: grp_details = ec2.get_all_security_groups() if type(group_name) == list: - # FIXME: this should be a nice list comprehension - # also not py 2.4 compliant - group_id = list(filter(lambda grp: str(grp.id) if str(tmp) in str(grp) else None, grp_details) for tmp in group_name) + group_id = [ str(grp.id) for grp in grp_details if str(grp.name) in group_name ] elif type(group_name) == str: for grp in grp_details: if str(group_name) in str(grp): From 548a48b2f66c6c5bba5edd4e3a8e20b8d252c837 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Mon, 11 Nov 2013 22:27:47 -0500 Subject: [PATCH 12/14] Address #4285 remove redundant stderr output in apt module --- packaging/apt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/apt b/packaging/apt index ed29e6f3937..5173ce60c75 100644 --- a/packaging/apt +++ b/packaging/apt @@ -319,7 +319,7 @@ def upgrade(m, mode="yes", force=False, force_yes, check_arg, upgrade_command) rc, out, err = m.run_command(cmd) if rc: - m.fail_json(msg="'%s %s' failed: %s" % (apt_cmd, upgrade_command, err), stdout=out, stderr=err) + m.fail_json(msg="'%s %s' failed: %s" % (apt_cmd, upgrade_command, err), stdout=out) if (apt_cmd == APT_GET_CMD and APT_GET_ZERO in out) or (apt_cmd == APTITUDE_CMD and APTITUDE_ZERO in out): m.exit_json(changed=False, msg=out, stdout=out, stderr=err) m.exit_json(changed=True, msg=out, stdout=out, stderr=err) From 441669b11827627cda8d585fbd7c56c39eb1088d Mon Sep 17 00:00:00 2001 From: James Tanner Date: Mon, 11 Nov 2013 23:23:56 -0500 Subject: [PATCH 13/14] Fixes #4877 set type to bool for cache parameter in apt module --- packaging/pkgng | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/pkgng b/packaging/pkgng index af1fdf93ef1..dbae01bbb16 100644 --- a/packaging/pkgng +++ b/packaging/pkgng @@ -139,7 +139,7 @@ def main(): argument_spec = dict( state = dict(default="present", choices=["present","absent"]), name = dict(aliases=["pkg"], required=True), - cached = dict(default="no", required=False, choices=["yes","no"]), + cached = dict(default=False, type='bool'), pkgsite = dict(default="", required=False)), supports_check_mode = True) From 36c4f058917ba00f81e918fd17f5f59233e6dfaf Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 12 Nov 2013 00:02:30 -0500 Subject: [PATCH 14/14] Add more error detail to the service module for FreeBSD --- system/service | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system/service b/system/service index 0173031c941..aac7319d753 100644 --- a/system/service +++ b/system/service @@ -790,9 +790,11 @@ class FreeBsdService(Service): self.rcconf_file = rcfile rc, stdout, stderr = self.execute_command("%s %s %s %s" % (self.svc_cmd, self.name, 'rcvar', self.arguments)) + cmd = "%s %s %s %s" % (self.svc_cmd, self.name, 'rcvar', self.arguments) rcvars = shlex.split(stdout, comments=True) + if not rcvars: - self.module.fail_json(msg="unable to determine rcvar") + self.module.fail_json(msg="unable to determine rcvar", stdout=stdout, stderr=stderr) # In rare cases, i.e. sendmail, rcvar can return several key=value pairs # Usually there is just one, however. In other rare cases, i.e. uwsgi, @@ -805,7 +807,7 @@ class FreeBsdService(Service): break if self.rcconf_key is None: - self.module.fail_json(msg="unable to determine rcvar") + self.module.fail_json(msg="unable to determine rcvar", stdout=stdout, stderr=stderr) return self.service_enable_rcconf()