202 lines
6.5 KiB
Plaintext
Raw Normal View History

2024-09-04 00:54:15 +06:00
#!/usr/bin/python
# The MIT License (MIT)
#
# Copyright (c) 2014 Austin Hyde
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import os
import pwd
import platform
def cower_in_path(module):
"""
Determine if cower is available.
"""
rc, stdout, stderr = module.run_command('which cower', check_rc=False)
return rc == 0
def pacman_in_path(module):
"""
Determine if pacman is available.
"""
rc, stdout, stderr = module.run_command('which pacman', check_rc=False)
return rc == 0
def package_installed(module, pkg):
"""
Determine if a package is already installed.
"""
rc, stdout, stderr = module.run_command('pacman -Q %s' % pkg, check_rc=False)
return rc == 0
def check_packages(module, pkgs):
"""
Inform the user what would change if the module were run.
"""
would_be_changed = []
for pkg in pkgs:
installed = package_installed(module, pkg)
if not installed:
would_be_changed.append(pkg)
if would_be_changed:
module.exit_json(changed=True, msg='%s package(s) would be installed' % (len(would_be_changed)))
else:
module.exit_json(changed=False, msg='all packages are already installed')
def download_packages(module, pkgs, dir, user):
"""
Download the specified packages.
"""
# Use cower, if available.
if cower_in_path(module):
cmds = ['sudo -u %s cower -dqf %s', ]
# Otherwise, fall back to cURL
else:
cmds = ['sudo -u %s curl -O https://aur.archlinux.org/cgit/aur.git/snapshot/%s.tar.gz',
'sudo -u %s tar xzf %s.tar.gz']
for pkg in pkgs:
# If the package is already installed, skip the download.
if package_installed(module, pkg):
continue
# Change into the specified directory for download.
os.chdir(dir)
# Attempt to install the package.
for cmd in cmds:
rc, stdout, stderr = module.run_command(cmd % (user, pkg), check_rc=False)
if rc != 0:
module.fail_json(msg='failed to download package %s, because: %s' % (pkg,stderr))
def install_packages(module, pkgs, dir, user, virtual):
"""
Install the specified packages via makepkg.
"""
num_installed = 0
if platform.machine().startswith('arm') or platform.machine().startswith('aarch64'):
makepkg_args = '-Acsrf'
else:
makepkg_args = '-csrf'
cmd = 'sudo -u %s PKGEXT=".pkg.tar" makepkg %s --noconfirm --needed --noprogressbar' % (user, makepkg_args)
if module.params['skip_pgp']:
cmd += ' --skippgpcheck'
for pkg in pkgs:
# If the package is already installed, skip the install.
if package_installed(module, pkg):
continue
# Change into the package directory.
# Check if the package is a virtual package
if virtual:
os.chdir(os.path.join(dir, virtual))
else:
os.chdir(os.path.join(dir, pkg))
# Attempt to build the directory.
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0:
module.fail_json(msg='failed to build package %s, because: %s' % (pkg,stderr))
# If the package was succesfully built, install it.
rc, stdout, stderr = module.run_command('pacman -U --noconfirm *.pkg.tar*', check_rc=False, use_unsafe_shell=True)
if rc != 0:
module.fail_json(msg='failed to install package %s, because: %s' % (pkg,stderr))
else:
num_installed += 1
# Exit with the number of packages succesfully installed.
if num_installed > 0:
module.exit_json(changed=True, msg='installed %s package(s)' % num_installed)
else:
module.exit_json(changed=False, msg='all packages were already installed')
def main():
module = AnsibleModule(
argument_spec = dict(
name = dict(required=True, type='list'),
user = dict(required=True),
dir = dict(),
skip_pgp = dict(default=False, type='bool'),
virtual = dict(),
),
supports_check_mode = True
)
# Fail of pacman is not available.
if not pacman_in_path(module):
module.fail_json(msg="could not locate pacman executable")
p = module.params
# Get all the requested package names.
pkgs = p['name']
# Fail if the specified user does not exist.
try:
pwd.getpwnam(p['user'])
except KeyError:
module.fail_json(msg="user %s does not exist" % p['user'])
else:
user = p['user']
# If no directory was given, assume the packages should be downloaded to
# ~user/aur.
if not p['dir']:
home = os.path.expanduser('~%s' % user)
if not os.path.exists(home):
module.fail_json(msg="%s's home directory %s does not exist" % (user, home))
dir = os.path.join(home, 'aur')
if not os.path.exists(dir):
os.makedirs(dir)
uid = pwd.getpwnam(user).pw_uid
os.chown(dir, uid, -1)
else:
dir = os.path.expanduser(p['dir'])
# Fail if the specified directory does not exist.
if not os.path.exists(dir):
module.fail_json(msg="directory %s does not exist" % dir)
if module.check_mode:
check_packages(module, pkgs)
download_packages(module, pkgs, dir, user)
# Check if the package is virtual
if p['virtual']:
virtual = p['virtual']
else:
virtual = False
install_packages(module, pkgs, dir, user, virtual)
from ansible.module_utils.basic import *
main()