2017-12-23 20:27:42 +03:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
from ansible.module_utils.basic import *
|
2017-12-31 20:12:28 +03:00
|
|
|
import json
|
Drop dependency on ansible (six.moves)
As it is, aur.py depends on ansible being installed on the target host.
So, you would need to get ansible installed in your target host just to be able
to make use of aur.py and install whatever packages you need.
Let's review the dependency:
from ansible.module_utils import six
from six.moves import urllib
I reckon that the six¹ package is there to isolate an ansible module's code from
the particular major version of python being used (2 or 3).
Fortunately, since last week², the ansible package in archlinux now depends
directly on python3, so I reckon that in this particular instance, we can safely
import urllib.request directly, which from now on will be spot on.
To recap, current arch ships python3, and the arch ansible package depends on it
to run. aur.py's purpose is to run on archlinux hosts, thus, python3 can be
safely assumed to be available. So we can depend directly on it and relax the
dependency on ansible itself.
On a personal note, I am using this nice module to help me bootstrap my arch
systems, so not having to install ansible just to be able to use it makes my day
a little better :-)
Thanks a bunch!
[Feel free to edit the commit log]
[1]: https://pythonhosted.org/six/
[2]: https://git.archlinux.org/svntogit/community.git/commit/trunk?h=packages/ansible&id=bb1a1cc822891387d5a8b3dad0d0ccdee94c0c51
2018-05-22 07:04:42 +03:00
|
|
|
import urllib.request
|
2017-12-31 20:12:28 +03:00
|
|
|
import tarfile
|
|
|
|
import os
|
|
|
|
import os.path
|
|
|
|
import tempfile
|
|
|
|
|
2018-04-14 13:53:14 +03:00
|
|
|
|
2018-03-17 11:15:06 +03:00
|
|
|
def_lang = ['env', 'LC_ALL=C']
|
|
|
|
|
2017-12-31 20:12:28 +03:00
|
|
|
use_cmd = {
|
2018-05-08 09:20:00 +03:00
|
|
|
'aurman': ['aurman', '-S', '--noconfirm', '--noedit', '--needed'],
|
|
|
|
'pacaur': ['pacaur', '-S', '--noconfirm', '--noedit', '--needed'],
|
|
|
|
'trizen': ['trizen', '-S', '--noconfirm', '--noedit', '--needed'],
|
2018-03-17 11:15:06 +03:00
|
|
|
'pikaur': ['pikaur', '-S', '--noconfirm', '--noedit', '--needed'],
|
|
|
|
'yaourt': ['yaourt', '-S', '--noconfirm', '--needed'],
|
|
|
|
'yay': ['yay', '-S', '--noconfirm'],
|
2018-05-16 22:06:06 +03:00
|
|
|
'makepkg': ['makepkg', '--syncdeps', '--install', '--noconfirm', '--needed']
|
2017-12-23 20:27:42 +03:00
|
|
|
}
|
2018-05-08 09:20:00 +03:00
|
|
|
# optional: aurman, pacaur, trizen have a --aur option, do things only for aur
|
2017-12-23 20:27:42 +03:00
|
|
|
|
|
|
|
|
2017-12-31 20:12:28 +03:00
|
|
|
def package_installed(module, package):
|
2018-05-16 22:30:58 +03:00
|
|
|
"""
|
|
|
|
Determine if the package is already installed
|
|
|
|
"""
|
2017-12-31 20:12:28 +03:00
|
|
|
rc, _, _ = module.run_command(['pacman', '-Q', package], check_rc=False)
|
|
|
|
return rc == 0
|
|
|
|
|
|
|
|
|
2018-05-16 21:39:57 +03:00
|
|
|
def check_packages(module, packages):
|
|
|
|
"""
|
|
|
|
Inform the user what would change if the module were run
|
|
|
|
"""
|
|
|
|
would_be_changed = []
|
|
|
|
|
|
|
|
for package in packages:
|
|
|
|
installed = package_installed(module, package)
|
|
|
|
if not installed:
|
|
|
|
would_be_changed.append(package)
|
|
|
|
|
|
|
|
if would_be_changed:
|
|
|
|
status = True
|
|
|
|
if (len(packages) > 1):
|
|
|
|
message = '%s package(s) would be installed' % str(len(would_be_changed))
|
|
|
|
else:
|
|
|
|
message = 'package would be installed'
|
|
|
|
else:
|
|
|
|
status = False
|
|
|
|
if (len(packages) > 1):
|
|
|
|
message = 'all packages are already installed'
|
|
|
|
else:
|
|
|
|
message = 'package is already installed'
|
|
|
|
module.exit_json(changed=status, msg=message)
|
|
|
|
|
2018-05-16 22:06:06 +03:00
|
|
|
|
|
|
|
def install_with_makepkg(module, package):
|
2018-05-16 22:30:58 +03:00
|
|
|
"""
|
|
|
|
Install the specified package with makepkg
|
|
|
|
"""
|
2017-12-31 20:12:28 +03:00
|
|
|
f = urllib.request.urlopen('https://aur.archlinux.org/rpc/?v=5&type=info&arg={}'.format(package))
|
|
|
|
result = json.loads(f.read().decode('utf8'))
|
|
|
|
if result['resultcount'] != 1:
|
|
|
|
return (1, '', 'package not found')
|
|
|
|
result = result['results'][0]
|
|
|
|
f = urllib.request.urlopen('https://aur.archlinux.org/{}'.format(result['URLPath']))
|
|
|
|
current_path = os.getcwd()
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
|
|
os.chdir(tmpdir)
|
|
|
|
tar_file = '{}.tar.gz'.format(result['Name'])
|
|
|
|
with open(tar_file, 'wb') as out:
|
|
|
|
out.write(f.read())
|
|
|
|
tar = tarfile.open(tar_file)
|
|
|
|
tar.extractall()
|
|
|
|
tar.close()
|
|
|
|
os.chdir(format(result['Name']))
|
2018-05-16 22:20:30 +03:00
|
|
|
if module.params['skip_pgp_check']:
|
|
|
|
use_cmd['makepkg'].append('--skippgpcheck')
|
2018-05-16 22:06:06 +03:00
|
|
|
rc, out, err = module.run_command(use_cmd['makepkg'], check_rc=True)
|
2017-12-31 20:12:28 +03:00
|
|
|
os.chdir(current_path)
|
|
|
|
return (rc, out, err)
|
2017-12-23 20:27:42 +03:00
|
|
|
|
|
|
|
|
2017-12-31 20:12:28 +03:00
|
|
|
def upgrade(module, use):
|
2018-05-16 22:30:58 +03:00
|
|
|
"""
|
|
|
|
Upgrade the whole system
|
|
|
|
"""
|
2017-12-31 20:12:28 +03:00
|
|
|
assert use in use_cmd
|
|
|
|
|
2018-03-17 11:15:06 +03:00
|
|
|
rc, out, err = module.run_command(def_lang + use_cmd[use] + ['-u'], check_rc=True)
|
2017-12-23 20:27:42 +03:00
|
|
|
|
|
|
|
module.exit_json(
|
2018-04-14 13:37:11 +03:00
|
|
|
changed=not (out == '' or 'nothing to do' in out or 'No AUR updates found' in out),
|
2017-12-23 20:27:42 +03:00
|
|
|
msg='upgraded system',
|
2018-05-16 22:29:17 +03:00
|
|
|
helper=use,
|
2017-12-23 20:27:42 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2017-12-31 20:12:28 +03:00
|
|
|
def install_packages(module, packages, use, skip_installed):
|
2018-05-16 22:30:58 +03:00
|
|
|
"""
|
|
|
|
Install the specified packages
|
|
|
|
"""
|
2017-12-31 20:12:28 +03:00
|
|
|
assert use in use_cmd
|
2017-12-23 20:27:42 +03:00
|
|
|
|
2017-12-23 23:05:07 +03:00
|
|
|
changed_iter = False
|
2017-12-23 20:27:42 +03:00
|
|
|
|
2017-12-31 20:12:28 +03:00
|
|
|
for package in packages:
|
|
|
|
if skip_installed:
|
|
|
|
if package_installed(module, package):
|
|
|
|
rc = 0
|
|
|
|
continue
|
2018-05-16 22:06:06 +03:00
|
|
|
if use == 'makepkg':
|
|
|
|
rc, out, err = install_with_makepkg(module, package)
|
2017-12-31 20:12:28 +03:00
|
|
|
else:
|
2018-03-17 11:15:06 +03:00
|
|
|
rc, out, err = module.run_command(def_lang + use_cmd[use] + [package], check_rc=True)
|
2018-05-16 22:29:17 +03:00
|
|
|
|
2018-04-14 13:37:11 +03:00
|
|
|
changed_iter = changed_iter or not (out == '' or '-- skipping' in out or 'nothing to do' in out)
|
2017-12-23 20:27:42 +03:00
|
|
|
|
2018-05-16 22:29:17 +03:00
|
|
|
if changed_iter:
|
|
|
|
message = 'installed package(s)'
|
|
|
|
else:
|
|
|
|
message = 'package(s) already installed'
|
|
|
|
|
2017-12-23 20:27:42 +03:00
|
|
|
module.exit_json(
|
2017-12-23 23:05:07 +03:00
|
|
|
changed=changed_iter,
|
2018-05-16 22:29:17 +03:00
|
|
|
msg=message if not rc else err,
|
|
|
|
helper=use,
|
2017-12-31 20:12:28 +03:00
|
|
|
rc=rc,
|
2017-12-23 20:27:42 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
module = AnsibleModule(
|
|
|
|
argument_spec={
|
|
|
|
'name': {
|
2017-12-23 23:05:07 +03:00
|
|
|
'type': 'list',
|
2017-12-23 20:27:42 +03:00
|
|
|
},
|
|
|
|
'upgrade': {
|
|
|
|
'default': False,
|
|
|
|
'type': 'bool',
|
|
|
|
},
|
2017-12-24 10:21:11 +03:00
|
|
|
'use': {
|
|
|
|
'default': 'auto',
|
2018-05-16 22:06:06 +03:00
|
|
|
'choices': ['auto', 'aurman', 'pacaur', 'trizen', 'pikaur', 'yaourt', 'yay', 'makepkg'],
|
2017-12-31 20:12:28 +03:00
|
|
|
},
|
|
|
|
'skip_installed': {
|
2018-05-08 09:20:00 +03:00
|
|
|
'default': False,
|
2017-12-31 20:12:28 +03:00
|
|
|
'type': 'bool',
|
2017-12-23 20:27:42 +03:00
|
|
|
},
|
2018-05-16 22:20:30 +03:00
|
|
|
'skip_pgp_check': {
|
|
|
|
'default': False,
|
|
|
|
'type': 'bool',
|
|
|
|
},
|
2017-12-23 20:27:42 +03:00
|
|
|
},
|
|
|
|
required_one_of=[['name', 'upgrade']],
|
2018-05-16 21:39:57 +03:00
|
|
|
supports_check_mode=True
|
2017-12-23 20:27:42 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
params = module.params
|
|
|
|
|
2018-05-16 21:39:57 +03:00
|
|
|
if module.check_mode:
|
|
|
|
check_packages(module, params['name'])
|
|
|
|
|
2017-12-24 10:21:11 +03:00
|
|
|
if params['use'] == 'auto':
|
2018-05-16 22:06:06 +03:00
|
|
|
use = 'makepkg'
|
2018-05-08 09:20:00 +03:00
|
|
|
# auto: select the first helper for which the bin is found
|
2017-12-31 20:12:28 +03:00
|
|
|
for k in use_cmd:
|
2017-12-24 10:21:11 +03:00
|
|
|
if module.get_bin_path(k, False):
|
2017-12-31 20:12:28 +03:00
|
|
|
use = k
|
2017-12-24 10:21:11 +03:00
|
|
|
break
|
|
|
|
else:
|
2017-12-31 20:12:28 +03:00
|
|
|
use = params['use']
|
2017-12-24 10:21:11 +03:00
|
|
|
|
2018-05-16 22:06:06 +03:00
|
|
|
if params['upgrade'] and (params['name'] or params['skip_installed'] or use == 'makepkg'):
|
2017-12-31 20:12:28 +03:00
|
|
|
module.fail_json(msg="Upgrade cannot be used with this option.")
|
2017-12-23 20:27:42 +03:00
|
|
|
else:
|
2017-12-31 20:12:28 +03:00
|
|
|
if params['upgrade']:
|
|
|
|
upgrade(module, use)
|
|
|
|
else:
|
|
|
|
install_packages(module, params['name'], use, params['skip_installed'])
|
2017-12-23 20:27:42 +03:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|