Repository: ansible/ansible

Issue:
zypper module with 'update_cache=yes' fails in check_mode

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
zypper

##### ANSIBLE VERSION
```
ansible 2.2.0.0
  config file = /Users/xyz/.ansible.cfg
  configured module search path = Default w/o overrides
```

##### OS / ENVIRONMENT
N/A (tested on OSX 10.12 and openSUSE Tumbleweed)

##### SUMMARY
Calling a zypper task with 'update_cache=yes' in check_mode (ansible-playbook ... --check) results in an error:
```
fatal: [foobar]: FAILED! => {"changed": false, "cmd": ["/usr/bin/zypper", "--quiet", "--non-interactive", "--xmlout", "refresh", "--dry-run"], "failed": true, "msg": "Zypper run command failed with return code 2.", "rc": 2, "stderr": "Unknown option '--dry-run'\n", "stdout": "<?xml version='1.0'?>\n<stream>\n</stream>\n", "stdout_lines": ["<?xml version='1.0'?>", "<stream>", "</stream>"]}
```
This is due to the reason that 'zypper install' has a --dry-run switch, while zypper refresh (which is being called when update_cache is set to yes) does not have this.

##### STEPS TO REPRODUCE
Call the following playbook with the --check option:
ansible-playbook zypper.yml --check

```
---
# file zypper.yml
- hosts: foobar
  tasks:
    - zypper:
        name: dracut
        state: latest
        update_cache: yes
```

##### EXPECTED RESULTS
It would be nice if this would not error out. But it can't work, because either
- it does actually refresh the cache, even in check_mode or
- it does not refresh the cache and thus might not know about new package or newer versions

##### ACTUAL RESULTS
The task throws an error
```
fatal: [foobar]: FAILED! => {"changed": false, "cmd": ["/usr/bin/zypper", "--quiet", "--non-interactive", "--xmlout", "refresh", "--dry-run"], "failed": true, "msg": "Zypper run command failed with return code 2.", "rc": 2, "stderr": "Unknown option '--dry-run'\n", "stdout": "<?xml version='1.0'?>\n<stream>\n</stream>\n", "stdout_lines": ["<?xml version='1.0'?>", "<stream>", "</stream>"]}
```



Discussion:
cc @robinro
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/packaging/os/zypper.py b/lib/ansible/modules/packaging/os/zypper.py
--- a/lib/ansible/modules/packaging/os/zypper.py
+++ b/lib/ansible/modules/packaging/os/zypper.py
@@ -95,7 +95,7 @@
     update_cache:
         version_added: "2.2"
         description:
-          - Run the equivalent of C(zypper refresh) before the operation.
+          - Run the equivalent of C(zypper refresh) before the operation. Disabled in check mode.
         required: false
         default: "no"
         choices: [ "yes", "no" ]
@@ -442,7 +442,7 @@ def main():
     name = filter(None, name)
 
     # Refresh repositories
-    if update_cache:
+    if update_cache and not module.check_mode:
         retvals = repo_refresh(module)
 
         if retvals['rc'] != 0:


Test patch:
diff --git a/test/integration/targets/zypper/tasks/zypper.yml b/test/integration/targets/zypper/tasks/zypper.yml
--- a/test/integration/targets/zypper/tasks/zypper.yml
+++ b/test/integration/targets/zypper/tasks/zypper.yml
@@ -334,3 +334,27 @@
         - zypperin1|changed
         - not zypperin2|changed
   when: ansible_distribution == 'openSUSE Leap' and ansible_distribution_version == '42.1'
+
+
+# check for https://github.com/ansible/ansible/issues/20139
+- name: run updatecache
+  zypper:
+    name: hello
+    state: present
+    update_cache: True
+  register: zypper_result_update_cache
+
+- name: run updatecache in check mode
+  zypper:
+    name: hello
+    state: present
+    update_cache: True
+  check_mode: True
+  register: zypper_result_update_cache_check
+
+
+- assert:
+    that:
+      - zypper_result_update_cache|success
+      - zypper_result_update_cache_check|success
+      - not zypper_result_update_cache_check|changed