* 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:
parent
d424a0468a
commit
1fdcda0996
8 changed files with 265 additions and 43 deletions
|
@ -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'])
|
||||||
|
|
||||||
|
|
|
@ -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.')
|
||||||
|
|
|
@ -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
|
||||||
|
|
47
test/integration/targets/dnf/tasks/dnfinstallroot.yml
Normal file
47
test/integration/targets/dnf/tasks/dnfinstallroot.yml
Normal 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
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
60
test/integration/targets/yum/tasks/yuminstallroot.yml
Normal file
60
test/integration/targets/yum/tasks/yuminstallroot.yml
Normal 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
|
Loading…
Reference in a new issue