We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
tag attribute in ec2_snapshot_facts module should be dict instead of list
##### ISSUE TYPE
 - Documentation Report

##### COMPONENT NAME
ansible-modules-extras/cloud/amazon/ec2_snapshot_facts.py

##### ANSIBLE VERSION
```
$ ansible --version
ansible 2.2.1.0
  config file = /home/psd/.ansible.cfg
  configured module search path = ['/home/psd/.ansible/library']
```

##### CONFIGURATION
N/A. Not configuration-specific

##### OS / ENVIRONMENT
N/A

##### SUMMARY
The returned snapshots dict have a tag attribute, it was already [converted to dict in the code](https://github.com/ansible/ansible-modules-extras/blob/devel/cloud/amazon/ec2_snapshot_facts.py#L196)

So the expected tag attr in this module is a dict, not a list(which is the return value type in boto3)

##### STEPS TO REPRODUCE
get snapshot_facts, we have an example output in the next section:

##### ACTUAL RESULTS

```
        {
            "description": "",
            "encrypted": false,
            "owner_id": "omitted",
            "progress": "100%",
            "snapshot_id": "snap-omitted",
            "start_time": "2017-03-08T03:52:29+00:00",
            "state": "completed",
            "tags": {
                "Name": "some name",
                "creator": "cron on some machine",
                "frequency": "hourly"
            },
            "volume_id": "vol-omitted",
            "volume_size": 40
        }
```
As you can see, the tags attr is a dict.

--- 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/cloud/amazon/ec2_snapshot_facts.py`
Content:
```
1 #!/usr/bin/python
2 # This file is part of Ansible
3 #
4 # Ansible is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # Ansible is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
16 
17 ANSIBLE_METADATA = {'status': ['preview'],
18                     'supported_by': 'community',
19                     'version': '1.0'}
20 
21 DOCUMENTATION = '''
22 ---
23 module: ec2_snapshot_facts
24 short_description: Gather facts about ec2 volume snapshots in AWS
25 description:
26     - Gather facts about ec2 volume snapshots in AWS
27 version_added: "2.1"
28 author: "Rob White (@wimnat)"
29 options:
30   snapshot_ids:
31     description:
32       - If you specify one or more snapshot IDs, only snapshots that have the specified IDs are returned.
33     required: false
34     default: []
35   owner_ids:
36     description:
37       - If you specify one or more snapshot owners, only snapshots from the specified owners and for which you have \
38       access are returned.
39     required: false
40     default: []
41   restorable_by_user_ids:
42     description:
43       - If you specify a list of restorable users, only snapshots with create snapshot permissions for those users are \
44       returned.
45     required: false
46     default: []
47   filters:
48     description:
49       - A dict of filters to apply. Each dict item consists of a filter key and a filter value. See \
50       U(http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSnapshots.html) for possible filters. Filter \
51       names and values are case sensitive.
52     required: false
53     default: {}
54 notes:
55   - By default, the module will return all snapshots, including public ones. To limit results to snapshots owned by \
56   the account use the filter 'owner-id'.
57 
58 extends_documentation_fragment:
59     - aws
60     - ec2
61 '''
62 
63 EXAMPLES = '''
64 # Note: These examples do not set authentication details, see the AWS Guide for details.
65 
66 # Gather facts about all snapshots, including public ones
67 - ec2_snapshot_facts:
68 
69 # Gather facts about all snapshots owned by the account 0123456789
70 - ec2_snapshot_facts:
71     filters:
72       owner-id: 0123456789
73 
74 # Or alternatively...
75 - ec2_snapshot_facts:
76     owner_ids:
77       - 0123456789
78 
79 # Gather facts about a particular snapshot using ID
80 - ec2_snapshot_facts:
81     filters:
82       snapshot-id: snap-00112233
83 
84 # Or alternatively...
85 - ec2_snapshot_facts:
86     snapshot_ids:
87       - snap-00112233
88 
89 # Gather facts about any snapshot with a tag key Name and value Example
90 - ec2_snapshot_facts:
91     filters:
92       "tag:Name": Example
93 
94 # Gather facts about any snapshot with an error status
95 - ec2_snapshot_facts:
96     filters:
97       status: error
98 
99 '''
100 
101 RETURN = '''
102 snapshot_id:
103     description: The ID of the snapshot. Each snapshot receives a unique identifier when it is created.
104     type: string
105     sample: snap-01234567
106 volume_id:
107     description: The ID of the volume that was used to create the snapshot.
108     type: string
109     sample: vol-01234567
110 state:
111     description: The snapshot state (completed, pending or error).
112     type: string
113     sample: completed
114 state_message:
115     description: Encrypted Amazon EBS snapshots are copied asynchronously. If a snapshot copy operation fails (for example, if the proper AWS Key Management Service (AWS KMS) permissions are not obtained) this field displays error state details to help you diagnose why the error occurred.
116     type: string
117     sample:
118 start_time:
119     description: The time stamp when the snapshot was initiated.
120     type: datetime
121     sample: 2015-02-12T02:14:02+00:00
122 progress:
123     description: The progress of the snapshot, as a percentage.
124     type: string
125     sample: 100%
126 owner_id:
127     description: The AWS account ID of the EBS snapshot owner.
128     type: string
129     sample: 099720109477
130 description:
131     description: The description for the snapshot.
132     type: string
133     sample: My important backup
134 volume_size:
135     description: The size of the volume, in GiB.
136     type: integer
137     sample: 8
138 owner_alias:
139     description: The AWS account alias (for example, amazon, self) or AWS account ID that owns the snapshot.
140     type: string
141     sample: 033440102211
142 tags:
143     description: Any tags assigned to the snapshot.
144     type: list
145     sample: "{ 'my_tag_key': 'my_tag_value' }"
146 encrypted:
147     description: Indicates whether the snapshot is encrypted.
148     type: boolean
149     sample: True
150 kms_key_id:
151     description: The full ARN of the AWS Key Management Service (AWS KMS) customer master key (CMK) that was used to \
152     protect the volume encryption key for the parent volume.
153     type: string
154     sample: 74c9742a-a1b2-45cb-b3fe-abcdef123456
155 data_encryption_key_id:
156     description: The data encryption key identifier for the snapshot. This value is a unique identifier that \
157     corresponds to the data encryption key that was used to encrypt the original volume or snapshot copy.
158     type: string
159     sample: "arn:aws:kms:ap-southeast-2:012345678900:key/74c9742a-a1b2-45cb-b3fe-abcdef123456"
160 
161 '''
162 
163 try:
164     import boto3
165     from botocore.exceptions import ClientError, NoCredentialsError
166     HAS_BOTO3 = True
167 except ImportError:
168     HAS_BOTO3 = False
169 
170 from ansible.module_utils.basic import AnsibleModule
171 from ansible.module_utils.ec2 import (ansible_dict_to_boto3_filter_list,
172         boto3_conn, boto3_tag_list_to_ansible_dict, camel_dict_to_snake_dict,
173         ec2_argument_spec, get_aws_connection_info)
174 
175 
176 def list_ec2_snapshots(connection, module):
177 
178     snapshot_ids = module.params.get("snapshot_ids")
179     owner_ids = map(str, module.params.get("owner_ids"))
180     restorable_by_user_ids = module.params.get("restorable_by_user_ids")
181     filters = ansible_dict_to_boto3_filter_list(module.params.get("filters"))
182 
183     try:
184         snapshots = connection.describe_snapshots(SnapshotIds=snapshot_ids, OwnerIds=owner_ids, RestorableByUserIds=restorable_by_user_ids, Filters=filters)
185     except ClientError as e:
186         module.fail_json(msg=e.message)
187 
188     # Turn the boto3 result in to ansible_friendly_snaked_names
189     snaked_snapshots = []
190     for snapshot in snapshots['Snapshots']:
191         snaked_snapshots.append(camel_dict_to_snake_dict(snapshot))
192 
193     # Turn the boto3 result in to ansible friendly tag dictionary
194     for snapshot in snaked_snapshots:
195         if 'tags' in snapshot:
196             snapshot['tags'] = boto3_tag_list_to_ansible_dict(snapshot['tags'])
197 
198     module.exit_json(snapshots=snaked_snapshots)
199 
200 
201 def main():
202 
203     argument_spec = ec2_argument_spec()
204     argument_spec.update(
205         dict(
206             snapshot_ids=dict(default=[], type='list'),
207             owner_ids=dict(default=[], type='list'),
208             restorable_by_user_ids=dict(default=[], type='list'),
209             filters=dict(default={}, type='dict')
210         )
211     )
212 
213     module = AnsibleModule(argument_spec=argument_spec,
214                            mutually_exclusive=[
215                                ['snapshot_ids', 'owner_ids', 'restorable_by_user_ids', 'filters']
216                            ]
217                            )
218 
219     if not HAS_BOTO3:
220         module.fail_json(msg='boto3 required for this module')
221 
222     region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)
223 
224     if region:
225         connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params)
226     else:
227         module.fail_json(msg="region must be specified")
228 
229     list_ec2_snapshots(connection, module)
230 
231 
232 if __name__ == '__main__':
233     main()
234
```
--- 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/cloud/amazon/ec2_snapshot_facts.py b/lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py
--- a/lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py
+++ b/lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py
@@ -141,7 +141,7 @@
     sample: 033440102211
 tags:
     description: Any tags assigned to the snapshot.
-    type: list
+    type: dict
     sample: "{ 'my_tag_key': 'my_tag_value' }"
 encrypted:
     description: Indicates whether the snapshot is encrypted.

{"golden_diff": "diff --git a/lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py b/lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py\n--- a/lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py\n+++ b/lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py\n@@ -141,7 +141,7 @@\n     sample: 033440102211\n tags:\n     description: Any tags assigned to the snapshot.\n-    type: list\n+    type: dict\n     sample: \"{ 'my_tag_key': 'my_tag_value' }\"\n encrypted:\n     description: Indicates whether the snapshot is encrypted.\n", "issue": "tag attribute in ec2_snapshot_facts module should be dict instead of list\n##### ISSUE TYPE\r\n - Documentation Report\r\n\r\n##### COMPONENT NAME\r\nansible-modules-extras/cloud/amazon/ec2_snapshot_facts.py\r\n\r\n##### ANSIBLE VERSION\r\n```\r\n$ ansible --version\r\nansible 2.2.1.0\r\n  config file = /home/psd/.ansible.cfg\r\n  configured module search path = ['/home/psd/.ansible/library']\r\n```\r\n\r\n##### CONFIGURATION\r\nN/A. Not configuration-specific\r\n\r\n##### OS / ENVIRONMENT\r\nN/A\r\n\r\n##### SUMMARY\r\nThe returned snapshots dict have a tag attribute, it was already [converted to dict in the code](https://github.com/ansible/ansible-modules-extras/blob/devel/cloud/amazon/ec2_snapshot_facts.py#L196)\r\n\r\nSo the expected tag attr in this module is a dict, not a list(which is the return value type in boto3)\r\n\r\n##### STEPS TO REPRODUCE\r\nget snapshot_facts, we have an example output in the next section:\r\n\r\n##### ACTUAL RESULTS\r\n\r\n```\r\n        {\r\n            \"description\": \"\",\r\n            \"encrypted\": false,\r\n            \"owner_id\": \"omitted\",\r\n            \"progress\": \"100%\",\r\n            \"snapshot_id\": \"snap-omitted\",\r\n            \"start_time\": \"2017-03-08T03:52:29+00:00\",\r\n            \"state\": \"completed\",\r\n            \"tags\": {\r\n                \"Name\": \"some name\",\r\n                \"creator\": \"cron on some machine\",\r\n                \"frequency\": \"hourly\"\r\n            },\r\n            \"volume_id\": \"vol-omitted\",\r\n            \"volume_size\": 40\r\n        }\r\n```\r\nAs you can see, the tags attr is a dict.\n", "before_files": [{"content": "#!/usr/bin/python\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nANSIBLE_METADATA = {'status': ['preview'],\n                    'supported_by': 'community',\n                    'version': '1.0'}\n\nDOCUMENTATION = '''\n---\nmodule: ec2_snapshot_facts\nshort_description: Gather facts about ec2 volume snapshots in AWS\ndescription:\n    - Gather facts about ec2 volume snapshots in AWS\nversion_added: \"2.1\"\nauthor: \"Rob White (@wimnat)\"\noptions:\n  snapshot_ids:\n    description:\n      - If you specify one or more snapshot IDs, only snapshots that have the specified IDs are returned.\n    required: false\n    default: []\n  owner_ids:\n    description:\n      - If you specify one or more snapshot owners, only snapshots from the specified owners and for which you have \\\n      access are returned.\n    required: false\n    default: []\n  restorable_by_user_ids:\n    description:\n      - If you specify a list of restorable users, only snapshots with create snapshot permissions for those users are \\\n      returned.\n    required: false\n    default: []\n  filters:\n    description:\n      - A dict of filters to apply. Each dict item consists of a filter key and a filter value. See \\\n      U(http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSnapshots.html) for possible filters. Filter \\\n      names and values are case sensitive.\n    required: false\n    default: {}\nnotes:\n  - By default, the module will return all snapshots, including public ones. To limit results to snapshots owned by \\\n  the account use the filter 'owner-id'.\n\nextends_documentation_fragment:\n    - aws\n    - ec2\n'''\n\nEXAMPLES = '''\n# Note: These examples do not set authentication details, see the AWS Guide for details.\n\n# Gather facts about all snapshots, including public ones\n- ec2_snapshot_facts:\n\n# Gather facts about all snapshots owned by the account 0123456789\n- ec2_snapshot_facts:\n    filters:\n      owner-id: 0123456789\n\n# Or alternatively...\n- ec2_snapshot_facts:\n    owner_ids:\n      - 0123456789\n\n# Gather facts about a particular snapshot using ID\n- ec2_snapshot_facts:\n    filters:\n      snapshot-id: snap-00112233\n\n# Or alternatively...\n- ec2_snapshot_facts:\n    snapshot_ids:\n      - snap-00112233\n\n# Gather facts about any snapshot with a tag key Name and value Example\n- ec2_snapshot_facts:\n    filters:\n      \"tag:Name\": Example\n\n# Gather facts about any snapshot with an error status\n- ec2_snapshot_facts:\n    filters:\n      status: error\n\n'''\n\nRETURN = '''\nsnapshot_id:\n    description: The ID of the snapshot. Each snapshot receives a unique identifier when it is created.\n    type: string\n    sample: snap-01234567\nvolume_id:\n    description: The ID of the volume that was used to create the snapshot.\n    type: string\n    sample: vol-01234567\nstate:\n    description: The snapshot state (completed, pending or error).\n    type: string\n    sample: completed\nstate_message:\n    description: Encrypted Amazon EBS snapshots are copied asynchronously. If a snapshot copy operation fails (for example, if the proper AWS Key Management Service (AWS KMS) permissions are not obtained) this field displays error state details to help you diagnose why the error occurred.\n    type: string\n    sample:\nstart_time:\n    description: The time stamp when the snapshot was initiated.\n    type: datetime\n    sample: 2015-02-12T02:14:02+00:00\nprogress:\n    description: The progress of the snapshot, as a percentage.\n    type: string\n    sample: 100%\nowner_id:\n    description: The AWS account ID of the EBS snapshot owner.\n    type: string\n    sample: 099720109477\ndescription:\n    description: The description for the snapshot.\n    type: string\n    sample: My important backup\nvolume_size:\n    description: The size of the volume, in GiB.\n    type: integer\n    sample: 8\nowner_alias:\n    description: The AWS account alias (for example, amazon, self) or AWS account ID that owns the snapshot.\n    type: string\n    sample: 033440102211\ntags:\n    description: Any tags assigned to the snapshot.\n    type: list\n    sample: \"{ 'my_tag_key': 'my_tag_value' }\"\nencrypted:\n    description: Indicates whether the snapshot is encrypted.\n    type: boolean\n    sample: True\nkms_key_id:\n    description: The full ARN of the AWS Key Management Service (AWS KMS) customer master key (CMK) that was used to \\\n    protect the volume encryption key for the parent volume.\n    type: string\n    sample: 74c9742a-a1b2-45cb-b3fe-abcdef123456\ndata_encryption_key_id:\n    description: The data encryption key identifier for the snapshot. This value is a unique identifier that \\\n    corresponds to the data encryption key that was used to encrypt the original volume or snapshot copy.\n    type: string\n    sample: \"arn:aws:kms:ap-southeast-2:012345678900:key/74c9742a-a1b2-45cb-b3fe-abcdef123456\"\n\n'''\n\ntry:\n    import boto3\n    from botocore.exceptions import ClientError, NoCredentialsError\n    HAS_BOTO3 = True\nexcept ImportError:\n    HAS_BOTO3 = False\n\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible.module_utils.ec2 import (ansible_dict_to_boto3_filter_list,\n        boto3_conn, boto3_tag_list_to_ansible_dict, camel_dict_to_snake_dict,\n        ec2_argument_spec, get_aws_connection_info)\n\n\ndef list_ec2_snapshots(connection, module):\n\n    snapshot_ids = module.params.get(\"snapshot_ids\")\n    owner_ids = map(str, module.params.get(\"owner_ids\"))\n    restorable_by_user_ids = module.params.get(\"restorable_by_user_ids\")\n    filters = ansible_dict_to_boto3_filter_list(module.params.get(\"filters\"))\n\n    try:\n        snapshots = connection.describe_snapshots(SnapshotIds=snapshot_ids, OwnerIds=owner_ids, RestorableByUserIds=restorable_by_user_ids, Filters=filters)\n    except ClientError as e:\n        module.fail_json(msg=e.message)\n\n    # Turn the boto3 result in to ansible_friendly_snaked_names\n    snaked_snapshots = []\n    for snapshot in snapshots['Snapshots']:\n        snaked_snapshots.append(camel_dict_to_snake_dict(snapshot))\n\n    # Turn the boto3 result in to ansible friendly tag dictionary\n    for snapshot in snaked_snapshots:\n        if 'tags' in snapshot:\n            snapshot['tags'] = boto3_tag_list_to_ansible_dict(snapshot['tags'])\n\n    module.exit_json(snapshots=snaked_snapshots)\n\n\ndef main():\n\n    argument_spec = ec2_argument_spec()\n    argument_spec.update(\n        dict(\n            snapshot_ids=dict(default=[], type='list'),\n            owner_ids=dict(default=[], type='list'),\n            restorable_by_user_ids=dict(default=[], type='list'),\n            filters=dict(default={}, type='dict')\n        )\n    )\n\n    module = AnsibleModule(argument_spec=argument_spec,\n                           mutually_exclusive=[\n                               ['snapshot_ids', 'owner_ids', 'restorable_by_user_ids', 'filters']\n                           ]\n                           )\n\n    if not HAS_BOTO3:\n        module.fail_json(msg='boto3 required for this module')\n\n    region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)\n\n    if region:\n        connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params)\n    else:\n        module.fail_json(msg=\"region must be specified\")\n\n    list_ec2_snapshots(connection, module)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py"}], "after_files": [{"content": "#!/usr/bin/python\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nANSIBLE_METADATA = {'status': ['preview'],\n                    'supported_by': 'community',\n                    'version': '1.0'}\n\nDOCUMENTATION = '''\n---\nmodule: ec2_snapshot_facts\nshort_description: Gather facts about ec2 volume snapshots in AWS\ndescription:\n    - Gather facts about ec2 volume snapshots in AWS\nversion_added: \"2.1\"\nauthor: \"Rob White (@wimnat)\"\noptions:\n  snapshot_ids:\n    description:\n      - If you specify one or more snapshot IDs, only snapshots that have the specified IDs are returned.\n    required: false\n    default: []\n  owner_ids:\n    description:\n      - If you specify one or more snapshot owners, only snapshots from the specified owners and for which you have \\\n      access are returned.\n    required: false\n    default: []\n  restorable_by_user_ids:\n    description:\n      - If you specify a list of restorable users, only snapshots with create snapshot permissions for those users are \\\n      returned.\n    required: false\n    default: []\n  filters:\n    description:\n      - A dict of filters to apply. Each dict item consists of a filter key and a filter value. See \\\n      U(http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSnapshots.html) for possible filters. Filter \\\n      names and values are case sensitive.\n    required: false\n    default: {}\nnotes:\n  - By default, the module will return all snapshots, including public ones. To limit results to snapshots owned by \\\n  the account use the filter 'owner-id'.\n\nextends_documentation_fragment:\n    - aws\n    - ec2\n'''\n\nEXAMPLES = '''\n# Note: These examples do not set authentication details, see the AWS Guide for details.\n\n# Gather facts about all snapshots, including public ones\n- ec2_snapshot_facts:\n\n# Gather facts about all snapshots owned by the account 0123456789\n- ec2_snapshot_facts:\n    filters:\n      owner-id: 0123456789\n\n# Or alternatively...\n- ec2_snapshot_facts:\n    owner_ids:\n      - 0123456789\n\n# Gather facts about a particular snapshot using ID\n- ec2_snapshot_facts:\n    filters:\n      snapshot-id: snap-00112233\n\n# Or alternatively...\n- ec2_snapshot_facts:\n    snapshot_ids:\n      - snap-00112233\n\n# Gather facts about any snapshot with a tag key Name and value Example\n- ec2_snapshot_facts:\n    filters:\n      \"tag:Name\": Example\n\n# Gather facts about any snapshot with an error status\n- ec2_snapshot_facts:\n    filters:\n      status: error\n\n'''\n\nRETURN = '''\nsnapshot_id:\n    description: The ID of the snapshot. Each snapshot receives a unique identifier when it is created.\n    type: string\n    sample: snap-01234567\nvolume_id:\n    description: The ID of the volume that was used to create the snapshot.\n    type: string\n    sample: vol-01234567\nstate:\n    description: The snapshot state (completed, pending or error).\n    type: string\n    sample: completed\nstate_message:\n    description: Encrypted Amazon EBS snapshots are copied asynchronously. If a snapshot copy operation fails (for example, if the proper AWS Key Management Service (AWS KMS) permissions are not obtained) this field displays error state details to help you diagnose why the error occurred.\n    type: string\n    sample:\nstart_time:\n    description: The time stamp when the snapshot was initiated.\n    type: datetime\n    sample: 2015-02-12T02:14:02+00:00\nprogress:\n    description: The progress of the snapshot, as a percentage.\n    type: string\n    sample: 100%\nowner_id:\n    description: The AWS account ID of the EBS snapshot owner.\n    type: string\n    sample: 099720109477\ndescription:\n    description: The description for the snapshot.\n    type: string\n    sample: My important backup\nvolume_size:\n    description: The size of the volume, in GiB.\n    type: integer\n    sample: 8\nowner_alias:\n    description: The AWS account alias (for example, amazon, self) or AWS account ID that owns the snapshot.\n    type: string\n    sample: 033440102211\ntags:\n    description: Any tags assigned to the snapshot.\n    type: dict\n    sample: \"{ 'my_tag_key': 'my_tag_value' }\"\nencrypted:\n    description: Indicates whether the snapshot is encrypted.\n    type: boolean\n    sample: True\nkms_key_id:\n    description: The full ARN of the AWS Key Management Service (AWS KMS) customer master key (CMK) that was used to \\\n    protect the volume encryption key for the parent volume.\n    type: string\n    sample: 74c9742a-a1b2-45cb-b3fe-abcdef123456\ndata_encryption_key_id:\n    description: The data encryption key identifier for the snapshot. This value is a unique identifier that \\\n    corresponds to the data encryption key that was used to encrypt the original volume or snapshot copy.\n    type: string\n    sample: \"arn:aws:kms:ap-southeast-2:012345678900:key/74c9742a-a1b2-45cb-b3fe-abcdef123456\"\n\n'''\n\ntry:\n    import boto3\n    from botocore.exceptions import ClientError, NoCredentialsError\n    HAS_BOTO3 = True\nexcept ImportError:\n    HAS_BOTO3 = False\n\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible.module_utils.ec2 import (ansible_dict_to_boto3_filter_list,\n        boto3_conn, boto3_tag_list_to_ansible_dict, camel_dict_to_snake_dict,\n        ec2_argument_spec, get_aws_connection_info)\n\n\ndef list_ec2_snapshots(connection, module):\n\n    snapshot_ids = module.params.get(\"snapshot_ids\")\n    owner_ids = map(str, module.params.get(\"owner_ids\"))\n    restorable_by_user_ids = module.params.get(\"restorable_by_user_ids\")\n    filters = ansible_dict_to_boto3_filter_list(module.params.get(\"filters\"))\n\n    try:\n        snapshots = connection.describe_snapshots(SnapshotIds=snapshot_ids, OwnerIds=owner_ids, RestorableByUserIds=restorable_by_user_ids, Filters=filters)\n    except ClientError as e:\n        module.fail_json(msg=e.message)\n\n    # Turn the boto3 result in to ansible_friendly_snaked_names\n    snaked_snapshots = []\n    for snapshot in snapshots['Snapshots']:\n        snaked_snapshots.append(camel_dict_to_snake_dict(snapshot))\n\n    # Turn the boto3 result in to ansible friendly tag dictionary\n    for snapshot in snaked_snapshots:\n        if 'tags' in snapshot:\n            snapshot['tags'] = boto3_tag_list_to_ansible_dict(snapshot['tags'])\n\n    module.exit_json(snapshots=snaked_snapshots)\n\n\ndef main():\n\n    argument_spec = ec2_argument_spec()\n    argument_spec.update(\n        dict(\n            snapshot_ids=dict(default=[], type='list'),\n            owner_ids=dict(default=[], type='list'),\n            restorable_by_user_ids=dict(default=[], type='list'),\n            filters=dict(default={}, type='dict')\n        )\n    )\n\n    module = AnsibleModule(argument_spec=argument_spec,\n                           mutually_exclusive=[\n                               ['snapshot_ids', 'owner_ids', 'restorable_by_user_ids', 'filters']\n                           ]\n                           )\n\n    if not HAS_BOTO3:\n        module.fail_json(msg='boto3 required for this module')\n\n    region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)\n\n    if region:\n        connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params)\n    else:\n        module.fail_json(msg=\"region must be specified\")\n\n    list_ec2_snapshots(connection, module)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py"}]}