Initial commit of boto_elb module and state.

This commit adds execution module and state module support for AWS ELBs. The
state module provides support for ensuring ELBs are absent or present. If present
the state will ensure health checks, listeners, availability zones, attributes,
and other ELB properties. The execution module adds support for all the necessary
actions in the state.
This commit is contained in:
Ryan Lane 2014-04-25 16:02:39 -07:00
parent 2e2a266622
commit 804e67cf8f
2 changed files with 1084 additions and 0 deletions

531
salt/modules/boto_elb.py Normal file
View file

@ -0,0 +1,531 @@
# -*- coding: utf-8 -*-
'''
Connection module for Amazon ELB
.. versionadded:: Helium
:configuration: This module accepts explicit elb credentials but can also utilize
IAM roles assigned to the instance trough Instance Profiles. Dynamic
credentials are then automatically obtained from AWS API and no further
configuration is necessary. More Information available at::
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
If IAM roles are not used you need to specify them either in a pillar or
in the minion's config file::
elb.keyid: GKTADJGHEIQSXMKKRBJ08H
elb.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
A region may also be specified in the configuration::
elb.region: us-east-1
If a region is not specified, the default is us-east-1.
It's also possible to specify key, keyid and region via a profile, either
as a passed in dict, or as a string to pull from pillars or minion config:
myprofile:
keyid: GKTADJGHEIQSXMKKRBJ08H
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
region: us-east-1
:depends: boto
'''
# Import Python libs
import logging
import json
log = logging.getLogger(__name__)
# Import third party libs
try:
import boto
import boto.ec2
import boto.ec2.elb
from boto.ec2.elb import HealthCheck
from boto.ec2.elb.attributes import AccessLogAttribute
from boto.ec2.elb.attributes import CrossZoneLoadBalancingAttribute
logging.getLogger('boto').setLevel(logging.CRITICAL)
HAS_BOTO = True
except ImportError:
HAS_BOTO = False
from salt._compat import string_types
import salt.utils.odict as odict
def __virtual__():
'''
Only load if boto libraries exist.
'''
if not HAS_BOTO:
return False
return True
def exists(name, region=None, key=None, keyid=None, profile=None):
'''
Check to see if an ELB exists.
CLI example::
salt myminion boto_elb.exists myelb region=us-east-1
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
try:
conn.get_all_load_balancers(load_balancer_names=[name])
return True
except boto.exception.BotoServerError as e:
log.debug(e)
return False
def get_elb_config(name, region=None, key=None, keyid=None, profile=None):
'''
Check to see if an ELB exists.
CLI example::
salt myminion boto_elb.exists myelb region=us-east-1
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return []
try:
lb = conn.get_all_load_balancers(load_balancer_names=[name])
lb = lb[0]
ret = {}
ret['availability_zones'] = lb.availability_zones
listeners = []
for _listener in lb.listeners:
# Making this a list makes our life easier and is also the only way
# to include the certificate.
complex_listener = list(_listener.get_complex_tuple())
# boto, you're *killing* me with this. boto doesn't include the
# certificate when calling get_complex_tuple, so you need to also
# get the certificate. So. Much. Hate.
if _listener.ssl_certificate_id:
complex_listener.append(_listener.ssl_certificate_id)
listeners.append(complex_listener)
ret['listeners'] = listeners
ret['subnets'] = lb.subnets
ret['security_groups'] = lb.security_groups
ret['scheme'] = lb.scheme
return ret
except boto.exception.BotoServerError as e:
log.debug(e)
return []
def create(name, availability_zones, listeners=None, subnets=None,
security_groups=None, scheme='internet-facing',
region=None, key=None, keyid=None,
profile=None):
'''
Create an ELB
CLI example to create an ELB::
salt myminion boto_elb.create myelb '["us-east-1a", "us-east-1e"]' listeners='[["HTTPS", "HTTP", 443, 80, "arn:aws:iam::1111111:server-certificate/mycert"]]' region=us-east-1
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if __salt__['boto_elb.exists'](name, region, key, keyid, profile):
return True
if isinstance(availability_zones, string_types):
availability_zones = json.loads(availability_zones)
if isinstance(listeners, string_types):
listeners = json.loads(listeners)
# Combining listeners and complex_listeners together makes our lives
# easier in some ways, especially since during introspection you can
# only get a combined set of listeners back from boto; however, boto
# requires us to send in separate listeners and complex listeners and
# the only real difference is the size. It feels like amazon/boto hate
# developers and wish to make us suffer.
_listeners = []
_complex_listeners = []
for listener in listeners:
if len(listener) <= 3:
_listeners.append(listener)
else:
_complex_listeners.append(listener)
try:
lb = conn.create_load_balancer(name, availability_zones, _listeners,
subnets, security_groups, scheme,
_complex_listeners)
if lb:
log.info('Created ELB {0}'.format(name))
return True
else:
msg = 'Failed to create ELB {0}'.format(name)
log.error(msg)
return False
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to create ELB {0}'.format(name)
log.error(msg)
return False
def delete(name, region=None, key=None, keyid=None, profile=None):
'''
Delete an ELB.
CLI example to delete an ELB::
salt myminion boto_elb.delete myelb region=us-east-1
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if not __salt__['boto_elb.exists'](name, region, key, keyid, profile):
return True
try:
conn.delete_load_balancer(name)
msg = 'Deleted ELB {0}.'.format(name)
log.info(msg)
return True
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to delete ELB {0}'.format(name)
log.error(msg)
return False
def create_listeners(name, listeners=None, region=None, key=None, keyid=None,
profile=None):
'''
Create listeners on an ELB.
CLI example::
salt myminion boto_elb.create_listeners myelb listeners='[["HTTPS", "HTTP", 443, 80, "arn:aws:iam::11 11111:server-certificate/mycert"]]'
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if isinstance(listeners, string_types):
listeners = json.loads(listeners)
# Combining listeners and complex_listeners together makes our lives
# easier in some ways, especially since during introspection you can
# only get a combined set of listeners back from boto; however, boto
# requires us to send in separate listeners and complex listeners and
# the only real difference is the size. It feels like amazon/boto hate
# developers and wish to make us suffer.
_listeners = []
_complex_listeners = []
for listener in listeners:
if len(listener) <= 3:
_listeners.append(listener)
else:
_complex_listeners.append(listener)
try:
conn.create_load_balancer_listeners(name, _listeners,
_complex_listeners)
msg = 'Created ELB listeners on {0}'.format(name)
log.info(msg)
return True
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to create ELB listeners on {0}'.format(name)
log.error(msg)
return False
def delete_listeners(name, ports, region=None, key=None, keyid=None,
profile=None):
'''
Delete listeners on an ELB.
CLI example::
salt myminion boto_elb.delete_listeners myelb '[80,443]'
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if isinstance(ports, string_types):
ports = json.loads(ports)
try:
conn.delete_load_balancer_listeners(name, ports)
msg = 'Deleted ELB listeners on {0}'.format(name)
log.info(msg)
return True
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to delete ELB listeners on {0}'.format(name)
log.error(msg)
return False
def enable_availability_zones(name, availability_zones, region=None, key=None,
keyid=None, profile=None):
'''
Enable availability zones for ELB.
CLI example::
salt myminion boto_elb.enable_availability_zones myelb '["us-east-1a"]'
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if isinstance(availability_zones, string_types):
availability_zones = json.loads(availability_zones)
try:
conn.enable_availability_zones(name, availability_zones)
msg = 'Enabled availability_zones on ELB {0}'.format(name)
log.info(msg)
return True
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to enable availability_zones on ELB {0}'.format(name)
log.error(msg)
return False
def disable_availability_zones(name, availability_zones, region=None, key=None,
keyid=None, profile=None):
'''
Disable availability zones for ELB.
CLI example::
salt myminion boto_elb.disable_availability_zones myelb '["us-east-1a"]'
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if isinstance(availability_zones, string_types):
availability_zones = json.loads(availability_zones)
try:
conn.disable_availability_zones(name, availability_zones)
msg = 'Disabled availability_zones on ELB {0}'.format(name)
log.info(msg)
return True
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to disable availability_zones on ELB {0}'.format(name)
log.error(msg)
return False
def attach_subnets(name, subnets, region=None, key=None, keyid=None,
profile=None):
'''
Attach ELB to subnets.
CLI example::
salt myminion boto_elb.attach_subnets myelb '["mysubnet"]'
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if isinstance(subnets, string_types):
subnets = json.loads(subnets)
try:
conn.attach_lb_to_subnets(name, subnets)
msg = 'Attached ELB {0} on subnets.'.format(name)
log.info(msg)
return True
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to attach ELB {0} on subnets.'.format(name)
log.error(msg)
return False
def detach_subnets(name, subnets, region=None, key=None, keyid=None,
profile=None):
'''
Detach ELB from subnets.
CLI example::
salt myminion boto_elb.detach_subnets myelb '["mysubnet"]'
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
if isinstance(subnets, string_types):
subnets = json.loads(subnets)
try:
conn.detach_lb_from_subnets(name, subnets)
msg = 'Detatched ELB {0} from subnets.'.format(name)
log.info(msg)
return True
except boto.exception.BotoServerError as e:
log.debug(e)
msg = 'Failed to detach ELB {0} from subnets.'.format(name)
log.error(msg)
return False
def get_attributes(name, region=None, key=None, keyid=None, profile=None):
'''
Check to see if attributes are set on an ELB.
CLI example::
salt myminion boto_elb.get_attributes myelb
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return {}
try:
lbattrs = conn.get_all_lb_attributes(name)
ret = odict.OrderedDict()
ret['access_log'] = odict.OrderedDict()
ret['cross_zone_load_balancing'] = odict.OrderedDict()
al = lbattrs.access_log
czlb = lbattrs.cross_zone_load_balancing
ret['access_log']['enabled'] = al.enabled
ret['access_log']['s3_bucket_name'] = al.s3_bucket_name
ret['access_log']['s3_bucket_prefix'] = al.s3_bucket_prefix
ret['access_log']['emit_interval'] = al.emit_interval
ret['cross_zone_load_balancing']['enabled'] = czlb.enabled
return ret
except boto.exception.BotoServerError as e:
log.debug(e)
log.error('ELB {0} does not exist.'.format(name))
return {}
def set_attributes(name, attributes, region=None, key=None, keyid=None,
profile=None):
'''
Set attributes on an ELB.
CLI example to set attributes on an ELB::
salt myminion boto_elb.set_attributes myelb '{"access_log": {"enabled": "true", "s3_bucket_name": "mybucket", "s3_bucket_prefix": "mylogs/", "emit_interval": "5"}}' region=us-east-1
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
al = attributes.get('access_log', {})
czlb = attributes.get('cross_zone_load_balancing', {})
if not al and not czlb:
log.error('No supported attributes for ELB.')
return False
if al:
_al = AccessLogAttribute()
_al.enabled = al.get('enabled', False)
if not _al.enabled:
msg = 'Access log attribute configured, but enabled config missing'
log.error(msg)
return False
_al.s3_bucket_name = al.get('s3_bucket_name', None)
_al.s3_bucket_prefix = al.get('s3_bucket_prefix', None)
_al.emit_interval = al.get('emit_interval', None)
added_attr = conn.modify_lb_attribute(name, 'accessLog', _al)
if added_attr:
log.info('Added access_log attribute to {0} elb.'.format(name))
else:
msg = 'Failed to add access_log attribute to {0} elb.'
log.error(msg.format(name))
return False
if czlb:
_czlb = CrossZoneLoadBalancingAttribute()
_czlb.enabled = czlb['enabled']
added_attr = conn.modify_lb_attribute(name, 'crossZoneLoadBalancing',
_czlb.enabled)
if added_attr:
msg = 'Added cross_zone_load_balancing attribute to {0} elb.'
log.info(msg.format(name))
else:
log.error('Failed to add cross_zone_load_balancing attribute.')
return False
return True
def get_health_check(name, region=None, key=None, keyid=None, profile=None):
'''
Get the health check configured for this ELB.
CLI example::
salt myminion boto_elb.get_health_check myelb
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return {}
try:
lb = conn.get_all_load_balancers(load_balancer_names=[name])
lb = lb[0]
ret = odict.OrderedDict()
hc = lb.health_check
ret['interval'] = hc.interval
ret['target'] = hc.target
ret['healthy_threshold'] = hc.healthy_threshold
ret['timeout'] = hc.timeout
ret['unhealthy_threshold'] = hc.unhealthy_threshold
return ret
except boto.exception.BotoServerError as e:
log.debug(e)
log.error('ELB {0} does not exist.'.format(name))
return {}
def set_health_check(name, health_check, region=None, key=None, keyid=None,
profile=None):
'''
Set attributes on an ELB.
CLI example to set attributes on an ELB::
salt myminion boto_elb.set_health_check myelb '{"target": "HTTP:80/"}'
'''
conn = _get_conn(region, key, keyid, profile)
if not conn:
return False
hc = HealthCheck(**health_check)
try:
conn.configure_health_check(name, hc)
log.info('Configured health check on ELB {0}'.format(name))
except boto.exception.BotoServerError as e:
log.debug(e)
log.info('Failed to configure health check on ELB {0}'.format(name))
return False
return True
def _get_conn(region, key, keyid, profile):
'''
Get a boto connection to ELB.
'''
if profile:
if isinstance(profile, string_types):
_profile = __salt__['config.option'](profile)
elif isinstance(profile, dict):
_profile = profile
key = _profile.get('key', None)
keyid = _profile.get('keyid', None)
region = _profile.get('keyid', None)
if not region and __salt__['config.option']('elb.region'):
region = __salt__['config.option']('elb.region')
if not region:
region = 'us-east-1'
if not key and __salt__['config.option']('elb.key'):
key = __salt__['config.option']('elb.key')
if not keyid and __salt__['config.option']('elb.keyid'):
keyid = __salt__['config.option']('elb.keyid')
try:
conn = boto.ec2.elb.connect_to_region(region, aws_access_key_id=keyid,
aws_secret_access_key=key)
except boto.exception.NoAuthHandlerFound:
log.error('No authentication credentials found when attempting to'
' make boto elb connection.')
return None
return conn

553
salt/states/boto_elb.py Normal file
View file

@ -0,0 +1,553 @@
# -*- coding: utf-8 -*-
'''
Manage ELBs
=================
.. versionadded:: Helium
Create and destroy ELBs. Be aware that this interacts with Amazon's
services, and so may incur charges.
This module uses boto, which can be installed via package, or pip.
This module accepts explicit elb credentials but can also utilize
IAM roles assigned to the instance trough Instance Profiles. Dynamic
credentials are then automatically obtained from AWS API and no further
configuration is necessary. More Information available at::
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
If IAM roles are not used you need to specify them either in a pillar or
in the minion's config file::
elb.keyid: GKTADJGHEIQSXMKKRBJ08H
elb.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
It's also possible to specify key, keyid and region via a profile, either
as a passed in dict, or as a string to pull from pillars or minion config:
myprofile:
keyid: GKTADJGHEIQSXMKKRBJ08H
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
region: us-east-1
.. code-block:: yaml
myelb:
boto_elb.present:
- region: us-east-1
- keyid: GKTADJGHEIQSXMKKRBJ08H
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
- listeners:
- - 443
- 80
- HTTPS
- HTTP
- 'arn:aws:iam::1111111:server-certificate/mycert'
- - 8210
- 8210
- TCP
- TCP
- health_check:
target: 'HTTP:80/'
- attributes:
cross_zone_load_balancing:
enabled: true
access_log:
enabled: true
s3_bucket_name: 'mybucket'
s3_bucket_prefix: '/my-logs/'
emit_interval: 5
# Using a profile from pillars
myelb:
boto_elb.present:
- region: us-east-1
- profile: myelbprofile
# Passing in a profile
myelb:
boto_elb.present:
- region: us-east-1
- profile:
keyid: GKTADJGHEIQSXMKKRBJ08H
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
'''
import salt.utils.dictupdate as dictupdate
from salt.exceptions import SaltInvocationError
def __virtual__():
'''
Only load if boto is available.
'''
return 'boto_elb' if 'boto_elb.exists' in __salt__ else False
def present(
name,
availability_zones,
listeners,
subnets=None,
security_groups=None,
scheme='internet-facing',
health_check=None,
attributes=None,
region=None,
key=None,
keyid=None,
profile=None):
'''
Ensure the IAM role exists.
name
Name of the IAM role.
availability_zones
A list of availability zones for this ELB.
listeners
A list of listener lists; example: [['443', 'HTTPS', 'arn:aws:iam::1111111:server-certificate/mycert'], ['8443', '80', 'HTTPS', 'HTTP', 'arn:aws:iam::1111111:server-certificate/mycert']]
subnets
A list of subnet IDs in your VPC to attach to your LoadBalancer.
security_groups
The security groups assigned to your LoadBalancer within your VPC.
scheme
The type of a LoadBalancer. internet-facing or internal. Once set, can not be modified.
health_check
A dict defining the health check for this ELB.
attributes
A dict defining the attributes to set on this ELB.
region
Region to connect to.
key
Secret key to be used.
keyid
Access key to be used.
profile
A dict with region, key and keyid, or a pillar key (string)
that contains a dict with region, key and keyid.
'''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
_ret = _elb_present(name, availability_zones, listeners, subnets,
security_groups, scheme, region, key, keyid, profile)
ret['changes'] = _ret['changes']
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if _ret['result'] is not None:
ret['result'] = _ret['result']
if ret['result'] is False:
return ret
_ret = _attributes_present(name, attributes, region, key, keyid, profile)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if _ret['result'] is not None:
ret['result'] = _ret['result']
if ret['result'] is False:
return ret
_ret = _health_check_present(name, health_check, region, key, keyid,
profile)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if _ret['result'] is not None:
ret['result'] = _ret['result']
return ret
def _elb_present(
name,
availability_zones,
listeners,
subnets,
security_groups,
scheme,
region,
key,
keyid,
profile):
ret = {'result': None, 'comment': '', 'changes': {}}
if not listeners:
listeners = []
for listener in listeners:
if len(listener) < 3:
raise SaltInvocationError('Listeners must have at minimum port,'
' instance_port and protocol values in'
' the provided list.')
elif len(listener) == 3:
# Returned listeners will have 4 values. There's no way for us to
# reliably get back complex and non-complex listeners, so we'll
# have to make due with this.
listener.append(listener[2])
exists = __salt__['boto_elb.exists'](name, region, key, keyid, profile)
if not exists:
if __opts__['test']:
ret['comment'] = 'ELB {0} is set to be created.'.format(name)
return ret
created = __salt__['boto_elb.create'](name, availability_zones,
listeners, subnets,
security_groups, scheme, region,
key, keyid, profile)
if created:
ret['result'] = True
ret['changes']['old'] = {'elb': None}
ret['changes']['new'] = {'elb': name}
ret['comment'] = 'ELB {0} created.'.format(name)
else:
ret['result'] = False
ret['comment'] = 'Failed to create {0} ELB.'.format(name)
else:
ret['comment'] = 'ELB {0} present.'.format(name)
_ret = _listeners_present(name, listeners, region, key, keyid, profile)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if _ret['result'] is not None:
ret['result'] = _ret['result']
if ret['result'] is False:
return ret
_ret = _zones_present(name, availability_zones, region, key, keyid,
profile)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if _ret['result'] is not None:
ret['result'] = _ret['result']
if ret['result'] is False:
return ret
_ret = _subnets_present(name, subnets, region, key, keyid,
profile)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if _ret['result'] is not None:
ret['result'] = _ret['result']
return ret
def _listeners_present(
name,
listeners,
region,
key,
keyid,
profile):
ret = {'result': None, 'comment': '', 'changes': {}}
lb = __salt__['boto_elb.get_elb_config'](name, region, key, keyid, profile)
if not lb:
msg = '{0} ELB configuration could not be retreived.'.format(name)
ret['comment'] = msg
ret['result'] = False
return ret
if not listeners:
listeners = []
to_delete = []
to_create = []
for listener in listeners:
if listener not in lb['listeners']:
to_create.append(listener)
for listener in lb['listeners']:
if listener not in listeners:
to_delete.append(listener[0])
if to_create or to_delete:
if __opts__['test']:
msg = 'ELB {0} set to have listeners modified.'.format(name)
ret['comment'] = msg
return ret
if to_delete:
deleted = __salt__['boto_elb.delete_listeners'](name, to_delete,
region, key, keyid,
profile)
if deleted:
ret['comment'] = 'Deleted listeners on {0} ELB.'.format(name)
ret['result'] = True
else:
msg = 'Failed to delete listeners on {0} ELB.'.format(name)
ret['comment'] = msg
ret['result'] = False
if to_create:
created = __salt__['boto_elb.create_listeners'](name, to_create,
region, key, keyid,
profile)
if created:
msg = 'Created listeners on {0} ELB.'
ret['comment'] = ' '.join([ret['comment'], msg.format(name)])
if ret['result'] is not False:
ret['result'] = True
else:
msg = 'Failed to create listeners on {0} ELB.'
ret['comment'] = ' '.join([ret['comment'], msg.format(name)])
ret['result'] = False
ret['changes']['old'] = {'listeners': lb['listeners']}
lb = __salt__['boto_elb.get_elb_config'](name, region, key, keyid,
profile)
ret['changes']['new'] = {'listeners': lb['listeners']}
return ret
def _attributes_present(
name,
attributes,
region,
key,
keyid,
profile):
ret = {'result': None, 'comment': '', 'changes': {}}
_attributes = __salt__['boto_elb.get_attributes'](name, region, key, keyid,
profile)
if not _attributes:
if not __opts__['test']:
ret['result'] = False
msg = 'Failed to retrieve attributes for ELB {0}.'.format(name)
ret['comment'] = msg
return ret
attrs_to_set = []
if 'cross_zone_load_balancing' in attributes:
czlb = attributes['cross_zone_load_balancing']
_czlb = _attributes['cross_zone_load_balancing']
if czlb['enabled'] != _czlb['enabled']:
attrs_to_set.append('cross_zone_load_balancing')
if 'access_log' in attributes:
for attr, val in attributes['access_log'].iteritems():
if str(_attributes['access_log'][attr]) != str(val):
attrs_to_set.append('access_log')
if 's3_bucket_prefix' in attributes['access_log']:
sbp = attributes['access_log']['s3_bucket_prefix']
if sbp.startswith('/') or sbp.endswith('/'):
raise SaltInvocationError('s3_bucket_prefix can not start or'
' end with /.')
if attrs_to_set:
if __opts__['test']:
ret['comment'] = 'ELB {0} set to have attributes set.'.format(name)
return ret
was_set = __salt__['boto_elb.set_attributes'](name, attributes,
region, key, keyid,
profile)
if was_set:
ret['result'] = True
ret['changes']['old'] = {'attributes': _attributes}
ret['changes']['new'] = {'attributes': attributes}
ret['comment'] = 'Set attributes on ELB {0}.'.format(name)
else:
ret['result'] = False
msg = 'Failed to set attributes on ELB {0}.'.format(name)
ret['comment'] = msg
else:
ret['comment'] = 'Attributes already set on ELB {0}.'.format(name)
return ret
def _health_check_present(
name,
health_check,
region,
key,
keyid,
profile):
ret = {'result': None, 'comment': '', 'changes': {}}
if not health_check:
health_check = {}
_health_check = __salt__['boto_elb.get_health_check'](name, region, key,
keyid, profile)
if not _health_check:
if not __opts__['test']:
ret['result'] = False
msg = 'Failed to retrieve health_check for ELB {0}.'.format(name)
ret['comment'] = msg
return ret
need_to_set = False
for attr, val in health_check.iteritems():
if str(_health_check[attr]) != str(val):
need_to_set = True
if need_to_set:
if __opts__['test']:
msg = 'ELB {0} set to have health check set.'.format(name)
ret['comment'] = msg
return ret
was_set = __salt__['boto_elb.set_health_check'](name, health_check,
region, key, keyid,
profile)
if was_set:
ret['result'] = True
ret['changes']['old'] = {'health_check': _health_check}
_health_check = __salt__['boto_elb.get_health_check'](name, region,
key, keyid,
profile)
ret['changes']['new'] = {'health_check': _health_check}
ret['comment'] = 'Set health check on ELB {0}.'.format(name)
else:
ret['result'] = False
msg = 'Failed to set health check on ELB {0}.'.format(name)
ret['comment'] = msg
else:
ret['comment'] = 'Health check already set on ELB {0}.'.format(name)
return ret
def _zones_present(
name,
availability_zones,
region,
key,
keyid,
profile):
ret = {'result': None, 'comment': '', 'changes': {}}
lb = __salt__['boto_elb.get_elb_config'](name, region, key, keyid, profile)
if not lb:
if not __opts__['test']:
ret['result'] = False
msg = 'Failed to retrieve ELB {0}.'.format(name)
ret['comment'] = msg
return ret
to_enable = []
to_disable = []
_zones = lb['availability_zones']
for zone in availability_zones:
if zone not in _zones:
to_enable.append(zone)
for zone in _zones:
if zone not in availability_zones:
to_disable.append(zone)
if to_enable or to_disable:
if __opts__['test']:
msg = 'ELB {0} to have availability zones set.'.format(name)
ret['comment'] = msg
return ret
if to_enable:
enabled = __salt__['boto_elb.enable_availability_zones'](name,
to_enable,
region,
key,
keyid,
profile)
if enabled:
msg = 'Enabled availability zones on {0} ELB.'.format(name)
ret['comment'] = msg
ret['result'] = True
else:
msg = 'Failed to enable availability zones on {0} ELB.'
ret['comment'] = msg.format(name)
ret['result'] = False
if to_disable:
disabled = __salt__['boto_elb.disable_availability_zones'](name,
to_disable,
region,
key,
keyid,
profile)
if disabled:
msg = 'Disabled availability zones on {0} ELB.'
ret['comment'] = ' '.join([ret['comment'], msg.format(name)])
ret['result'] = True
else:
msg = 'Failed to disable availability zones on {0} ELB.'
ret['comment'] = ' '.join([ret['comment'], msg.format(name)])
ret['result'] = False
ret['changes']['old'] = {'availability_zones':
lb['availability_zones']}
lb = __salt__['boto_elb.get_elb_config'](name, region, key, keyid,
profile)
ret['changes']['new'] = {'availability_zones':
lb['availability_zones']}
else:
msg = 'Availability zones already set on ELB {0}.'.format(name)
ret['comment'] = msg
return ret
def _subnets_present(
name,
subnets,
region,
key,
keyid,
profile):
ret = {'result': None, 'comment': '', 'changes': {}}
if not subnets:
subnets = []
lb = __salt__['boto_elb.get_elb_config'](name, region, key, keyid, profile)
if not lb:
if not __opts__['test']:
ret['result'] = False
msg = 'Failed to retrieve ELB {0}.'.format(name)
ret['comment'] = msg
return ret
to_enable = []
to_disable = []
_subnets = lb['subnets']
for subnet in subnets:
if subnet not in _subnets:
to_enable.append(subnet)
for subnet in _subnets:
if subnet not in subnets:
to_disable.append(subnet)
if to_enable or to_disable:
if __opts__['test']:
msg = 'ELB {0} to have subnets set.'.format(name)
ret['comment'] = msg
return ret
if to_enable:
attached = __salt__['boto_elb.attach_subnets'](name, to_enable,
region, key, keyid,
profile)
if attached:
msg = 'Attached subnets on {0} ELB.'.format(name)
ret['comment'] = msg
ret['result'] = True
else:
msg = 'Failed to attach subnets on {0} ELB.'
ret['comment'] = msg.format(name)
ret['result'] = False
if to_disable:
detached = __salt__['boto_elb.detach_subnets'](name, to_disable,
region, key, keyid,
profile)
if detached:
msg = 'Detached subnets on {0} ELB.'
ret['comment'] = ' '.join([ret['comment'], msg.format(name)])
ret['result'] = True
else:
msg = 'Failed to detach subnets on {0} ELB.'
ret['comment'] = ' '.join([ret['comment'], msg.format(name)])
ret['result'] = False
ret['changes']['old'] = {'subnets': lb['subnets']}
lb = __salt__['boto_elb.get_elb_config'](name, region, key, keyid,
profile)
ret['changes']['new'] = {'subnets': lb['subnets']}
else:
msg = 'Subnets already set on ELB {0}.'.format(name)
ret['comment'] = msg
return ret
def absent(
name,
region=None,
key=None,
keyid=None,
profile=None):
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
exists = __salt__['boto_elb.exists'](name, region, key, keyid, profile)
if exists:
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'ELB {0} is set to be removed.'.format(name)
return ret
deleted = __salt__['boto_elb.delete'](name, region, key, keyid,
profile)
if deleted:
ret['result'] = True
ret['changes']['old'] = {'elb': name}
ret['changes']['new'] = {'elb': None}
ret['comment'] = 'ELB {0} deleted.'.format(name)
else:
ret['result'] = False
ret['comment'] = 'Failed to delete {0} ELB.'.format(name)
else:
ret['comment'] = '{0} ELB does not exist.'.format(name)
return ret