From 869f95c0a62e543589b79da2204de08916a3778d Mon Sep 17 00:00:00 2001 From: Gareth Rushgrove Date: Sat, 1 Mar 2014 16:06:19 +0000 Subject: [PATCH 1/3] Added modules to manage ec2 autoscaling groups Includes management of Launch Configuration and related Autoscaling Groups --- cloud/ec2_asg | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/ec2_lc | 159 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 349 insertions(+) create mode 100644 cloud/ec2_asg create mode 100644 cloud/ec2_lc diff --git a/cloud/ec2_asg b/cloud/ec2_asg new file mode 100644 index 00000000000..0a6fe651baf --- /dev/null +++ b/cloud/ec2_asg @@ -0,0 +1,190 @@ +#!/usr/bin/python +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +DOCUMENTATION = """ +--- +module: ec2_asg +short_description: Create or delete AWS Autoscaling Groups +description: + - Can create or delete AWS Autoscaling Groups + - Works with the ec2_lc module to manage Launch Configurations +version_added: "1.0" +requirements: [ "boto" ] +author: Gareth Rushgrove +options: + state: + description: + - register or deregister the instance + required: true + choices: ['present', 'absent'] + group: + description: + - Unique name for group to be created or deleted + required: true + load_balancers: + description: + - List of ELB names to use for the group + required: true + availability_zones: + description: + - List of availability zone names in which to create the group. + required: true + launch_config_name: + description: + - Name of the Launch configuration to use for the group. See the ec2_lc module for managing these. + required: true + min_size: + description: + - Minimum number of instances in group + required: true + max_size: + description: + - Maximum number of instances in group + required: true + aws_secret_key: + description: + - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. + required: false + default: None + aliases: ['ec2_secret_key', 'secret_key' ] + aws_access_key: + description: + - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. + required: false + default: None + aliases: ['ec2_access_key', 'access_key' ] + region: + description: + - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. + required: false + aliases: ['aws_region', 'ec2_region'] +""" + +EXAMPLES = ''' +- ec2_asg: > + group_name: special + load_balancers: 'lb1,lb2' + availability_zones: 'eu-west-1a,eu-west-1b' + launch_config_name: 'lc-1' + min_size: 1 + max_size: 10 +''' + +import sys +import time + +from ansible.module_utils.basic import * +from ansible.module_utils.ec2 import * + +try: + import boto.ec2.autoscale + from boto.ec2.autoscale import AutoScaleConnection, AutoScalingGroup + from boto.exception import BotoServerError +except ImportError: + print "failed=True msg='boto required for this module'" + sys.exit(1) + +AWS_REGIONS = ['ap-northeast-1', + 'ap-southeast-1', + 'ap-southeast-2', + 'eu-west-1', + 'sa-east-1', + 'us-east-1', + 'us-west-1', + 'us-west-2'] + + +def create_autoscaling_group(connection, module): + group_name = module.params.get('name') + load_balancers = module.params['load_balancers'] + availability_zones = module.params['availability_zones'] + launch_config_name = module.params.get('launch_config_name') + min_size = module.params.get('min_size') + max_size = module.params.get('max_size') + + launch_configs = connection.get_all_launch_configurations(name=[launch_config_name]) + + ag = AutoScalingGroup( + group_name=group_name, + load_balancers=load_balancers, + availability_zones=availability_zones, + launch_config=launch_configs[0], + min_size=min_size, + max_size=max_size, + connection=connection) + + try: + connection.create_auto_scaling_group(ag) + module.exit_json(changed=True) + except BotoServerError, e: + module.exit_json(changed=False, msg=str(e)) + + +def delete_autoscaling_group(connection, module): + group_name = module.params.get('name') + groups = connection.get_all_groups(names=[group_name]) + if groups: + group = groups[0] + group.shutdown_instances() + + instances = True + while instances: + connection.get_all_groups() + for group in groups: + if group.name == group_name: + if not group.instances: + instances = False + time.sleep(10) + + group.delete() + module.exit_json(changed=True) + else: + module.exit_json(changed=False) + + +def main(): + module = AnsibleModule( + argument_spec = dict( + name = dict(required=True, type='str'), + load_balancers = dict(required=True, type='list'), + availability_zones = dict(required=True, type='list'), + launch_config_name = dict(required=True, type='str'), + min_size = dict(required=True, type='int'), + max_size = dict(required=True, type='int'), + state = dict(default='present', choices=['present', 'absent']), + region = dict(aliases=['aws_region', 'ec2_region'], choices=AWS_REGIONS), + ec2_url = dict(), + ec2_secret_key = dict(aliases=['aws_secret_key', 'secret_key'], no_log=True), + ec2_access_key = dict(aliases=['aws_access_key', 'access_key']), + ) + ) + + ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module) + + state = module.params.get('state') + + try: + connection = boto.ec2.autoscale.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key) + except boto.exception.NoAuthHandlerFound, e: + module.fail_json(msg = str(e)) + + if state == 'present': + create_autoscaling_group(connection, module) + elif state == 'absent': + delete_autoscaling_group(connection, module) + + +main() diff --git a/cloud/ec2_lc b/cloud/ec2_lc new file mode 100644 index 00000000000..a84449d7d91 --- /dev/null +++ b/cloud/ec2_lc @@ -0,0 +1,159 @@ +#!/usr/bin/python +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +DOCUMENTATION = """ +--- +module: ec2_lc +short_description: Create or delete AWS Autoscaling Launch Configurations +description: + - Can create or delete AwS Autoscaling Configurations + - Works with the ec2_asg module to manage Autoscaling Groups +version_added: "1.6" +requirements: [ "boto" ] +author: Gareth Rushgrove +options: + state: + description: + - register or deregister the instance + required: true + choices: ['present', 'absent'] + name: + description: + - Unique name for configuration + required: true + image_id: + description: + - The AMI unique identifier to be used for the group + required: true + key_name: + description: + - The SSH key name to be used for access to managed instances + required: true + security_groups: + description: + - A list of security groups into which instances should be found + required: true + aws_secret_key: + description: + - AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. + required: false + default: None + aliases: ['ec2_secret_key', 'secret_key' ] + aws_access_key: + description: + - AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. + required: false + default: None + aliases: ['ec2_access_key', 'access_key' ] + region: + description: + - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. + required: false + aliases: ['aws_region', 'ec2_region'] +""" + +EXAMPLES = ''' +- ec2_lc: > + name: special + image_id: ami-XXX + key_name: default + security_groups: 'group,group2' + +''' + +import sys +import time + +from ansible.module_utils.basic import * +from ansible.module_utils.ec2 import * + +try: + import boto.ec2.autoscale + from boto.ec2.autoscale import LaunchConfiguration + from boto.exception import BotoServerError +except ImportError: + print "failed=True msg='boto required for this module'" + sys.exit(1) + +AWS_REGIONS = ['ap-northeast-1', + 'ap-southeast-1', + 'ap-southeast-2', + 'eu-west-1', + 'sa-east-1', + 'us-east-1', + 'us-west-1', + 'us-west-2'] + + +def create_launch_config(connection, module): + name = module.params.get('name') + image_id = module.params.get('image_id') + key_name = module.params.get('key_name') + security_groups = module.params['security_groups'] + + lc = LaunchConfiguration( + name=name, + image_id=image_id, + key_name=key_name, + security_groups=security_groups) + + try: + connection.create_launch_configuration(lc) + module.exit_json(changed=True) + except BotoServerError, e: + module.exit_json(changed=False, msg=str(e)) + + +def delete_launch_config(connection, module): + name = module.params.get('name') + launch_configs = connection.get_all_launch_configurations(name=[name]) + if launch_configs: + launch_configs[0].delete() + module.exit_json(changed=True) + else: + module.exit_json(changed=False) + + +def main(): + module = AnsibleModule( + argument_spec = dict( + name = dict(required=True, type='str'), + image_id = dict(required=True, type='str'), + key_name = dict(required=True, type='str'), + security_groups = dict(required=True, type='list'), + state = dict(default='present', choices=['present', 'absent']), + region = dict(aliases=['aws_region', 'ec2_region'], choices=AWS_REGIONS), + ec2_url = dict(), + ec2_secret_key = dict(aliases=['aws_secret_key', 'secret_key'], no_log=True), + ec2_access_key = dict(aliases=['aws_access_key', 'access_key']), + ) + ) + + ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module) + + try: + connection = boto.ec2.autoscale.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key) + except boto.exception.NoAuthHandlerFound, e: + module.fail_json(msg = str(e)) + + state = module.params.get('state') + + if state == 'present': + create_launch_config(connection, module) + elif state == 'absent': + delete_launch_config(connection, module) + +main() From 0fd56284829741961805ffd73494b6ccae1dc805 Mon Sep 17 00:00:00 2001 From: Gareth Rushgrove Date: Sun, 2 Mar 2014 11:58:22 +0000 Subject: [PATCH 2/3] correct version added --- cloud/ec2_asg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloud/ec2_asg b/cloud/ec2_asg index 0a6fe651baf..6aee6f5e152 100644 --- a/cloud/ec2_asg +++ b/cloud/ec2_asg @@ -21,7 +21,7 @@ short_description: Create or delete AWS Autoscaling Groups description: - Can create or delete AWS Autoscaling Groups - Works with the ec2_lc module to manage Launch Configurations -version_added: "1.0" +version_added: "1.6" requirements: [ "boto" ] author: Gareth Rushgrove options: From 89148e15ed1073c703d3ed9ff28969bfa88557cb Mon Sep 17 00:00:00 2001 From: Gareth Rushgrove Date: Sun, 2 Mar 2014 12:00:50 +0000 Subject: [PATCH 3/3] correct name in documentation and example --- cloud/ec2_asg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloud/ec2_asg b/cloud/ec2_asg index 6aee6f5e152..a411bcd4279 100644 --- a/cloud/ec2_asg +++ b/cloud/ec2_asg @@ -30,7 +30,7 @@ options: - register or deregister the instance required: true choices: ['present', 'absent'] - group: + name: description: - Unique name for group to be created or deleted required: true @@ -75,7 +75,7 @@ options: EXAMPLES = ''' - ec2_asg: > - group_name: special + name: special load_balancers: 'lb1,lb2' availability_zones: 'eu-west-1a,eu-west-1b' launch_config_name: 'lc-1'