@ -37,7 +37,9 @@ options:
id :
version_added : " 1.1 "
description :
- identifier for this instance or set of instances , so that the module will be idempotent with respect to EC2 instances . This identifier is valid for at least 24 hours after the termination of the instance , and should not be reused for another call later on . For details , see the description of client token at U ( http : / / docs . aws . amazon . com / AWSEC2 / latest / UserGuide / Run_Instance_Idempotency . html ) .
- identifier for this instance or set of instances , so that the module will be idempotent with respect to EC2 instances .
This identifier is valid for at least 24 hours after the termination of the instance , and should not be reused for another call later on .
For details , see the description of client token at U ( http : / / docs . aws . amazon . com / AWSEC2 / latest / UserGuide / Run_Instance_Idempotency . html ) .
required : false
default : null
aliases : [ ]
@ -57,7 +59,9 @@ options:
region :
version_added : " 1.2 "
description :
- The AWS region to use . Must be specified if ec2_url is not used . If not specified then the value of the EC2_REGION environment variable , if any , is used . See U ( http : / / docs . aws . amazon . com / general / latest / gr / rande . html #ec2_region)
- The AWS region to use . Must be specified if ec2_url is not used .
If not specified then the value of the EC2_REGION environment variable , if any , is used .
See U ( http : / / docs . aws . amazon . com / general / latest / gr / rande . html #ec2_region)
required : false
default : null
aliases : [ ' aws_region ' , ' ec2_region ' ]
@ -77,7 +81,8 @@ options:
tenancy :
version_added : " 1.9 "
description :
- An instance with a tenancy of " dedicated " runs on single - tenant hardware and can only be launched into a VPC . Note that to use dedicated tenancy you MUST specify a vpc_subnet_id as well . Dedicated tenancy is not available for EC2 " micro " instances .
- An instance with a tenancy of " dedicated " runs on single - tenant hardware and can only be launched into a VPC .
Note that to use dedicated tenancy you MUST specify a vpc_subnet_id as well . Dedicated tenancy is not available for EC2 " micro " instances .
required : false
default : default
choices : [ " default " , " dedicated " ]
@ -85,7 +90,8 @@ options:
spot_price :
version_added : " 1.5 "
description :
- Maximum spot price to bid , If not set a regular on - demand instance is requested . A spot request is made with this maximum bid . When it is filled , the instance is started .
- Maximum spot price to bid , If not set a regular on - demand instance is requested . A spot request is made with this maximum bid .
When it is filled , the instance is started .
required : false
default : null
aliases : [ ]
@ -236,7 +242,10 @@ options:
volumes :
version_added : " 1.5 "
description :
- a list of hash / dictionaries of volumes to add to the new instance ; ' [ { " key " : " value " , " key " : " value " }] ' ; keys allowed are - device_name ( str ; required ) , delete_on_termination ( bool ; False ) , device_type ( deprecated ) , ephemeral ( str ) , encrypted ( bool ; False ) , snapshot ( str ) , volume_type ( str ) , iops ( int ) - device_type is deprecated use volume_type , iops must be set when volume_type = ' io1 ' , ephemeral and snapshot are mutually exclusive .
- a list of hash / dictionaries of volumes to add to the new instance ; ' [ { " key " : " value " , " key " : " value " }] ' ; keys allowed
are - device_name ( str ; required ) , delete_on_termination ( bool ; False ) , device_type ( deprecated ) , ephemeral ( str ) ,
encrypted ( bool ; False ) , snapshot ( str ) , volume_type ( str ) , iops ( int ) - device_type is deprecated use volume_type ,
iops must be set when volume_type = ' io1 ' , ephemeral and snapshot are mutually exclusive .
required : false
default : null
aliases : [ ]
@ -249,21 +258,26 @@ options:
exact_count :
version_added : " 1.5 "
description :
- An integer value which indicates how many instances that match the ' count_tag ' parameter should be running . Instances are either created or terminated based on this value .
- An integer value which indicates how many instances that match the ' count_tag ' parameter should be running .
Instances are either created or terminated based on this value .
required : false
default : null
aliases : [ ]
count_tag :
version_added : " 1.5 "
description :
- Used with ' exact_count ' to determine how many nodes based on a specific tag criteria should be running . This can be expressed in multiple ways and is shown in the EXAMPLES section . For instance , one can request 25 servers that are tagged with " class=webserver " . The specified tag must already exist or be passed in as the ' instance_tags ' option .
- Used with ' exact_count ' to determine how many nodes based on a specific tag criteria should be running .
This can be expressed in multiple ways and is shown in the EXAMPLES section . For instance , one can request 25 servers
that are tagged with " class=webserver " . The specified tag must already exist or be passed in as the ' instance_tags ' option .
required : false
default : null
aliases : [ ]
network_interfaces :
version_added : " 2.0 "
description :
- A list of existing network interfaces to attach to the instance at launch . When specifying existing network interfaces , none of the assign_public_ip , private_ip , vpc_subnet_id , group , or group_id parameters may be used . ( Those parameters are for creating a new network interface at launch . )
- A list of existing network interfaces to attach to the instance at launch . When specifying existing network interfaces ,
none of the assign_public_ip , private_ip , vpc_subnet_id , group , or group_id parameters may be used . ( Those parameters are
for creating a new network interface at launch . )
required : false
default : null
aliases : [ ' network_interface ' ]
@ -601,9 +615,9 @@ EXAMPLES = '''
import time
from ast import literal_eval
from ansible . module_utils . six import iteritems
from ansible . module_utils . six import get_function_code
from ansible . module_utils . basic import AnsibleModule
from ansible . module_utils . ec2 import get_aws_connection_info , ec2_argument_spec , ec2_connect , connect_to_aws
from distutils . version import LooseVersion
try :
@ -662,14 +676,14 @@ def get_reservations(module, ec2, tags=None, state=None, zone=None):
for x in tags :
if isinstance ( x , dict ) :
x = _set_none_to_blank ( x )
filters . update ( dict ( ( " tag: " + tn , tv ) for ( tn , tv ) in iteritems ( x ) ) )
filters . update ( dict ( ( " tag: " + tn , tv ) for ( tn , tv ) in x . items ( ) ) )
else :
filters . update ( { " tag-key " : x } )
# if dict, add the key and value to the filter
if isinstance ( tags , dict ) :
tags = _set_none_to_blank ( tags )
filters . update ( dict ( ( " tag: " + tn , tv ) for ( tn , tv ) in iteritems ( tags ) ) )
filters . update ( dict ( ( " tag: " + tn , tv ) for ( tn , tv ) in tags . items ( ) ) )
if state :
# http://stackoverflow.com/questions/437511/what-are-the-valid-instancestates-for-the-amazon-ec2-api
@ -682,6 +696,7 @@ def get_reservations(module, ec2, tags=None, state=None, zone=None):
return results
def get_instance_info ( inst ) :
"""
Retrieves instance information from an instance
@ -741,6 +756,7 @@ def get_instance_info(inst):
return instance_info
def boto_supports_associate_public_ip_address ( ec2 ) :
"""
Check if Boto library has associate_public_ip_address in the NetworkInterfaceSpecification
@ -759,6 +775,7 @@ def boto_supports_associate_public_ip_address(ec2):
except AttributeError :
return False
def boto_supports_profile_name_arg ( ec2 ) :
"""
Check if Boto library has instance_profile_name argument . instance_profile_name has been added in Boto 2.5 .0
@ -771,6 +788,7 @@ def boto_supports_profile_name_arg(ec2):
run_instances_method = getattr ( ec2 , ' run_instances ' )
return ' instance_profile_name ' in get_function_code ( run_instances_method ) . co_varnames
def boto_supports_volume_encryption ( ) :
"""
Check if Boto library supports encryption of EBS volumes ( added in 2.29 .0 )
@ -780,6 +798,7 @@ def boto_supports_volume_encryption():
"""
return hasattr ( boto , ' Version ' ) and LooseVersion ( boto . Version ) > = LooseVersion ( ' 2.29.0 ' )
def create_block_device ( module , ec2 , volume ) :
# Not aware of a way to determine this programatically
# http://aws.amazon.com/about-aws/whats-new/2013/10/09/ebs-provisioned-iops-maximum-iops-gb-ratio-increased-to-30-1/
@ -826,6 +845,7 @@ def create_block_device(module, ec2, volume):
delete_on_termination = volume . get ( ' delete_on_termination ' , False ) ,
iops = volume . get ( ' iops ' ) )
def boto_supports_param_in_spot_request ( ec2 , param ) :
"""
Check if Boto library has a < param > in its request_spot_instances ( ) method . For example , the placement_group parameter wasn ' t added until 2.3.0.
@ -838,6 +858,7 @@ def boto_supports_param_in_spot_request(ec2, param):
method = getattr ( ec2 , ' request_spot_instances ' )
return param in get_function_code ( method ) . co_varnames
def await_spot_requests ( module , ec2 , spot_requests , count ) :
"""
Wait for a group of spot requests to be fulfilled , or fail .
@ -1000,10 +1021,6 @@ def create_instances(module, ec2, vpc, override_count=None):
spot_launch_group = module . params . get ( ' spot_launch_group ' )
instance_initiated_shutdown_behavior = module . params . get ( ' instance_initiated_shutdown_behavior ' )
# group_id and group_name are exclusive of each other
if group_id and group_name :
module . fail_json ( msg = str ( " Use only one type of parameter (group_name) or (group_id) " ) )
vpc_id = None
if vpc_subnet_id :
if not vpc :
@ -1135,20 +1152,24 @@ def create_instances(module, ec2, vpc, override_count=None):
# check to see if we're using spot pricing first before starting instances
if not spot_price :
if assign_public_ip and private_ip :
params . update ( dict (
params . update (
dict (
min_count = count_remaining ,
max_count = count_remaining ,
client_token = id ,
placement_group = placement_group ,
) )
)
)
else :
params . update ( dict (
params . update (
dict (
min_count = count_remaining ,
max_count = count_remaining ,
client_token = id ,
placement_group = placement_group ,
private_ip_address = private_ip ,
) )
)
)
# For ordinary (not spot) instances, we can select 'stop'
# (the default) or 'terminate' here.
@ -1315,8 +1336,7 @@ def terminate_instances(module, ec2, instance_ids):
num_terminated = 0
wait_timeout = time . time ( ) + wait_timeout
while wait_timeout > time . time ( ) and num_terminated < len ( terminated_instance_ids ) :
response = ec2 . get_all_instances ( \
instance_ids = terminated_instance_ids , \
response = ec2 . get_all_instances ( instance_ids = terminated_instance_ids ,
filters = { ' instance-state-name ' : ' terminated ' } )
try :
num_terminated = sum ( [ len ( res . instances ) for res in response ] )
@ -1334,12 +1354,10 @@ def terminate_instances(module, ec2, instance_ids):
module . fail_json ( msg = " wait for instance termination timeout on %s " % time . asctime ( ) )
# Lets get the current state of the instances after terminating - issue600
instance_dict_array = [ ]
for res in ec2 . get_all_instances ( instance_ids = terminated_instance_ids , \
filters = { ' instance-state-name ' : ' terminated ' } ) :
for res in ec2 . get_all_instances ( instance_ids = terminated_instance_ids , filters = { ' instance-state-name ' : ' terminated ' } ) :
for inst in res . instances :
instance_dict_array . append ( get_instance_info ( inst ) )
return ( changed , instance_dict_array , terminated_instance_ids )
@ -1411,8 +1429,7 @@ def startstop_instances(module, ec2, instance_ids, state, instance_tags):
exception = traceback . format_exc ( ) )
# Check "termination_protection" attribute
if ( inst . get_attribute ( ' disableApiTermination ' ) [ ' disableApiTermination ' ] != termination_protection
and termination_protection is not None ) :
if ( inst . get_attribute ( ' disableApiTermination ' ) [ ' disableApiTermination ' ] != termination_protection and termination_protection is not None ) :
inst . modify_attribute ( ' disableApiTermination ' , termination_protection )
changed = True
@ -1430,7 +1447,7 @@ def startstop_instances(module, ec2, instance_ids, state, instance_tags):
existing_instances_array . append ( inst . id )
instance_ids = list ( set ( existing_instances_array + ( instance_ids or [ ] ) ) )
# # Wait for all the instances to finish starting or stopping
# Wait for all the instances to finish starting or stopping
wait_timeout = time . time ( ) + wait_timeout
while wait and wait_timeout > time . time ( ) :
instance_dict_array = [ ]
@ -1451,6 +1468,7 @@ def startstop_instances(module, ec2, instance_ids, state, instance_tags):
return ( changed , instance_dict_array , instance_ids )
def restart_instances ( module , ec2 , instance_ids , state , instance_tags ) :
"""
Restarts a list of existing instances
@ -1518,8 +1536,7 @@ def restart_instances(module, ec2, instance_ids, state, instance_tags):
exception = traceback . format_exc ( ) )
# Check "termination_protection" attribute
if ( inst . get_attribute ( ' disableApiTermination ' ) [ ' disableApiTermination ' ] != termination_protection
and termination_protection is not None ) :
if ( inst . get_attribute ( ' disableApiTermination ' ) [ ' disableApiTermination ' ] != termination_protection and termination_protection is not None ) :
inst . modify_attribute ( ' disableApiTermination ' , termination_protection )
changed = True
@ -1537,7 +1554,8 @@ def restart_instances(module, ec2, instance_ids, state, instance_tags):
def main ( ) :
argument_spec = ec2_argument_spec ( )
argument_spec . update ( dict (
argument_spec . update (
dict (
key_name = dict ( aliases = [ ' keypair ' ] ) ,
id = dict ( ) ,
group = dict ( type = ' list ' , aliases = [ ' groups ' ] ) ,
@ -1579,6 +1597,7 @@ def main():
module = AnsibleModule (
argument_spec = argument_spec ,
mutually_exclusive = [
[ ' group_name ' , ' group_id ' ] ,
[ ' exact_count ' , ' count ' ] ,
[ ' exact_count ' , ' state ' ] ,
[ ' exact_count ' , ' instance_ids ' ] ,
@ -1644,9 +1663,6 @@ def main():
module . exit_json ( changed = changed , instance_ids = new_instance_ids , instances = instance_dict_array , tagged_instances = tagged_instances )
# import module snippets
from ansible . module_utils . basic import *
from ansible . module_utils . ec2 import *
if __name__ == ' __main__ ' :
main ( )