|
|
|
@ -78,12 +78,13 @@ options:
|
|
|
|
|
default: null
|
|
|
|
|
delete_snapshot:
|
|
|
|
|
description:
|
|
|
|
|
- Whether or not to delete an AMI while deregistering it.
|
|
|
|
|
- Whether or not to delete snapshots when deregistering AMI.
|
|
|
|
|
required: false
|
|
|
|
|
default: null
|
|
|
|
|
default: "no"
|
|
|
|
|
choices: [ "yes", "no" ]
|
|
|
|
|
tags:
|
|
|
|
|
description:
|
|
|
|
|
- a hash/dictionary of tags to add to the new image; '{"key":"value"}' and '{"key":"value","key":"value"}'
|
|
|
|
|
- a dictionary of tags to add to the new image; '{"key":"value"}' and '{"key":"value","key":"value"}'
|
|
|
|
|
required: false
|
|
|
|
|
default: null
|
|
|
|
|
version_added: "2.0"
|
|
|
|
@ -92,10 +93,13 @@ options:
|
|
|
|
|
- Users and groups that should be able to launch the ami. Expects dictionary with a key of user_ids and/or group_names. user_ids should be a list of account ids. group_name should be a list of groups, "all" is the only acceptable value currently.
|
|
|
|
|
required: false
|
|
|
|
|
default: null
|
|
|
|
|
aliases: []
|
|
|
|
|
|
|
|
|
|
author: "Evan Duffield (@scicoin-project) <eduffield@iacquire.com>"
|
|
|
|
|
extends_documentation_fragment: aws
|
|
|
|
|
version_added: "2.0"
|
|
|
|
|
author:
|
|
|
|
|
- "Evan Duffield (@scicoin-project) <eduffield@iacquire.com>"
|
|
|
|
|
- "Constantin Bugneac (@Constantin07) <constantin.bugneac@endava.com>"
|
|
|
|
|
extends_documentation_fragment:
|
|
|
|
|
- aws
|
|
|
|
|
- ec2
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
# Thank you to iAcquire for sponsoring development of this module.
|
|
|
|
@ -155,22 +159,22 @@ EXAMPLES = '''
|
|
|
|
|
no_device: yes
|
|
|
|
|
register: instance
|
|
|
|
|
|
|
|
|
|
# Deregister/Delete AMI
|
|
|
|
|
# Deregister/Delete AMI (keep associated snapshots)
|
|
|
|
|
- ec2_ami:
|
|
|
|
|
aws_access_key: xxxxxxxxxxxxxxxxxxxxxxx
|
|
|
|
|
aws_secret_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
|
|
|
region: xxxxxx
|
|
|
|
|
image_id: "{{ instance.image_id }}"
|
|
|
|
|
delete_snapshot: True
|
|
|
|
|
delete_snapshot: False
|
|
|
|
|
state: absent
|
|
|
|
|
|
|
|
|
|
# Deregister AMI
|
|
|
|
|
# Deregister AMI (delete associated snapshots too)
|
|
|
|
|
- ec2_ami:
|
|
|
|
|
aws_access_key: xxxxxxxxxxxxxxxxxxxxxxx
|
|
|
|
|
aws_secret_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
|
|
|
region: xxxxxx
|
|
|
|
|
image_id: "{{ instance.image_id }}"
|
|
|
|
|
delete_snapshot: False
|
|
|
|
|
delete_snapshot: True
|
|
|
|
|
state: absent
|
|
|
|
|
|
|
|
|
|
# Update AMI Launch Permissions, making it public
|
|
|
|
@ -194,6 +198,102 @@ EXAMPLES = '''
|
|
|
|
|
user_ids: ['123456789012']
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
RETURN = '''
|
|
|
|
|
architecture:
|
|
|
|
|
description: architecture of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "x86_64"
|
|
|
|
|
block_device_mapping:
|
|
|
|
|
description: block device mapping associated with image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: a dictionary of block devices
|
|
|
|
|
sample: {
|
|
|
|
|
"/dev/sda1": {
|
|
|
|
|
"delete_on_termination": true,
|
|
|
|
|
"encrypted": false,
|
|
|
|
|
"size": 10,
|
|
|
|
|
"snapshot_id": "snap-1a03b80e7",
|
|
|
|
|
"volume_type": "standard"
|
|
|
|
|
}
|
|
|
|
|
creationDate:
|
|
|
|
|
description: creation date of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "2015-10-15T22:43:44.000Z"
|
|
|
|
|
description:
|
|
|
|
|
description: description of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "nat-server"
|
|
|
|
|
hypervisor:
|
|
|
|
|
description: type of hypervisor
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "xen"
|
|
|
|
|
is_public:
|
|
|
|
|
description: whether image is public
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: bool
|
|
|
|
|
sample: false
|
|
|
|
|
location:
|
|
|
|
|
description: location of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "315210894379/nat-server"
|
|
|
|
|
name:
|
|
|
|
|
description: ami name of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "nat-server"
|
|
|
|
|
owner_id:
|
|
|
|
|
description: owner of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "435210894375"
|
|
|
|
|
platform:
|
|
|
|
|
description: plaform of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: null
|
|
|
|
|
root_device_name:
|
|
|
|
|
description: root device name of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "/dev/sda1"
|
|
|
|
|
root_device_type:
|
|
|
|
|
description: root device type of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "ebs"
|
|
|
|
|
state:
|
|
|
|
|
description: state of image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "available"
|
|
|
|
|
tags:
|
|
|
|
|
description: a dictionary of tags assigned to image
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: dictionary of tags
|
|
|
|
|
sample: {
|
|
|
|
|
"Env": "devel",
|
|
|
|
|
"Name": "nat-server"
|
|
|
|
|
}
|
|
|
|
|
virtualization_type:
|
|
|
|
|
description: image virtualization type
|
|
|
|
|
returned: when AMI is created or already exists
|
|
|
|
|
type: string
|
|
|
|
|
sample: "hvm"
|
|
|
|
|
snapshots_deleted:
|
|
|
|
|
description: a list of snapshot ids deleted after deregistering image
|
|
|
|
|
returned: after AMI is deregistered, if 'delete_snapshot' is set to 'yes'
|
|
|
|
|
type: list
|
|
|
|
|
sample: [
|
|
|
|
|
"snap-fbcccb8f",
|
|
|
|
|
"snap-cfe7cdb4"
|
|
|
|
|
]
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
@ -205,6 +305,47 @@ except ImportError:
|
|
|
|
|
HAS_BOTO = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_block_device_mapping(image):
|
|
|
|
|
"""
|
|
|
|
|
Retrieves block device mapping from AMI
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
bdm_dict = dict()
|
|
|
|
|
|
|
|
|
|
if image is not None and hasattr(image, 'block_device_mapping'):
|
|
|
|
|
bdm = getattr(image,'block_device_mapping')
|
|
|
|
|
for device_name in bdm.keys():
|
|
|
|
|
bdm_dict[device_name] = {
|
|
|
|
|
'size': bdm[device_name].size,
|
|
|
|
|
'snapshot_id': bdm[device_name].snapshot_id,
|
|
|
|
|
'volume_type': bdm[device_name].volume_type,
|
|
|
|
|
'encrypted': bdm[device_name].encrypted,
|
|
|
|
|
'delete_on_termination': bdm[device_name].delete_on_termination
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bdm_dict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_ami_info(image):
|
|
|
|
|
|
|
|
|
|
return dict(
|
|
|
|
|
image_id=image.id,
|
|
|
|
|
state=image.state,
|
|
|
|
|
architecture=image.architecture,
|
|
|
|
|
block_device_mapping=get_block_device_mapping(image),
|
|
|
|
|
creationDate=image.creationDate,
|
|
|
|
|
description=image.description,
|
|
|
|
|
hypervisor=image.hypervisor,
|
|
|
|
|
is_public=image.is_public,
|
|
|
|
|
location=image.location,
|
|
|
|
|
ownerId=image.ownerId,
|
|
|
|
|
root_device_name=image.root_device_name,
|
|
|
|
|
root_device_type=image.root_device_type,
|
|
|
|
|
tags=image.tags,
|
|
|
|
|
virtualization_type = image.virtualization_type
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_image(module, ec2):
|
|
|
|
|
"""
|
|
|
|
|
Creates new AMI
|
|
|
|
@ -278,7 +419,7 @@ def create_image(module, ec2):
|
|
|
|
|
except boto.exception.BotoServerError, e:
|
|
|
|
|
module.fail_json(msg="%s: %s" % (e.error_code, e.error_message), image_id=image_id)
|
|
|
|
|
|
|
|
|
|
module.exit_json(msg="AMI creation operation complete", image_id=image_id, state=img.state, changed=True)
|
|
|
|
|
module.exit_json(msg="AMI creation operation complete", changed=True, **get_ami_info(img))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def deregister_image(module, ec2):
|
|
|
|
@ -295,13 +436,23 @@ def deregister_image(module, ec2):
|
|
|
|
|
if img == None:
|
|
|
|
|
module.fail_json(msg = "Image %s does not exist" % image_id, changed=False)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
params = {'image_id': image_id,
|
|
|
|
|
'delete_snapshot': delete_snapshot}
|
|
|
|
|
# Get all associated snapshot ids before deregistering image otherwise this information becomes unavailable
|
|
|
|
|
snapshots = []
|
|
|
|
|
if hasattr(img, 'block_device_mapping'):
|
|
|
|
|
for key in img.block_device_mapping:
|
|
|
|
|
snapshots.append(img.block_device_mapping[key].snapshot_id)
|
|
|
|
|
|
|
|
|
|
res = ec2.deregister_image(**params)
|
|
|
|
|
except boto.exception.BotoServerError, e:
|
|
|
|
|
module.fail_json(msg = "%s: %s" % (e.error_code, e.error_message))
|
|
|
|
|
# When trying to re-delete already deleted image it doesn't raise an exception
|
|
|
|
|
# It just returns an object without image attributes
|
|
|
|
|
if hasattr(img, 'id'):
|
|
|
|
|
try:
|
|
|
|
|
params = {'image_id': image_id,
|
|
|
|
|
'delete_snapshot': delete_snapshot}
|
|
|
|
|
res = ec2.deregister_image(**params)
|
|
|
|
|
except boto.exception.BotoServerError, e:
|
|
|
|
|
module.fail_json(msg = "%s: %s" % (e.error_code, e.error_message))
|
|
|
|
|
else:
|
|
|
|
|
module.exit_json(msg = "Image %s has already been deleted" % image_id, changed=False)
|
|
|
|
|
|
|
|
|
|
# wait here until the image is gone
|
|
|
|
|
img = ec2.get_image(image_id)
|
|
|
|
@ -311,9 +462,21 @@ def deregister_image(module, ec2):
|
|
|
|
|
time.sleep(3)
|
|
|
|
|
if wait and wait_timeout <= time.time():
|
|
|
|
|
# waiting took too long
|
|
|
|
|
module.fail_json(msg = "timed out waiting for image to be reregistered/deleted")
|
|
|
|
|
module.fail_json(msg = "timed out waiting for image to be deregistered/deleted")
|
|
|
|
|
|
|
|
|
|
module.exit_json(msg="AMI deregister/delete operation complete", changed=True)
|
|
|
|
|
# Boto library has hardcoded the deletion of the snapshot for the root volume mounted as '/dev/sda1' only
|
|
|
|
|
# Make it possible to delete all snapshots which belong to image, including root block device mapped as '/dev/xvda'
|
|
|
|
|
if delete_snapshot:
|
|
|
|
|
try:
|
|
|
|
|
for snapshot_id in snapshots:
|
|
|
|
|
ec2.delete_snapshot(snapshot_id)
|
|
|
|
|
except boto.exception.BotoServerError, e:
|
|
|
|
|
if e.error_code == 'InvalidSnapshot.NotFound':
|
|
|
|
|
# Don't error out if root volume snapshot was already deleted as part of deregister_image
|
|
|
|
|
pass
|
|
|
|
|
module.exit_json(msg="AMI deregister/delete operation complete", changed=True, snapshots_deleted=snapshots)
|
|
|
|
|
else:
|
|
|
|
|
module.exit_json(msg="AMI deregister/delete operation complete", changed=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_image(module, ec2):
|
|
|
|
@ -351,12 +514,12 @@ def main():
|
|
|
|
|
argument_spec.update(dict(
|
|
|
|
|
instance_id = dict(),
|
|
|
|
|
image_id = dict(),
|
|
|
|
|
delete_snapshot = dict(),
|
|
|
|
|
delete_snapshot = dict(default=False, type='bool'),
|
|
|
|
|
name = dict(),
|
|
|
|
|
wait = dict(type="bool", default=False),
|
|
|
|
|
wait = dict(type='bool', default=False),
|
|
|
|
|
wait_timeout = dict(default=900),
|
|
|
|
|
description = dict(default=""),
|
|
|
|
|
no_reboot = dict(default=False, type="bool"),
|
|
|
|
|
no_reboot = dict(default=False, type='bool'),
|
|
|
|
|
state = dict(default='present'),
|
|
|
|
|
device_mapping = dict(type='list'),
|
|
|
|
|
tags = dict(type='dict'),
|
|
|
|
@ -396,5 +559,5 @@ def main():
|
|
|
|
|
from ansible.module_utils.basic import *
|
|
|
|
|
from ansible.module_utils.ec2 import *
|
|
|
|
|
|
|
|
|
|
main()
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|
|
|
|
|