1 # -*- coding: utf-8 -*-
3 # Copyright: (c) 2019, Marcin Krol <hawk@tld-linux.org>
4 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
6 from __future__ import absolute_import, division, print_function
9 ANSIBLE_METADATA = {'metadata_version': '1.0',
10 'status': ['preview'],
11 'supported_by': 'community'}
16 short_description: Manage packages with I(poldek)
18 - Manage packages with the I(poldek) package manager, which is used by TLD Linux and PLD Linux
21 - Marcin Krol <hawk@tld-linux.org>
25 - Name or list of names of the package(s) or file(s) to install, upgrade, or remove.
26 Can't be used in combination with C(upgrade).
27 aliases: [ package, pkg ]
31 - Desired state of the package.
33 choices: [ absent, latest, present ]
37 - Additional option to pass to poldek when enforcing C(state).
42 - Whether or not to refresh the master package lists.
43 - This can be run as part of a package installation or as a separate step.
46 aliases: [ update-cache ]
48 update_cache_extra_args:
50 - Additional option to pass to poldek when enforcing C(update_cache).
55 - Whether or not to upgrade the whole system.
56 Can't be used in combination with C(name).
62 - Additional option to pass to poldek when enforcing C(upgrade).
68 description: a list of packages that have been changed
69 returned: when upgrade is set to yes
71 sample: [ package, other-package ]
75 - name: Install packages foo and bar
82 - name: Update package cache and upgrade package foo
88 - name: Remove packages foo and bar
95 - name: Update package cache only
99 - name: Update package cache and upgrade all packages
107 from ansible.module_utils.basic import AnsibleModule
110 def query_package(module, poldek_path, name):
111 """Query the package status in both the local system and the repository. Returns a boolean to indicate if the package is installed, a second
112 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.
114 lcmd = "%s -q --shcmd='ls -n --installed %s'" % (poldek_path, name)
115 lrc, lstdout, lstderr = module.run_command(lcmd, check_rc=False)
116 rcmd = "%s -q --shcmd='ls -n --installed --upgradeable %s'" % (poldek_path, name)
117 rrc, rstdout, rstderr = module.run_command(rcmd, check_rc=False)
118 if lrc != 0 or rrc != 0:
128 def update_package_db(module, poldek_path):
129 if module.params['force']:
130 module.params["update_cache_extra_args"] += " --upa"
132 cmd = "%s --noask --up %s" % (poldek_path, module.params["update_cache_extra_args"])
133 rc, stdout, stderr = module.run_command(cmd, check_rc=False)
138 module.fail_json(msg="error updating package database")
141 def upgrade(module, poldek_path):
142 cmdupgrade = "%s -v --noask --upgrade-dist %s" % (poldek_path, module.params["upgrade_extra_args"])
143 cmdupgradeable = "%s -q --shcmd='ls --upgradeable --qf=\"%%{NAME}-%%{VERSION}-%%{RELEASE}\n\"' %s" % (poldek_path, module.params["upgrade_extra_args"])
144 rc, stdout, stderr = module.run_command(cmdupgradeable, check_rc=False)
146 packages = stdout.split('\n')[:-1]
148 module.exit_json(changed=False, msg='Nothing to upgrade', packages=packages, stdout=stdout, stderr=stderr, rc=rc)
150 if module.check_mode:
151 module.exit_json(changed=True, msg="%s package(s) would be upgraded" % (len(packages)), packages=packages, stdout=stdout, stderr=stderr, rc=rc)
152 rc, stdout, stderr = module.run_command(cmdupgrade, check_rc=False)
154 module.exit_json(changed=True, msg="%s package(s) upgraded" % (len(packages)), packages=packages, stdout=stdout, stderr=stderr, rc=rc)
156 module.fail_json(msg="Error while upgrading packages", stdout=stdout, stderr=stderr, rc=rc)
159 def remove_packages(module, poldek_path, packages):
160 if module.params["force"]:
161 module.params["extra_args"] += " --force --nodeps"
167 for package in packages:
168 installed, updated = query_package(module, poldek_path, package)
172 cmd = "%s -v --noask --erase %s %s" % (poldek_path, module.params["extra_args"], package)
173 rc, stdout, stderr = module.run_command(cmd, check_rc=False)
179 module.fail_json(msg="failed to remove %s" % (package), stdout=out, stderr=err, rc=rc)
184 module.exit_json(changed=True, msg="removed %s package(s)" % (remove_c), packages=packages, stdout=out, stderr=err, rc=0)
186 module.exit_json(changed=False, msg="package(s) already absent", packages=packages, stdout=out, stderr=err, rc=0)
189 def install_packages(module, poldek_path, state, packages):
190 if module.params["force"]:
191 module.params["extra_args"] += " --force --nodeps"
197 for package in packages:
198 installed, updated = query_package(module, poldek_path, package)
199 if installed and (state == 'present' or (state == 'latest' and updated)):
202 cmd = "%s -v --noask --upgrade %s %s" % (poldek_path, module.params["extra_args"], package)
203 rc, stdout, stderr = module.run_command(cmd, check_rc=False)
209 module.fail_json(msg="failed to install %s" % (package), stdout=out, stderr=err, rc=rc)
214 module.exit_json(changed=True, msg="installed %s package(s)" % (install_c), packages=packages, stdout=out, stderr=err, rc=0)
216 module.exit_json(changed=False, msg="package(s) already installed", packages=packages, stdout=out, stderr=err, rc=0)
219 def check_packages(module, poldek_path, packages, state):
220 would_be_changed = []
222 for package in packages:
223 installed, updated = query_package(module, poldek_path, package)
224 if ((state in ["present", "latest"] and not installed) or
225 (state == "absent" and installed) or
226 (state == "latest" and not updated)):
227 would_be_changed.append(package)
229 if state == "absent":
231 if state == "present" or state == "latest":
235 module.exit_json(changed=True, msg="%s package(s) would be %s" % (
236 len(would_be_changed), state))
238 module.exit_json(changed=False, msg="package(s) already %s" % state)
242 module = AnsibleModule(
244 name=dict(type='list', aliases=['pkg', 'package']),
245 state=dict(type='str', default='present', choices=['present', 'installed', 'latest', 'absent', 'removed']),
246 extra_args=dict(type='str', default=''),
247 upgrade=dict(type='bool', default=False),
248 upgrade_extra_args=dict(type='str', default=''),
249 update_cache=dict(type='bool', default=False, aliases=['update-cache']),
250 update_cache_extra_args=dict(type='str', default=''),
251 force=dict(type='bool', default=False),
253 required_one_of=[['name', 'update_cache', 'upgrade']],
254 mutually_exclusive=[['name', 'upgrade']],
255 supports_check_mode=True,
258 poldek_path = module.get_bin_path('poldek', True)
262 if p['state'] in ['present', 'installed']:
263 p['state'] = 'present'
264 elif p['state'] in ['absent', 'removed']:
265 p['state'] = 'absent'
267 if p["update_cache"] and not module.check_mode:
268 update_package_db(module, poldek_path)
269 if not (p['name'] or p['upgrade']):
270 module.exit_json(changed=True, msg='Updated package database')
272 if p['update_cache'] and module.check_mode and not (p['name'] or p['upgrade']):
273 module.exit_json(changed=True, msg='Would have updated package database')
276 upgrade(module, poldek_path)
281 if module.check_mode:
282 check_packages(module, poldek_path, pkgs, p['state'])
284 if p['state'] in ['present', 'latest']:
285 install_packages(module, poldek_path, p['state'], pkgs)
286 elif p['state'] == 'absent':
287 remove_packages(module, poldek_path, pkgs)
289 module.exit_json(changed=False, msg="No package specified to work on")
292 if __name__ == "__main__":