From 8171b7ba48d701846aabf1982592703beee0aabb Mon Sep 17 00:00:00 2001 From: Bruce Pennypacker Date: Thu, 1 Aug 2013 16:50:01 -0400 Subject: [PATCH] Added optional region parameter. Fail if you specify an ELB that doesn't exist. Boto blindly assumes the us-east-1 region if you don't hardcode a region in it's config, so you could end up attempting to modify ELB's in one region from a totally different region. If a region isn't specified then default to the region that the module is being run within rather than the default us-east-1 region since it's a pretty safe assumption that you intend to work on the ELB's within your current region. Also throw an error if a specified ELB instance doesn't exist. The old behavior would be to silently succeed with changed=false, so if you had so much as a typo in the name of your ELB (or were in the wrong region like my initial testing) you wouldn't get a clear indication that a problem had occurred. --- library/cloud/ec2_elb | 68 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/library/cloud/ec2_elb b/library/cloud/ec2_elb index ca776c4edf9..0c130981f97 100644 --- a/library/cloud/ec2_elb +++ b/library/cloud/ec2_elb @@ -25,7 +25,7 @@ description: if state=absent is passed as an argument. - Will be marked changed when called only if there are ELBs found to operate on. version_added: "1.2" -requirements: [ "boto" ] +requirements: [ "boto", "urllib2" ] author: John Jarvis options: state: @@ -53,6 +53,11 @@ options: - AWS Access API key required: false default: None + ec2_region: + description: + - AWS region of your load balancer. If not set then the region in which + this module is running will be used. + required: false """ @@ -81,23 +86,41 @@ import time import sys import os +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'] + try: import boto + import boto.ec2.elb + from boto.regioninfo import RegionInfo except ImportError: print "failed=True msg='boto required for this module'" sys.exit(1) +try: + import urllib2 +except ImportError: + print "failed=True msg='urllib2 required for this module'" + sys.exit(1) class ElbManager: """Handles EC2 instance ELB registration and de-registration""" def __init__(self, module, instance_id=None, ec2_elbs=None, - ec2_access_key=None, ec2_secret_key=None): + ec2_access_key=None, ec2_secret_key=None, ec2_region=None): self.ec2_access_key = ec2_access_key self.ec2_secret_key = ec2_secret_key self.module = module self.instance_id = instance_id + self.ec2_region = ec2_region self.lbs = self._get_instance_lbs(ec2_elbs) + # if there are no ELBs to operate on # there will be no changes made if len(self.lbs) > 0: @@ -121,6 +144,17 @@ class ElbManager: lb.register_instances([self.instance_id]) self._await_elb_instance_state(lb, 'InService') + def exists(self, lbtest): + """ Verify that the named ELB actually exists """ + + found = False + for lb in self.lbs: + if lb.name == lbtest: + found=True + break + return found + + def _await_elb_instance_state(self, lb, awaited_state): """Wait for an ELB to change state lb: load balancer @@ -140,9 +174,12 @@ class ElbManager: are attached to self.instance_id""" try: - elb = boto.connect_elb(self.ec2_access_key, self.ec2_secret_key) + endpoint="elasticloadbalancing.%s.amazonaws.com" % self.ec2_region + connect_region = RegionInfo(name=self.ec2_region, endpoint=endpoint) + elb = boto.ec2.elb.ELBConnection(self.ec2_access_key, self.ec2_secret_key, region=connect_region) except boto.exception.NoAuthHandlerFound, e: self.module.fail_json(msg=str(e)) + elbs = elb.get_all_load_balancers() if ec2_elbs: @@ -165,13 +202,15 @@ def main(): instance_id={'required': True}, ec2_elbs={'default': None, 'required': False}, ec2_secret_key={'default': None, 'aliases': ['EC2_SECRET_KEY']}, - ec2_access_key={'default': None, 'aliases': ['EC2_ACCESS_KEY']} + ec2_access_key={'default': None, 'aliases': ['EC2_ACCESS_KEY']}, + ec2_region={'default': None, 'required': False, 'choices':AWS_REGIONS} ) ) ec2_secret_key = module.params['ec2_secret_key'] ec2_access_key = module.params['ec2_access_key'] ec2_elbs = module.params['ec2_elbs'] + ec2_region = module.params['ec2_region'] if module.params['state'] == 'present' and 'ec2_elbs' not in module.params: module.fail_json(msg="ELBs are required for registration") @@ -181,9 +220,28 @@ def main(): if not ec2_access_key and 'EC2_ACCESS_KEY' in os.environ: ec2_access_key = os.environ['EC2_ACCESS_KEY'] + if not ec2_region and 'EC2_REGION' in os.environ: + ec2_region = os.environ['EC2_REGION'] + + if not ec2_region: + response = urllib2.urlopen('http://169.254.169.254/latest/meta-data/placement/availability-zone') + az = response.read() + for r in AWS_REGIONS: + if az.startswith(r): + ec2_region = r + break + + if not ec2_region: + module.fail_json(msg = str("ec2_region not specified and unable to determine region from AWS.")) + instance_id = module.params['instance_id'] elb_man = ElbManager(module, instance_id, ec2_elbs, ec2_access_key, - ec2_secret_key) + ec2_secret_key, ec2_region=ec2_region) + + for elb in [ ec2_elbs ]: + if not elb_man.exists(elb): + str="ELB %s does not exist" % elb + module.fail_json(msg=str) if module.params['state'] == 'present': elb_man.register()