We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[rpm_key] When no key is installed module fail to install any new key
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
rpm_key

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/lbednar/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/lbednar/work/kubevirt-org/kubevirt-ansible/E/lib/python2.7/site-packages/ansible
  executable location = /home/lbednar/work/kubevirt-org/kubevirt-ansible/E/bin/ansible
  python version = 2.7.13 (default, May 10 2017, 20:04:28) [GCC 6.3.1 20161221 (Red Hat 6.3.1-1)]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"

Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).

-->
```
DEFAULT_ROLES_PATH(env: ANSIBLE_ROLES_PATH) = [u'/home/lbednar/work/kubevirt-org/kubevirt-ansible/galaxy-roles']
```

##### 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.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
Target system CentOS 7.3

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

When running `rpm_key` to add new key on system which doesn't have any keys installed yet (I want to install first key), then module fails to add new key during execution following line:

https://github.com/ansible/ansible/blob/e609618274db6a7e3c273abde457f53de8c9976c/lib/ansible/modules/packaging/os/rpm_key.py#L173

the command fails with:
```
$ /usr/bin/rpm -q  gpg-pubkey --qf "%{description}"
package gpg-pubkey is not installed
```
and then following command in shell pipe fails on
```
$ /usr/bin/gpg --no-tty --batch --with-colons --fixed-list-mode -
gpg: no valid OpenPGP data found.
gpg: processing message failed: Unknown system error
```
At this point module stops execution and fail.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

**You need to make sure that you don't have any RPM KEY installed yet.**
This issue is reproducible only in case of when you are adding first rpm key.

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: import rpm keys
  rpm_key: 
    state: present
    key: "{{ item }}"
  with_items:
    - "https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg"
```

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

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

I would like to get rpm keys imported.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

No key is added and getting following output instead.

<!--- Paste verbatim command output between quotes below -->
```
failed: [vm-69-15.qa.lab.tlv.redhat.com] (item=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg) => {"changed": false, "failed": true, "item": "https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg", "msg": "gpg: no valid OpenPGP data found.\ngpg: processing message failed: Unknown system error\n"}
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/ansible/modules/packaging/os/rpm_key.py`
Content:
```
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 
4 # Ansible module to import third party repo keys to your rpm db
5 # (c) 2013, Héctor Acosta <hector.acosta@gazzang.com>
6 #
7 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
8 
9 from __future__ import absolute_import, division, print_function
10 __metaclass__ = type
11 
12 
13 ANSIBLE_METADATA = {'metadata_version': '1.1',
14                     'status': ['preview'],
15                     'supported_by': 'core'}
16 
17 
18 DOCUMENTATION = '''
19 ---
20 module: rpm_key
21 author: "Hector Acosta (@hacosta) <hector.acosta@gazzang.com>"
22 short_description: Adds or removes a gpg key from the rpm db
23 description:
24     - Adds or removes (rpm --import) a gpg key to your rpm database.
25 version_added: "1.3"
26 options:
27     key:
28       required: true
29       default: null
30       aliases: []
31       description:
32           - Key that will be modified. Can be a url, a file, or a keyid if the key already exists in the database.
33     state:
34       required: false
35       default: "present"
36       choices: [present, absent]
37       description:
38           - If the key will be imported or removed from the rpm db.
39     validate_certs:
40       description:
41           - If C(no) and the C(key) is a url starting with https, SSL certificates will not be validated. This should only be used
42             on personally controlled sites using self-signed certificates.
43       required: false
44       default: 'yes'
45       choices: ['yes', 'no']
46 
47 '''
48 
49 EXAMPLES = '''
50 # Example action to import a key from a url
51 - rpm_key:
52     state: present
53     key: http://apt.sw.be/RPM-GPG-KEY.dag.txt
54 
55 # Example action to import a key from a file
56 - rpm_key:
57     state: present
58     key: /path/to/key.gpg
59 
60 # Example action to ensure a key is not present in the db
61 - rpm_key:
62     state: absent
63     key: DEADB33F
64 '''
65 import re
66 import os.path
67 import tempfile
68 
69 # import module snippets
70 from ansible.module_utils.basic import AnsibleModule
71 from ansible.module_utils.urls import fetch_url
72 from ansible.module_utils._text import to_native
73 
74 
75 def is_pubkey(string):
76     """Verifies if string is a pubkey"""
77     pgp_regex = ".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*"
78     return bool(re.match(pgp_regex, to_native(string, errors='surrogate_or_strict'), re.DOTALL))
79 
80 
81 class RpmKey(object):
82 
83     def __init__(self, module):
84         # If the key is a url, we need to check if it's present to be idempotent,
85         # to do that, we need to check the keyid, which we can get from the armor.
86         keyfile = None
87         should_cleanup_keyfile = False
88         self.module = module
89         self.rpm = self.module.get_bin_path('rpm', True)
90         state = module.params['state']
91         key = module.params['key']
92 
93         self.gpg = self.module.get_bin_path('gpg')
94         if not self.gpg:
95             self.gpg = self.module.get_bin_path('gpg2',required=True)
96 
97         if '://' in key:
98             keyfile = self.fetch_key(key)
99             keyid = self.getkeyid(keyfile)
100             should_cleanup_keyfile = True
101         elif self.is_keyid(key):
102             keyid = key
103         elif os.path.isfile(key):
104             keyfile = key
105             keyid = self.getkeyid(keyfile)
106         else:
107             self.module.fail_json(msg="Not a valid key %s" % key)
108         keyid = self.normalize_keyid(keyid)
109 
110         if state == 'present':
111             if self.is_key_imported(keyid):
112                 module.exit_json(changed=False)
113             else:
114                 if not keyfile:
115                     self.module.fail_json(msg="When importing a key, a valid file must be given")
116                 self.import_key(keyfile)
117                 if should_cleanup_keyfile:
118                     self.module.cleanup(keyfile)
119                 module.exit_json(changed=True)
120         else:
121             if self.is_key_imported(keyid):
122                 self.drop_key(keyid)
123                 module.exit_json(changed=True)
124             else:
125                 module.exit_json(changed=False)
126 
127     def fetch_key(self, url):
128         """Downloads a key from url, returns a valid path to a gpg key"""
129         rsp, info = fetch_url(self.module, url)
130         if info['status'] != 200:
131             self.module.fail_json(msg="failed to fetch key at %s , error was: %s" % (url, info['msg']))
132 
133         key = rsp.read()
134         if not is_pubkey(key):
135             self.module.fail_json(msg="Not a public key: %s" % url)
136         tmpfd, tmpname = tempfile.mkstemp()
137         self.module.add_cleanup_file(tmpname)
138         tmpfile = os.fdopen(tmpfd, "w+b")
139         tmpfile.write(key)
140         tmpfile.close()
141         return tmpname
142 
143     def normalize_keyid(self, keyid):
144         """Ensure a keyid doesn't have a leading 0x, has leading or trailing whitespace, and make sure is uppercase"""
145         ret = keyid.strip().upper()
146         if ret.startswith('0x'):
147             return ret[2:]
148         elif ret.startswith('0X'):
149             return ret[2:]
150         else:
151             return ret
152 
153     def getkeyid(self, keyfile):
154         stdout, stderr = self.execute_command([self.gpg, '--no-tty', '--batch', '--with-colons', '--fixed-list-mode', keyfile])
155         for line in stdout.splitlines():
156             line = line.strip()
157             if line.startswith('pub:'):
158                 return line.split(':')[4]
159 
160         self.module.fail_json(msg="Unexpected gpg output")
161 
162     def is_keyid(self, keystr):
163         """Verifies if a key, as provided by the user is a keyid"""
164         return re.match('(0x)?[0-9a-f]{8}', keystr, flags=re.IGNORECASE)
165 
166     def execute_command(self, cmd):
167         rc, stdout, stderr = self.module.run_command(cmd, use_unsafe_shell=True)
168         if rc != 0:
169             self.module.fail_json(msg=stderr)
170         return stdout, stderr
171 
172     def is_key_imported(self, keyid):
173         cmd=self.rpm + ' -q  gpg-pubkey --qf "%{description}" | ' + self.gpg + ' --no-tty --batch --with-colons --fixed-list-mode -'
174         stdout, stderr = self.execute_command(cmd)
175         for line in stdout.splitlines():
176             if keyid in line.split(':')[4]:
177                     return True
178         return False
179 
180     def import_key(self, keyfile):
181         if not self.module.check_mode:
182             self.execute_command([self.rpm, '--import', keyfile])
183 
184     def drop_key(self, keyid):
185         if not self.module.check_mode:
186             self.execute_command([self.rpm, '--erase', '--allmatches', "gpg-pubkey-%s" % keyid[-8:].lower()])
187 
188 
189 def main():
190     module = AnsibleModule(
191         argument_spec = dict(
192             state=dict(default='present', choices=['present', 'absent'], type='str'),
193             key=dict(required=True, type='str'),
194             validate_certs=dict(default='yes', type='bool'),
195             ),
196         supports_check_mode=True
197         )
198 
199     RpmKey(module)
200 
201 
202 if __name__ == '__main__':
203     main()
204
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lib/ansible/modules/packaging/os/rpm_key.py b/lib/ansible/modules/packaging/os/rpm_key.py
--- a/lib/ansible/modules/packaging/os/rpm_key.py
+++ b/lib/ansible/modules/packaging/os/rpm_key.py
@@ -170,11 +170,15 @@
         return stdout, stderr
 
     def is_key_imported(self, keyid):
-        cmd=self.rpm + ' -q  gpg-pubkey --qf "%{description}" | ' + self.gpg + ' --no-tty --batch --with-colons --fixed-list-mode -'
+        cmd = self.rpm + ' -q  gpg-pubkey'
+        rc, stdout, stderr = self.module.run_command(cmd)
+        if rc != 0:  # No key is installed on system
+            return False
+        cmd += ' --qf "%{description}" | ' + self.gpg + ' --no-tty --batch --with-colons --fixed-list-mode -'
         stdout, stderr = self.execute_command(cmd)
         for line in stdout.splitlines():
             if keyid in line.split(':')[4]:
-                    return True
+                return True
         return False
 
     def import_key(self, keyfile):

{"golden_diff": "diff --git a/lib/ansible/modules/packaging/os/rpm_key.py b/lib/ansible/modules/packaging/os/rpm_key.py\n--- a/lib/ansible/modules/packaging/os/rpm_key.py\n+++ b/lib/ansible/modules/packaging/os/rpm_key.py\n@@ -170,11 +170,15 @@\n         return stdout, stderr\n \n     def is_key_imported(self, keyid):\n-        cmd=self.rpm + ' -q  gpg-pubkey --qf \"%{description}\" | ' + self.gpg + ' --no-tty --batch --with-colons --fixed-list-mode -'\n+        cmd = self.rpm + ' -q  gpg-pubkey'\n+        rc, stdout, stderr = self.module.run_command(cmd)\n+        if rc != 0:  # No key is installed on system\n+            return False\n+        cmd += ' --qf \"%{description}\" | ' + self.gpg + ' --no-tty --batch --with-colons --fixed-list-mode -'\n         stdout, stderr = self.execute_command(cmd)\n         for line in stdout.splitlines():\n             if keyid in line.split(':')[4]:\n-                    return True\n+                return True\n         return False\n \n     def import_key(self, keyfile):\n", "issue": "[rpm_key] When no key is installed module fail to install any new key\n<!---\r\nVerify first that your issue/request is not already reported on GitHub.\r\nAlso test if the latest release, and master branch are affected too.\r\n-->\r\n\r\n##### ISSUE TYPE\r\n<!--- Pick one below and delete the rest: -->\r\n - Bug Report\r\n\r\n##### COMPONENT NAME\r\n<!--- Name of the module/plugin/task/feature -->\r\nrpm_key\r\n\r\n##### ANSIBLE VERSION\r\n<!--- Paste verbatim output from \"ansible --version\" between quotes below -->\r\n```\r\nansible 2.4.0.0\r\n  config file = /etc/ansible/ansible.cfg\r\n  configured module search path = [u'/home/lbednar/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']\r\n  ansible python module location = /home/lbednar/work/kubevirt-org/kubevirt-ansible/E/lib/python2.7/site-packages/ansible\r\n  executable location = /home/lbednar/work/kubevirt-org/kubevirt-ansible/E/bin/ansible\r\n  python version = 2.7.13 (default, May 10 2017, 20:04:28) [GCC 6.3.1 20161221 (Red Hat 6.3.1-1)]\r\n```\r\n\r\n##### CONFIGURATION\r\n<!---\r\nIf using Ansible 2.4 or above, paste the results of \"ansible-config dump --only-changed\"\r\n\r\nOtherwise, mention any settings you have changed/added/removed in ansible.cfg\r\n(or using the ANSIBLE_* environment variables).\r\n\r\n-->\r\n```\r\nDEFAULT_ROLES_PATH(env: ANSIBLE_ROLES_PATH) = [u'/home/lbednar/work/kubevirt-org/kubevirt-ansible/galaxy-roles']\r\n```\r\n\r\n##### OS / ENVIRONMENT\r\n<!---\r\nMention the OS you are running Ansible from, and the OS you are\r\nmanaging, or say \"N/A\" for anything that is not platform-specific.\r\nAlso mention the specific version of what you are trying to control,\r\ne.g. if this is a network bug the version of firmware on the network device.\r\n-->\r\nTarget system CentOS 7.3\r\n\r\n##### SUMMARY\r\n<!--- Explain the problem briefly -->\r\n\r\nWhen running `rpm_key` to add new key on system which doesn't have any keys installed yet (I want to install first key), then module fails to add new key during execution following line:\r\n\r\nhttps://github.com/ansible/ansible/blob/e609618274db6a7e3c273abde457f53de8c9976c/lib/ansible/modules/packaging/os/rpm_key.py#L173\r\n\r\nthe command fails with:\r\n```\r\n$ /usr/bin/rpm -q  gpg-pubkey --qf \"%{description}\"\r\npackage gpg-pubkey is not installed\r\n```\r\nand then following command in shell pipe fails on\r\n```\r\n$ /usr/bin/gpg --no-tty --batch --with-colons --fixed-list-mode -\r\ngpg: no valid OpenPGP data found.\r\ngpg: processing message failed: Unknown system error\r\n```\r\nAt this point module stops execution and fail.\r\n\r\n##### STEPS TO REPRODUCE\r\n<!---\r\nFor bugs, show exactly how to reproduce the problem, using a minimal test-case.\r\nFor new features, show how the feature would be used.\r\n-->\r\n\r\n**You need to make sure that you don't have any RPM KEY installed yet.**\r\nThis issue is reproducible only in case of when you are adding first rpm key.\r\n\r\n<!--- Paste example playbooks or commands between quotes below -->\r\n```yaml\r\n- name: import rpm keys\r\n  rpm_key: \r\n    state: present\r\n    key: \"{{ item }}\"\r\n  with_items:\r\n    - \"https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg\"\r\n```\r\n\r\n<!--- You can also paste gist.github.com links for larger files -->\r\n\r\n##### EXPECTED RESULTS\r\n<!--- What did you expect to happen when running the steps above? -->\r\n\r\nI would like to get rpm keys imported.\r\n\r\n##### ACTUAL RESULTS\r\n<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->\r\n\r\nNo key is added and getting following output instead.\r\n\r\n<!--- Paste verbatim command output between quotes below -->\r\n```\r\nfailed: [vm-69-15.qa.lab.tlv.redhat.com] (item=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg) => {\"changed\": false, \"failed\": true, \"item\": \"https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg\", \"msg\": \"gpg: no valid OpenPGP data found.\\ngpg: processing message failed: Unknown system error\\n\"}\r\n```\r\n\n", "before_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# Ansible module to import third party repo keys to your rpm db\n# (c) 2013, H\u00e9ctor Acosta <hector.acosta@gazzang.com>\n#\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\nfrom __future__ import absolute_import, division, print_function\n__metaclass__ = type\n\n\nANSIBLE_METADATA = {'metadata_version': '1.1',\n                    'status': ['preview'],\n                    'supported_by': 'core'}\n\n\nDOCUMENTATION = '''\n---\nmodule: rpm_key\nauthor: \"Hector Acosta (@hacosta) <hector.acosta@gazzang.com>\"\nshort_description: Adds or removes a gpg key from the rpm db\ndescription:\n    - Adds or removes (rpm --import) a gpg key to your rpm database.\nversion_added: \"1.3\"\noptions:\n    key:\n      required: true\n      default: null\n      aliases: []\n      description:\n          - Key that will be modified. Can be a url, a file, or a keyid if the key already exists in the database.\n    state:\n      required: false\n      default: \"present\"\n      choices: [present, absent]\n      description:\n          - If the key will be imported or removed from the rpm db.\n    validate_certs:\n      description:\n          - If C(no) and the C(key) is a url starting with https, SSL certificates will not be validated. This should only be used\n            on personally controlled sites using self-signed certificates.\n      required: false\n      default: 'yes'\n      choices: ['yes', 'no']\n\n'''\n\nEXAMPLES = '''\n# Example action to import a key from a url\n- rpm_key:\n    state: present\n    key: http://apt.sw.be/RPM-GPG-KEY.dag.txt\n\n# Example action to import a key from a file\n- rpm_key:\n    state: present\n    key: /path/to/key.gpg\n\n# Example action to ensure a key is not present in the db\n- rpm_key:\n    state: absent\n    key: DEADB33F\n'''\nimport re\nimport os.path\nimport tempfile\n\n# import module snippets\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible.module_utils.urls import fetch_url\nfrom ansible.module_utils._text import to_native\n\n\ndef is_pubkey(string):\n    \"\"\"Verifies if string is a pubkey\"\"\"\n    pgp_regex = \".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*\"\n    return bool(re.match(pgp_regex, to_native(string, errors='surrogate_or_strict'), re.DOTALL))\n\n\nclass RpmKey(object):\n\n    def __init__(self, module):\n        # If the key is a url, we need to check if it's present to be idempotent,\n        # to do that, we need to check the keyid, which we can get from the armor.\n        keyfile = None\n        should_cleanup_keyfile = False\n        self.module = module\n        self.rpm = self.module.get_bin_path('rpm', True)\n        state = module.params['state']\n        key = module.params['key']\n\n        self.gpg = self.module.get_bin_path('gpg')\n        if not self.gpg:\n            self.gpg = self.module.get_bin_path('gpg2',required=True)\n\n        if '://' in key:\n            keyfile = self.fetch_key(key)\n            keyid = self.getkeyid(keyfile)\n            should_cleanup_keyfile = True\n        elif self.is_keyid(key):\n            keyid = key\n        elif os.path.isfile(key):\n            keyfile = key\n            keyid = self.getkeyid(keyfile)\n        else:\n            self.module.fail_json(msg=\"Not a valid key %s\" % key)\n        keyid = self.normalize_keyid(keyid)\n\n        if state == 'present':\n            if self.is_key_imported(keyid):\n                module.exit_json(changed=False)\n            else:\n                if not keyfile:\n                    self.module.fail_json(msg=\"When importing a key, a valid file must be given\")\n                self.import_key(keyfile)\n                if should_cleanup_keyfile:\n                    self.module.cleanup(keyfile)\n                module.exit_json(changed=True)\n        else:\n            if self.is_key_imported(keyid):\n                self.drop_key(keyid)\n                module.exit_json(changed=True)\n            else:\n                module.exit_json(changed=False)\n\n    def fetch_key(self, url):\n        \"\"\"Downloads a key from url, returns a valid path to a gpg key\"\"\"\n        rsp, info = fetch_url(self.module, url)\n        if info['status'] != 200:\n            self.module.fail_json(msg=\"failed to fetch key at %s , error was: %s\" % (url, info['msg']))\n\n        key = rsp.read()\n        if not is_pubkey(key):\n            self.module.fail_json(msg=\"Not a public key: %s\" % url)\n        tmpfd, tmpname = tempfile.mkstemp()\n        self.module.add_cleanup_file(tmpname)\n        tmpfile = os.fdopen(tmpfd, \"w+b\")\n        tmpfile.write(key)\n        tmpfile.close()\n        return tmpname\n\n    def normalize_keyid(self, keyid):\n        \"\"\"Ensure a keyid doesn't have a leading 0x, has leading or trailing whitespace, and make sure is uppercase\"\"\"\n        ret = keyid.strip().upper()\n        if ret.startswith('0x'):\n            return ret[2:]\n        elif ret.startswith('0X'):\n            return ret[2:]\n        else:\n            return ret\n\n    def getkeyid(self, keyfile):\n        stdout, stderr = self.execute_command([self.gpg, '--no-tty', '--batch', '--with-colons', '--fixed-list-mode', keyfile])\n        for line in stdout.splitlines():\n            line = line.strip()\n            if line.startswith('pub:'):\n                return line.split(':')[4]\n\n        self.module.fail_json(msg=\"Unexpected gpg output\")\n\n    def is_keyid(self, keystr):\n        \"\"\"Verifies if a key, as provided by the user is a keyid\"\"\"\n        return re.match('(0x)?[0-9a-f]{8}', keystr, flags=re.IGNORECASE)\n\n    def execute_command(self, cmd):\n        rc, stdout, stderr = self.module.run_command(cmd, use_unsafe_shell=True)\n        if rc != 0:\n            self.module.fail_json(msg=stderr)\n        return stdout, stderr\n\n    def is_key_imported(self, keyid):\n        cmd=self.rpm + ' -q  gpg-pubkey --qf \"%{description}\" | ' + self.gpg + ' --no-tty --batch --with-colons --fixed-list-mode -'\n        stdout, stderr = self.execute_command(cmd)\n        for line in stdout.splitlines():\n            if keyid in line.split(':')[4]:\n                    return True\n        return False\n\n    def import_key(self, keyfile):\n        if not self.module.check_mode:\n            self.execute_command([self.rpm, '--import', keyfile])\n\n    def drop_key(self, keyid):\n        if not self.module.check_mode:\n            self.execute_command([self.rpm, '--erase', '--allmatches', \"gpg-pubkey-%s\" % keyid[-8:].lower()])\n\n\ndef main():\n    module = AnsibleModule(\n        argument_spec = dict(\n            state=dict(default='present', choices=['present', 'absent'], type='str'),\n            key=dict(required=True, type='str'),\n            validate_certs=dict(default='yes', type='bool'),\n            ),\n        supports_check_mode=True\n        )\n\n    RpmKey(module)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "lib/ansible/modules/packaging/os/rpm_key.py"}], "after_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# Ansible module to import third party repo keys to your rpm db\n# (c) 2013, H\u00e9ctor Acosta <hector.acosta@gazzang.com>\n#\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\nfrom __future__ import absolute_import, division, print_function\n__metaclass__ = type\n\n\nANSIBLE_METADATA = {'metadata_version': '1.1',\n                    'status': ['preview'],\n                    'supported_by': 'core'}\n\n\nDOCUMENTATION = '''\n---\nmodule: rpm_key\nauthor: \"Hector Acosta (@hacosta) <hector.acosta@gazzang.com>\"\nshort_description: Adds or removes a gpg key from the rpm db\ndescription:\n    - Adds or removes (rpm --import) a gpg key to your rpm database.\nversion_added: \"1.3\"\noptions:\n    key:\n      required: true\n      default: null\n      aliases: []\n      description:\n          - Key that will be modified. Can be a url, a file, or a keyid if the key already exists in the database.\n    state:\n      required: false\n      default: \"present\"\n      choices: [present, absent]\n      description:\n          - If the key will be imported or removed from the rpm db.\n    validate_certs:\n      description:\n          - If C(no) and the C(key) is a url starting with https, SSL certificates will not be validated. This should only be used\n            on personally controlled sites using self-signed certificates.\n      required: false\n      default: 'yes'\n      choices: ['yes', 'no']\n\n'''\n\nEXAMPLES = '''\n# Example action to import a key from a url\n- rpm_key:\n    state: present\n    key: http://apt.sw.be/RPM-GPG-KEY.dag.txt\n\n# Example action to import a key from a file\n- rpm_key:\n    state: present\n    key: /path/to/key.gpg\n\n# Example action to ensure a key is not present in the db\n- rpm_key:\n    state: absent\n    key: DEADB33F\n'''\nimport re\nimport os.path\nimport tempfile\n\n# import module snippets\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible.module_utils.urls import fetch_url\nfrom ansible.module_utils._text import to_native\n\n\ndef is_pubkey(string):\n    \"\"\"Verifies if string is a pubkey\"\"\"\n    pgp_regex = \".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*\"\n    return bool(re.match(pgp_regex, to_native(string, errors='surrogate_or_strict'), re.DOTALL))\n\n\nclass RpmKey(object):\n\n    def __init__(self, module):\n        # If the key is a url, we need to check if it's present to be idempotent,\n        # to do that, we need to check the keyid, which we can get from the armor.\n        keyfile = None\n        should_cleanup_keyfile = False\n        self.module = module\n        self.rpm = self.module.get_bin_path('rpm', True)\n        state = module.params['state']\n        key = module.params['key']\n\n        self.gpg = self.module.get_bin_path('gpg')\n        if not self.gpg:\n            self.gpg = self.module.get_bin_path('gpg2',required=True)\n\n        if '://' in key:\n            keyfile = self.fetch_key(key)\n            keyid = self.getkeyid(keyfile)\n            should_cleanup_keyfile = True\n        elif self.is_keyid(key):\n            keyid = key\n        elif os.path.isfile(key):\n            keyfile = key\n            keyid = self.getkeyid(keyfile)\n        else:\n            self.module.fail_json(msg=\"Not a valid key %s\" % key)\n        keyid = self.normalize_keyid(keyid)\n\n        if state == 'present':\n            if self.is_key_imported(keyid):\n                module.exit_json(changed=False)\n            else:\n                if not keyfile:\n                    self.module.fail_json(msg=\"When importing a key, a valid file must be given\")\n                self.import_key(keyfile)\n                if should_cleanup_keyfile:\n                    self.module.cleanup(keyfile)\n                module.exit_json(changed=True)\n        else:\n            if self.is_key_imported(keyid):\n                self.drop_key(keyid)\n                module.exit_json(changed=True)\n            else:\n                module.exit_json(changed=False)\n\n    def fetch_key(self, url):\n        \"\"\"Downloads a key from url, returns a valid path to a gpg key\"\"\"\n        rsp, info = fetch_url(self.module, url)\n        if info['status'] != 200:\n            self.module.fail_json(msg=\"failed to fetch key at %s , error was: %s\" % (url, info['msg']))\n\n        key = rsp.read()\n        if not is_pubkey(key):\n            self.module.fail_json(msg=\"Not a public key: %s\" % url)\n        tmpfd, tmpname = tempfile.mkstemp()\n        self.module.add_cleanup_file(tmpname)\n        tmpfile = os.fdopen(tmpfd, \"w+b\")\n        tmpfile.write(key)\n        tmpfile.close()\n        return tmpname\n\n    def normalize_keyid(self, keyid):\n        \"\"\"Ensure a keyid doesn't have a leading 0x, has leading or trailing whitespace, and make sure is uppercase\"\"\"\n        ret = keyid.strip().upper()\n        if ret.startswith('0x'):\n            return ret[2:]\n        elif ret.startswith('0X'):\n            return ret[2:]\n        else:\n            return ret\n\n    def getkeyid(self, keyfile):\n        stdout, stderr = self.execute_command([self.gpg, '--no-tty', '--batch', '--with-colons', '--fixed-list-mode', keyfile])\n        for line in stdout.splitlines():\n            line = line.strip()\n            if line.startswith('pub:'):\n                return line.split(':')[4]\n\n        self.module.fail_json(msg=\"Unexpected gpg output\")\n\n    def is_keyid(self, keystr):\n        \"\"\"Verifies if a key, as provided by the user is a keyid\"\"\"\n        return re.match('(0x)?[0-9a-f]{8}', keystr, flags=re.IGNORECASE)\n\n    def execute_command(self, cmd):\n        rc, stdout, stderr = self.module.run_command(cmd, use_unsafe_shell=True)\n        if rc != 0:\n            self.module.fail_json(msg=stderr)\n        return stdout, stderr\n\n    def is_key_imported(self, keyid):\n        cmd = self.rpm + ' -q  gpg-pubkey'\n        rc, stdout, stderr = self.module.run_command(cmd)\n        if rc != 0:  # No key is installed on system\n            return False\n        cmd += ' --qf \"%{description}\" | ' + self.gpg + ' --no-tty --batch --with-colons --fixed-list-mode -'\n        stdout, stderr = self.execute_command(cmd)\n        for line in stdout.splitlines():\n            if keyid in line.split(':')[4]:\n                return True\n        return False\n\n    def import_key(self, keyfile):\n        if not self.module.check_mode:\n            self.execute_command([self.rpm, '--import', keyfile])\n\n    def drop_key(self, keyid):\n        if not self.module.check_mode:\n            self.execute_command([self.rpm, '--erase', '--allmatches', \"gpg-pubkey-%s\" % keyid[-8:].lower()])\n\n\ndef main():\n    module = AnsibleModule(\n        argument_spec = dict(\n            state=dict(default='present', choices=['present', 'absent'], type='str'),\n            key=dict(required=True, type='str'),\n            validate_certs=dict(default='yes', type='bool'),\n            ),\n        supports_check_mode=True\n        )\n\n    RpmKey(module)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "lib/ansible/modules/packaging/os/rpm_key.py"}]}