Add --installroot to YUM and DNF modules, issue #11310 (#19861)

* Add --installroot to YUM and DNF modules, issue #11310

This continues ansible-modules-core#1558, and
ansible-modules-core#1669

Allow specifying installroot for the yum and dnf modules
to install and remove packages in a location other than /.

* Remove empty aliases

* Simpler installroot set default logic
This commit is contained in:
berenddeschouwer 2017-01-05 05:20:00 +02:00 committed by Toshio Kuratomi
parent d424a0468a
commit 1fdcda0996
8 changed files with 265 additions and 43 deletions

View file

@ -86,6 +86,14 @@ options:
choices: ["yes", "no"] choices: ["yes", "no"]
aliases: [] aliases: []
installroot:
description:
- Specifies an alternative installroot, relative to which all packages
will be installed.
required: false
version_added: "2.3"
default: "/"
notes: [] notes: []
# informational: requirements for nodes # informational: requirements for nodes
requirements: requirements:
@ -94,6 +102,7 @@ requirements:
author: author:
- '"Igor Gnatenko (@ignatenkobrain)" <i.gnatenko.brain@gmail.com>' - '"Igor Gnatenko (@ignatenkobrain)" <i.gnatenko.brain@gmail.com>'
- '"Cristian van Ee (@DJMuggs)" <cristian at cvee.org>' - '"Cristian van Ee (@DJMuggs)" <cristian at cvee.org>'
- "Berend De Schouwer (github.com/berenddeschouwer)"
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -176,7 +185,7 @@ def _ensure_dnf(module):
" Please install `{0}` package.".format(package)) " Please install `{0}` package.".format(package))
def _configure_base(module, base, conf_file, disable_gpg_check): def _configure_base(module, base, conf_file, disable_gpg_check, installroot='/'):
"""Configure the dnf Base object.""" """Configure the dnf Base object."""
conf = base.conf conf = base.conf
@ -189,6 +198,9 @@ def _configure_base(module, base, conf_file, disable_gpg_check):
# Don't prompt for user confirmations # Don't prompt for user confirmations
conf.assumeyes = True conf.assumeyes = True
# Set installroot
conf.installroot = installroot
# Change the configuration file path if provided # Change the configuration file path if provided
if conf_file: if conf_file:
# Fail if we can't read the configuration file. # Fail if we can't read the configuration file.
@ -218,10 +230,10 @@ def _specify_repositories(base, disablerepo, enablerepo):
repo.enable() repo.enable()
def _base(module, conf_file, disable_gpg_check, disablerepo, enablerepo): def _base(module, conf_file, disable_gpg_check, disablerepo, enablerepo, installroot):
"""Return a fully configured dnf Base object.""" """Return a fully configured dnf Base object."""
base = dnf.Base() base = dnf.Base()
_configure_base(module, base, conf_file, disable_gpg_check) _configure_base(module, base, conf_file, disable_gpg_check, installroot)
_specify_repositories(base, disablerepo, enablerepo) _specify_repositories(base, disablerepo, enablerepo)
base.fill_sack(load_system_repo='auto') base.fill_sack(load_system_repo='auto')
return base return base
@ -450,6 +462,7 @@ def main():
list=dict(), list=dict(),
conf_file=dict(default=None, type='path'), conf_file=dict(default=None, type='path'),
disable_gpg_check=dict(default=False, type='bool'), disable_gpg_check=dict(default=False, type='bool'),
installroot=dict(default='/', type='path'),
), ),
required_one_of=[['name', 'list']], required_one_of=[['name', 'list']],
mutually_exclusive=[['name', 'list']], mutually_exclusive=[['name', 'list']],
@ -461,7 +474,7 @@ def main():
if params['list']: if params['list']:
base = _base( base = _base(
module, params['conf_file'], params['disable_gpg_check'], module, params['conf_file'], params['disable_gpg_check'],
params['disablerepo'], params['enablerepo']) params['disablerepo'], params['enablerepo'], params['installroot'])
list_items(module, base, params['list']) list_items(module, base, params['list'])
else: else:
# Note: base takes a long time to run so we want to check for failure # Note: base takes a long time to run so we want to check for failure
@ -470,7 +483,7 @@ def main():
module.fail_json(msg="This command has to be run under the root user.") module.fail_json(msg="This command has to be run under the root user.")
base = _base( base = _base(
module, params['conf_file'], params['disable_gpg_check'], module, params['conf_file'], params['disable_gpg_check'],
params['disablerepo'], params['enablerepo']) params['disablerepo'], params['enablerepo'], params['installroot'])
ensure(module, base, params['state'], params['name']) ensure(module, base, params['state'], params['name'])

View file

@ -129,6 +129,15 @@ options:
choices: ["yes", "no"] choices: ["yes", "no"]
version_added: "2.1" version_added: "2.1"
installroot:
description:
- Specifies an alternative installroot, relative to which all packages
will be installed.
required: false
version_added: "2.3"
default: "/"
aliases: []
notes: notes:
- When used with a loop of package names in a playbook, ansible optimizes - When used with a loop of package names in a playbook, ansible optimizes
the call to the yum module. Instead of calling the module with a single the call to the yum module. Instead of calling the module with a single
@ -156,6 +165,8 @@ requirements: [ yum ]
author: author:
- "Ansible Core Team" - "Ansible Core Team"
- "Seth Vidal" - "Seth Vidal"
- "Eduard Snesarev (github.com/verm666)"
- "Berend De Schouwer (github.com/berenddeschouwer)"
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -212,12 +223,18 @@ BUFSIZE = 65536
def_qf = "%{name}-%{version}-%{release}.%{arch}" def_qf = "%{name}-%{version}-%{release}.%{arch}"
rpmbin = None rpmbin = None
def yum_base(conf_file=None): def yum_base(conf_file=None, installroot='/'):
my = yum.YumBase() my = yum.YumBase()
my.preconf.debuglevel=0 my.preconf.debuglevel=0
my.preconf.errorlevel=0 my.preconf.errorlevel=0
my.preconf.plugins = True my.preconf.plugins = True
#my.preconf.releasever = '/'
if installroot != '/':
# do not setup installroot by default, because of error
# CRITICAL:yum.cli:Config Error: Error accessing file for config file:////etc/yum.conf
# in old yum version (like in CentOS 6.6)
my.conf.installroot=installroot
if conf_file and os.path.exists(conf_file): if conf_file and os.path.exists(conf_file):
my.preconf.fn = conf_file my.preconf.fn = conf_file
if os.geteuid() != 0: if os.geteuid() != 0:
@ -270,7 +287,7 @@ def po_to_nevra(po):
else: else:
return '%s-%s-%s.%s' % (po.name, po.version, po.release, po.arch) return '%s-%s-%s.%s' % (po.name, po.version, po.release, po.arch)
def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, is_pkg=False): def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, is_pkg=False, installroot='/'):
if en_repos is None: if en_repos is None:
en_repos = [] en_repos = []
if dis_repos is None: if dis_repos is None:
@ -279,7 +296,7 @@ def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
if not repoq: if not repoq:
pkgs = [] pkgs = []
try: try:
my = yum_base(conf_file) my = yum_base(conf_file, installroot)
for rid in dis_repos: for rid in dis_repos:
my.repos.disableRepo(rid) my.repos.disableRepo(rid)
for rid in en_repos: for rid in en_repos:
@ -326,7 +343,7 @@ def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
return [] return []
def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None): def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'):
if en_repos is None: if en_repos is None:
en_repos = [] en_repos = []
if dis_repos is None: if dis_repos is None:
@ -336,7 +353,7 @@ def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
pkgs = [] pkgs = []
try: try:
my = yum_base(conf_file) my = yum_base(conf_file, installroot)
for rid in dis_repos: for rid in dis_repos:
my.repos.disableRepo(rid) my.repos.disableRepo(rid)
for rid in en_repos: for rid in en_repos:
@ -370,7 +387,7 @@ def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
return [] return []
def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None): def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'):
if en_repos is None: if en_repos is None:
en_repos = [] en_repos = []
if dis_repos is None: if dis_repos is None:
@ -383,7 +400,7 @@ def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_r
updates = [] updates = []
try: try:
my = yum_base(conf_file) my = yum_base(conf_file, installroot)
for rid in dis_repos: for rid in dis_repos:
my.repos.disableRepo(rid) my.repos.disableRepo(rid)
for rid in en_repos: for rid in en_repos:
@ -422,7 +439,7 @@ def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_r
return set() return set()
def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None, dis_repos=None): def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'):
if en_repos is None: if en_repos is None:
en_repos = [] en_repos = []
if dis_repos is None: if dis_repos is None:
@ -439,7 +456,7 @@ def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None,
pkgs = [] pkgs = []
try: try:
my = yum_base(conf_file) my = yum_base(conf_file, installroot)
for rid in dis_repos: for rid in dis_repos:
my.repos.disableRepo(rid) my.repos.disableRepo(rid)
for rid in en_repos: for rid in en_repos:
@ -475,7 +492,7 @@ def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None,
out += out2 out += out2
pkgs = set([ p for p in out.split('\n') if p.strip() ]) pkgs = set([ p for p in out.split('\n') if p.strip() ])
if not pkgs: if not pkgs:
pkgs = is_installed(module, repoq, req_spec, conf_file, qf=qf) pkgs = is_installed(module, repoq, req_spec, conf_file, qf=qf, installroot=installroot)
return pkgs return pkgs
else: else:
module.fail_json(msg='Error from repoquery: %s: %s' % (cmd, err + err2)) module.fail_json(msg='Error from repoquery: %s: %s' % (cmd, err + err2))
@ -570,7 +587,7 @@ def repolist(module, repoq, qf="%{repoid}"):
ret = set([ p for p in out.split('\n') if p.strip() ]) ret = set([ p for p in out.split('\n') if p.strip() ])
return ret return ret
def list_stuff(module, repoquerybin, conf_file, stuff): def list_stuff(module, repoquerybin, conf_file, stuff, installroot='/'):
qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}" qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}"
# is_installed goes through rpm instead of repoquery so it needs a slightly different format # is_installed goes through rpm instead of repoquery so it needs a slightly different format
@ -580,17 +597,17 @@ def list_stuff(module, repoquerybin, conf_file, stuff):
repoq += ['-c', conf_file] repoq += ['-c', conf_file]
if stuff == 'installed': if stuff == 'installed':
return [ pkg_to_dict(p) for p in sorted(is_installed(module, repoq, '-a', conf_file, qf=is_installed_qf)) if p.strip() ] return [ pkg_to_dict(p) for p in sorted(is_installed(module, repoq, '-a', conf_file, qf=is_installed_qf, installroot=installroot)) if p.strip() ]
elif stuff == 'updates': elif stuff == 'updates':
return [ pkg_to_dict(p) for p in sorted(is_update(module, repoq, '-a', conf_file, qf=qf)) if p.strip() ] return [ pkg_to_dict(p) for p in sorted(is_update(module, repoq, '-a', conf_file, qf=qf, installroot=installroot)) if p.strip() ]
elif stuff == 'available': elif stuff == 'available':
return [ pkg_to_dict(p) for p in sorted(is_available(module, repoq, '-a', conf_file, qf=qf)) if p.strip() ] return [ pkg_to_dict(p) for p in sorted(is_available(module, repoq, '-a', conf_file, qf=qf, installroot=installroot)) if p.strip() ]
elif stuff == 'repos': elif stuff == 'repos':
return [ dict(repoid=name, state='enabled') for name in sorted(repolist(module, repoq)) if name.strip() ] return [ dict(repoid=name, state='enabled') for name in sorted(repolist(module, repoq)) if name.strip() ]
else: else:
return [ pkg_to_dict(p) for p in sorted(is_installed(module, repoq, stuff, conf_file, qf=is_installed_qf) + is_available(module, repoq, stuff, conf_file, qf=qf)) if p.strip() ] return [ pkg_to_dict(p) for p in sorted(is_installed(module, repoq, stuff, conf_file, qf=is_installed_qf, installroot=installroot) + is_available(module, repoq, stuff, conf_file, qf=qf, installroot=installroot)) if p.strip() ]
def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, installroot='/'):
pkgs = [] pkgs = []
res = {} res = {}
@ -616,7 +633,7 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
nvra = local_nvra(module, spec) nvra = local_nvra(module, spec)
# look for them in the rpmdb # look for them in the rpmdb
if is_installed(module, repoq, nvra, conf_file, en_repos=en_repos, dis_repos=dis_repos): if is_installed(module, repoq, nvra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
# if they are there, skip it # if they are there, skip it
continue continue
pkg = spec pkg = spec
@ -626,7 +643,7 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
# download package so that we can check if it's already installed # download package so that we can check if it's already installed
package = fetch_rpm_from_url(spec, module=module) package = fetch_rpm_from_url(spec, module=module)
nvra = local_nvra(module, package) nvra = local_nvra(module, package)
if is_installed(module, repoq, nvra, conf_file, en_repos=en_repos, dis_repos=dis_repos): if is_installed(module, repoq, nvra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
# if it's there, skip it # if it's there, skip it
continue continue
pkg = package pkg = package
@ -642,13 +659,13 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
# short circuit all the bs - and search for it as a pkg in is_installed # short circuit all the bs - and search for it as a pkg in is_installed
# if you find it then we're done # if you find it then we're done
if not set(['*','?']).intersection(set(spec)): if not set(['*','?']).intersection(set(spec)):
installed_pkgs = is_installed(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos, is_pkg=True) installed_pkgs = is_installed(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos, is_pkg=True, installroot=installroot)
if installed_pkgs: if installed_pkgs:
res['results'].append('%s providing %s is already installed' % (installed_pkgs[0], spec)) res['results'].append('%s providing %s is already installed' % (installed_pkgs[0], spec))
continue continue
# look up what pkgs provide this # look up what pkgs provide this
pkglist = what_provides(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos) pkglist = what_provides(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot)
if not pkglist: if not pkglist:
res['msg'] += "No package matching '%s' found available, installed or updated" % spec res['msg'] += "No package matching '%s' found available, installed or updated" % spec
res['results'].append("No package matching '%s' found available, installed or updated" % spec) res['results'].append("No package matching '%s' found available, installed or updated" % spec)
@ -668,7 +685,7 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
found = False found = False
for this in pkglist: for this in pkglist:
if is_installed(module, repoq, this, conf_file, en_repos=en_repos, dis_repos=dis_repos, is_pkg=True): if is_installed(module, repoq, this, conf_file, en_repos=en_repos, dis_repos=dis_repos, is_pkg=True, installroot=installroot):
found = True found = True
res['results'].append('%s providing %s is already installed' % (this, spec)) res['results'].append('%s providing %s is already installed' % (this, spec))
break break
@ -679,7 +696,7 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
# but virt provides should be all caught in what_provides on its own. # but virt provides should be all caught in what_provides on its own.
# highly irritating # highly irritating
if not found: if not found:
if is_installed(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos): if is_installed(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
found = True found = True
res['results'].append('package providing %s is already installed' % (spec)) res['results'].append('package providing %s is already installed' % (spec))
@ -747,7 +764,7 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
return res return res
def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, installroot='/'):
pkgs = [] pkgs = []
res = {} res = {}
@ -762,7 +779,7 @@ def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
if pkg.startswith('@'): if pkg.startswith('@'):
is_group = True is_group = True
else: else:
if not is_installed(module, repoq, pkg, conf_file, en_repos=en_repos, dis_repos=dis_repos): if not is_installed(module, repoq, pkg, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
res['results'].append('%s is not installed' % pkg) res['results'].append('%s is not installed' % pkg)
continue continue
@ -791,7 +808,7 @@ def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
for pkg in pkgs: for pkg in pkgs:
if not pkg.startswith('@'): # we can't sensibly check for a group being uninstalled reliably if not pkg.startswith('@'): # we can't sensibly check for a group being uninstalled reliably
# look to see if the pkg shows up from is_installed. If it doesn't # look to see if the pkg shows up from is_installed. If it doesn't
if not is_installed(module, repoq, pkg, conf_file, en_repos=en_repos, dis_repos=dis_repos): if not is_installed(module, repoq, pkg, conf_file, en_repos=en_repos, dis_repos=dis_repos,installroot=installroot):
res['changed'] = True res['changed'] = True
else: else:
module.fail_json(**res) module.fail_json(**res)
@ -801,7 +818,7 @@ def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
return res return res
def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, installroot='/'):
res = {} res = {}
res['results'] = [] res['results'] = []
@ -859,11 +876,11 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
continue continue
# dep/pkgname - find it # dep/pkgname - find it
else: else:
if is_installed(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos): if is_installed(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
pkgs['update'].append(spec) pkgs['update'].append(spec)
else: else:
pkgs['install'].append(spec) pkgs['install'].append(spec)
pkglist = what_provides(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos) pkglist = what_provides(module, repoq, spec, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot)
# FIXME..? may not be desirable to throw an exception here if a single package is missing # FIXME..? may not be desirable to throw an exception here if a single package is missing
if not pkglist: if not pkglist:
res['msg'] += "No package matching '%s' found available, installed or updated" % spec res['msg'] += "No package matching '%s' found available, installed or updated" % spec
@ -873,7 +890,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
nothing_to_do = True nothing_to_do = True
for this in pkglist: for this in pkglist:
if spec in pkgs['install'] and is_available(module, repoq, this, conf_file, en_repos=en_repos, dis_repos=dis_repos): if spec in pkgs['install'] and is_available(module, repoq, this, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
nothing_to_do = False nothing_to_do = False
break break
@ -960,7 +977,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos):
return res return res
def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo, def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo,
disable_gpg_check, exclude, repoq): disable_gpg_check, exclude, repoq, installroot='/'):
# fedora will redirect yum to dnf, which has incompatibilities # fedora will redirect yum to dnf, which has incompatibilities
# with how this module expects yum to operate. If yum-deprecated # with how this module expects yum to operate. If yum-deprecated
@ -993,12 +1010,19 @@ def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo,
e_cmd = ['--exclude=%s' % exclude] e_cmd = ['--exclude=%s' % exclude]
yum_basecmd.extend(e_cmd) yum_basecmd.extend(e_cmd)
if installroot != '/':
# do not setup installroot by default, because of error
# CRITICAL:yum.cli:Config Error: Error accessing file for config file:////etc/yum.conf
# in old yum version (like in CentOS 6.6)
e_cmd = ['--installroot=%s' % installroot]
yum_basecmd.extend(e_cmd)
if state in ['installed', 'present', 'latest']: if state in ['installed', 'present', 'latest']:
if module.params.get('update_cache'): if module.params.get('update_cache'):
module.run_command(yum_basecmd + ['makecache']) module.run_command(yum_basecmd + ['makecache'])
my = yum_base(conf_file) my = yum_base(conf_file, installroot)
try: try:
if disablerepo: if disablerepo:
my.repos.disableRepo(disablerepo) my.repos.disableRepo(disablerepo)
@ -1021,13 +1045,13 @@ def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo,
if state in ['installed', 'present']: if state in ['installed', 'present']:
if disable_gpg_check: if disable_gpg_check:
yum_basecmd.append('--nogpgcheck') yum_basecmd.append('--nogpgcheck')
res = install(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos) res = install(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos, installroot=installroot)
elif state in ['removed', 'absent']: elif state in ['removed', 'absent']:
res = remove(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos) res = remove(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos, installroot=installroot)
elif state == 'latest': elif state == 'latest':
if disable_gpg_check: if disable_gpg_check:
yum_basecmd.append('--nogpgcheck') yum_basecmd.append('--nogpgcheck')
res = latest(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos) res = latest(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos, installroot=installroot)
else: else:
# should be caught by AnsibleModule argument_spec # should be caught by AnsibleModule argument_spec
module.fail_json(msg="we should never get here unless this all" module.fail_json(msg="we should never get here unless this all"
@ -1062,6 +1086,7 @@ def main():
disable_gpg_check=dict(required=False, default="no", type='bool'), disable_gpg_check=dict(required=False, default="no", type='bool'),
update_cache=dict(required=False, default="no", type='bool'), update_cache=dict(required=False, default="no", type='bool'),
validate_certs=dict(required=False, default="yes", type='bool'), validate_certs=dict(required=False, default="yes", type='bool'),
installroot=dict(required=False, default="/", type='str'),
# this should not be needed, but exists as a failsafe # this should not be needed, but exists as a failsafe
install_repoquery=dict(required=False, default="yes", type='bool'), install_repoquery=dict(required=False, default="yes", type='bool'),
), ),
@ -1076,14 +1101,14 @@ def main():
repoquerybin = ensure_yum_utils(module) repoquerybin = ensure_yum_utils(module)
if not repoquerybin: if not repoquerybin:
module.fail_json(msg="repoquery is required to use list= with this module. Please install the yum-utils package.") module.fail_json(msg="repoquery is required to use list= with this module. Please install the yum-utils package.")
results = dict(results=list_stuff(module, repoquerybin, params['conf_file'], params['list'])) results = dict(results=list_stuff(module, repoquerybin, params['conf_file'], params['list'], params['installroot']))
else: else:
# If rhn-plugin is installed and no rhn-certificate is available on # If rhn-plugin is installed and no rhn-certificate is available on
# the system then users will see an error message using the yum API. # the system then users will see an error message using the yum API.
# Use repoquery in those cases. # Use repoquery in those cases.
my = yum_base(params['conf_file']) my = yum_base(params['conf_file'], params['installroot'])
# A sideeffect of accessing conf is that the configuration is # A sideeffect of accessing conf is that the configuration is
# loaded and plugins are discovered # loaded and plugins are discovered
my.conf my.conf
@ -1105,7 +1130,8 @@ def main():
disablerepo = params.get('disablerepo', '') disablerepo = params.get('disablerepo', '')
disable_gpg_check = params['disable_gpg_check'] disable_gpg_check = params['disable_gpg_check']
results = ensure(module, state, pkg, params['conf_file'], enablerepo, results = ensure(module, state, pkg, params['conf_file'], enablerepo,
disablerepo, disable_gpg_check, exclude, repoquery) disablerepo, disable_gpg_check, exclude, repoquery,
params['installroot'])
if repoquery: if repoquery:
results['msg'] = '%s %s' % (results.get('msg',''), results['msg'] = '%s %s' % (results.get('msg',''),
'Warning: Due to potential bad behaviour with rhnplugin and certificates, used slower repoquery calls instead of Yum API.') 'Warning: Due to potential bad behaviour with rhnplugin and certificates, used slower repoquery calls instead of Yum API.')

View file

@ -210,3 +210,33 @@
assert: assert:
that: that:
- non_existent_rpm|failed - non_existent_rpm|failed
# Install in installroot='/'. This should be identical to default
- name: install sos in /
dnf: name=sos state=present installroot='/'
register: dnf_result
- name: check sos with rpm in /
shell: rpm -q sos --root=/
failed_when: False
register: rpm_result
- debug: var=dnf_result
- debug: var=rpm_result
- name: verify installation of sos in /
assert:
that:
- "not dnf_result.failed | default(False)"
- "dnf_result.changed"
- "rpm_result.rc == 0"
- name: verify dnf module outputs in /
assert:
that:
- "'changed' in dnf_result"
- "'results' in dnf_result"
- name: uninstall sos in /
dnf: name=sos installroot='/'
register: dnf_result

View file

@ -0,0 +1,47 @@
# make a installroot
- name: Create installroot
local_action:
module: command mktemp -d "{{ lookup('env', 'TMPDIR') | default('/tmp', true) }}/ansible.test.XXXXXX"
register: dnfroot
- name: Make a necessary directory
file:
path: "/{{ dnfroot.stdout }}/etc/dnf/vars/"
state: directory
mode: 0755
- name: Populate directory
copy:
content: "{{ ansible_distribution_version }}\n"
dest: "/{{ dnfroot.stdout }}/etc/dnf/vars/releasever"
# This will drag in > 200 MB.
- name: attempt installroot
dnf: name=sos installroot="/{{ dnfroot.stdout }}/" disable_gpg_check=yes
register: dnf_result
- name: check sos with rpm in installroot
shell: rpm -q sos --root="/{{ dnfroot.stdout }}/"
failed_when: False
register: rpm_result
- debug: var=dnf_result
- debug: var=rpm_result
- name: verify installation of sos in installroot
assert:
that:
- "not dnf_result.failed | default(False)"
- "dnf_result.changed"
- "rpm_result.rc == 0"
- name: verify dnf module outputs in /
assert:
that:
- "'changed' in dnf_result"
- "'results' in dnf_result"
- name: cleanup installroot
file:
path: "/{{ dnfroot.stdout }}/"
state: absent

View file

@ -18,5 +18,9 @@
# Note: We install the yum package onto Fedora so that this will work on dnf systems # Note: We install the yum package onto Fedora so that this will work on dnf systems
# We want to test that for people who don't want to upgrade their systems. # We want to test that for people who don't want to upgrade their systems.
- include: 'dnf.yml' - include: 'dnf.yml'
when: (ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] and False) or (ansible_distribution in ['Fedora'] and ansible_distribution_major_version >= 23) when: (ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] and False) or (ansible_distribution in ['Fedora'] and ansible_distribution_major_version >= 23)
- include: 'dnfinstallroot.yml'
when: (ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] and False) or (ansible_distribution in ['Fedora'] and ansible_distribution_major_version >= 23)

View file

@ -19,4 +19,14 @@
# Note: We install the yum package onto Fedora so that this will work on dnf systems # Note: We install the yum package onto Fedora so that this will work on dnf systems
# We want to test that for people who don't want to upgrade their systems. # We want to test that for people who don't want to upgrade their systems.
- include: 'yum.yml' - include: 'yum.yml'
when: ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux', 'Fedora'] and ansible_python.version.major == 2 when: ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux', 'Fedora'] and
ansible_python.version.major == 2
# We can't run yum --installroot tests on dnf systems. Dnf systems revert to
# yum-deprecated, and yum-deprecated refuses to run if yum.conf exists
# so we cannot configure yum-deprecated correctly in an empty /tmp/fake.root/
# It will always run with $releasever unset
- include: 'yuminstallroot.yml'
when: (ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] or
(ansible_distribution in ['Fedora'] and ansible_distribution_major_version < 23)) and
ansible_python.version.major == 2

View file

@ -197,3 +197,35 @@
assert: assert:
that: that:
- non_existent_rpm|failed - non_existent_rpm|failed
# Install in installroot='/'
- name: install sos
yum: name=sos state=present installroot='/'
register: yum_result
- name: check sos with rpm
shell: rpm -q sos --root=/
failed_when: False
register: rpm_result
- debug: var=yum_result
- debug: var=rpm_result
- name: verify installation of sos
assert:
that:
- "yum_result.rc == 0"
- "yum_result.changed"
- "rpm_result.rc == 0"
- name: verify yum module outputs
assert:
that:
- "'changed' in yum_result"
- "'msg' in yum_result"
- "'rc' in yum_result"
- "'results' in yum_result"
- name: uninstall sos
yum: name=sos installroot='/'
register: yum_result

View file

@ -0,0 +1,60 @@
# make a installroot
- name: Create installroot
local_action:
module: command mktemp -d "{{ lookup('env', 'TMPDIR') | default('/tmp', true) }}/ansible.test.XXXXXX"
register: yumroot
#- name: Populate directory
# file:
# path: "/{{ yumroot.stdout }}/etc/"
# state: directory
# mode: 0755
#
#- name: Populate directory2
# copy:
# content: "[main]\ndistropkgver={{ ansible_distribution_version }}\n"
# dest: "/{{ yumroot.stdout }}/etc/yum.conf"
- name: Make a necessary directory
file:
path: "/{{ yumroot.stdout }}/etc/yum/vars/"
state: directory
mode: 0755
- name: Populate directory
copy:
content: "{{ ansible_lsb.major_release }}\n"
dest: "/{{ yumroot.stdout }}/etc/yum/vars/releasever"
# This will drag in > 200 MB.
- name: attempt installroot
yum: name=sos installroot="/{{ yumroot.stdout }}/" disable_gpg_check=yes
register: yum_result
- name: check sos with rpm in installroot
shell: rpm -q sos --root="/{{ yumroot.stdout }}/"
failed_when: False
register: rpm_result
- debug: var=yum_result
- debug: var=rpm_result
- name: verify installation of sos
assert:
that:
- "yum_result.rc == 0"
- "yum_result.changed"
- "rpm_result.rc == 0"
- name: verify yum module outputs
assert:
that:
- "'changed' in yum_result"
- "'msg' in yum_result"
- "'rc' in yum_result"
- "'results' in yum_result"
- name: cleanup installroot
file:
path: "/{{ yumroot.stdout }}/"
state: absent