Repository: ansible/ansible-modules-extras

Issue:
zypper_repository fails with Unknown option '--gpgcheck' on SLES 11.1
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### COMPONENT NAME

<!--- Name of the plugin/module/task -->
- zypper_repository
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
$ ansible --version
ansible 2.1.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
##### OS / ENVIRONMENT

<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

From

```
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04 LTS"
```

Managing

```
# cat /etc/SuSE-release
SUSE Linux Enterprise Server 11 (x86_64)
VERSION = 11
PATCHLEVEL = 1
```
##### SUMMARY

<!--- Explain the problem briefly -->

Trying to add a new repository using the `zypper_repository` module results in the following error.

```
Unknown option '--gpgcheck'
```
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

Get a clean install SLES 11.1, and try to add a repository.

<!--- Paste example playbooks or commands between quotes below -->

```
  zypper_repository: name=NAME
                     repo=REPO_URL
                     state=present
```

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->

No error.
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with high verbosity (-vvvv) -->

Error.

<!--- Paste verbatim command output between quotes below -->

```
fatal: [endpoint]: FAILED! => {"changed": false, "failed": true, "msg": "Unknown option '--gpgcheck'\n"}
```
##### ADDITIONAL INFORMATION

This works fine with SLES 11.4. The zypper versions and help output are as follows.

SLES11.1

```
# /usr/bin/zypper --version
zypper 1.3.7
# zypper ar --help
addrepo (ar) [options] <URI> <alias>
addrepo (ar) [options] <file.repo>

Add a repository to the sytem. The repository can be specified by its URI or can be read from specified .repo file (even remote).

  Command options:
-r, --repo <file.repo>  Just another means to specify a .repo file to read.
-t, --type <type>       Type of repository (yast2, rpm-md, plaindir).
-d, --disable           Add the repository as disabled.
-c, --check             Probe URI.
-C, --no-check          Don't probe URI, probe later during refresh.
-n, --name <name>       Specify descriptive name for the repository.
-k, --keep-packages     Enable RPM files caching.
-K, --no-keep-packages  Disable RPM files caching.
-f, --refresh           Enable autorefresh of the repository.
```

SLES 11.4

```
# zypper --version
zypper 1.6.326
# zypper ar --help
addrepo (ar) [options] <URI> <alias>
addrepo (ar) [options] <file.repo>

Add a repository to the system. The repository can be specified by its URI or can be read from specified .repo file (even remote).

  Command options:
-r, --repo <file.repo>  Just another means to specify a .repo file to read.
-t, --type <type>       Type of repository (yast2, rpm-md, plaindir).
-d, --disable           Add the repository as disabled.
-c, --check             Probe URI.
-C, --no-check          Don't probe URI, probe later during refresh.
-n, --name <name>       Specify descriptive name for the repository.
-k, --keep-packages     Enable RPM files caching.
-K, --no-keep-packages  Disable RPM files caching.
-g, --gpgcheck          Enable GPG check for this repository.
-G, --no-gpgcheck       Disable GPG check for this repository.
-f, --refresh           Enable autorefresh of the repository.
```



Discussion:
@robinro If you need any more information, just let me know.


Resolving patch:
diff --git a/packaging/os/zypper_repository.py b/packaging/os/zypper_repository.py
--- a/packaging/os/zypper_repository.py
+++ b/packaging/os/zypper_repository.py
@@ -55,6 +55,7 @@
             - Whether to disable GPG signature checking of
               all packages. Has an effect only if state is
               I(present).
+            - Needs zypper version >= 1.6.2.
         required: false
         default: "no"
         choices: [ "yes", "no" ]
@@ -68,6 +69,7 @@
         description:
             - Set priority of repository. Packages will always be installed
               from the repository with the smallest priority number.
+            - Needs zypper version >= 1.12.25.
         required: false
         version_added: "2.1"
     overwrite_multiple:
@@ -95,6 +97,8 @@
 
 REPO_OPTS = ['alias', 'name', 'priority', 'enabled', 'autorefresh', 'gpgcheck']
 
+from distutils.version import LooseVersion
+
 def _parse_repos(module):
     """parses the output of zypper -x lr and return a parse repo dictionary"""
     cmd = ['/usr/bin/zypper', '-x', 'lr']
@@ -167,22 +171,33 @@ def repo_exists(module, repodata, overwrite_multiple):
             module.fail_json(msg=errmsg)
 
 
-def modify_repo(module, repodata, old_repos):
+def modify_repo(module, repodata, old_repos, zypper_version, warnings):
     repo = repodata['url']
     cmd = ['/usr/bin/zypper', 'ar', '--check']
     if repodata['name']:
         cmd.extend(['--name', repodata['name']])
 
+    # priority on addrepo available since 1.12.25
+    # https://github.com/openSUSE/zypper/blob/b9b3cb6db76c47dc4c47e26f6a4d2d4a0d12b06d/package/zypper.changes#L327-L336 
     if repodata['priority']:
-        cmd.extend(['--priority', str(repodata['priority'])])
+        if zypper_version >= LooseVersion('1.12.25'):
+            cmd.extend(['--priority', str(repodata['priority'])])
+        else:
+            warnings.append("Setting priority only available for zypper >= 1.12.25. Ignoring priority argument.")
 
     if repodata['enabled'] == '0':
         cmd.append('--disable')
 
-    if repodata['gpgcheck'] == '1':
-        cmd.append('--gpgcheck')
+    # gpgcheck available since 1.6.2
+    # https://github.com/openSUSE/zypper/blob/b9b3cb6db76c47dc4c47e26f6a4d2d4a0d12b06d/package/zypper.changes#L2446-L2449
+    # the default changed in the past, so don't assume a default here and show warning for old zypper versions
+    if zypper_version >= LooseVersion('1.6.2'):
+        if repodata['gpgcheck'] == '1':
+            cmd.append('--gpgcheck')
+        else:
+            cmd.append('--no-gpgcheck')
     else:
-        cmd.append('--no-gpgcheck')
+        warnings.append("Enabling/disabling gpgcheck only available for zypper >= 1.6.2. Using zypper default value.")
 
     if repodata['autorefresh'] == '1':
         cmd.append('--refresh')
@@ -217,6 +232,13 @@ def remove_repo(module, repo):
     return changed
 
 
+def get_zypper_version(module):
+    rc, stdout, stderr = module.run_command(['/usr/bin/zypper', '--version'])
+    if rc != 0 or not stdout.startswith('zypper '):
+        return LooseVersion('1.0')
+    return LooseVersion(stdout.split()[1])
+
+
 def fail_if_rc_is_null(module, rc, stdout, stderr):
     if rc != 0:
         #module.fail_json(msg=stderr if stderr else stdout)
@@ -233,11 +255,11 @@ def main():
             repo=dict(required=False),
             state=dict(choices=['present', 'absent'], default='present'),
             description=dict(required=False),
-            disable_gpg_check = dict(required=False, default='no', type='bool'),
-            refresh = dict(required=False, default='yes', type='bool'),
+            disable_gpg_check = dict(required=False, default=False, type='bool'),
+            refresh = dict(required=False, default=True, type='bool'),
             priority = dict(required=False, type='int'),
-            enabled = dict(required=False, default='yes', type='bool'),
-            overwrite_multiple = dict(required=False, default='no', type='bool'),
+            enabled = dict(required=False, default=True, type='bool'),
+            overwrite_multiple = dict(required=False, default=False, type='bool'),
         ),
         supports_check_mode=False,
     )
@@ -247,6 +269,9 @@ def main():
     state = module.params['state']
     overwrite_multiple = module.params['overwrite_multiple']
 
+    zypper_version = get_zypper_version(module)
+    warnings = []  # collect warning messages for final output
+
     repodata = {
         'url': repo,
         'alias': alias,
@@ -288,7 +313,7 @@ def exit_unchanged():
     if state == 'present':
         if exists and not mod:
             exit_unchanged()
-        changed = modify_repo(module, repodata, old_repos)
+        changed = modify_repo(module, repodata, old_repos, zypper_version, warnings)
     elif state == 'absent':
         if not exists:
             exit_unchanged()
@@ -296,7 +321,7 @@ def exit_unchanged():
             repo=alias
         changed = remove_repo(module, repo)
 
-    module.exit_json(changed=changed, repodata=repodata, state=state)
+    module.exit_json(changed=changed, repodata=repodata, state=state, warnings=warnings)
 
 # import module snippets
 from ansible.module_utils.basic import *


Test patch: