Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added optional region parameter. Fail if you specify an ELB that doesn'... #3728

Merged
merged 1 commit into from
Aug 2, 2013
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 63 additions & 5 deletions library/cloud/ec2_elb
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

"""

Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use the elb regions needing endpoint hostnames goes away too

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:
Expand All @@ -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")
Expand All @@ -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')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs all previously referred to this being a local action, so calls to AWS that can only be made from an instance don't make sense in that context? How will this behave if the controlling node isn't on ec2? will this throw an exception?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, agreed and mentioned the same to Bruce in the other ticket, he'll make
the changes.

We also need to keep endpoint connection open outside of regions for
Eucalyptus cloud support.
On 2 Aug 2013 22:06, "ianoc" notifications@github.com wrote:

In library/cloud/ec2_elb:

@@ -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')
    

The docs all previously referred to this being a local action, so calls to
AWS that can only be made from an instance don't make sense in that
context? How will this behave if the controlling node isn't on ec2? will
this throw an exception?


Reply to this email directly or view it on GitHubhttps://github.com//pull/3728/files#r5562980
.

az = response.read()
for r in AWS_REGIONS:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elb_regions is a function in boto that should be used instead of another variable that will need to be maintained externally to boto?

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()
Expand Down