Browse code

[cloud] Rename ec2_facts to ec2_metadata_facts (#26293)

- Update CHANGELOG with ec2_facts deprecation notice

Vinay Dandekar authored on 2017/07/19 05:11:09
Showing 4 changed files
... ...
@@ -45,6 +45,9 @@ Ansible Changes By Release
45 45
   module is deprecated and slated to go away in 2.8.  The functionality has been
46 46
   moved to `ansible.utils.unsafe_proxy` to avoid a circular import.
47 47
 
48
+#### Deprecated Modules:
49
+* ec2_facts (removed in 2.7), replaced by ec2_metadata_facts
50
+
48 51
 ### Minor Changes
49 52
 * removed previously deprecated config option `hostfile` and env var `ANSIBLE_HOSTS`
50 53
 * removed unused and deprecated config option `pattern`
... ...
@@ -109,6 +112,7 @@ Ansible Changes By Release
109 109
 
110 110
 - aix_lvol
111 111
 - amazon
112
+  * ec2_metadata_facts
112 113
   * ec2_vpc_endpoint
113 114
   * iam_cert_facts
114 115
   * lightsail
115 116
new file mode 120000
... ...
@@ -0,0 +1 @@
0
+ec2_metadata_facts.py
0 1
\ No newline at end of file
1 2
deleted file mode 100644
... ...
@@ -1,549 +0,0 @@
1
-#!/usr/bin/python
2
-# -*- coding: utf-8 -*-
3
-
4
-# This file is part of Ansible
5
-#
6
-# Ansible is free software: you can redistribute it and/or modify
7
-# it under the terms of the GNU General Public License as published by
8
-# the Free Software Foundation, either version 3 of the License, or
9
-# (at your option) any later version.
10
-#
11
-# Ansible is distributed in the hope that it will be useful,
12
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
-# GNU General Public License for more details.
15
-#
16
-# You should have received a copy of the GNU General Public License
17
-# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
18
-
19
-ANSIBLE_METADATA = {'metadata_version': '1.0',
20
-                    'status': ['stableinterface'],
21
-                    'supported_by': 'curated'}
22
-
23
-
24
-DOCUMENTATION = '''
25
-module: ec2_facts
26
-short_description: Gathers facts (instance metadata) about remote hosts within ec2
27
-version_added: "1.0"
28
-author:
29
-    - Silviu Dicu (@silviud)
30
-    - Vinay Dandekar (@roadmapper)
31
-description:
32
-    - This module fetches data from the instance metadata endpoint in ec2 as per
33
-      http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html.
34
-      The module must be called from within the EC2 instance itself.
35
-notes:
36
-    - Parameters to filter on ec2_facts may be added later.
37
-'''
38
-
39
-EXAMPLES = '''
40
-# Gather EC2 facts
41
-- ec2_facts:
42
-
43
-- debug:
44
-    msg: "This instance is a t1.micro"
45
-  when: ansible_ec2_instance_type == "t1.micro"
46
-'''
47
-
48
-RETURN = '''
49
-ansible_facts:
50
-    description: Dictionary of new facts representing discovered properties of the EC2 instance.
51
-    returned: changed
52
-    type: complex
53
-    contains:
54
-        ansible_ec2_ami_id:
55
-            description: The AMI ID used to launch the instance.
56
-            type: string
57
-            sample: "ami-XXXXXXXX"
58
-        ansible_ec2_ami_launch_index:
59
-            description:
60
-                - If you started more than one instance at the same time, this value indicates the order in which the instance was launched.
61
-                  The value of the first instance launched is 0.
62
-            type: string
63
-            sample: "0"
64
-        ansible_ec2_ami_manifest_path:
65
-            description:
66
-                - The path to the AMI manifest file in Amazon S3.
67
-                  If you used an Amazon EBS-backed AMI to launch the instance, the returned result is unknown.
68
-            type: string
69
-            sample: "(unknown)"
70
-        ansible_ec2_ancestor_ami_ids:
71
-            description:
72
-                - The AMI IDs of any instances that were rebundled to create this AMI.
73
-                  This value will only exist if the AMI manifest file contained an ancestor-amis key.
74
-            type: string
75
-            sample: "(unknown)"
76
-        ansible_ec2_block_device_mapping_ami:
77
-            description: The virtual device that contains the root/boot file system.
78
-            type: string
79
-            sample: "/dev/sda1"
80
-        ansible_ec2_block_device_mapping_ebsN:
81
-            description:
82
-                - The virtual devices associated with Amazon EBS volumes, if any are present.
83
-                  Amazon EBS volumes are only available in metadata if they were present at launch time or when the instance was last started.
84
-                  The N indicates the index of the Amazon EBS volume (such as ebs1 or ebs2).
85
-            type: string
86
-            sample: "/dev/xvdb"
87
-        ansible_ec2_block_device_mapping_ephemeralN:
88
-            description: The virtual devices associated with ephemeral devices, if any are present. The N indicates the index of the ephemeral volume.
89
-            type: string
90
-            sample: "/dev/xvdc"
91
-        ansible_ec2_block_device_mapping_root:
92
-            description:
93
-                - The virtual devices or partitions associated with the root devices, or partitions on the virtual device,
94
-                  where the root (/ or C) file system is associated with the given instance.
95
-            type: string
96
-            sample: "/dev/sda1"
97
-        ansible_ec2_block_device_mapping_swap:
98
-            description: The virtual devices associated with swap. Not always present.
99
-            type: string
100
-            sample: "/dev/sda2"
101
-        ansible_ec2_fws_instance_monitoring:
102
-            description: "Value showing whether the customer has enabled detailed one-minute monitoring in CloudWatch."
103
-            type: string
104
-            sample: "enabled"
105
-        ansible_ec2_hostname:
106
-            description:
107
-                - The private IPv4 DNS hostname of the instance.
108
-                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
109
-            type: string
110
-            sample: "ip-10-0-0-1.ec2.internal"
111
-        ansible_ec2_iam_info:
112
-            description:
113
-                - If there is an IAM role associated with the instance, contains information about the last time the instance profile was updated,
114
-                  including the instance's LastUpdated date, InstanceProfileArn, and InstanceProfileId. Otherwise, not present.
115
-            type: complex
116
-            sample: ""
117
-        ansible_ec2_iam_info_instanceprofilearn:
118
-            description: The IAM instance profile ARN.
119
-            type: string
120
-            sample: "arn:aws:iam::<account id>:instance-profile/<role name>"
121
-        ansible_ec2_iam_info_instanceprofileid:
122
-            description: IAM instance profile ID.
123
-            type: string
124
-            sample: ""
125
-        ansible_ec2_iam_info_lastupdated:
126
-            description: IAM info last updated time.
127
-            type: string
128
-            sample: "2017-05-12T02:42:27Z"
129
-        ansible_ec2_iam_instance_profile_role:
130
-            description: IAM instance role.
131
-            type: string
132
-            sample: "role_name"
133
-        ansible_ec2_iam_security_credentials_<role name>:
134
-            description:
135
-                - If there is an IAM role associated with the instance, role-name is the name of the role,
136
-                  and role-name contains the temporary security credentials associated with the role. Otherwise, not present.
137
-            type: string
138
-            sample: ""
139
-        ansible_ec2_iam_security_credentials_<role name>_accesskeyid:
140
-            description: IAM role access key ID.
141
-            type: string
142
-            sample: ""
143
-        ansible_ec2_iam_security_credentials_<role name>_code:
144
-            description: IAM code.
145
-            type: string
146
-            sample: "Success"
147
-        ansible_ec2_iam_security_credentials_<role name>_expiration:
148
-            description: IAM role credentials expiration time.
149
-            type: string
150
-            sample: "2017-05-12T09:11:41Z"
151
-        ansible_ec2_iam_security_credentials_<role name>_lastupdated:
152
-            description: IAM role last updated time.
153
-            type: string
154
-            sample: "2017-05-12T02:40:44Z"
155
-        ansible_ec2_iam_security_credentials_<role name>_secretaccesskey:
156
-            description: IAM role secret access key.
157
-            type: string
158
-            sample: ""
159
-        ansible_ec2_iam_security_credentials_<role name>_token:
160
-            description: IAM role token.
161
-            type: string
162
-            sample: ""
163
-        ansible_ec2_iam_security_credentials_<role name>_type:
164
-            description: IAM role type.
165
-            type: string
166
-            sample: "AWS-HMAC"
167
-        ansible_ec2_instance_action:
168
-            description: Notifies the instance that it should reboot in preparation for bundling.
169
-            type: string
170
-            sample: "none"
171
-        ansible_ec2_instance_id:
172
-            description: The ID of this instance.
173
-            type: string
174
-            sample: "i-XXXXXXXXXXXXXXXXX"
175
-        ansible_ec2_instance_identity_document:
176
-            description: JSON containing instance attributes, such as instance-id, private IP address, etc.
177
-            type: string
178
-            sample: ""
179
-        ansible_ec2_instance_identity_document_accountid:
180
-            description: ""
181
-            type: string
182
-            sample: "012345678901"
183
-        ansible_ec2_instance_identity_document_architecture:
184
-            description: Instance system architecture.
185
-            type: string
186
-            sample: "x86_64"
187
-        ansible_ec2_instance_identity_document_availabilityzone:
188
-            description: The Availability Zone in which the instance launched.
189
-            type: string
190
-            sample: "us-east-1a"
191
-        ansible_ec2_instance_identity_document_billingproducts:
192
-            description: Billing products for this instance.
193
-            type: string
194
-            sample: ""
195
-        ansible_ec2_instance_identity_document_devpayproductcodes:
196
-            description: Product codes for the launched AMI.
197
-            type: string
198
-            sample: ""
199
-        ansible_ec2_instance_identity_document_imageid:
200
-            description: The AMI ID used to launch the instance.
201
-            type: string
202
-            sample: "ami-01234567"
203
-        ansible_ec2_instance_identity_document_instanceid:
204
-            description: The ID of this instance.
205
-            type: string
206
-            sample: "i-0123456789abcdef0"
207
-        ansible_ec2_instance_identity_document_instancetype:
208
-            description: The type of instance.
209
-            type: string
210
-            sample: "m4.large"
211
-        ansible_ec2_instance_identity_document_kernelid:
212
-            description: The ID of the kernel launched with this instance, if applicable.
213
-            type: string
214
-            sample: ""
215
-        ansible_ec2_instance_identity_document_pendingtime:
216
-            description: The instance pending time.
217
-            type: string
218
-            sample: "2017-05-11T20:51:20Z"
219
-        ansible_ec2_instance_identity_document_privateip:
220
-            description:
221
-                - The private IPv4 address of the instance.
222
-                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
223
-            type: string
224
-            sample: "10.0.0.1"
225
-        ansible_ec2_instance_identity_document_ramdiskid:
226
-            description: The ID of the RAM disk specified at launch time, if applicable.
227
-            type: string
228
-            sample: ""
229
-        ansible_ec2_instance_identity_document_region:
230
-            description: The Region in which the instance launched.
231
-            type: string
232
-            sample: "us-east-1"
233
-        ansible_ec2_instance_identity_document_version:
234
-            description: Identity document version.
235
-            type: string
236
-            sample: "2010-08-31"
237
-        ansible_ec2_instance_identity_pkcs7:
238
-            description: Used to verify the document's authenticity and content against the signature.
239
-            type: string
240
-            sample: ""
241
-        ansible_ec2_instance_identity_rsa2048:
242
-            description: Used to verify the document's authenticity and content against the signature.
243
-            type: string
244
-            sample: ""
245
-        ansible_ec2_instance_identity_signature:
246
-            description: Data that can be used by other parties to verify its origin and authenticity.
247
-            type: string
248
-            sample: ""
249
-        ansible_ec2_instance_type:
250
-            description: The type of instance.
251
-            type: string
252
-            sample: "m4.large"
253
-        ansible_ec2_local_hostname:
254
-            description:
255
-                - The private IPv4 DNS hostname of the instance.
256
-                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
257
-            type: string
258
-            sample: "ip-10-0-0-1.ec2.internal"
259
-        ansible_ec2_local_ipv4:
260
-            description:
261
-                - The private IPv4 address of the instance.
262
-                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
263
-            type: string
264
-            sample: "10.0.0.1"
265
-        ansible_ec2_mac:
266
-            description:
267
-                - The instance's media access control (MAC) address.
268
-                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
269
-            type: string
270
-            sample: "00:11:22:33:44:55"
271
-        ansible_ec2_metrics_vhostmd:
272
-            description: Metrics.
273
-            type: string
274
-            sample: ""
275
-        ansible_ec2_network_interfaces_macs_<mac address>_device_number:
276
-            description:
277
-                - The unique device number associated with that interface. The device number corresponds to the device name;
278
-                  for example, a device-number of 2 is for the eth2 device.
279
-                  This category corresponds to the DeviceIndex and device-index fields that are used by the Amazon EC2 API and the EC2 commands for the AWS CLI.
280
-            type: string
281
-            sample: "0"
282
-        ansible_ec2_network_interfaces_macs_<mac address>_interface_id:
283
-            description: The elastic network interface ID.
284
-            type: string
285
-            sample: "eni-12345678"
286
-        ansible_ec2_network_interfaces_macs_<mac address>_ipv4_associations_<ip address>:
287
-            description: The private IPv4 addresses that are associated with each public-ip address and assigned to that interface.
288
-            type: string
289
-            sample: ""
290
-        ansible_ec2_network_interfaces_macs_<mac address>_ipv6s:
291
-            description: The IPv6 addresses associated with the interface. Returned only for instances launched into a VPC.
292
-            type: string
293
-            sample: ""
294
-        ansible_ec2_network_interfaces_macs_<mac address>_local_hostname:
295
-            description: The interface's local hostname.
296
-            type: string
297
-            sample: ""
298
-        ansible_ec2_network_interfaces_macs_<mac address>_local_ipv4s:
299
-            description: The private IPv4 addresses associated with the interface.
300
-            type: string
301
-            sample: ""
302
-        ansible_ec2_network_interfaces_macs_<mac address>_mac:
303
-            description: The instance's MAC address.
304
-            type: string
305
-            sample: "00:11:22:33:44:55"
306
-        ansible_ec2_network_interfaces_macs_<mac address>_owner_id:
307
-            description:
308
-                - The ID of the owner of the network interface.
309
-                  In multiple-interface environments, an interface can be attached by a third party, such as Elastic Load Balancing.
310
-                  Traffic on an interface is always billed to the interface owner.
311
-            type: string
312
-            sample: "01234567890"
313
-        ansible_ec2_network_interfaces_macs_<mac address>_public_hostname:
314
-            description:
315
-                - The interface's public DNS (IPv4). If the instance is in a VPC,
316
-                  this category is only returned if the enableDnsHostnames attribute is set to true.
317
-            type: string
318
-            sample: "ec2-1-2-3-4.compute-1.amazonaws.com"
319
-        ansible_ec2_network_interfaces_macs_<mac address>_public_ipv4s:
320
-            description: The Elastic IP addresses associated with the interface. There may be multiple IPv4 addresses on an instance.
321
-            type: string
322
-            sample: "1.2.3.4"
323
-        ansible_ec2_network_interfaces_macs_<mac address>_security_group_ids:
324
-            description: The IDs of the security groups to which the network interface belongs. Returned only for instances launched into a VPC.
325
-            type: string
326
-            sample: "sg-01234567,sg-01234568"
327
-        ansible_ec2_network_interfaces_macs_<mac address>_security_groups:
328
-            description: Security groups to which the network interface belongs. Returned only for instances launched into a VPC.
329
-            type: string
330
-            sample: "secgroup1,secgroup2"
331
-        ansible_ec2_network_interfaces_macs_<mac address>_subnet_id:
332
-            description: The ID of the subnet in which the interface resides. Returned only for instances launched into a VPC.
333
-            type: string
334
-            sample: "subnet-01234567"
335
-        ansible_ec2_network_interfaces_macs_<mac address>_subnet_ipv4_cidr_block:
336
-            description: The IPv4 CIDR block of the subnet in which the interface resides. Returned only for instances launched into a VPC.
337
-            type: string
338
-            sample: "10.0.1.0/24"
339
-        ansible_ec2_network_interfaces_macs_<mac address>_subnet_ipv6_cidr_blocks:
340
-            description: The IPv6 CIDR block of the subnet in which the interface resides. Returned only for instances launched into a VPC.
341
-            type: string
342
-            sample: ""
343
-        ansible_ec2_network_interfaces_macs_<mac address>_vpc_id:
344
-            description: The ID of the VPC in which the interface resides. Returned only for instances launched into a VPC.
345
-            type: string
346
-            sample: "vpc-0123456"
347
-        ansible_ec2_network_interfaces_macs_<mac address>_vpc_ipv4_cidr_block:
348
-            description: The IPv4 CIDR block of the VPC in which the interface resides. Returned only for instances launched into a VPC.
349
-            type: string
350
-            sample: "10.0.0.0/16"
351
-        ansible_ec2_network_interfaces_macs_<mac address>_vpc_ipv4_cidr_blocks:
352
-            description: The IPv4 CIDR block of the VPC in which the interface resides. Returned only for instances launched into a VPC.
353
-            type: string
354
-            sample: "10.0.0.0/16"
355
-        ansible_ec2_network_interfaces_macs_<mac address>_vpc_ipv6_cidr_blocks:
356
-            description: The IPv6 CIDR block of the VPC in which the interface resides. Returned only for instances launched into a VPC.
357
-            type: string
358
-            sample: ""
359
-        ansible_ec2_placement_availability_zone:
360
-            description: The Availability Zone in which the instance launched.
361
-            type: string
362
-            sample: "us-east-1a"
363
-        ansible_ec2_placement_region:
364
-            description: The Region in which the instance launched.
365
-            type: string
366
-            sample: "us-east-1"
367
-        ansible_ec2_product_codes:
368
-            description: Product codes associated with the instance, if any.
369
-            type: string
370
-            sample: "aw0evgkw8e5c1q413zgy5pjce"
371
-        ansible_ec2_profile:
372
-            description: EC2 instance hardware profile.
373
-            type: string
374
-            sample: "default-hvm"
375
-        ansible_ec2_public_hostname:
376
-            description:
377
-                - The instance's public DNS. If the instance is in a VPC, this category is only returned if the enableDnsHostnames attribute is set to true.
378
-            type: string
379
-            sample: "ec2-1-2-3-4.compute-1.amazonaws.com"
380
-        ansible_ec2_public_ipv4:
381
-            description: The public IPv4 address. If an Elastic IP address is associated with the instance, the value returned is the Elastic IP address.
382
-            type: string
383
-            sample: "1.2.3.4"
384
-        ansible_ec2_public_key:
385
-            description: Public key. Only available if supplied at instance launch time.
386
-            type: string
387
-            sample: ""
388
-        ansible_ec2_ramdisk_id:
389
-            description: The ID of the RAM disk specified at launch time, if applicable.
390
-            type: string
391
-            sample: ""
392
-        ansible_ec2_reservation_id:
393
-            description: The ID of the reservation.
394
-            type: string
395
-            sample: "r-0123456789abcdef0"
396
-        ansible_ec2_security_groups:
397
-            description:
398
-                - The names of the security groups applied to the instance. After launch, you can only change the security groups of instances running in a VPC.
399
-                  Such changes are reflected here and in network/interfaces/macs/mac/security-groups.
400
-            type: string
401
-            sample: "securitygroup1,securitygroup2"
402
-        ansible_ec2_services_domain:
403
-            description: The domain for AWS resources for the region; for example, amazonaws.com for us-east-1.
404
-            type: string
405
-            sample: "amazonaws.com"
406
-        ansible_ec2_services_partition:
407
-            description:
408
-                - The partition that the resource is in. For standard AWS regions, the partition is aws.
409
-                  If you have resources in other partitions, the partition is aws-partitionname.
410
-                  For example, the partition for resources in the China (Beijing) region is aws-cn.
411
-            type: string
412
-            sample: "aws"
413
-        ansible_ec2_spot_termination_time:
414
-            description:
415
-                - The approximate time, in UTC, that the operating system for your Spot instance will receive the shutdown signal.
416
-                  This item is present and contains a time value only if the Spot instance has been marked for termination by Amazon EC2.
417
-                  The termination-time item is not set to a time if you terminated the Spot instance yourself.
418
-            type: string
419
-            sample: "2015-01-05T18:02:00Z"
420
-        ansible_ec2_user_data:
421
-            description: The instance user data.
422
-            type: string
423
-            sample: "#!/bin/bash"
424
-'''
425
-
426
-import socket
427
-import re
428
-import json
429
-
430
-from ansible.module_utils._text import to_text
431
-from ansible.module_utils.basic import AnsibleModule
432
-from ansible.module_utils.urls import fetch_url, url_argument_spec
433
-
434
-socket.setdefaulttimeout(5)
435
-
436
-
437
-class Ec2Metadata(object):
438
-    ec2_metadata_uri = 'http://169.254.169.254/latest/meta-data/'
439
-    ec2_sshdata_uri = 'http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key'
440
-    ec2_userdata_uri = 'http://169.254.169.254/latest/user-data/'
441
-    ec2_dynamicdata_uri = 'http://169.254.169.254/latest/dynamic/'
442
-
443
-    def __init__(self, module, ec2_metadata_uri=None, ec2_sshdata_uri=None, ec2_userdata_uri=None, ec2_dynamicdata_uri=None):
444
-        self.module = module
445
-        self.uri_meta = ec2_metadata_uri or self.ec2_metadata_uri
446
-        self.uri_user = ec2_userdata_uri or self.ec2_userdata_uri
447
-        self.uri_ssh = ec2_sshdata_uri or self.ec2_sshdata_uri
448
-        self.uri_dynamic = ec2_dynamicdata_uri or self.ec2_dynamicdata_uri
449
-        self._data = {}
450
-        self._prefix = 'ansible_ec2_%s'
451
-
452
-    def _fetch(self, url):
453
-        (response, info) = fetch_url(self.module, url, force=True)
454
-        if response:
455
-            data = response.read()
456
-        else:
457
-            data = None
458
-        return to_text(data)
459
-
460
-    def _mangle_fields(self, fields, uri, filter_patterns=['public-keys-0']):
461
-        new_fields = {}
462
-        for key, value in fields.items():
463
-            split_fields = key[len(uri):].split('/')
464
-            if len(split_fields) == 3 and split_fields[0:2] == ['iam', 'security-credentials'] and '_' not in split_fields[2]:
465
-                new_fields[self._prefix % "iam-instance-profile-role"] = split_fields[2]
466
-            if len(split_fields) > 1 and split_fields[1]:
467
-                new_key = "-".join(split_fields)
468
-                new_fields[self._prefix % new_key] = value
469
-            else:
470
-                new_key = "".join(split_fields)
471
-                new_fields[self._prefix % new_key] = value
472
-        for pattern in filter_patterns:
473
-            for key in dict(new_fields):
474
-                match = re.search(pattern, key)
475
-                if match:
476
-                    new_fields.pop(key)
477
-        return new_fields
478
-
479
-    def fetch(self, uri, recurse=True):
480
-        raw_subfields = self._fetch(uri)
481
-        if not raw_subfields:
482
-            return
483
-        subfields = raw_subfields.split('\n')
484
-        for field in subfields:
485
-            if field.endswith('/') and recurse:
486
-                self.fetch(uri + field)
487
-            if uri.endswith('/'):
488
-                new_uri = uri + field
489
-            else:
490
-                new_uri = uri + '/' + field
491
-            if new_uri not in self._data and not new_uri.endswith('/'):
492
-                content = self._fetch(new_uri)
493
-                if field == 'security-groups' or field == 'security-group-ids':
494
-                    sg_fields = ",".join(content.split('\n'))
495
-                    self._data['%s' % (new_uri)] = sg_fields
496
-                else:
497
-                    try:
498
-                        dict = json.loads(content)
499
-                        self._data['%s' % (new_uri)] = content
500
-                        for (key, value) in dict.items():
501
-                            self._data['%s_%s' % (new_uri, key.lower())] = value
502
-                    except:
503
-                        self._data['%s' % (new_uri)] = content  # not a stringifed JSON string
504
-
505
-    def fix_invalid_varnames(self, data):
506
-        """Change ':'' and '-' to '_' to ensure valid template variable names"""
507
-        new_data = data.copy()
508
-        for key, value in data.items():
509
-            if ':' in key or '-' in key:
510
-                newkey = re.sub(':|-', '_', key)
511
-                new_data[newkey] = value
512
-                del new_data[key]
513
-
514
-        return new_data
515
-
516
-    def run(self):
517
-        self.fetch(self.uri_meta)  # populate _data with metadata
518
-        data = self._mangle_fields(self._data, self.uri_meta)
519
-        data[self._prefix % 'user-data'] = self._fetch(self.uri_user)
520
-        data[self._prefix % 'public-key'] = self._fetch(self.uri_ssh)
521
-
522
-        self._data = {}  # clear out metadata in _data
523
-        self.fetch(self.uri_dynamic)  # populate _data with dynamic data
524
-        dyndata = self._mangle_fields(self._data, self.uri_dynamic)
525
-        data.update(dyndata)
526
-        data = self.fix_invalid_varnames(data)
527
-
528
-        # Maintain old key for backwards compatibility
529
-        data['ansible_ec2_placement_region'] = data['ansible_ec2_instance_identity_document_region']
530
-        return data
531
-
532
-
533
-def main():
534
-    argument_spec = url_argument_spec()
535
-
536
-    module = AnsibleModule(
537
-        argument_spec=argument_spec,
538
-        supports_check_mode=True,
539
-    )
540
-
541
-    ec2_facts = Ec2Metadata(module).run()
542
-    ec2_facts_result = dict(changed=False, ansible_facts=ec2_facts)
543
-
544
-    module.exit_json(**ec2_facts_result)
545
-
546
-
547
-if __name__ == '__main__':
548
-    main()
549 1
new file mode 100644
... ...
@@ -0,0 +1,552 @@
0
+#!/usr/bin/python
1
+# -*- coding: utf-8 -*-
2
+
3
+# This file is part of Ansible
4
+#
5
+# Ansible is free software: you can redistribute it and/or modify
6
+# it under the terms of the GNU General Public License as published by
7
+# the Free Software Foundation, either version 3 of the License, or
8
+# (at your option) any later version.
9
+#
10
+# Ansible is distributed in the hope that it will be useful,
11
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+# GNU General Public License for more details.
14
+#
15
+# You should have received a copy of the GNU General Public License
16
+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ANSIBLE_METADATA = {'metadata_version': '1.0',
19
+                    'status': ['stableinterface'],
20
+                    'supported_by': 'curated'}
21
+
22
+
23
+DOCUMENTATION = '''
24
+---
25
+module: ec2_metadata_facts
26
+short_description: Gathers facts (instance metadata) about remote hosts within ec2
27
+version_added: "1.0"
28
+author:
29
+    - Silviu Dicu (@silviud)
30
+    - Vinay Dandekar (@roadmapper)
31
+description:
32
+    - This module fetches data from the instance metadata endpoint in ec2 as per
33
+      http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html.
34
+      The module must be called from within the EC2 instance itself.
35
+notes:
36
+    - Parameters to filter on ec2_metadata_facts may be added later.
37
+'''
38
+
39
+EXAMPLES = '''
40
+# Gather EC2 metadata facts
41
+- ec2_metadata_facts:
42
+
43
+- debug:
44
+    msg: "This instance is a t1.micro"
45
+  when: ansible_ec2_instance_type == "t1.micro"
46
+'''
47
+
48
+RETURN = '''
49
+ansible_facts:
50
+    description: Dictionary of new facts representing discovered properties of the EC2 instance.
51
+    returned: changed
52
+    type: complex
53
+    contains:
54
+        ansible_ec2_ami_id:
55
+            description: The AMI ID used to launch the instance.
56
+            type: string
57
+            sample: "ami-XXXXXXXX"
58
+        ansible_ec2_ami_launch_index:
59
+            description:
60
+                - If you started more than one instance at the same time, this value indicates the order in which the instance was launched.
61
+                  The value of the first instance launched is 0.
62
+            type: string
63
+            sample: "0"
64
+        ansible_ec2_ami_manifest_path:
65
+            description:
66
+                - The path to the AMI manifest file in Amazon S3.
67
+                  If you used an Amazon EBS-backed AMI to launch the instance, the returned result is unknown.
68
+            type: string
69
+            sample: "(unknown)"
70
+        ansible_ec2_ancestor_ami_ids:
71
+            description:
72
+                - The AMI IDs of any instances that were rebundled to create this AMI.
73
+                  This value will only exist if the AMI manifest file contained an ancestor-amis key.
74
+            type: string
75
+            sample: "(unknown)"
76
+        ansible_ec2_block_device_mapping_ami:
77
+            description: The virtual device that contains the root/boot file system.
78
+            type: string
79
+            sample: "/dev/sda1"
80
+        ansible_ec2_block_device_mapping_ebsN:
81
+            description:
82
+                - The virtual devices associated with Amazon EBS volumes, if any are present.
83
+                  Amazon EBS volumes are only available in metadata if they were present at launch time or when the instance was last started.
84
+                  The N indicates the index of the Amazon EBS volume (such as ebs1 or ebs2).
85
+            type: string
86
+            sample: "/dev/xvdb"
87
+        ansible_ec2_block_device_mapping_ephemeralN:
88
+            description: The virtual devices associated with ephemeral devices, if any are present. The N indicates the index of the ephemeral volume.
89
+            type: string
90
+            sample: "/dev/xvdc"
91
+        ansible_ec2_block_device_mapping_root:
92
+            description:
93
+                - The virtual devices or partitions associated with the root devices, or partitions on the virtual device,
94
+                  where the root (/ or C) file system is associated with the given instance.
95
+            type: string
96
+            sample: "/dev/sda1"
97
+        ansible_ec2_block_device_mapping_swap:
98
+            description: The virtual devices associated with swap. Not always present.
99
+            type: string
100
+            sample: "/dev/sda2"
101
+        ansible_ec2_fws_instance_monitoring:
102
+            description: "Value showing whether the customer has enabled detailed one-minute monitoring in CloudWatch."
103
+            type: string
104
+            sample: "enabled"
105
+        ansible_ec2_hostname:
106
+            description:
107
+                - The private IPv4 DNS hostname of the instance.
108
+                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
109
+            type: string
110
+            sample: "ip-10-0-0-1.ec2.internal"
111
+        ansible_ec2_iam_info:
112
+            description:
113
+                - If there is an IAM role associated with the instance, contains information about the last time the instance profile was updated,
114
+                  including the instance's LastUpdated date, InstanceProfileArn, and InstanceProfileId. Otherwise, not present.
115
+            type: complex
116
+            sample: ""
117
+        ansible_ec2_iam_info_instanceprofilearn:
118
+            description: The IAM instance profile ARN.
119
+            type: string
120
+            sample: "arn:aws:iam::<account id>:instance-profile/<role name>"
121
+        ansible_ec2_iam_info_instanceprofileid:
122
+            description: IAM instance profile ID.
123
+            type: string
124
+            sample: ""
125
+        ansible_ec2_iam_info_lastupdated:
126
+            description: IAM info last updated time.
127
+            type: string
128
+            sample: "2017-05-12T02:42:27Z"
129
+        ansible_ec2_iam_instance_profile_role:
130
+            description: IAM instance role.
131
+            type: string
132
+            sample: "role_name"
133
+        ansible_ec2_iam_security_credentials_<role name>:
134
+            description:
135
+                - If there is an IAM role associated with the instance, role-name is the name of the role,
136
+                  and role-name contains the temporary security credentials associated with the role. Otherwise, not present.
137
+            type: string
138
+            sample: ""
139
+        ansible_ec2_iam_security_credentials_<role name>_accesskeyid:
140
+            description: IAM role access key ID.
141
+            type: string
142
+            sample: ""
143
+        ansible_ec2_iam_security_credentials_<role name>_code:
144
+            description: IAM code.
145
+            type: string
146
+            sample: "Success"
147
+        ansible_ec2_iam_security_credentials_<role name>_expiration:
148
+            description: IAM role credentials expiration time.
149
+            type: string
150
+            sample: "2017-05-12T09:11:41Z"
151
+        ansible_ec2_iam_security_credentials_<role name>_lastupdated:
152
+            description: IAM role last updated time.
153
+            type: string
154
+            sample: "2017-05-12T02:40:44Z"
155
+        ansible_ec2_iam_security_credentials_<role name>_secretaccesskey:
156
+            description: IAM role secret access key.
157
+            type: string
158
+            sample: ""
159
+        ansible_ec2_iam_security_credentials_<role name>_token:
160
+            description: IAM role token.
161
+            type: string
162
+            sample: ""
163
+        ansible_ec2_iam_security_credentials_<role name>_type:
164
+            description: IAM role type.
165
+            type: string
166
+            sample: "AWS-HMAC"
167
+        ansible_ec2_instance_action:
168
+            description: Notifies the instance that it should reboot in preparation for bundling.
169
+            type: string
170
+            sample: "none"
171
+        ansible_ec2_instance_id:
172
+            description: The ID of this instance.
173
+            type: string
174
+            sample: "i-XXXXXXXXXXXXXXXXX"
175
+        ansible_ec2_instance_identity_document:
176
+            description: JSON containing instance attributes, such as instance-id, private IP address, etc.
177
+            type: string
178
+            sample: ""
179
+        ansible_ec2_instance_identity_document_accountid:
180
+            description: ""
181
+            type: string
182
+            sample: "012345678901"
183
+        ansible_ec2_instance_identity_document_architecture:
184
+            description: Instance system architecture.
185
+            type: string
186
+            sample: "x86_64"
187
+        ansible_ec2_instance_identity_document_availabilityzone:
188
+            description: The Availability Zone in which the instance launched.
189
+            type: string
190
+            sample: "us-east-1a"
191
+        ansible_ec2_instance_identity_document_billingproducts:
192
+            description: Billing products for this instance.
193
+            type: string
194
+            sample: ""
195
+        ansible_ec2_instance_identity_document_devpayproductcodes:
196
+            description: Product codes for the launched AMI.
197
+            type: string
198
+            sample: ""
199
+        ansible_ec2_instance_identity_document_imageid:
200
+            description: The AMI ID used to launch the instance.
201
+            type: string
202
+            sample: "ami-01234567"
203
+        ansible_ec2_instance_identity_document_instanceid:
204
+            description: The ID of this instance.
205
+            type: string
206
+            sample: "i-0123456789abcdef0"
207
+        ansible_ec2_instance_identity_document_instancetype:
208
+            description: The type of instance.
209
+            type: string
210
+            sample: "m4.large"
211
+        ansible_ec2_instance_identity_document_kernelid:
212
+            description: The ID of the kernel launched with this instance, if applicable.
213
+            type: string
214
+            sample: ""
215
+        ansible_ec2_instance_identity_document_pendingtime:
216
+            description: The instance pending time.
217
+            type: string
218
+            sample: "2017-05-11T20:51:20Z"
219
+        ansible_ec2_instance_identity_document_privateip:
220
+            description:
221
+                - The private IPv4 address of the instance.
222
+                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
223
+            type: string
224
+            sample: "10.0.0.1"
225
+        ansible_ec2_instance_identity_document_ramdiskid:
226
+            description: The ID of the RAM disk specified at launch time, if applicable.
227
+            type: string
228
+            sample: ""
229
+        ansible_ec2_instance_identity_document_region:
230
+            description: The Region in which the instance launched.
231
+            type: string
232
+            sample: "us-east-1"
233
+        ansible_ec2_instance_identity_document_version:
234
+            description: Identity document version.
235
+            type: string
236
+            sample: "2010-08-31"
237
+        ansible_ec2_instance_identity_pkcs7:
238
+            description: Used to verify the document's authenticity and content against the signature.
239
+            type: string
240
+            sample: ""
241
+        ansible_ec2_instance_identity_rsa2048:
242
+            description: Used to verify the document's authenticity and content against the signature.
243
+            type: string
244
+            sample: ""
245
+        ansible_ec2_instance_identity_signature:
246
+            description: Data that can be used by other parties to verify its origin and authenticity.
247
+            type: string
248
+            sample: ""
249
+        ansible_ec2_instance_type:
250
+            description: The type of instance.
251
+            type: string
252
+            sample: "m4.large"
253
+        ansible_ec2_local_hostname:
254
+            description:
255
+                - The private IPv4 DNS hostname of the instance.
256
+                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
257
+            type: string
258
+            sample: "ip-10-0-0-1.ec2.internal"
259
+        ansible_ec2_local_ipv4:
260
+            description:
261
+                - The private IPv4 address of the instance.
262
+                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
263
+            type: string
264
+            sample: "10.0.0.1"
265
+        ansible_ec2_mac:
266
+            description:
267
+                - The instance's media access control (MAC) address.
268
+                  In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
269
+            type: string
270
+            sample: "00:11:22:33:44:55"
271
+        ansible_ec2_metrics_vhostmd:
272
+            description: Metrics.
273
+            type: string
274
+            sample: ""
275
+        ansible_ec2_network_interfaces_macs_<mac address>_device_number:
276
+            description:
277
+                - The unique device number associated with that interface. The device number corresponds to the device name;
278
+                  for example, a device-number of 2 is for the eth2 device.
279
+                  This category corresponds to the DeviceIndex and device-index fields that are used by the Amazon EC2 API and the EC2 commands for the AWS CLI.
280
+            type: string
281
+            sample: "0"
282
+        ansible_ec2_network_interfaces_macs_<mac address>_interface_id:
283
+            description: The elastic network interface ID.
284
+            type: string
285
+            sample: "eni-12345678"
286
+        ansible_ec2_network_interfaces_macs_<mac address>_ipv4_associations_<ip address>:
287
+            description: The private IPv4 addresses that are associated with each public-ip address and assigned to that interface.
288
+            type: string
289
+            sample: ""
290
+        ansible_ec2_network_interfaces_macs_<mac address>_ipv6s:
291
+            description: The IPv6 addresses associated with the interface. Returned only for instances launched into a VPC.
292
+            type: string
293
+            sample: ""
294
+        ansible_ec2_network_interfaces_macs_<mac address>_local_hostname:
295
+            description: The interface's local hostname.
296
+            type: string
297
+            sample: ""
298
+        ansible_ec2_network_interfaces_macs_<mac address>_local_ipv4s:
299
+            description: The private IPv4 addresses associated with the interface.
300
+            type: string
301
+            sample: ""
302
+        ansible_ec2_network_interfaces_macs_<mac address>_mac:
303
+            description: The instance's MAC address.
304
+            type: string
305
+            sample: "00:11:22:33:44:55"
306
+        ansible_ec2_network_interfaces_macs_<mac address>_owner_id:
307
+            description:
308
+                - The ID of the owner of the network interface.
309
+                  In multiple-interface environments, an interface can be attached by a third party, such as Elastic Load Balancing.
310
+                  Traffic on an interface is always billed to the interface owner.
311
+            type: string
312
+            sample: "01234567890"
313
+        ansible_ec2_network_interfaces_macs_<mac address>_public_hostname:
314
+            description:
315
+                - The interface's public DNS (IPv4). If the instance is in a VPC,
316
+                  this category is only returned if the enableDnsHostnames attribute is set to true.
317
+            type: string
318
+            sample: "ec2-1-2-3-4.compute-1.amazonaws.com"
319
+        ansible_ec2_network_interfaces_macs_<mac address>_public_ipv4s:
320
+            description: The Elastic IP addresses associated with the interface. There may be multiple IPv4 addresses on an instance.
321
+            type: string
322
+            sample: "1.2.3.4"
323
+        ansible_ec2_network_interfaces_macs_<mac address>_security_group_ids:
324
+            description: The IDs of the security groups to which the network interface belongs. Returned only for instances launched into a VPC.
325
+            type: string
326
+            sample: "sg-01234567,sg-01234568"
327
+        ansible_ec2_network_interfaces_macs_<mac address>_security_groups:
328
+            description: Security groups to which the network interface belongs. Returned only for instances launched into a VPC.
329
+            type: string
330
+            sample: "secgroup1,secgroup2"
331
+        ansible_ec2_network_interfaces_macs_<mac address>_subnet_id:
332
+            description: The ID of the subnet in which the interface resides. Returned only for instances launched into a VPC.
333
+            type: string
334
+            sample: "subnet-01234567"
335
+        ansible_ec2_network_interfaces_macs_<mac address>_subnet_ipv4_cidr_block:
336
+            description: The IPv4 CIDR block of the subnet in which the interface resides. Returned only for instances launched into a VPC.
337
+            type: string
338
+            sample: "10.0.1.0/24"
339
+        ansible_ec2_network_interfaces_macs_<mac address>_subnet_ipv6_cidr_blocks:
340
+            description: The IPv6 CIDR block of the subnet in which the interface resides. Returned only for instances launched into a VPC.
341
+            type: string
342
+            sample: ""
343
+        ansible_ec2_network_interfaces_macs_<mac address>_vpc_id:
344
+            description: The ID of the VPC in which the interface resides. Returned only for instances launched into a VPC.
345
+            type: string
346
+            sample: "vpc-0123456"
347
+        ansible_ec2_network_interfaces_macs_<mac address>_vpc_ipv4_cidr_block:
348
+            description: The IPv4 CIDR block of the VPC in which the interface resides. Returned only for instances launched into a VPC.
349
+            type: string
350
+            sample: "10.0.0.0/16"
351
+        ansible_ec2_network_interfaces_macs_<mac address>_vpc_ipv4_cidr_blocks:
352
+            description: The IPv4 CIDR block of the VPC in which the interface resides. Returned only for instances launched into a VPC.
353
+            type: string
354
+            sample: "10.0.0.0/16"
355
+        ansible_ec2_network_interfaces_macs_<mac address>_vpc_ipv6_cidr_blocks:
356
+            description: The IPv6 CIDR block of the VPC in which the interface resides. Returned only for instances launched into a VPC.
357
+            type: string
358
+            sample: ""
359
+        ansible_ec2_placement_availability_zone:
360
+            description: The Availability Zone in which the instance launched.
361
+            type: string
362
+            sample: "us-east-1a"
363
+        ansible_ec2_placement_region:
364
+            description: The Region in which the instance launched.
365
+            type: string
366
+            sample: "us-east-1"
367
+        ansible_ec2_product_codes:
368
+            description: Product codes associated with the instance, if any.
369
+            type: string
370
+            sample: "aw0evgkw8e5c1q413zgy5pjce"
371
+        ansible_ec2_profile:
372
+            description: EC2 instance hardware profile.
373
+            type: string
374
+            sample: "default-hvm"
375
+        ansible_ec2_public_hostname:
376
+            description:
377
+                - The instance's public DNS. If the instance is in a VPC, this category is only returned if the enableDnsHostnames attribute is set to true.
378
+            type: string
379
+            sample: "ec2-1-2-3-4.compute-1.amazonaws.com"
380
+        ansible_ec2_public_ipv4:
381
+            description: The public IPv4 address. If an Elastic IP address is associated with the instance, the value returned is the Elastic IP address.
382
+            type: string
383
+            sample: "1.2.3.4"
384
+        ansible_ec2_public_key:
385
+            description: Public key. Only available if supplied at instance launch time.
386
+            type: string
387
+            sample: ""
388
+        ansible_ec2_ramdisk_id:
389
+            description: The ID of the RAM disk specified at launch time, if applicable.
390
+            type: string
391
+            sample: ""
392
+        ansible_ec2_reservation_id:
393
+            description: The ID of the reservation.
394
+            type: string
395
+            sample: "r-0123456789abcdef0"
396
+        ansible_ec2_security_groups:
397
+            description:
398
+                - The names of the security groups applied to the instance. After launch, you can only change the security groups of instances running in a VPC.
399
+                  Such changes are reflected here and in network/interfaces/macs/mac/security-groups.
400
+            type: string
401
+            sample: "securitygroup1,securitygroup2"
402
+        ansible_ec2_services_domain:
403
+            description: The domain for AWS resources for the region; for example, amazonaws.com for us-east-1.
404
+            type: string
405
+            sample: "amazonaws.com"
406
+        ansible_ec2_services_partition:
407
+            description:
408
+                - The partition that the resource is in. For standard AWS regions, the partition is aws.
409
+                  If you have resources in other partitions, the partition is aws-partitionname.
410
+                  For example, the partition for resources in the China (Beijing) region is aws-cn.
411
+            type: string
412
+            sample: "aws"
413
+        ansible_ec2_spot_termination_time:
414
+            description:
415
+                - The approximate time, in UTC, that the operating system for your Spot instance will receive the shutdown signal.
416
+                  This item is present and contains a time value only if the Spot instance has been marked for termination by Amazon EC2.
417
+                  The termination-time item is not set to a time if you terminated the Spot instance yourself.
418
+            type: string
419
+            sample: "2015-01-05T18:02:00Z"
420
+        ansible_ec2_user_data:
421
+            description: The instance user data.
422
+            type: string
423
+            sample: "#!/bin/bash"
424
+'''
425
+
426
+import socket
427
+import re
428
+import json
429
+
430
+from ansible.module_utils._text import to_text
431
+from ansible.module_utils.basic import AnsibleModule
432
+from ansible.module_utils.urls import fetch_url, url_argument_spec
433
+
434
+socket.setdefaulttimeout(5)
435
+
436
+
437
+class Ec2Metadata(object):
438
+    ec2_metadata_uri = 'http://169.254.169.254/latest/meta-data/'
439
+    ec2_sshdata_uri = 'http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key'
440
+    ec2_userdata_uri = 'http://169.254.169.254/latest/user-data/'
441
+    ec2_dynamicdata_uri = 'http://169.254.169.254/latest/dynamic/'
442
+
443
+    def __init__(self, module, ec2_metadata_uri=None, ec2_sshdata_uri=None, ec2_userdata_uri=None, ec2_dynamicdata_uri=None):
444
+        self.module = module
445
+        self.uri_meta = ec2_metadata_uri or self.ec2_metadata_uri
446
+        self.uri_user = ec2_userdata_uri or self.ec2_userdata_uri
447
+        self.uri_ssh = ec2_sshdata_uri or self.ec2_sshdata_uri
448
+        self.uri_dynamic = ec2_dynamicdata_uri or self.ec2_dynamicdata_uri
449
+        self._data = {}
450
+        self._prefix = 'ansible_ec2_%s'
451
+
452
+    def _fetch(self, url):
453
+        (response, info) = fetch_url(self.module, url, force=True)
454
+        if response:
455
+            data = response.read()
456
+        else:
457
+            data = None
458
+        return to_text(data)
459
+
460
+    def _mangle_fields(self, fields, uri, filter_patterns=['public-keys-0']):
461
+        new_fields = {}
462
+        for key, value in fields.items():
463
+            split_fields = key[len(uri):].split('/')
464
+            if len(split_fields) == 3 and split_fields[0:2] == ['iam', 'security-credentials'] and '_' not in split_fields[2]:
465
+                new_fields[self._prefix % "iam-instance-profile-role"] = split_fields[2]
466
+            if len(split_fields) > 1 and split_fields[1]:
467
+                new_key = "-".join(split_fields)
468
+                new_fields[self._prefix % new_key] = value
469
+            else:
470
+                new_key = "".join(split_fields)
471
+                new_fields[self._prefix % new_key] = value
472
+        for pattern in filter_patterns:
473
+            for key in dict(new_fields):
474
+                match = re.search(pattern, key)
475
+                if match:
476
+                    new_fields.pop(key)
477
+        return new_fields
478
+
479
+    def fetch(self, uri, recurse=True):
480
+        raw_subfields = self._fetch(uri)
481
+        if not raw_subfields:
482
+            return
483
+        subfields = raw_subfields.split('\n')
484
+        for field in subfields:
485
+            if field.endswith('/') and recurse:
486
+                self.fetch(uri + field)
487
+            if uri.endswith('/'):
488
+                new_uri = uri + field
489
+            else:
490
+                new_uri = uri + '/' + field
491
+            if new_uri not in self._data and not new_uri.endswith('/'):
492
+                content = self._fetch(new_uri)
493
+                if field == 'security-groups' or field == 'security-group-ids':
494
+                    sg_fields = ",".join(content.split('\n'))
495
+                    self._data['%s' % (new_uri)] = sg_fields
496
+                else:
497
+                    try:
498
+                        dict = json.loads(content)
499
+                        self._data['%s' % (new_uri)] = content
500
+                        for (key, value) in dict.items():
501
+                            self._data['%s_%s' % (new_uri, key.lower())] = value
502
+                    except:
503
+                        self._data['%s' % (new_uri)] = content  # not a stringifed JSON string
504
+
505
+    def fix_invalid_varnames(self, data):
506
+        """Change ':'' and '-' to '_' to ensure valid template variable names"""
507
+        new_data = data.copy()
508
+        for key, value in data.items():
509
+            if ':' in key or '-' in key:
510
+                newkey = re.sub(':|-', '_', key)
511
+                new_data[newkey] = value
512
+                del new_data[key]
513
+
514
+        return new_data
515
+
516
+    def run(self):
517
+        self.fetch(self.uri_meta)  # populate _data with metadata
518
+        data = self._mangle_fields(self._data, self.uri_meta)
519
+        data[self._prefix % 'user-data'] = self._fetch(self.uri_user)
520
+        data[self._prefix % 'public-key'] = self._fetch(self.uri_ssh)
521
+
522
+        self._data = {}  # clear out metadata in _data
523
+        self.fetch(self.uri_dynamic)  # populate _data with dynamic data
524
+        dyndata = self._mangle_fields(self._data, self.uri_dynamic)
525
+        data.update(dyndata)
526
+        data = self.fix_invalid_varnames(data)
527
+
528
+        # Maintain old key for backwards compatibility
529
+        data['ansible_ec2_placement_region'] = data['ansible_ec2_instance_identity_document_region']
530
+        return data
531
+
532
+
533
+def main():
534
+    argument_spec = url_argument_spec()
535
+
536
+    module = AnsibleModule(
537
+        argument_spec=argument_spec,
538
+        supports_check_mode=True,
539
+    )
540
+
541
+    if module._name == 'ec2_facts':
542
+        module.deprecate("The 'ec2_facts' module is being renamed 'ec2_metadata_facts'", version=2.7)
543
+
544
+    ec2_metadata_facts = Ec2Metadata(module).run()
545
+    ec2_metadata_facts_result = dict(changed=False, ansible_facts=ec2_metadata_facts)
546
+
547
+    module.exit_json(**ec2_metadata_facts_result)
548
+
549
+
550
+if __name__ == '__main__':
551
+    main()