@ -243,6 +243,136 @@ EXAMPLES = '''
region : us - east - 1
region : us - east - 1
'''
'''
RETURN = '''
- - -
default_cooldown :
description : The default cooldown time in seconds .
returned : success
type : int
sample : 300
desired_capacity :
description : The number of EC2 instances that should be running in this group .
returned : success
type : int
sample : 3
healthcheck_period :
description : Length of time in seconds after a new EC2 instance comes into service that Auto Scaling starts checking its health .
returned : success
type : int
sample : 30
healthcheck_type :
description : The service you want the health status from , one of " EC2 " or " ELB " .
returned : success
type : str
sample : " ELB "
healthy_instances :
description : Number of instances in a healthy state
returned : success
type : int
sample : 5
in_service_instances :
description : Number of instances in service
returned : success
type : int
sample : 3
instance_facts :
description : Dictionary of EC2 instances and their status as it relates to the ASG .
returned : success
type : dict
sample : {
" i-0123456789012 " : {
" health_status " : " Healthy " ,
" launch_config_name " : " public-webapp-production-1 " ,
" lifecycle_state " : " InService "
}
}
instances :
description : list of instance IDs in the ASG
returned : success
type : list
sample : [
" i-0123456789012 "
]
launch_config_name :
description : >
Name of launch configuration associated with the ASG . Same as launch_configuration_name ,
provided for compatibility with ec2_asg module .
returned : success
type : str
sample : " public-webapp-production-1 "
load_balancers :
description : List of load balancers names attached to the ASG .
returned : success
type : list
sample : [ " elb-webapp-prod " ]
max_size :
description : Maximum size of group
returned : success
type : int
sample : 3
min_size :
description : Minimum size of group
returned : success
type : int
sample : 1
pending_instances :
description : Number of instances in pending state
returned : success
type : int
sample : 1
tags :
description : List of tags for the ASG , and whether or not each tag propagates to instances at launch .
returned : success
type : list
sample : [
{
" key " : " Name " ,
" value " : " public-webapp-production-1 " ,
" resource_id " : " public-webapp-production-1 " ,
" resource_type " : " auto-scaling-group " ,
" propagate_at_launch " : " true "
} ,
{
" key " : " env " ,
" value " : " production " ,
" resource_id " : " public-webapp-production-1 " ,
" resource_type " : " auto-scaling-group " ,
" propagate_at_launch " : " true "
}
]
target_group_arns :
description : List of ARNs of the target groups that the ASG populates
returned : success
type : list
sample : [
" arn:aws:elasticloadbalancing:ap-southeast-2:123456789012:targetgroup/target-group-host-hello/1a2b3c4d5e6f1a2b " ,
" arn:aws:elasticloadbalancing:ap-southeast-2:123456789012:targetgroup/target-group-path-world/abcd1234abcd1234 "
]
target_group_names :
description : List of names of the target groups that the ASG populates
returned : success
type : list
sample : [
" target-group-host-hello " ,
" target-group-path-world "
]
termination_policies :
description : A list of termination policies for the group .
returned : success
type : str
sample : [ " Default " ]
unhealthy_instances :
description : Number of instances in an unhealthy state
returned : success
type : int
sample : 0
viable_instances :
description : Number of instances in a viable state
returned : success
type : int
sample : 1
'''
import time
import time
import logging as log
import logging as log
import traceback
import traceback
@ -277,7 +407,7 @@ def enforce_required_arguments(module):
module . fail_json ( msg = " Missing required arguments for autoscaling group create/update: %s " % " , " . join ( missing_args ) )
module . fail_json ( msg = " Missing required arguments for autoscaling group create/update: %s " % " , " . join ( missing_args ) )
def get_properties ( autoscaling_group ):
def get_properties ( autoscaling_group , module ):
properties = dict ( )
properties = dict ( )
properties [ ' healthy_instances ' ] = 0
properties [ ' healthy_instances ' ] = 0
properties [ ' in_service_instances ' ] = 0
properties [ ' in_service_instances ' ] = 0
@ -320,6 +450,21 @@ def get_properties(autoscaling_group):
properties [ ' healthcheck_type ' ] = autoscaling_group . get ( ' HealthCheckType ' )
properties [ ' healthcheck_type ' ] = autoscaling_group . get ( ' HealthCheckType ' )
properties [ ' default_cooldown ' ] = autoscaling_group . get ( ' DefaultCooldown ' )
properties [ ' default_cooldown ' ] = autoscaling_group . get ( ' DefaultCooldown ' )
properties [ ' termination_policies ' ] = autoscaling_group . get ( ' TerminationPolicies ' )
properties [ ' termination_policies ' ] = autoscaling_group . get ( ' TerminationPolicies ' )
properties [ ' target_group_arns ' ] = autoscaling_group . get ( ' TargetGroupARNs ' )
if properties [ ' target_group_arns ' ] :
region , ec2_url , aws_connect_params = get_aws_connection_info ( module , boto3 = True )
elbv2_connection = boto3_conn ( module ,
conn_type = ' client ' ,
resource = ' elbv2 ' ,
region = region ,
endpoint = ec2_url ,
* * aws_connect_params )
tg_paginator = elbv2_connection . get_paginator ( ' describe_target_groups ' )
tg_result = tg_paginator . paginate ( TargetGroupArns = properties [ ' target_group_arns ' ] ) . build_full_result ( )
target_groups = tg_result [ ' TargetGroups ' ]
else :
target_groups = [ ]
properties [ ' target_group_names ' ] = [ tg [ ' TargetGroupName ' ] for tg in target_groups ]
return properties
return properties
@ -363,7 +508,7 @@ def elb_dreg(asg_connection, module, group_name, instance_id):
def elb_healthy ( asg_connection , elb_connection , module , group_name ) :
def elb_healthy ( asg_connection , elb_connection , module , group_name ) :
healthy_instances = set ( )
healthy_instances = set ( )
as_group = asg_connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = asg_connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
# get healthy, inservice instances from ASG
# get healthy, inservice instances from ASG
instances = [ ]
instances = [ ]
for instance , settings in props [ ' instance_facts ' ] . items ( ) :
for instance , settings in props [ ' instance_facts ' ] . items ( ) :
@ -397,7 +542,7 @@ def elb_healthy(asg_connection, elb_connection, module, group_name):
def tg_healthy ( asg_connection , elbv2_connection , module , group_name ) :
def tg_healthy ( asg_connection , elbv2_connection , module , group_name ) :
healthy_instances = set ( )
healthy_instances = set ( )
as_group = asg_connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = asg_connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
# get healthy, inservice instances from ASG
# get healthy, inservice instances from ASG
instances = [ ]
instances = [ ]
for instance , settings in props [ ' instance_facts ' ] . items ( ) :
for instance , settings in props [ ' instance_facts ' ] . items ( ) :
@ -605,7 +750,7 @@ def create_autoscaling_group(connection, module):
NotificationTypes = notification_types
NotificationTypes = notification_types
)
)
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
asg_properties = get_properties ( as_group )
asg_properties = get_properties ( as_group , module )
changed = True
changed = True
return changed , asg_properties
return changed , asg_properties
except ( botocore . exceptions . BotoCoreError , botocore . exceptions . ClientError ) as e :
except ( botocore . exceptions . BotoCoreError , botocore . exceptions . ClientError ) as e :
@ -613,7 +758,7 @@ def create_autoscaling_group(connection, module):
exception = traceback . format_exc ( ) , * * camel_dict_to_snake_dict ( e . response ) )
exception = traceback . format_exc ( ) , * * camel_dict_to_snake_dict ( e . response ) )
else :
else :
as_group = as_groups [ ' AutoScalingGroups ' ] [ 0 ]
as_group = as_groups [ ' AutoScalingGroups ' ] [ 0 ]
initial_asg_properties = get_properties ( as_group )
initial_asg_properties = get_properties ( as_group , module )
changed = False
changed = False
if suspend_processes ( connection , as_group , module ) :
if suspend_processes ( connection , as_group , module ) :
@ -768,7 +913,7 @@ def create_autoscaling_group(connection, module):
try :
try :
as_group = connection . describe_auto_scaling_groups (
as_group = connection . describe_auto_scaling_groups (
AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
asg_properties = get_properties ( as_group )
asg_properties = get_properties ( as_group , module )
if asg_properties != initial_asg_properties :
if asg_properties != initial_asg_properties :
changed = True
changed = True
except ( botocore . exceptions . BotoCoreError , botocore . exceptions . ClientError ) as e :
except ( botocore . exceptions . BotoCoreError , botocore . exceptions . ClientError ) as e :
@ -851,7 +996,7 @@ def replace(connection, module):
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
wait_for_new_inst ( module , connection , group_name , wait_timeout , as_group [ ' MinSize ' ] , ' viable_instances ' )
wait_for_new_inst ( module , connection , group_name , wait_timeout , as_group [ ' MinSize ' ] , ' viable_instances ' )
props = get_properties ( as_group )
props = get_properties ( as_group , module )
instances = props [ ' instances ' ]
instances = props [ ' instances ' ]
if replace_instances :
if replace_instances :
instances = replace_instances
instances = replace_instances
@ -865,7 +1010,7 @@ def replace(connection, module):
log . debug ( " No new instances needed, but old instances are present. Removing old instances " )
log . debug ( " No new instances needed, but old instances are present. Removing old instances " )
terminate_batch ( connection , module , old_instances , instances , True )
terminate_batch ( connection , module , old_instances , instances , True )
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
changed = True
changed = True
return ( changed , props )
return ( changed , props )
@ -894,7 +1039,7 @@ def replace(connection, module):
wait_for_elb ( connection , module , group_name )
wait_for_elb ( connection , module , group_name )
wait_for_target_group ( connection , module , group_name )
wait_for_target_group ( connection , module , group_name )
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
instances = props [ ' instances ' ]
instances = props [ ' instances ' ]
if replace_instances :
if replace_instances :
instances = replace_instances
instances = replace_instances
@ -912,7 +1057,7 @@ def replace(connection, module):
break
break
update_size ( connection , as_group , max_size , min_size , desired_capacity )
update_size ( connection , as_group , max_size , min_size , desired_capacity )
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
asg_properties = get_properties ( as_group )
asg_properties = get_properties ( as_group , module )
log . debug ( " Rolling update complete. " )
log . debug ( " Rolling update complete. " )
changed = True
changed = True
return ( changed , asg_properties )
return ( changed , asg_properties )
@ -965,13 +1110,12 @@ def terminate_batch(connection, module, replace_instances, initial_instances, le
min_size = module . params . get ( ' min_size ' )
min_size = module . params . get ( ' min_size ' )
desired_capacity = module . params . get ( ' desired_capacity ' )
desired_capacity = module . params . get ( ' desired_capacity ' )
group_name = module . params . get ( ' name ' )
group_name = module . params . get ( ' name ' )
wait_timeout = int ( module . params . get ( ' wait_timeout ' ) )
lc_check = module . params . get ( ' lc_check ' )
lc_check = module . params . get ( ' lc_check ' )
decrement_capacity = False
decrement_capacity = False
break_loop = False
break_loop = False
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
desired_size = as_group [ ' MinSize ' ]
desired_size = as_group [ ' MinSize ' ]
new_instances , old_instances = get_instances_by_lc ( props , lc_check , initial_instances )
new_instances , old_instances = get_instances_by_lc ( props , lc_check , initial_instances )
@ -1022,20 +1166,17 @@ def terminate_batch(connection, module, replace_instances, initial_instances, le
def wait_for_term_inst ( connection , module , term_instances ) :
def wait_for_term_inst ( connection , module , term_instances ) :
batch_size = module . params . get ( ' replace_batch_size ' )
wait_timeout = module . params . get ( ' wait_timeout ' )
wait_timeout = module . params . get ( ' wait_timeout ' )
group_name = module . params . get ( ' name ' )
group_name = module . params . get ( ' name ' )
lc_check = module . params . get ( ' lc_check ' )
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
count = 1
count = 1
wait_timeout = time . time ( ) + wait_timeout
wait_timeout = time . time ( ) + wait_timeout
while wait_timeout > time . time ( ) and count > 0 :
while wait_timeout > time . time ( ) and count > 0 :
log . debug ( " waiting for instances to terminate " )
log . debug ( " waiting for instances to terminate " )
count = 0
count = 0
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
instance_facts = props [ ' instance_facts ' ]
instance_facts = props [ ' instance_facts ' ]
instances = ( i for i in instance_facts if i in term_instances )
instances = ( i for i in instance_facts if i in term_instances )
for i in instances :
for i in instances :
@ -1055,7 +1196,7 @@ def wait_for_new_inst(module, connection, group_name, wait_timeout, desired_size
# make sure we have the latest stats after that last loop.
# make sure we have the latest stats after that last loop.
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
log . debug ( " Waiting for {0} = {1} , currently {2} " . format ( prop , desired_size , props [ prop ] ) )
log . debug ( " Waiting for {0} = {1} , currently {2} " . format ( prop , desired_size , props [ prop ] ) )
# now we make sure that we have enough instances in a viable state
# now we make sure that we have enough instances in a viable state
wait_timeout = time . time ( ) + wait_timeout
wait_timeout = time . time ( ) + wait_timeout
@ -1063,7 +1204,7 @@ def wait_for_new_inst(module, connection, group_name, wait_timeout, desired_size
log . debug ( " Waiting for {0} = {1} , currently {2} " . format ( prop , desired_size , props [ prop ] ) )
log . debug ( " Waiting for {0} = {1} , currently {2} " . format ( prop , desired_size , props [ prop ] ) )
time . sleep ( 10 )
time . sleep ( 10 )
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
as_group = connection . describe_auto_scaling_groups ( AutoScalingGroupNames = [ group_name ] ) [ ' AutoScalingGroups ' ] [ 0 ]
props = get_properties ( as_group )
props = get_properties ( as_group , module )
if wait_timeout < = time . time ( ) :
if wait_timeout < = time . time ( ) :
# waiting took too long
# waiting took too long
module . fail_json ( msg = " Waited too long for new instances to become viable. %s " % time . asctime ( ) )
module . fail_json ( msg = " Waited too long for new instances to become viable. %s " % time . asctime ( ) )