Repository: ansible/ansible

Issue:
yum module does not respect disablerepo and enablerepo when list is used
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
yum

##### ANSIBLE VERSION
```
ansible 2.2.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
No changes to ansible.cfg, and no ANSIBLE_* environment variables are set 

##### OS / ENVIRONMENT
Control machine: Arch Linux x64
Target machine: CentOS 6 and CentOS 7

##### SUMMARY
yum module does not respect disablerepo and enablerepo while querying the RPM packages (repoquery)
If one of the repos, whose enabled is set to 1 in /etc/yum.repos.d/, is temporarily unavailable, even it's has been listed in disablerepo argument, yum module will still fail.

##### STEPS TO REPRODUCE
Fresh install a CentOS 7, then intentionally add a repo config as /etc/yum.repos.d/unavailable.repo
```ini
[unavailable]
name=unavailable repo
baseurl=http://localhost/does/not/exist
enabled=1
gpgcheck=0
```

Then from control machine, issue the following command for querying packages on CentOS
```
ansible CENTOS7 -vvvv -m yum -a 'disablerepo=* enablerepo=base list=zlib'
```

##### EXPECTED RESULTS
```
Using /etc/ansible/ansible.cfg as config file
Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/site-packages/ansible/plugins/callback/__init__.pyc
Using module file /usr/lib/python2.7/site-packages/ansible/modules/core/packaging/os/yum.py
<172.16.3.118> ESTABLISH SSH CONNECTION FOR USER: root
<172.16.3.118> SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r 172.16.3.118 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo ~/.ansible/tmp/ansible-tmp-1490192981.95-117749880161901 `" && echo ansible-tmp-1490192981.95-117749880161901="` echo ~/.ansible/tmp/ansible-tmp-1490192981.95-117749880161901 `" ) && sleep 0'"'"''
<172.16.3.118> PUT /tmp/tmpM2ZNYY TO /root/.ansible/tmp/ansible-tmp-1490192981.95-117749880161901/yum.py
<172.16.3.118> SSH: EXEC sshpass -d12 sftp -o BatchMode=no -b - -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r '[172.16.3.118]'
<172.16.3.118> ESTABLISH SSH CONNECTION FOR USER: root
<172.16.3.118> SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r 172.16.3.118 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1490192981.95-117749880161901/ /root/.ansible/tmp/ansible-tmp-1490192981.95-117749880161901/yum.py && sleep 0'"'"''
<172.16.3.118> ESTABLISH SSH CONNECTION FOR USER: root
<172.16.3.118> SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r -tt 172.16.3.118 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1490192981.95-117749880161901/yum.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1490192981.95-117749880161901/" > /dev/null 2>&1 && sleep 0'"'"''
172.16.3.118 | SUCCESS => {
    "changed": false, 
    "invocation": {
        "module_args": {
            "conf_file": null, 
            "disable_gpg_check": false, 
            "disablerepo": "*", 
            "enablerepo": "base", 
            "exclude": null, 
            "install_repoquery": true, 
            "list": "zlib", 
            "name": null, 
            "state": "installed", 
            "update_cache": false, 
            "validate_certs": true
        }, 
        "module_name": "yum"
    }, 
    "results": [
        {
            "arch": "x86_64", 
            "epoch": "0", 
            "name": "zlib", 
            "nevra": "0:zlib-1.2.7-15.el7.x86_64", 
            "release": "15.el7", 
            "repo": "installed", 
            "version": "1.2.7", 
            "yumstate": "installed"
        }, 
        {
            "arch": "i686", 
            "epoch": "0", 
            "name": "zlib", 
            "nevra": "0:zlib-1.2.7-17.el7.i686", 
            "release": "17.el7", 
            "repo": "base", 
            "version": "1.2.7", 
            "yumstate": "available"
        }, 
        {
            "arch": "x86_64", 
            "epoch": "0", 
            "name": "zlib", 
            "nevra": "0:zlib-1.2.7-17.el7.x86_64", 
            "release": "17.el7", 
            "repo": "base", 
            "version": "1.2.7", 
            "yumstate": "available"
        }
    ]
}
```

##### ACTUAL RESULTS
```
Using /etc/ansible/ansible.cfg as config file
Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/site-packages/ansible/plugins/callback/__init__.pyc
Using module file /usr/lib/python2.7/site-packages/ansible/modules/core/packaging/os/yum.py
<172.16.3.118> ESTABLISH SSH CONNECTION FOR USER: root
<172.16.3.118> SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r 172.16.3.118 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo ~/.ansible/tmp/ansible-tmp-1490193076.22-207032486798751 `" && echo ansible-tmp-1490193076.22-207032486798751="` echo ~/.ansible/tmp/ansible-tmp-1490193076.22-207032486798751 `" ) && sleep 0'"'"''
<172.16.3.118> PUT /tmp/tmpuTFEqF TO /root/.ansible/tmp/ansible-tmp-1490193076.22-207032486798751/yum.py
<172.16.3.118> SSH: EXEC sshpass -d12 sftp -o BatchMode=no -b - -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r '[172.16.3.118]'
<172.16.3.118> ESTABLISH SSH CONNECTION FOR USER: root
<172.16.3.118> SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r 172.16.3.118 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1490193076.22-207032486798751/ /root/.ansible/tmp/ansible-tmp-1490193076.22-207032486798751/yum.py && sleep 0'"'"''
<172.16.3.118> ESTABLISH SSH CONNECTION FOR USER: root
<172.16.3.118> SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=root -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r -tt 172.16.3.118 '/bin/sh -c '"'"'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1490193076.22-207032486798751/yum.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1490193076.22-207032486798751/" > /dev/null 2>&1 && sleep 0'"'"''
172.16.3.118 | FAILED! => {
    "changed": false, 
    "failed": true, 
    "invocation": {
        "module_args": {
            "conf_file": null, 
            "disable_gpg_check": false, 
            "disablerepo": "*", 
            "enablerepo": "base", 
            "exclude": null, 
            "install_repoquery": true, 
            "list": "zlib", 
            "name": null, 
            "state": "installed", 
            "update_cache": false, 
            "validate_certs": true
        }, 
        "module_name": "yum"
    }, 
    "msg": "Error from repoquery: ['/usr/bin/repoquery', '--show-duplicates', '--plugins', '--quiet', '--disablerepo', '', '--enablerepo', '', '--qf', '%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}', 'zlib']: Could not match packages: failure: repodata/repomd.xml from unavailable: [Errno 256] No more mirrors to try.\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\nhttp://localhost/does/not/exist/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed connect to localhost:80; Connection refused\"\n"
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/modules/packaging/os/yum.py b/lib/ansible/modules/packaging/os/yum.py
--- a/lib/ansible/modules/packaging/os/yum.py
+++ b/lib/ansible/modules/packaging/os/yum.py
@@ -624,12 +624,16 @@ 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, installroot='/'):
+def list_stuff(module, repoquerybin, conf_file, stuff, installroot='/', disablerepo='', enablerepo=''):
 
     qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}"
     # is_installed goes through rpm instead of repoquery so it needs a slightly different format
     is_installed_qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|installed\n"
     repoq = [repoquerybin, '--show-duplicates', '--plugins', '--quiet']
+    if disablerepo:
+        repoq.extend(['--disablerepo', disablerepo])
+    if enablerepo:
+        repoq.extend(['--enablerepo', enablerepo])
     if installroot != '/':
         repoq.extend(['--installroot', installroot])
     if conf_file and os.path.exists(conf_file):
@@ -1216,7 +1220,9 @@ 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'], params['installroot']))
+        results = {'results': list_stuff(module, repoquerybin, params['conf_file'],
+                                         params['list'], params['installroot'],
+                                         params['disablerepo'], params['enablerepo'])}
 
     else:
         # If rhn-plugin is installed and no rhn-certificate is available on


Test patch: