ec2_ami_find.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #!/usr/bin/python
  2. #pylint: skip-file
  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. DOCUMENTATION = '''
  19. ---
  20. module: ec2_ami_find
  21. version_added: 2.0
  22. short_description: Searches for AMIs to obtain the AMI ID and other information
  23. description:
  24. - Returns list of matching AMIs with AMI ID, along with other useful information
  25. - Can search AMIs with different owners
  26. - Can search by matching tag(s), by AMI name and/or other criteria
  27. - Results can be sorted and sliced
  28. author: Tom Bamford
  29. notes:
  30. - This module is not backwards compatible with the previous version of the ec2_search_ami module which worked only for Ubuntu AMIs listed on cloud-images.ubuntu.com.
  31. - See the example below for a suggestion of how to search by distro/release.
  32. options:
  33. region:
  34. description:
  35. - The AWS region to use.
  36. required: true
  37. aliases: [ 'aws_region', 'ec2_region' ]
  38. owner:
  39. description:
  40. - Search AMIs owned by the specified owner
  41. - Can specify an AWS account ID, or one of the special IDs 'self', 'amazon' or 'aws-marketplace'
  42. - If not specified, all EC2 AMIs in the specified region will be searched.
  43. - You can include wildcards in many of the search options. An asterisk (*) matches zero or more characters, and a question mark (?) matches exactly one character. You can escape special characters using a backslash (\) before the character. For example, a value of \*amazon\?\\ searches for the literal string *amazon?\.
  44. required: false
  45. default: null
  46. ami_id:
  47. description:
  48. - An AMI ID to match.
  49. default: null
  50. required: false
  51. ami_tags:
  52. description:
  53. - A hash/dictionary of tags to match for the AMI.
  54. default: null
  55. required: false
  56. architecture:
  57. description:
  58. - An architecture type to match (e.g. x86_64).
  59. default: null
  60. required: false
  61. hypervisor:
  62. description:
  63. - A hypervisor type type to match (e.g. xen).
  64. default: null
  65. required: false
  66. is_public:
  67. description:
  68. - Whether or not the image(s) are public.
  69. choices: ['yes', 'no']
  70. default: null
  71. required: false
  72. name:
  73. description:
  74. - An AMI name to match.
  75. default: null
  76. required: false
  77. platform:
  78. description:
  79. - Platform type to match.
  80. default: null
  81. required: false
  82. sort:
  83. description:
  84. - Optional attribute which with to sort the results.
  85. - If specifying 'tag', the 'tag_name' parameter is required.
  86. choices: ['name', 'description', 'tag']
  87. default: null
  88. required: false
  89. sort_tag:
  90. description:
  91. - Tag name with which to sort results.
  92. - Required when specifying 'sort=tag'.
  93. default: null
  94. required: false
  95. sort_order:
  96. description:
  97. - Order in which to sort results.
  98. - Only used when the 'sort' parameter is specified.
  99. choices: ['ascending', 'descending']
  100. default: 'ascending'
  101. required: false
  102. sort_start:
  103. description:
  104. - Which result to start with (when sorting).
  105. - Corresponds to Python slice notation.
  106. default: null
  107. required: false
  108. sort_end:
  109. description:
  110. - Which result to end with (when sorting).
  111. - Corresponds to Python slice notation.
  112. default: null
  113. required: false
  114. state:
  115. description:
  116. - AMI state to match.
  117. default: 'available'
  118. required: false
  119. virtualization_type:
  120. description:
  121. - Virtualization type to match (e.g. hvm).
  122. default: null
  123. required: false
  124. no_result_action:
  125. description:
  126. - What to do when no results are found.
  127. - "'success' reports success and returns an empty array"
  128. - "'fail' causes the module to report failure"
  129. choices: ['success', 'fail']
  130. default: 'success'
  131. required: false
  132. requirements:
  133. - boto
  134. '''
  135. EXAMPLES = '''
  136. # Note: These examples do not set authentication details, see the AWS Guide for details.
  137. # Search for the AMI tagged "project:website"
  138. - ec2_ami_find:
  139. owner: self
  140. tags:
  141. project: website
  142. no_result_action: fail
  143. register: ami_find
  144. # Search for the latest Ubuntu 14.04 AMI
  145. - ec2_ami_find:
  146. name: "ubuntu/images/ebs/ubuntu-trusty-14.04-amd64-server-*"
  147. owner: 099720109477
  148. sort: name
  149. sort_order: descending
  150. sort_end: 1
  151. register: ami_find
  152. # Launch an EC2 instance
  153. - ec2:
  154. image: "{{ ami_search.results[0].ami_id }}"
  155. instance_type: m4.medium
  156. key_name: mykey
  157. wait: yes
  158. '''
  159. try:
  160. import boto.ec2
  161. HAS_BOTO=True
  162. except ImportError:
  163. HAS_BOTO=False
  164. import json
  165. def main():
  166. argument_spec = ec2_argument_spec()
  167. argument_spec.update(dict(
  168. region = dict(required=True,
  169. aliases = ['aws_region', 'ec2_region']),
  170. owner = dict(required=False, default=None),
  171. ami_id = dict(required=False),
  172. ami_tags = dict(required=False, type='dict',
  173. aliases = ['search_tags', 'image_tags']),
  174. architecture = dict(required=False),
  175. hypervisor = dict(required=False),
  176. is_public = dict(required=False),
  177. name = dict(required=False),
  178. platform = dict(required=False),
  179. sort = dict(required=False, default=None,
  180. choices=['name', 'description', 'tag']),
  181. sort_tag = dict(required=False),
  182. sort_order = dict(required=False, default='ascending',
  183. choices=['ascending', 'descending']),
  184. sort_start = dict(required=False),
  185. sort_end = dict(required=False),
  186. state = dict(required=False, default='available'),
  187. virtualization_type = dict(required=False),
  188. no_result_action = dict(required=False, default='success',
  189. choices = ['success', 'fail']),
  190. )
  191. )
  192. module = AnsibleModule(
  193. argument_spec=argument_spec,
  194. )
  195. if not HAS_BOTO:
  196. module.fail_json(msg='boto required for this module, install via pip or your package manager')
  197. ami_id = module.params.get('ami_id')
  198. ami_tags = module.params.get('ami_tags')
  199. architecture = module.params.get('architecture')
  200. hypervisor = module.params.get('hypervisor')
  201. is_public = module.params.get('is_public')
  202. name = module.params.get('name')
  203. owner = module.params.get('owner')
  204. platform = module.params.get('platform')
  205. sort = module.params.get('sort')
  206. sort_tag = module.params.get('sort_tag')
  207. sort_order = module.params.get('sort_order')
  208. sort_start = module.params.get('sort_start')
  209. sort_end = module.params.get('sort_end')
  210. state = module.params.get('state')
  211. virtualization_type = module.params.get('virtualization_type')
  212. no_result_action = module.params.get('no_result_action')
  213. filter = {'state': state}
  214. if ami_id:
  215. filter['image_id'] = ami_id
  216. if ami_tags:
  217. for tag in ami_tags:
  218. filter['tag:'+tag] = ami_tags[tag]
  219. if architecture:
  220. filter['architecture'] = architecture
  221. if hypervisor:
  222. filter['hypervisor'] = hypervisor
  223. if is_public:
  224. filter['is_public'] = is_public
  225. if name:
  226. filter['name'] = name
  227. if platform:
  228. filter['platform'] = platform
  229. if virtualization_type:
  230. filter['virtualization_type'] = virtualization_type
  231. ec2 = ec2_connect(module)
  232. images_result = ec2.get_all_images(owners=owner, filters=filter)
  233. if no_result_action == 'fail' and len(images_result) == 0:
  234. module.fail_json(msg="No AMIs matched the attributes: %s" % json.dumps(filter))
  235. results = []
  236. for image in images_result:
  237. data = {
  238. 'ami_id': image.id,
  239. 'architecture': image.architecture,
  240. 'description': image.description,
  241. 'is_public': image.is_public,
  242. 'name': image.name,
  243. 'owner_id': image.owner_id,
  244. 'platform': image.platform,
  245. 'root_device_name': image.root_device_name,
  246. 'root_device_type': image.root_device_type,
  247. 'state': image.state,
  248. 'tags': image.tags,
  249. 'virtualization_type': image.virtualization_type,
  250. }
  251. if image.kernel_id:
  252. data['kernel_id'] = image.kernel_id
  253. if image.ramdisk_id:
  254. data['ramdisk_id'] = image.ramdisk_id
  255. results.append(data)
  256. if sort == 'tag':
  257. if not sort_tag:
  258. module.fail_json(msg="'sort_tag' option must be given with 'sort=tag'")
  259. results.sort(key=lambda e: e['tags'][sort_tag], reverse=(sort_order=='descending'))
  260. elif sort:
  261. results.sort(key=lambda e: e[sort], reverse=(sort_order=='descending'))
  262. try:
  263. if sort and sort_start and sort_end:
  264. results = results[int(sort_start):int(sort_end)]
  265. elif sort and sort_start:
  266. results = results[int(sort_start):]
  267. elif sort and sort_end:
  268. results = results[:int(sort_end)]
  269. except TypeError:
  270. module.fail_json(msg="Please supply numeric values for sort_start and/or sort_end")
  271. module.exit_json(results=results)
  272. # import module snippets
  273. from ansible.module_utils.basic import *
  274. from ansible.module_utils.ec2 import *
  275. if __name__ == '__main__':
  276. main()