2 # -*- coding: utf-8 -*-
4 # Copyright: (c) 2019, Marcin Krol <hawk@tld-linux.org>
5 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7 from __future__ import absolute_import, division, print_function
10 ANSIBLE_METADATA = {'metadata_version': '1.0',
11 'status': ['preview'],
12 'supported_by': 'community'}
17 short_description: Manage packages with I(poldek)
19 - Manage packages with the I(poldek) package manager, which is used by TLD Linux and PLD Linux
22 - Marcin Krol <hawk@tld-linux.org>
26 - Name or list of names of the package(s) or file(s) to install, upgrade, or remove.
27 Can't be used in combination with C(upgrade).
28 aliases: [ package, pkg ]
32 - Desired state of the package.
34 choices: [ absent, latest, present ]
38 - Additional option to pass to poldek when enforcing C(state).
43 - Whether or not to refresh the master package lists.
44 - This can be run as part of a package installation or as a separate step.
47 aliases: [ update-cache ]
49 update_cache_extra_args:
51 - Additional option to pass to poldek when enforcing C(update_cache).
56 - Whether or not to upgrade the whole system.
57 Can't be used in combination with C(name).
63 - Additional option to pass to poldek when enforcing C(upgrade).
69 description: a list of packages that have been changed
70 returned: when upgrade is set to yes
72 sample: [ package, other-package ]
76 - name: Install packages foo and bar
83 - name: Update package cache and upgrade package foo
89 - name: Remove packages foo and bar
96 - name: Update package cache only
100 - name: Update package cache and upgrade all packages
108 from ansible.module_utils.basic import AnsibleModule
111 def query_package(module, poldek_path, name):
112 """Query the package status in both the local system and the repository. Returns a boolean to indicate if the package is installed, a second
113 boolean to indicate if the package is up-to-date. Note: indexes must be up to date to ensure that poldek knows latest version of package.
115 lcmd = "%s -q --shcmd='ls -n --installed %s'" % (poldek_path, name)
116 lrc, lstdout, lstderr = module.run_command(lcmd, check_rc=False)
117 rcmd = "%s -q --shcmd='ls -n --installed --upgradeable %s'" % (poldek_path, name)
118 rrc, rstdout, rstderr = module.run_command(rcmd, check_rc=False)
119 if lrc != 0 or rrc != 0:
129 def update_package_db(module, poldek_path):
130 if module.params['force']:
131 module.params["update_cache_extra_args"] += " --upa"
133 cmd = "%s --noask --up %s" % (poldek_path, module.params["update_cache_extra_args"])
134 rc, stdout, stderr = module.run_command(cmd, check_rc=False)
139 module.fail_json(msg="error updating package database")
142 def upgrade(module, poldek_path):
143 cmdupgrade = "%s -v --noask --upgrade-dist %s" % (poldek_path, module.params["upgrade_extra_args"])
144 cmdupgradeable = "%s -q --shcmd='ls --upgradeable --qf=\"%%{NAME}-%%{VERSION}-%%{RELEASE}\n\"' %s" % (poldek_path, module.params["upgrade_extra_args"])
145 rc, stdout, stderr = module.run_command(cmdupgradeable, check_rc=False)
147 packages = stdout.split('\n')[:-1]
149 module.exit_json(changed=False, msg='Nothing to upgrade', packages=packages, stdout=stdout, stderr=stderr, rc=rc)
151 if module.check_mode:
152 module.exit_json(changed=True, msg="%s package(s) would be upgraded" % (len(packages)), packages=packages, stdout=stdout, stderr=stderr, rc=rc)
153 rc, stdout, stderr = module.run_command(cmdupgrade, check_rc=False)
155 module.exit_json(changed=True, msg="%s package(s) upgraded" % (len(packages)), packages=packages, stdout=stdout, stderr=stderr, rc=rc)
157 module.fail_json(msg="Error while upgrading packages", stdout=stdout, stderr=stderr, rc=rc)
160 def remove_packages(module, poldek_path, packages):
161 if module.params["force"]:
162 module.params["extra_args"] += " --force --nodeps"
168 for package in packages:
169 installed, updated = query_package(module, poldek_path, package)
173 cmd = "%s -v --noask --erase %s %s" % (poldek_path, module.params["extra_args"], package)
174 rc, stdout, stderr = module.run_command(cmd, check_rc=False)
180 module.fail_json(msg="failed to remove %s" % (package), stdout=out, stderr=err, rc=rc)
185 module.exit_json(changed=True, msg="removed %s package(s)" % (remove_c), packages=packages, stdout=out, stderr=err, rc=0)
187 module.exit_json(changed=False, msg="package(s) already absent", packages=packages, stdout=out, stderr=err, rc=0)
190 def install_packages(module, poldek_path, state, packages):
191 if module.params["force"]:
192 module.params["extra_args"] += " --force --nodeps"
198 for package in packages:
199 installed, updated = query_package(module, poldek_path, package)
200 if installed and (state == 'present' or (state == 'latest' and updated)):
203 cmd = "%s -v --noask --upgrade %s %s" % (poldek_path, module.params["extra_args"], package)
204 rc, stdout, stderr = module.run_command(cmd, check_rc=False)
210 module.fail_json(msg="failed to install %s" % (package), stdout=out, stderr=err, rc=rc)
215 module.exit_json(changed=True, msg="installed %s package(s)" % (install_c), packages=packages, stdout=out, stderr=err, rc=0)
217 module.exit_json(changed=False, msg="package(s) already installed", packages=packages, stdout=out, stderr=err, rc=0)
220 def check_packages(module, poldek_path, packages, state):
221 would_be_changed = []
223 for package in packages:
224 installed, updated = query_package(module, poldek_path, package)
225 if ((state in ["present", "latest"] and not installed) or
226 (state == "absent" and installed) or
227 (state == "latest" and not updated)):
228 would_be_changed.append(package)
230 if state == "absent":
232 if state == "present" or state == "latest":
236 module.exit_json(changed=True, msg="%s package(s) would be %s" % (
237 len(would_be_changed), state))
239 module.exit_json(changed=False, msg="package(s) already %s" % state)
243 module = AnsibleModule(
245 name=dict(type='list', aliases=['pkg', 'package']),
246 state=dict(type='str', default='present', choices=['present', 'installed', 'latest', 'absent', 'removed']),
247 extra_args=dict(type='str', default=''),
248 upgrade=dict(type='bool', default=False),
249 upgrade_extra_args=dict(type='str', default=''),
250 update_cache=dict(type='bool', default=False, aliases=['update-cache']),
251 update_cache_extra_args=dict(type='str', default=''),
252 force=dict(type='bool', default=False),
254 required_one_of=[['name', 'update_cache', 'upgrade']],
255 mutually_exclusive=[['name', 'upgrade']],
256 supports_check_mode=True,
259 poldek_path = module.get_bin_path('poldek', True)
263 if p['state'] in ['present', 'installed']:
264 p['state'] = 'present'
265 elif p['state'] in ['absent', 'removed']:
266 p['state'] = 'absent'
268 if p["update_cache"] and not module.check_mode:
269 update_package_db(module, poldek_path)
270 if not (p['name'] or p['upgrade']):
271 module.exit_json(changed=True, msg='Updated package database')
273 if p['update_cache'] and module.check_mode and not (p['name'] or p['upgrade']):
274 module.exit_json(changed=True, msg='Would have updated package database')
277 upgrade(module, poldek_path)
282 if module.check_mode:
283 check_packages(module, poldek_path, pkgs, p['state'])
285 if p['state'] in ['present', 'latest']:
286 install_packages(module, poldek_path, p['state'], pkgs)
287 elif p['state'] == 'absent':
288 remove_packages(module, poldek_path, pkgs)
290 module.exit_json(changed=False, msg="No package specified to work on")
293 if __name__ == "__main__":