diff --git a/lib/ansible/modules/packaging/os/dnf.py b/lib/ansible/modules/packaging/os/dnf.py index 016fdf6045..bf138974a1 100644 --- a/lib/ansible/modules/packaging/os/dnf.py +++ b/lib/ansible/modules/packaging/os/dnf.py @@ -86,6 +86,14 @@ options: choices: ["yes", "no"] aliases: [] + installroot: + description: + - Specifies an alternative installroot, relative to which all packages + will be installed. + required: false + version_added: "2.3" + default: "/" + notes: [] # informational: requirements for nodes requirements: @@ -94,6 +102,7 @@ requirements: author: - '"Igor Gnatenko (@ignatenkobrain)" ' - '"Cristian van Ee (@DJMuggs)" ' + - "Berend De Schouwer (github.com/berenddeschouwer)" ''' EXAMPLES = ''' @@ -176,7 +185,7 @@ def _ensure_dnf(module): " 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.""" conf = base.conf @@ -189,6 +198,9 @@ def _configure_base(module, base, conf_file, disable_gpg_check): # Don't prompt for user confirmations conf.assumeyes = True + # Set installroot + conf.installroot = installroot + # Change the configuration file path if provided if conf_file: # Fail if we can't read the configuration file. @@ -218,10 +230,10 @@ def _specify_repositories(base, disablerepo, enablerepo): 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.""" 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) base.fill_sack(load_system_repo='auto') return base @@ -450,6 +462,7 @@ def main(): list=dict(), conf_file=dict(default=None, type='path'), disable_gpg_check=dict(default=False, type='bool'), + installroot=dict(default='/', type='path'), ), required_one_of=[['name', 'list']], mutually_exclusive=[['name', 'list']], @@ -461,7 +474,7 @@ def main(): if params['list']: base = _base( module, params['conf_file'], params['disable_gpg_check'], - params['disablerepo'], params['enablerepo']) + params['disablerepo'], params['enablerepo'], params['installroot']) list_items(module, base, params['list']) else: # 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.") base = _base( 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']) diff --git a/lib/ansible/modules/packaging/os/yum.py b/lib/ansible/modules/packaging/os/yum.py index 18e7171390..cfc3b059ba 100644 --- a/lib/ansible/modules/packaging/os/yum.py +++ b/lib/ansible/modules/packaging/os/yum.py @@ -129,6 +129,15 @@ options: choices: ["yes", "no"] 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: - 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 @@ -156,6 +165,8 @@ requirements: [ yum ] author: - "Ansible Core Team" - "Seth Vidal" + - "Eduard Snesarev (github.com/verm666)" + - "Berend De Schouwer (github.com/berenddeschouwer)" ''' EXAMPLES = ''' @@ -212,12 +223,18 @@ BUFSIZE = 65536 def_qf = "%{name}-%{version}-%{release}.%{arch}" rpmbin = None -def yum_base(conf_file=None): +def yum_base(conf_file=None, installroot='/'): my = yum.YumBase() my.preconf.debuglevel=0 my.preconf.errorlevel=0 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): my.preconf.fn = conf_file if os.geteuid() != 0: @@ -270,7 +287,7 @@ def po_to_nevra(po): else: 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: en_repos = [] 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: pkgs = [] try: - my = yum_base(conf_file) + my = yum_base(conf_file, installroot) for rid in dis_repos: my.repos.disableRepo(rid) 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 [] -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: en_repos = [] 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 = [] try: - my = yum_base(conf_file) + my = yum_base(conf_file, installroot) for rid in dis_repos: my.repos.disableRepo(rid) 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 [] -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: en_repos = [] 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 = [] try: - my = yum_base(conf_file) + my = yum_base(conf_file, installroot) for rid in dis_repos: my.repos.disableRepo(rid) 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() -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: en_repos = [] 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 = [] try: - my = yum_base(conf_file) + my = yum_base(conf_file, installroot) for rid in dis_repos: my.repos.disableRepo(rid) 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 pkgs = set([ p for p in out.split('\n') if p.strip() ]) 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 else: 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() ]) 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}" # 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] 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': - 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': - 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': return [ dict(repoid=name, state='enabled') for name in sorted(repolist(module, repoq)) if name.strip() ] 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 = [] res = {} @@ -616,7 +633,7 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): nvra = local_nvra(module, spec) # 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 continue 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 package = fetch_rpm_from_url(spec, module=module) 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 continue 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 # if you find it then we're done 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: res['results'].append('%s providing %s is already installed' % (installed_pkgs[0], spec)) continue # 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: 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) @@ -668,7 +685,7 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): found = False 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 res['results'].append('%s providing %s is already installed' % (this, spec)) 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. # highly irritating 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 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 -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 = [] res = {} @@ -762,7 +779,7 @@ def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): if pkg.startswith('@'): is_group = True 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) continue @@ -791,7 +808,7 @@ def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): for pkg in pkgs: 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 - 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 else: module.fail_json(**res) @@ -801,7 +818,7 @@ def remove(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): 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['results'] = [] @@ -859,11 +876,11 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): continue # dep/pkgname - find it 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) else: 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 if not pkglist: 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 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 break @@ -960,7 +977,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): return res 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 # 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] 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 module.params.get('update_cache'): module.run_command(yum_basecmd + ['makecache']) - my = yum_base(conf_file) + my = yum_base(conf_file, installroot) try: if disablerepo: my.repos.disableRepo(disablerepo) @@ -1021,13 +1045,13 @@ def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo, if state in ['installed', 'present']: if disable_gpg_check: 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']: - 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': if disable_gpg_check: 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: # should be caught by AnsibleModule argument_spec 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'), update_cache=dict(required=False, default="no", 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 install_repoquery=dict(required=False, default="yes", type='bool'), ), @@ -1076,14 +1101,14 @@ def main(): repoquerybin = ensure_yum_utils(module) if not repoquerybin: 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: # 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. # 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 # loaded and plugins are discovered my.conf @@ -1105,7 +1130,8 @@ def main(): disablerepo = params.get('disablerepo', '') disable_gpg_check = params['disable_gpg_check'] 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: 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.') diff --git a/test/integration/targets/dnf/tasks/dnf.yml b/test/integration/targets/dnf/tasks/dnf.yml index b381334086..d37f5ed882 100644 --- a/test/integration/targets/dnf/tasks/dnf.yml +++ b/test/integration/targets/dnf/tasks/dnf.yml @@ -210,3 +210,33 @@ assert: that: - 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 diff --git a/test/integration/targets/dnf/tasks/dnfinstallroot.yml b/test/integration/targets/dnf/tasks/dnfinstallroot.yml new file mode 100644 index 0000000000..1cd2a21be6 --- /dev/null +++ b/test/integration/targets/dnf/tasks/dnfinstallroot.yml @@ -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 diff --git a/test/integration/targets/dnf/tasks/main.yml b/test/integration/targets/dnf/tasks/main.yml index 755c807e7d..4a9addb573 100644 --- a/test/integration/targets/dnf/tasks/main.yml +++ b/test/integration/targets/dnf/tasks/main.yml @@ -18,5 +18,9 @@ # 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. + - include: 'dnf.yml' 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) diff --git a/test/integration/targets/yum/tasks/main.yml b/test/integration/targets/yum/tasks/main.yml index 209362d44e..5670171d5c 100644 --- a/test/integration/targets/yum/tasks/main.yml +++ b/test/integration/targets/yum/tasks/main.yml @@ -19,4 +19,14 @@ # 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. - 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 diff --git a/test/integration/targets/yum/tasks/yum.yml b/test/integration/targets/yum/tasks/yum.yml index f285326f5f..8299ec587d 100644 --- a/test/integration/targets/yum/tasks/yum.yml +++ b/test/integration/targets/yum/tasks/yum.yml @@ -197,3 +197,35 @@ assert: that: - 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 diff --git a/test/integration/targets/yum/tasks/yuminstallroot.yml b/test/integration/targets/yum/tasks/yuminstallroot.yml new file mode 100644 index 0000000000..0663027304 --- /dev/null +++ b/test/integration/targets/yum/tasks/yuminstallroot.yml @@ -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