123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- #!/usr/bin/python2.7 -tt
- # -*- coding: utf-8 -*-
- def update_package_db(module, paths):
- cmd = "%s -S" % paths['install']
- rc, sout, serr = module.run_command(cmd, check_rc=False)
- if rc == 0:
- return True
- else:
- module.fail_json(msg="could not update package db", rc=rc, stdout=sout, stderr=serr)
- def query_package(module, paths, pkg):
- '''
- pkg: a package name
- returns: (installed, available, latest) as booleans
- '''
- query_local = '%s -S %s | grep "^pkgver: "' % (paths['query'], pkg)
- query_repo = '%s -RS %s | grep "^pkgver: "' % (paths['query'], pkg)
- # query local installed packages
- qlrc, qlsout, qlserr = module.run_command(query_local, use_unsafe_shell=True, check_rc=False)
- if qlrc == 0:
- # pkg installed
- installed = True
- else:
- installed = False
- # query repo conent
- qrrc, qrsout, qrserr = module.run_command(query_repo, use_unsafe_shell=True, check_rc=False)
- if qrrc == 0:
- # pkg available
- available = True
- else:
- available = False
- if qlsout == qrsout:
- # same pkgver
- latest = True
- else:
- latest = False
- #FIXME module.fail_json(msg='foo', ql=query_local, qlrc=qlrc, qlsout=qlsout, qlserr=qlserr, qr=query_repo, qrrc=qrrc, qrsout=qrsout, qrserr=qrserr)
- return (installed, available, latest)
- def get_changed_packages(module, paths, pkgs, desired_state):
- '''
- pkgs: list of packages
- desired_state: desired state (present, latest, absent)
- returns: list of packages to be changed
- '''
- to_be_changed = []
- for pkg in pkgs:
- (installed, available, latest) = query_package(module, paths, pkg)
- #FIXME module.fail_json(msg='foo', installed=installed, available=available, latest=latest)
- if desired_state == 'latest' and not latest:
- to_be_changed.append(pkg)
- elif desired_state == 'present' and not installed:
- to_be_changed.append(pkg)
- elif desired_state == 'absent' and installed:
- to_be_changed.append(pkg)
- return to_be_changed
- def check_packages(module, paths, pkgs, desired_state):
- '''
- pkgs: list of packages
- desired_state: desired state (present, latest, absent)
- retuns: n/a, exit module
- '''
- to_be_changed = get_changed_packages(module, paths, pkgs, desired_state)
- if to_be_changed:
- module.exit_json(changed=True, msg="%s package(s) not in state %s" % (
- len(to_be_changed), state))
- else:
- module.exit_json(changed=False, msg="package(s) already in state %s" % state)
- def upgrade(module, paths, check_mode):
- '''
- returns: (updates_available, updates_successful)
- '''
- # Check for updates
- cmd = "%s -un" % paths['install']
- rc, sout, serr = module.run_command(cmd, check_rc=False)
- if sout:
- # packages for upgrade available
- if check_mode:
- return (True, False)
- # do upgrade
- cmd = "%s -uy" % paths['install']
- rc, sout, serr = module.run_command(cmd, check_rc=False)
- if rc == 0:
- return (True, True)
- else:
- module.fail_json(msg="could not upgrade packages", rc=rc, stdout=sout, stderr=serr)
- else:
- return (False, False)
- def ensure_packages_state(module, paths, pkgs, desired_state):
- '''
- pkgs: list of packages
- desired_state: desired state (present, latest, absent)
- returns: list of packages to be changed
- '''
- # which packages must change state
- pkgs2do = get_changed_packages(module, paths, pkgs, desired_state)
- if not pkgs2do:
- module.exit_json(msg='All packages in desired state')
- if desired_state in ['present', 'latest']:
- cmdtype = 'install'
- elif desired_state == 'absent':
- cmdtype = 'remove'
- cmd = '%s -y %s' % (paths[cmdtype], ' '.join(pkgs2do))
- rc, sout, serr = module.run_command(cmd, check_rc=False)
- if rc == 0:
- msg = '%s package' % len(pkgs2do)
- msg += '%s ' % len(pkgs2do) == 1 and '' or 's'
- if cmdtype == 'install':
- msg += 'installed'
- elif cmdtype == 'remove':
- msg += 'removed'
- module.exit_json(msg=msg, rc=rc, stdout=sout, stderr=serr)
- else:
- module.fail_json(msg="could not install/remove package(s)", rc=rc, stdout=sout, stderr=serr)
- def main():
- module = AnsibleModule(
- argument_spec = dict(
- name = dict(aliases=['pkg', 'package'], type='list'),
- state = dict(default='present', choices=['present', 'installed', "latest", 'absent', 'removed']),
- force = dict(default=False, type='bool'),
- upgrade = dict(default=False, type='bool'),
- update_cache = dict(default=False, aliases=['update-cache'], type='bool')
- ),
- required_one_of = [['name', 'update_cache', 'upgrade']],
- supports_check_mode = True)
- paths = {}
- paths['install'] = module.get_bin_path('xbps-install', True)
- paths['remove'] = module.get_bin_path('xbps-remove', True)
- paths['query'] = module.get_bin_path('xbps-query', True)
- p = module.params
- # normalize the state parameter
- if p['state'] in ['present', 'installed']:
- p['state'] = 'present'
- elif p['state'] in ['absent', 'removed']:
- p['state'] = 'absent'
- # do update if package name is "*"
- if p['name'] and p['name'][0] == '*' and p['state'] == 'latest':
- p['update'] = True
- p['name'] = []
- # sync repo index
- if p["update_cache"] and not module.check_mode:
- update_package_db(module, paths) # FIXME
- if not (p['name'] or p['upgrade']):
- module.exit_json(changed=True, msg='Updated the package master lists')
- if p['update_cache'] and module.check_mode and not (p['name'] or p['upgrade']):
- module.exit_json(changed=True, msg='Would have updated the package cache')
- # update/upgrade all installed packages
- if p['upgrade']:
- (upg_avail, upg_successful) = upgrade(module, paths, module.check_mode)
- if not p['name']: # upgrade is last action
- if upg_avail:
- if upg_successful:
- module.exit_json(changed=True, msg="all packages upgraded")
- else:
- if module.check_mode:
- module.exit_json(msg="no packages upgraded in check mode")
- # should never happen, "upgrade" function should exit module
- module.fail_json(msg="could not upgrade packages", rc=rc, stdout=sout, stderr=serr)
- else:
- module.exit_json(msg="all packages uptodate")
- if p['name']:
- if module.check_mode:
- check_packages(module, paths, p['name'], p['state']) # FIXME
- ensure_packages_state(module, paths, p['name'], p['state']) # FIXME
- # import module snippets
- from ansible.module_utils.basic import *
- if __name__ == "__main__":
- main()
|