From 617093efa74821c9f7953ad586884090960a9f34 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 19 Jun 2018 10:42:22 -0400 Subject: [PATCH] Add upgrade ('latest') support to pkgng module (#41623) * Add upgrade ('latest') support to pkgng module * fixup for bad yaml * fixup for bcoca review: - add `version_added:` to description - change examples to use `name:` and remove comments - DRY out install_packages() - clean up state conditional check in modules.params * fixup to remove extra whitespace * fixup to handle custom pkgsite when checking for updates * fixup to remove misleading `version_added:` --- lib/ansible/modules/packaging/os/pkgng.py | 66 +++++++++++++++++------ 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/lib/ansible/modules/packaging/os/pkgng.py b/lib/ansible/modules/packaging/os/pkgng.py index 9d90c06954..d68967ca4d 100644 --- a/lib/ansible/modules/packaging/os/pkgng.py +++ b/lib/ansible/modules/packaging/os/pkgng.py @@ -33,7 +33,8 @@ options: state: description: - State of the package. - choices: [ 'present', 'absent' ] + - 'Note: "latest" added in 2.7' + choices: [ 'present', 'latest', 'absent' ] required: false default: present cached: @@ -91,20 +92,26 @@ notes: ''' EXAMPLES = ''' -# Install package foo -- pkgng: +- name: Install package foo + pkgng: name: foo state: present -# Annotate package foo and bar -- pkgng: +- name: Annotate package foo and bar + pkgng: name: foo,bar annotation: '+test1=baz,-test2,:test3=foobar' -# Remove packages foo and bar -- pkgng: +- name: Remove packages foo and bar + pkgng: name: foo,bar state: absent + +# "latest" support added in 2.7 +- name: Upgrade package baz + pkgng: + name: baz + state: latest ''' @@ -122,6 +129,22 @@ def query_package(module, pkgng_path, name, dir_arg): return False +def query_update(module, pkgng_path, name, dir_arg, old_pkgng, pkgsite): + + # Check to see if a package upgrade is available. + # rc = 0, no updates available or package not installed + # rc = 1, updates available + if old_pkgng: + rc, out, err = module.run_command("%s %s upgrade -g -n %s" % (pkgsite, pkgng_path, name)) + else: + rc, out, err = module.run_command("%s %s upgrade %s -g -n %s" % (pkgng_path, dir_arg, pkgsite, name)) + + if rc == 1: + return True + + return False + + def pkgng_older_than(module, pkgng_path, compare_version): rc, out, err = module.run_command("%s -v" % pkgng_path) @@ -163,7 +186,7 @@ def remove_packages(module, pkgng_path, packages, dir_arg): return (False, "package(s) already absent") -def install_packages(module, pkgng_path, packages, cached, pkgsite, dir_arg): +def install_packages(module, pkgng_path, packages, cached, pkgsite, dir_arg, state): install_c = 0 @@ -189,24 +212,33 @@ def install_packages(module, pkgng_path, packages, cached, pkgsite, dir_arg): module.fail_json(msg="Could not update catalogue") for package in packages: - if query_package(module, pkgng_path, package, dir_arg): + already_installed = query_package(module, pkgng_path, package, dir_arg) + if already_installed and state == "present": + continue + + update_available = query_update(module, pkgng_path, package, dir_arg, old_pkgng, pkgsite) + if not update_available and already_installed and state == "latest": continue if not module.check_mode: - if old_pkgng: - rc, out, err = module.run_command("%s %s %s install -g -U -y %s" % (batch_var, pkgsite, pkgng_path, package)) + if already_installed: + action = "upgrade" else: - rc, out, err = module.run_command("%s %s %s install %s -g -U -y %s" % (batch_var, pkgng_path, dir_arg, pkgsite, package)) + action = "install" + if old_pkgng: + rc, out, err = module.run_command("%s %s %s %s -g -U -y %s" % (batch_var, pkgsite, pkgng_path, action, package)) + else: + rc, out, err = module.run_command("%s %s %s %s %s -g -U -y %s" % (batch_var, pkgng_path, dir_arg, action, pkgsite, package)) if not module.check_mode and not query_package(module, pkgng_path, package, dir_arg): - module.fail_json(msg="failed to install %s: %s" % (package, out), stderr=err) + module.fail_json(msg="failed to %s %s: %s" % (action, package, out), stderr=err) install_c += 1 if install_c > 0: return (True, "added %s package(s)" % (install_c)) - return (False, "package(s) already present") + return (False, "package(s) already %s" % (state)) def annotation_query(module, pkgng_path, package, tag, dir_arg): @@ -312,7 +344,7 @@ def autoremove_packages(module, pkgng_path, dir_arg): def main(): module = AnsibleModule( argument_spec=dict( - state=dict(default="present", choices=["present", "absent"], required=False), + state=dict(default="present", choices=["present", "latest", "absent"], required=False), name=dict(aliases=["pkg"], required=True, type='list'), cached=dict(default=False, type='bool'), annotation=dict(default="", required=False), @@ -347,8 +379,8 @@ def main(): if p["jail"] != "": dir_arg = '--jail %s' % (p["jail"]) - if p["state"] == "present": - _changed, _msg = install_packages(module, pkgng_path, pkgs, p["cached"], p["pkgsite"], dir_arg) + if p["state"] in ("present", "latest"): + _changed, _msg = install_packages(module, pkgng_path, pkgs, p["cached"], p["pkgsite"], dir_arg, p["state"]) changed = changed or _changed msgs.append(_msg)