Completed ELBv2 implementation

This commit is contained in:
Terry Cain 2017-10-29 14:14:17 +00:00
parent a6e5ffb99b
commit 2a52a0f91b
5 changed files with 1070 additions and 59 deletions

View File

@ -2456,8 +2456,8 @@
- [ ] update_distribution - [ ] update_distribution
- [ ] update_streaming_distribution - [ ] update_streaming_distribution
## elbv2 - 54% implemented ## elbv2 - 100% implemented
- [ ] add_tags - [X] add_tags
- [X] create_listener - [X] create_listener
- [X] create_load_balancer - [X] create_load_balancer
- [X] create_rule - [X] create_rule
@ -2467,27 +2467,27 @@
- [X] delete_rule - [X] delete_rule
- [X] delete_target_group - [X] delete_target_group
- [X] deregister_targets - [X] deregister_targets
- [ ] describe_account_limits - [X] describe_account_limits
- [X] describe_listeners - [X] describe_listeners
- [ ] describe_load_balancer_attributes - [X] describe_load_balancer_attributes
- [X] describe_load_balancers - [X] describe_load_balancers
- [X] describe_rules - [X] describe_rules
- [ ] describe_ssl_policies - [X] describe_ssl_policies
- [ ] describe_tags - [X] describe_tags
- [ ] describe_target_group_attributes - [X] describe_target_group_attributes
- [X] describe_target_groups - [X] describe_target_groups
- [X] describe_target_health - [X] describe_target_health
- [ ] modify_listener - [X] modify_listener
- [ ] modify_load_balancer_attributes - [X] modify_load_balancer_attributes
- [X] modify_rule - [X] modify_rule
- [ ] modify_target_group - [X] modify_target_group
- [ ] modify_target_group_attributes - [X] modify_target_group_attributes
- [X] register_targets - [X] register_targets
- [ ] remove_tags - [X] remove_tags
- [ ] set_ip_address_type - [X] set_ip_address_type
- [X] set_rule_priorities - [X] set_rule_priorities
- [ ] set_security_groups - [X] set_security_groups
- [ ] set_subnets - [X] set_subnets
## sdb - 0% implemented ## sdb - 0% implemented
- [ ] batch_delete_attributes - [ ] batch_delete_attributes

View File

@ -88,7 +88,7 @@ It gets even better! Moto isn't just for Python code and it isn't just for S3. L
|------------------------------------------------------------------------------| |------------------------------------------------------------------------------|
| ELB | @mock_elb | core endpoints done | | ELB | @mock_elb | core endpoints done |
|------------------------------------------------------------------------------| |------------------------------------------------------------------------------|
| ELBv2 | @mock_elbv2 | core endpoints done | | ELBv2 | @mock_elbv2 | all endpoints done |
|------------------------------------------------------------------------------| |------------------------------------------------------------------------------|
| EMR | @mock_emr | core endpoints done | | EMR | @mock_emr | core endpoints done |
|------------------------------------------------------------------------------| |------------------------------------------------------------------------------|

View File

@ -3,8 +3,10 @@ from __future__ import unicode_literals
import datetime import datetime
import re import re
from moto.compat import OrderedDict from moto.compat import OrderedDict
from moto.core.exceptions import RESTError
from moto.core import BaseBackend, BaseModel from moto.core import BaseBackend, BaseModel
from moto.ec2.models import ec2_backends from moto.ec2.models import ec2_backends
from moto.acm.models import acm_backends
from .exceptions import ( from .exceptions import (
DuplicateLoadBalancerName, DuplicateLoadBalancerName,
DuplicateListenerError, DuplicateListenerError,
@ -40,6 +42,8 @@ class FakeHealthStatus(BaseModel):
class FakeTargetGroup(BaseModel): class FakeTargetGroup(BaseModel):
HTTP_CODE_REGEX = re.compile(r'(?:(?:\d+-\d+|\d+),?)+')
def __init__(self, def __init__(self,
name, name,
arn, arn,
@ -52,7 +56,8 @@ class FakeTargetGroup(BaseModel):
healthcheck_interval_seconds, healthcheck_interval_seconds,
healthcheck_timeout_seconds, healthcheck_timeout_seconds,
healthy_threshold_count, healthy_threshold_count,
unhealthy_threshold_count): unhealthy_threshold_count,
http_codes):
self.name = name self.name = name
self.arn = arn self.arn = arn
self.vpc_id = vpc_id self.vpc_id = vpc_id
@ -67,6 +72,7 @@ class FakeTargetGroup(BaseModel):
self.unhealthy_threshold_count = unhealthy_threshold_count self.unhealthy_threshold_count = unhealthy_threshold_count
self.load_balancer_arns = [] self.load_balancer_arns = []
self.tags = {} self.tags = {}
self.http_status_codes = http_codes
self.attributes = { self.attributes = {
'deregistration_delay.timeout_seconds': 300, 'deregistration_delay.timeout_seconds': 300,
@ -109,6 +115,7 @@ class FakeListener(BaseModel):
self.port = port self.port = port
self.ssl_policy = ssl_policy self.ssl_policy = ssl_policy
self.certificate = certificate self.certificate = certificate
self.certificates = [certificate] if certificate is not None else []
self.default_actions = default_actions self.default_actions = default_actions
self._non_default_rules = [] self._non_default_rules = []
self._default_rule = FakeRule( self._default_rule = FakeRule(
@ -153,6 +160,8 @@ class FakeBackend(BaseModel):
class FakeLoadBalancer(BaseModel): class FakeLoadBalancer(BaseModel):
VALID_ATTRS = {'access_logs.s3.enabled', 'access_logs.s3.bucket', 'access_logs.s3.prefix',
'deletion_protection.enabled', 'idle_timeout.timeout_seconds'}
def __init__(self, name, security_groups, subnets, vpc_id, arn, dns_name, scheme='internet-facing'): def __init__(self, name, security_groups, subnets, vpc_id, arn, dns_name, scheme='internet-facing'):
self.name = name self.name = name
@ -166,6 +175,15 @@ class FakeLoadBalancer(BaseModel):
self.arn = arn self.arn = arn
self.dns_name = dns_name self.dns_name = dns_name
self.stack = 'ipv4'
self.attrs = {
'access_logs.s3.enabled': 'false',
'access_logs.s3.bucket': None,
'access_logs.s3.prefix': None,
'deletion_protection.enabled': 'false',
'idle_timeout.timeout_seconds': '60'
}
@property @property
def physical_resource_id(self): def physical_resource_id(self):
return self.name return self.name
@ -194,6 +212,26 @@ class ELBv2Backend(BaseBackend):
self.target_groups = OrderedDict() self.target_groups = OrderedDict()
self.load_balancers = OrderedDict() self.load_balancers = OrderedDict()
@property
def ec2_backend(self):
"""
EC2 backend
:return: EC2 Backend
:rtype: moto.ec2.models.EC2Backend
"""
return ec2_backends[self.region_name]
@property
def acm_backend(self):
"""
ACM backend
:return: ACM Backend
:rtype: moto.acm.models.AWSCertificateManagerBackend
"""
return acm_backends[self.region_name]
def reset(self): def reset(self):
region_name = self.region_name region_name = self.region_name
self.__dict__ = {} self.__dict__ = {}
@ -201,12 +239,11 @@ class ELBv2Backend(BaseBackend):
def create_load_balancer(self, name, security_groups, subnet_ids, scheme='internet-facing'): def create_load_balancer(self, name, security_groups, subnet_ids, scheme='internet-facing'):
vpc_id = None vpc_id = None
ec2_backend = ec2_backends[self.region_name]
subnets = [] subnets = []
if not subnet_ids: if not subnet_ids:
raise SubnetNotFoundError() raise SubnetNotFoundError()
for subnet_id in subnet_ids: for subnet_id in subnet_ids:
subnet = ec2_backend.get_subnet(subnet_id) subnet = self.ec2_backend.get_subnet(subnet_id)
if subnet is None: if subnet is None:
raise SubnetNotFoundError() raise SubnetNotFoundError()
subnets.append(subnet) subnets.append(subnet)
@ -300,6 +337,9 @@ class ELBv2Backend(BaseBackend):
if target_group.name == name: if target_group.name == name:
raise DuplicateTargetGroupName() raise DuplicateTargetGroupName()
if FakeTargetGroup.HTTP_CODE_REGEX.match(kwargs['http_codes']) is None:
raise RESTError('InvalidParameterValue', 'HttpCode must be like 200 | 200-399 | 200,201 ...')
arn = "arn:aws:elasticloadbalancing:%s:1:targetgroup/%s/50dc6c495c0c9188" % (self.region_name, name) arn = "arn:aws:elasticloadbalancing:%s:1:targetgroup/%s/50dc6c495c0c9188" % (self.region_name, name)
target_group = FakeTargetGroup(name, arn, **kwargs) target_group = FakeTargetGroup(name, arn, **kwargs)
self.target_groups[target_group.arn] = target_group self.target_groups[target_group.arn] = target_group
@ -547,6 +587,166 @@ class ELBv2Backend(BaseBackend):
modified_rules.append(given_rule) modified_rules.append(given_rule)
return modified_rules return modified_rules
def set_ip_address_type(self, arn, ip_type):
if ip_type not in ('internal', 'dualstack'):
raise RESTError('InvalidParameterValue', 'IpAddressType must be either internal | dualstack')
balancer = self.load_balancers.get(arn)
if balancer is None:
raise LoadBalancerNotFoundError()
if ip_type == 'dualstack' and balancer.scheme == 'internal':
raise RESTError('InvalidConfigurationRequest', 'Internal load balancers cannot be dualstack')
balancer.stack = ip_type
def set_security_groups(self, arn, sec_groups):
balancer = self.load_balancers.get(arn)
if balancer is None:
raise LoadBalancerNotFoundError()
# Check all security groups exist
for sec_group_id in sec_groups:
if self.ec2_backend.get_security_group_from_id(sec_group_id) is None:
raise RESTError('InvalidSecurityGroup', 'Security group {0} does not exist'.format(sec_group_id))
balancer.security_groups = sec_groups
def set_subnets(self, arn, subnets):
balancer = self.load_balancers.get(arn)
if balancer is None:
raise LoadBalancerNotFoundError()
subnet_objects = []
sub_zone_list = {}
for subnet in subnets:
try:
subnet = self.ec2_backend.get_subnet(subnet)
if subnet.availability_zone in sub_zone_list:
raise RESTError('InvalidConfigurationRequest', 'More than 1 subnet cannot be specified for 1 availability zone')
sub_zone_list[subnet.availability_zone] = subnet.id
subnet_objects.append(subnet)
except Exception:
raise SubnetNotFoundError()
if len(sub_zone_list) < 2:
raise RESTError('InvalidConfigurationRequest', 'More than 1 availability zone must be specified')
balancer.subnets = subnet_objects
return sub_zone_list.items()
def modify_load_balancer_attributes(self, arn, attrs):
balancer = self.load_balancers.get(arn)
if balancer is None:
raise LoadBalancerNotFoundError()
for key in attrs:
if key not in FakeLoadBalancer.VALID_ATTRS:
raise RESTError('InvalidConfigurationRequest', 'Key {0} not valid'.format(key))
balancer.attrs.update(attrs)
return balancer.attrs
def describe_load_balancer_attributes(self, arn):
balancer = self.load_balancers.get(arn)
if balancer is None:
raise LoadBalancerNotFoundError()
return balancer.attrs
def modify_target_group(self, arn, health_check_proto=None, health_check_port=None, health_check_path=None, health_check_interval=None,
health_check_timeout=None, healthy_threshold_count=None, unhealthy_threshold_count=None, http_codes=None):
target_group = self.target_groups.get(arn)
if target_group is None:
raise TargetGroupNotFoundError()
if http_codes is not None and FakeTargetGroup.HTTP_CODE_REGEX.match(http_codes) is None:
raise RESTError('InvalidParameterValue', 'HttpCode must be like 200 | 200-399 | 200,201 ...')
if http_codes is not None:
target_group.http_status_codes = http_codes
if health_check_interval is not None:
target_group.healthcheck_interval_seconds = health_check_interval
if health_check_path is not None:
target_group.healthcheck_path = health_check_path
if health_check_port is not None:
target_group.healthcheck_port = health_check_port
if health_check_proto is not None:
target_group.healthcheck_protocol = health_check_proto
if health_check_timeout is not None:
target_group.healthcheck_timeout_seconds = health_check_timeout
if healthy_threshold_count is not None:
target_group.healthy_threshold_count = healthy_threshold_count
if unhealthy_threshold_count is not None:
target_group.unhealthy_threshold_count = unhealthy_threshold_count
return target_group
def modify_listener(self, arn, port=None, protocol=None, ssl_policy=None, certificates=None, default_actions=None):
for load_balancer in self.load_balancers.values():
if arn in load_balancer.listeners:
break
else:
raise ListenerNotFoundError()
listener = load_balancer.listeners[arn]
if port is not None:
for listener_arn, current_listener in load_balancer.listeners.items():
if listener_arn == arn:
continue
if listener.port == port:
raise DuplicateListenerError()
listener.port = port
if protocol is not None:
if protocol not in ('HTTP', 'HTTPS', 'TCP'):
raise RESTError('UnsupportedProtocol', 'Protocol {0} is not supported'.format(protocol))
# HTTPS checks
if protocol == 'HTTPS':
# HTTPS
# Might already be HTTPS so may not provide certs
if certificates is None and listener.protocol != 'HTTPS':
raise RESTError('InvalidConfigurationRequest', 'Certificates must be provided for HTTPS')
# Check certificates exist
if certificates is not None:
default_cert = None
all_certs = set() # for SNI
for cert in certificates:
if cert['is_default'] == 'true':
default_cert = cert['certificate_arn']
try:
self.acm_backend.get_certificate(cert['certificate_arn'])
except Exception:
raise RESTError('CertificateNotFound', 'Certificate {0} not found'.format(cert['certificate_arn']))
all_certs.add(cert['certificate_arn'])
if default_cert is None:
raise RESTError('InvalidConfigurationRequest', 'No default certificate')
listener.certificate = default_cert
listener.certificates = list(all_certs)
listener.protocol = protocol
if ssl_policy is not None:
# Its already validated in responses.py
listener.ssl_policy = ssl_policy
if default_actions is not None:
# Is currently not validated
listener.default_actions = default_actions
return listener
def _any_listener_using(self, target_group_arn): def _any_listener_using(self, target_group_arn):
for load_balancer in self.load_balancers.values(): for load_balancer in self.load_balancers.values():
for listener in load_balancer.listeners.values(): for listener in load_balancer.listeners.values():

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from moto.core.exceptions import RESTError
from moto.core.utils import amzn_request_id
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import elbv2_backends from .models import elbv2_backends
from .exceptions import DuplicateTagKeysError from .exceptions import DuplicateTagKeysError
@ -6,12 +8,131 @@ from .exceptions import LoadBalancerNotFoundError
from .exceptions import TargetGroupNotFoundError from .exceptions import TargetGroupNotFoundError
class ELBV2Response(BaseResponse): SSL_POLICIES = [
{
'name': 'ELBSecurityPolicy-2016-08',
'ssl_protocols': ['TLSv1', 'TLSv1.1', 'TLSv1.2'],
'ciphers': [
{'name': 'ECDHE-ECDSA-AES128-GCM-SHA256', 'priority': 1},
{'name': 'ECDHE-RSA-AES128-GCM-SHA256', 'priority': 2},
{'name': 'ECDHE-ECDSA-AES128-SHA256', 'priority': 3},
{'name': 'ECDHE-RSA-AES128-SHA256', 'priority': 4},
{'name': 'ECDHE-ECDSA-AES128-SHA', 'priority': 5},
{'name': 'ECDHE-RSA-AES128-SHA', 'priority': 6},
{'name': 'ECDHE-ECDSA-AES256-GCM-SHA384', 'priority': 7},
{'name': 'ECDHE-RSA-AES256-GCM-SHA384', 'priority': 8},
{'name': 'ECDHE-ECDSA-AES256-SHA384', 'priority': 9},
{'name': 'ECDHE-RSA-AES256-SHA384', 'priority': 10},
{'name': 'ECDHE-RSA-AES256-SHA', 'priority': 11},
{'name': 'ECDHE-ECDSA-AES256-SHA', 'priority': 12},
{'name': 'AES128-GCM-SHA256', 'priority': 13},
{'name': 'AES128-SHA256', 'priority': 14},
{'name': 'AES128-SHA', 'priority': 15},
{'name': 'AES256-GCM-SHA384', 'priority': 16},
{'name': 'AES256-SHA256', 'priority': 17},
{'name': 'AES256-SHA', 'priority': 18}
],
},
{
'name': 'ELBSecurityPolicy-TLS-1-2-2017-01',
'ssl_protocols': ['TLSv1.2'],
'ciphers': [
{'name': 'ECDHE-ECDSA-AES128-GCM-SHA256', 'priority': 1},
{'name': 'ECDHE-RSA-AES128-GCM-SHA256', 'priority': 2},
{'name': 'ECDHE-ECDSA-AES128-SHA256', 'priority': 3},
{'name': 'ECDHE-RSA-AES128-SHA256', 'priority': 4},
{'name': 'ECDHE-ECDSA-AES256-GCM-SHA384', 'priority': 5},
{'name': 'ECDHE-RSA-AES256-GCM-SHA384', 'priority': 6},
{'name': 'ECDHE-ECDSA-AES256-SHA384', 'priority': 7},
{'name': 'ECDHE-RSA-AES256-SHA384', 'priority': 8},
{'name': 'AES128-GCM-SHA256', 'priority': 9},
{'name': 'AES128-SHA256', 'priority': 10},
{'name': 'AES256-GCM-SHA384', 'priority': 11},
{'name': 'AES256-SHA256', 'priority': 12}
]
},
{
'name': 'ELBSecurityPolicy-TLS-1-1-2017-01',
'ssl_protocols': ['TLSv1.1', 'TLSv1.2'],
'ciphers': [
{'name': 'ECDHE-ECDSA-AES128-GCM-SHA256', 'priority': 1},
{'name': 'ECDHE-RSA-AES128-GCM-SHA256', 'priority': 2},
{'name': 'ECDHE-ECDSA-AES128-SHA256', 'priority': 3},
{'name': 'ECDHE-RSA-AES128-SHA256', 'priority': 4},
{'name': 'ECDHE-ECDSA-AES128-SHA', 'priority': 5},
{'name': 'ECDHE-RSA-AES128-SHA', 'priority': 6},
{'name': 'ECDHE-ECDSA-AES256-GCM-SHA384', 'priority': 7},
{'name': 'ECDHE-RSA-AES256-GCM-SHA384', 'priority': 8},
{'name': 'ECDHE-ECDSA-AES256-SHA384', 'priority': 9},
{'name': 'ECDHE-RSA-AES256-SHA384', 'priority': 10},
{'name': 'ECDHE-RSA-AES256-SHA', 'priority': 11},
{'name': 'ECDHE-ECDSA-AES256-SHA', 'priority': 12},
{'name': 'AES128-GCM-SHA256', 'priority': 13},
{'name': 'AES128-SHA256', 'priority': 14},
{'name': 'AES128-SHA', 'priority': 15},
{'name': 'AES256-GCM-SHA384', 'priority': 16},
{'name': 'AES256-SHA256', 'priority': 17},
{'name': 'AES256-SHA', 'priority': 18}
]
},
{
'name': 'ELBSecurityPolicy-2015-05',
'ssl_protocols': ['TLSv1', 'TLSv1.1', 'TLSv1.2'],
'ciphers': [
{'name': 'ECDHE-ECDSA-AES128-GCM-SHA256', 'priority': 1},
{'name': 'ECDHE-RSA-AES128-GCM-SHA256', 'priority': 2},
{'name': 'ECDHE-ECDSA-AES128-SHA256', 'priority': 3},
{'name': 'ECDHE-RSA-AES128-SHA256', 'priority': 4},
{'name': 'ECDHE-ECDSA-AES128-SHA', 'priority': 5},
{'name': 'ECDHE-RSA-AES128-SHA', 'priority': 6},
{'name': 'ECDHE-ECDSA-AES256-GCM-SHA384', 'priority': 7},
{'name': 'ECDHE-RSA-AES256-GCM-SHA384', 'priority': 8},
{'name': 'ECDHE-ECDSA-AES256-SHA384', 'priority': 9},
{'name': 'ECDHE-RSA-AES256-SHA384', 'priority': 10},
{'name': 'ECDHE-RSA-AES256-SHA', 'priority': 11},
{'name': 'ECDHE-ECDSA-AES256-SHA', 'priority': 12},
{'name': 'AES128-GCM-SHA256', 'priority': 13},
{'name': 'AES128-SHA256', 'priority': 14},
{'name': 'AES128-SHA', 'priority': 15},
{'name': 'AES256-GCM-SHA384', 'priority': 16},
{'name': 'AES256-SHA256', 'priority': 17},
{'name': 'AES256-SHA', 'priority': 18}
]
},
{
'name': 'ELBSecurityPolicy-TLS-1-0-2015-04',
'ssl_protocols': ['TLSv1', 'TLSv1.1', 'TLSv1.2'],
'ciphers': [
{'name': 'ECDHE-ECDSA-AES128-GCM-SHA256', 'priority': 1},
{'name': 'ECDHE-RSA-AES128-GCM-SHA256', 'priority': 2},
{'name': 'ECDHE-ECDSA-AES128-SHA256', 'priority': 3},
{'name': 'ECDHE-RSA-AES128-SHA256', 'priority': 4},
{'name': 'ECDHE-ECDSA-AES128-SHA', 'priority': 5},
{'name': 'ECDHE-RSA-AES128-SHA', 'priority': 6},
{'name': 'ECDHE-ECDSA-AES256-GCM-SHA384', 'priority': 7},
{'name': 'ECDHE-RSA-AES256-GCM-SHA384', 'priority': 8},
{'name': 'ECDHE-ECDSA-AES256-SHA384', 'priority': 9},
{'name': 'ECDHE-RSA-AES256-SHA384', 'priority': 10},
{'name': 'ECDHE-RSA-AES256-SHA', 'priority': 11},
{'name': 'ECDHE-ECDSA-AES256-SHA', 'priority': 12},
{'name': 'AES128-GCM-SHA256', 'priority': 13},
{'name': 'AES128-SHA256', 'priority': 14},
{'name': 'AES128-SHA', 'priority': 15},
{'name': 'AES256-GCM-SHA384', 'priority': 16},
{'name': 'AES256-SHA256', 'priority': 17},
{'name': 'AES256-SHA', 'priority': 18},
{'name': 'DES-CBC3-SHA', 'priority': 19}
]
}
]
class ELBV2Response(BaseResponse):
@property @property
def elbv2_backend(self): def elbv2_backend(self):
return elbv2_backends[self.region] return elbv2_backends[self.region]
@amzn_request_id
def create_load_balancer(self): def create_load_balancer(self):
load_balancer_name = self._get_param('Name') load_balancer_name = self._get_param('Name')
subnet_ids = self._get_multi_param("Subnets.member") subnet_ids = self._get_multi_param("Subnets.member")
@ -28,6 +149,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(CREATE_LOAD_BALANCER_TEMPLATE) template = self.response_template(CREATE_LOAD_BALANCER_TEMPLATE)
return template.render(load_balancer=load_balancer) return template.render(load_balancer=load_balancer)
@amzn_request_id
def create_rule(self): def create_rule(self):
lister_arn = self._get_param('ListenerArn') lister_arn = self._get_param('ListenerArn')
_conditions = self._get_list_prefix('Conditions.member') _conditions = self._get_list_prefix('Conditions.member')
@ -52,6 +174,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(CREATE_RULE_TEMPLATE) template = self.response_template(CREATE_RULE_TEMPLATE)
return template.render(rules=rules) return template.render(rules=rules)
@amzn_request_id
def create_target_group(self): def create_target_group(self):
name = self._get_param('Name') name = self._get_param('Name')
vpc_id = self._get_param('VpcId') vpc_id = self._get_param('VpcId')
@ -64,6 +187,7 @@ class ELBV2Response(BaseResponse):
healthcheck_timeout_seconds = self._get_param('HealthCheckTimeoutSeconds', '5') healthcheck_timeout_seconds = self._get_param('HealthCheckTimeoutSeconds', '5')
healthy_threshold_count = self._get_param('HealthyThresholdCount', '5') healthy_threshold_count = self._get_param('HealthyThresholdCount', '5')
unhealthy_threshold_count = self._get_param('UnhealthyThresholdCount', '2') unhealthy_threshold_count = self._get_param('UnhealthyThresholdCount', '2')
http_codes = self._get_param('Matcher.HttpCode', '200')
target_group = self.elbv2_backend.create_target_group( target_group = self.elbv2_backend.create_target_group(
name, name,
@ -77,11 +201,13 @@ class ELBV2Response(BaseResponse):
healthcheck_timeout_seconds=healthcheck_timeout_seconds, healthcheck_timeout_seconds=healthcheck_timeout_seconds,
healthy_threshold_count=healthy_threshold_count, healthy_threshold_count=healthy_threshold_count,
unhealthy_threshold_count=unhealthy_threshold_count, unhealthy_threshold_count=unhealthy_threshold_count,
http_codes=http_codes
) )
template = self.response_template(CREATE_TARGET_GROUP_TEMPLATE) template = self.response_template(CREATE_TARGET_GROUP_TEMPLATE)
return template.render(target_group=target_group) return template.render(target_group=target_group)
@amzn_request_id
def create_listener(self): def create_listener(self):
load_balancer_arn = self._get_param('LoadBalancerArn') load_balancer_arn = self._get_param('LoadBalancerArn')
protocol = self._get_param('Protocol') protocol = self._get_param('Protocol')
@ -105,6 +231,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(CREATE_LISTENER_TEMPLATE) template = self.response_template(CREATE_LISTENER_TEMPLATE)
return template.render(listener=listener) return template.render(listener=listener)
@amzn_request_id
def describe_load_balancers(self): def describe_load_balancers(self):
arns = self._get_multi_param("LoadBalancerArns.member") arns = self._get_multi_param("LoadBalancerArns.member")
names = self._get_multi_param("Names.member") names = self._get_multi_param("Names.member")
@ -124,6 +251,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DESCRIBE_LOAD_BALANCERS_TEMPLATE) template = self.response_template(DESCRIBE_LOAD_BALANCERS_TEMPLATE)
return template.render(load_balancers=load_balancers_resp, marker=next_marker) return template.render(load_balancers=load_balancers_resp, marker=next_marker)
@amzn_request_id
def describe_rules(self): def describe_rules(self):
listener_arn = self._get_param('ListenerArn') listener_arn = self._get_param('ListenerArn')
rule_arns = self._get_multi_param('RuleArns.member') if any(k for k in list(self.querystring.keys()) if k.startswith('RuleArns.member')) else None rule_arns = self._get_multi_param('RuleArns.member') if any(k for k in list(self.querystring.keys()) if k.startswith('RuleArns.member')) else None
@ -144,6 +272,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DESCRIBE_RULES_TEMPLATE) template = self.response_template(DESCRIBE_RULES_TEMPLATE)
return template.render(rules=rules_resp, marker=next_marker) return template.render(rules=rules_resp, marker=next_marker)
@amzn_request_id
def describe_target_groups(self): def describe_target_groups(self):
load_balancer_arn = self._get_param('LoadBalancerArn') load_balancer_arn = self._get_param('LoadBalancerArn')
target_group_arns = self._get_multi_param('TargetGroupArns.member') target_group_arns = self._get_multi_param('TargetGroupArns.member')
@ -153,6 +282,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DESCRIBE_TARGET_GROUPS_TEMPLATE) template = self.response_template(DESCRIBE_TARGET_GROUPS_TEMPLATE)
return template.render(target_groups=target_groups) return template.render(target_groups=target_groups)
@amzn_request_id
def describe_target_group_attributes(self): def describe_target_group_attributes(self):
target_group_arn = self._get_param('TargetGroupArn') target_group_arn = self._get_param('TargetGroupArn')
target_group = self.elbv2_backend.target_groups.get(target_group_arn) target_group = self.elbv2_backend.target_groups.get(target_group_arn)
@ -161,6 +291,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DESCRIBE_TARGET_GROUP_ATTRIBUTES_TEMPLATE) template = self.response_template(DESCRIBE_TARGET_GROUP_ATTRIBUTES_TEMPLATE)
return template.render(attributes=target_group.attributes) return template.render(attributes=target_group.attributes)
@amzn_request_id
def describe_listeners(self): def describe_listeners(self):
load_balancer_arn = self._get_param('LoadBalancerArn') load_balancer_arn = self._get_param('LoadBalancerArn')
listener_arns = self._get_multi_param('ListenerArns.member') listener_arns = self._get_multi_param('ListenerArns.member')
@ -171,30 +302,35 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DESCRIBE_LISTENERS_TEMPLATE) template = self.response_template(DESCRIBE_LISTENERS_TEMPLATE)
return template.render(listeners=listeners) return template.render(listeners=listeners)
@amzn_request_id
def delete_load_balancer(self): def delete_load_balancer(self):
arn = self._get_param('LoadBalancerArn') arn = self._get_param('LoadBalancerArn')
self.elbv2_backend.delete_load_balancer(arn) self.elbv2_backend.delete_load_balancer(arn)
template = self.response_template(DELETE_LOAD_BALANCER_TEMPLATE) template = self.response_template(DELETE_LOAD_BALANCER_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def delete_rule(self): def delete_rule(self):
arn = self._get_param('RuleArn') arn = self._get_param('RuleArn')
self.elbv2_backend.delete_rule(arn) self.elbv2_backend.delete_rule(arn)
template = self.response_template(DELETE_RULE_TEMPLATE) template = self.response_template(DELETE_RULE_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def delete_target_group(self): def delete_target_group(self):
arn = self._get_param('TargetGroupArn') arn = self._get_param('TargetGroupArn')
self.elbv2_backend.delete_target_group(arn) self.elbv2_backend.delete_target_group(arn)
template = self.response_template(DELETE_TARGET_GROUP_TEMPLATE) template = self.response_template(DELETE_TARGET_GROUP_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def delete_listener(self): def delete_listener(self):
arn = self._get_param('ListenerArn') arn = self._get_param('ListenerArn')
self.elbv2_backend.delete_listener(arn) self.elbv2_backend.delete_listener(arn)
template = self.response_template(DELETE_LISTENER_TEMPLATE) template = self.response_template(DELETE_LISTENER_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def modify_rule(self): def modify_rule(self):
rule_arn = self._get_param('RuleArn') rule_arn = self._get_param('RuleArn')
_conditions = self._get_list_prefix('Conditions.member') _conditions = self._get_list_prefix('Conditions.member')
@ -217,6 +353,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(MODIFY_RULE_TEMPLATE) template = self.response_template(MODIFY_RULE_TEMPLATE)
return template.render(rules=rules) return template.render(rules=rules)
@amzn_request_id
def modify_target_group_attributes(self): def modify_target_group_attributes(self):
target_group_arn = self._get_param('TargetGroupArn') target_group_arn = self._get_param('TargetGroupArn')
target_group = self.elbv2_backend.target_groups.get(target_group_arn) target_group = self.elbv2_backend.target_groups.get(target_group_arn)
@ -230,6 +367,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(MODIFY_TARGET_GROUP_ATTRIBUTES_TEMPLATE) template = self.response_template(MODIFY_TARGET_GROUP_ATTRIBUTES_TEMPLATE)
return template.render(attributes=attributes) return template.render(attributes=attributes)
@amzn_request_id
def register_targets(self): def register_targets(self):
target_group_arn = self._get_param('TargetGroupArn') target_group_arn = self._get_param('TargetGroupArn')
targets = self._get_list_prefix('Targets.member') targets = self._get_list_prefix('Targets.member')
@ -238,6 +376,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(REGISTER_TARGETS_TEMPLATE) template = self.response_template(REGISTER_TARGETS_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def deregister_targets(self): def deregister_targets(self):
target_group_arn = self._get_param('TargetGroupArn') target_group_arn = self._get_param('TargetGroupArn')
targets = self._get_list_prefix('Targets.member') targets = self._get_list_prefix('Targets.member')
@ -246,6 +385,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DEREGISTER_TARGETS_TEMPLATE) template = self.response_template(DEREGISTER_TARGETS_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def describe_target_health(self): def describe_target_health(self):
target_group_arn = self._get_param('TargetGroupArn') target_group_arn = self._get_param('TargetGroupArn')
targets = self._get_list_prefix('Targets.member') targets = self._get_list_prefix('Targets.member')
@ -254,6 +394,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DESCRIBE_TARGET_HEALTH_TEMPLATE) template = self.response_template(DESCRIBE_TARGET_HEALTH_TEMPLATE)
return template.render(target_health_descriptions=target_health_descriptions) return template.render(target_health_descriptions=target_health_descriptions)
@amzn_request_id
def set_rule_priorities(self): def set_rule_priorities(self):
rule_priorities = self._get_list_prefix('RulePriorities.member') rule_priorities = self._get_list_prefix('RulePriorities.member')
for rule_priority in rule_priorities: for rule_priority in rule_priorities:
@ -262,6 +403,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(SET_RULE_PRIORITIES_TEMPLATE) template = self.response_template(SET_RULE_PRIORITIES_TEMPLATE)
return template.render(rules=rules) return template.render(rules=rules)
@amzn_request_id
def add_tags(self): def add_tags(self):
resource_arns = self._get_multi_param('ResourceArns.member') resource_arns = self._get_multi_param('ResourceArns.member')
@ -281,6 +423,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(ADD_TAGS_TEMPLATE) template = self.response_template(ADD_TAGS_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def remove_tags(self): def remove_tags(self):
resource_arns = self._get_multi_param('ResourceArns.member') resource_arns = self._get_multi_param('ResourceArns.member')
tag_keys = self._get_multi_param('TagKeys.member') tag_keys = self._get_multi_param('TagKeys.member')
@ -301,6 +444,7 @@ class ELBV2Response(BaseResponse):
template = self.response_template(REMOVE_TAGS_TEMPLATE) template = self.response_template(REMOVE_TAGS_TEMPLATE)
return template.render() return template.render()
@amzn_request_id
def describe_tags(self): def describe_tags(self):
resource_arns = self._get_multi_param('ResourceArns.member') resource_arns = self._get_multi_param('ResourceArns.member')
resources = [] resources = []
@ -320,6 +464,125 @@ class ELBV2Response(BaseResponse):
template = self.response_template(DESCRIBE_TAGS_TEMPLATE) template = self.response_template(DESCRIBE_TAGS_TEMPLATE)
return template.render(resources=resources) return template.render(resources=resources)
@amzn_request_id
def describe_account_limits(self):
# Supports paging but not worth implementing yet
# marker = self._get_param('Marker')
# page_size = self._get_param('PageSize')
limits = {
'application-load-balancers': 20,
'target-groups': 3000,
'targets-per-application-load-balancer': 30,
'listeners-per-application-load-balancer': 50,
'rules-per-application-load-balancer': 100,
'network-load-balancers': 20,
'targets-per-network-load-balancer': 200,
'listeners-per-network-load-balancer': 50
}
template = self.response_template(DESCRIBE_LIMITS_TEMPLATE)
return template.render(limits=limits)
@amzn_request_id
def describe_ssl_policies(self):
names = self._get_multi_param('Names.member.')
# Supports paging but not worth implementing yet
# marker = self._get_param('Marker')
# page_size = self._get_param('PageSize')
policies = SSL_POLICIES
if names:
policies = filter(lambda policy: policy['name'] in names, policies)
template = self.response_template(DESCRIBE_SSL_POLICIES_TEMPLATE)
return template.render(policies=policies)
@amzn_request_id
def set_ip_address_type(self):
arn = self._get_param('LoadBalancerArn')
ip_type = self._get_param('IpAddressType')
self.elbv2_backend.set_ip_address_type(arn, ip_type)
template = self.response_template(SET_IP_ADDRESS_TYPE_TEMPLATE)
return template.render(ip_type=ip_type)
@amzn_request_id
def set_security_groups(self):
arn = self._get_param('LoadBalancerArn')
sec_groups = self._get_multi_param('SecurityGroups.member.')
self.elbv2_backend.set_security_groups(arn, sec_groups)
template = self.response_template(SET_SECURITY_GROUPS_TEMPLATE)
return template.render(sec_groups=sec_groups)
@amzn_request_id
def set_subnets(self):
arn = self._get_param('LoadBalancerArn')
subnets = self._get_multi_param('Subnets.member.')
subnet_zone_list = self.elbv2_backend.set_subnets(arn, subnets)
template = self.response_template(SET_SUBNETS_TEMPLATE)
return template.render(subnets=subnet_zone_list)
@amzn_request_id
def modify_load_balancer_attributes(self):
arn = self._get_param('LoadBalancerArn')
attrs = self._get_map_prefix('Attributes.member', key_end='Key', value_end='Value')
all_attrs = self.elbv2_backend.modify_load_balancer_attributes(arn, attrs)
template = self.response_template(MODIFY_LOADBALANCER_ATTRS_TEMPLATE)
return template.render(attrs=all_attrs)
@amzn_request_id
def describe_load_balancer_attributes(self):
arn = self._get_param('LoadBalancerArn')
attrs = self.elbv2_backend.describe_load_balancer_attributes(arn)
template = self.response_template(DESCRIBE_LOADBALANCER_ATTRS_TEMPLATE)
return template.render(attrs=attrs)
@amzn_request_id
def modify_target_group(self):
arn = self._get_param('TargetGroupArn')
health_check_proto = self._get_param('HealthCheckProtocol') # 'HTTP' | 'HTTPS' | 'TCP',
health_check_port = self._get_param('HealthCheckPort')
health_check_path = self._get_param('HealthCheckPath')
health_check_interval = self._get_param('HealthCheckIntervalSeconds')
health_check_timeout = self._get_param('HealthCheckTimeoutSeconds')
healthy_threshold_count = self._get_param('HealthyThresholdCount')
unhealthy_threshold_count = self._get_param('UnhealthyThresholdCount')
http_codes = self._get_param('Matcher.HttpCode')
target_group = self.elbv2_backend.modify_target_group(arn, health_check_proto, health_check_port, health_check_path, health_check_interval,
health_check_timeout, healthy_threshold_count, unhealthy_threshold_count, http_codes)
template = self.response_template(MODIFY_TARGET_GROUP_TEMPLATE)
return template.render(target_group=target_group)
@amzn_request_id
def modify_listener(self):
arn = self._get_param('ListenerArn')
port = self._get_param('Port')
protocol = self._get_param('Protocol')
ssl_policy = self._get_param('SslPolicy')
certificates = self._get_list_prefix('Certificates.member')
default_actions = self._get_list_prefix('DefaultActions.member')
# Should really move SSL Policies to models
if ssl_policy is not None and ssl_policy not in [item['name'] for item in SSL_POLICIES]:
raise RESTError('SSLPolicyNotFound', 'Policy {0} not found'.format(ssl_policy))
listener = self.elbv2_backend.modify_listener(arn, port, protocol, ssl_policy, certificates, default_actions)
template = self.response_template(MODIFY_LISTENER_TEMPLATE)
return template.render(listener=listener)
def _add_tags(self, resource): def _add_tags(self, resource):
tag_values = [] tag_values = []
tag_keys = [] tag_keys = []
@ -348,14 +611,14 @@ class ELBV2Response(BaseResponse):
ADD_TAGS_TEMPLATE = """<AddTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> ADD_TAGS_TEMPLATE = """<AddTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<AddTagsResult/> <AddTagsResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>360e81f7-1100-11e4-b6ed-0f30EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</AddTagsResponse>""" </AddTagsResponse>"""
REMOVE_TAGS_TEMPLATE = """<RemoveTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> REMOVE_TAGS_TEMPLATE = """<RemoveTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<RemoveTagsResult/> <RemoveTagsResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>360e81f7-1100-11e4-b6ed-0f30EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</RemoveTagsResponse>""" </RemoveTagsResponse>"""
@ -378,11 +641,10 @@ DESCRIBE_TAGS_TEMPLATE = """<DescribeTagsResponse xmlns="http://elasticloadbalan
</TagDescriptions> </TagDescriptions>
</DescribeTagsResult> </DescribeTagsResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>360e81f7-1100-11e4-b6ed-0f30EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeTagsResponse>""" </DescribeTagsResponse>"""
CREATE_LOAD_BALANCER_TEMPLATE = """<CreateLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> CREATE_LOAD_BALANCER_TEMPLATE = """<CreateLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<CreateLoadBalancerResult> <CreateLoadBalancerResult>
<LoadBalancers> <LoadBalancers>
@ -415,7 +677,7 @@ CREATE_LOAD_BALANCER_TEMPLATE = """<CreateLoadBalancerResponse xmlns="http://ela
</LoadBalancers> </LoadBalancers>
</CreateLoadBalancerResult> </CreateLoadBalancerResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>32d531b2-f2d0-11e5-9192-3fff33344cfa</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</CreateLoadBalancerResponse>""" </CreateLoadBalancerResponse>"""
@ -452,7 +714,7 @@ CREATE_RULE_TEMPLATE = """<CreateRuleResponse xmlns="http://elasticloadbalancing
</Rules> </Rules>
</CreateRuleResult> </CreateRuleResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>c5478c83-f397-11e5-bb98-57195a6eb84a</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</CreateRuleResponse>""" </CreateRuleResponse>"""
@ -479,7 +741,7 @@ CREATE_TARGET_GROUP_TEMPLATE = """<CreateTargetGroupResponse xmlns="http://elast
</TargetGroups> </TargetGroups>
</CreateTargetGroupResult> </CreateTargetGroupResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>b83fe90e-f2d5-11e5-b95d-3b2c1831fc26</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</CreateTargetGroupResponse>""" </CreateTargetGroupResponse>"""
@ -489,11 +751,13 @@ CREATE_LISTENER_TEMPLATE = """<CreateListenerResponse xmlns="http://elasticloadb
<member> <member>
<LoadBalancerArn>{{ listener.load_balancer_arn }}</LoadBalancerArn> <LoadBalancerArn>{{ listener.load_balancer_arn }}</LoadBalancerArn>
<Protocol>{{ listener.protocol }}</Protocol> <Protocol>{{ listener.protocol }}</Protocol>
{% if listener.certificate %} {% if listener.certificates %}
<Certificates> <Certificates>
{% for cert in listener.certificates %}
<member> <member>
<CertificateArn>{{ listener.certificate }}</CertificateArn> <CertificateArn>{{ cert }}</CertificateArn>
</member> </member>
{% endfor %}
</Certificates> </Certificates>
{% endif %} {% endif %}
<Port>{{ listener.port }}</Port> <Port>{{ listener.port }}</Port>
@ -511,35 +775,35 @@ CREATE_LISTENER_TEMPLATE = """<CreateListenerResponse xmlns="http://elasticloadb
</Listeners> </Listeners>
</CreateListenerResult> </CreateListenerResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>97f1bb38-f390-11e5-b95d-3b2c1831fc26</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</CreateListenerResponse>""" </CreateListenerResponse>"""
DELETE_LOAD_BALANCER_TEMPLATE = """<DeleteLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> DELETE_LOAD_BALANCER_TEMPLATE = """<DeleteLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DeleteLoadBalancerResult/> <DeleteLoadBalancerResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeleteLoadBalancerResponse>""" </DeleteLoadBalancerResponse>"""
DELETE_RULE_TEMPLATE = """<DeleteRuleResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> DELETE_RULE_TEMPLATE = """<DeleteRuleResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DeleteRuleResult/> <DeleteRuleResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeleteRuleResponse>""" </DeleteRuleResponse>"""
DELETE_TARGET_GROUP_TEMPLATE = """<DeleteTargetGroupResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> DELETE_TARGET_GROUP_TEMPLATE = """<DeleteTargetGroupResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DeleteTargetGroupResult/> <DeleteTargetGroupResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeleteTargetGroupResponse>""" </DeleteTargetGroupResponse>"""
DELETE_LISTENER_TEMPLATE = """<DeleteListenerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> DELETE_LISTENER_TEMPLATE = """<DeleteListenerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DeleteListenerResult/> <DeleteListenerResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeleteListenerResponse>""" </DeleteListenerResponse>"""
@ -580,7 +844,7 @@ DESCRIBE_LOAD_BALANCERS_TEMPLATE = """<DescribeLoadBalancersResponse xmlns="http
{% endif %} {% endif %}
</DescribeLoadBalancersResult> </DescribeLoadBalancersResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>f9880f01-7852-629d-a6c3-3ae2-666a409287e6dc0c</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeLoadBalancersResponse>""" </DescribeLoadBalancersResponse>"""
@ -620,7 +884,7 @@ DESCRIBE_RULES_TEMPLATE = """<DescribeRulesResponse xmlns="http://elasticloadbal
{% endif %} {% endif %}
</DescribeRulesResult> </DescribeRulesResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>74926cf3-f3a3-11e5-b543-9f2c3fbb9bee</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeRulesResponse>""" </DescribeRulesResponse>"""
@ -634,7 +898,7 @@ DESCRIBE_TARGET_GROUPS_TEMPLATE = """<DescribeTargetGroupsResponse xmlns="http:/
<Protocol>{{ target_group.protocol }}</Protocol> <Protocol>{{ target_group.protocol }}</Protocol>
<Port>{{ target_group.port }}</Port> <Port>{{ target_group.port }}</Port>
<VpcId>{{ target_group.vpc_id }}</VpcId> <VpcId>{{ target_group.vpc_id }}</VpcId>
<HealthCheckProtocol>{{ target_group.health_check_protocol }}</HealthCheckProtocol> <HealthCheckProtocol>{{ target_group.healthcheck_protocol }}</HealthCheckProtocol>
<HealthCheckPort>{{ target_group.healthcheck_port }}</HealthCheckPort> <HealthCheckPort>{{ target_group.healthcheck_port }}</HealthCheckPort>
<HealthCheckPath>{{ target_group.healthcheck_path }}</HealthCheckPath> <HealthCheckPath>{{ target_group.healthcheck_path }}</HealthCheckPath>
<HealthCheckIntervalSeconds>{{ target_group.healthcheck_interval_seconds }}</HealthCheckIntervalSeconds> <HealthCheckIntervalSeconds>{{ target_group.healthcheck_interval_seconds }}</HealthCheckIntervalSeconds>
@ -642,7 +906,7 @@ DESCRIBE_TARGET_GROUPS_TEMPLATE = """<DescribeTargetGroupsResponse xmlns="http:/
<HealthyThresholdCount>{{ target_group.healthy_threshold_count }}</HealthyThresholdCount> <HealthyThresholdCount>{{ target_group.healthy_threshold_count }}</HealthyThresholdCount>
<UnhealthyThresholdCount>{{ target_group.unhealthy_threshold_count }}</UnhealthyThresholdCount> <UnhealthyThresholdCount>{{ target_group.unhealthy_threshold_count }}</UnhealthyThresholdCount>
<Matcher> <Matcher>
<HttpCode>200</HttpCode> <HttpCode>{{ target_group.http_status_codes }}</HttpCode>
</Matcher> </Matcher>
<LoadBalancerArns> <LoadBalancerArns>
{% for load_balancer_arn in target_group.load_balancer_arns %} {% for load_balancer_arn in target_group.load_balancer_arns %}
@ -654,11 +918,10 @@ DESCRIBE_TARGET_GROUPS_TEMPLATE = """<DescribeTargetGroupsResponse xmlns="http:/
</TargetGroups> </TargetGroups>
</DescribeTargetGroupsResult> </DescribeTargetGroupsResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>70092c0e-f3a9-11e5-ae48-cff02092876b</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeTargetGroupsResponse>""" </DescribeTargetGroupsResponse>"""
DESCRIBE_TARGET_GROUP_ATTRIBUTES_TEMPLATE = """<DescribeTargetGroupAttributesResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> DESCRIBE_TARGET_GROUP_ATTRIBUTES_TEMPLATE = """<DescribeTargetGroupAttributesResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DescribeTargetGroupAttributesResult> <DescribeTargetGroupAttributesResult>
<Attributes> <Attributes>
@ -671,11 +934,10 @@ DESCRIBE_TARGET_GROUP_ATTRIBUTES_TEMPLATE = """<DescribeTargetGroupAttributesRes
</Attributes> </Attributes>
</DescribeTargetGroupAttributesResult> </DescribeTargetGroupAttributesResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>70092c0e-f3a9-11e5-ae48-cff02092876b</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeTargetGroupAttributesResponse>""" </DescribeTargetGroupAttributesResponse>"""
DESCRIBE_LISTENERS_TEMPLATE = """<DescribeLoadBalancersResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> DESCRIBE_LISTENERS_TEMPLATE = """<DescribeLoadBalancersResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DescribeListenersResult> <DescribeListenersResult>
<Listeners> <Listeners>
@ -706,7 +968,7 @@ DESCRIBE_LISTENERS_TEMPLATE = """<DescribeLoadBalancersResponse xmlns="http://el
</Listeners> </Listeners>
</DescribeListenersResult> </DescribeListenersResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>65a3a7ea-f39c-11e5-b543-9f2c3fbb9bee</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeLoadBalancersResponse>""" </DescribeLoadBalancersResponse>"""
@ -721,7 +983,7 @@ CONFIGURE_HEALTH_CHECK_TEMPLATE = """<ConfigureHealthCheckResponse xmlns="http:/
</HealthCheck> </HealthCheck>
</ConfigureHealthCheckResult> </ConfigureHealthCheckResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>f9880f01-7852-629d-a6c3-3ae2-666a409287e6dc0c</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</ConfigureHealthCheckResponse>""" </ConfigureHealthCheckResponse>"""
@ -758,7 +1020,7 @@ MODIFY_RULE_TEMPLATE = """<ModifyRuleResponse xmlns="http://elasticloadbalancing
</Rules> </Rules>
</ModifyRuleResult> </ModifyRuleResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>c5478c83-f397-11e5-bb98-57195a6eb84a</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</ModifyRuleResponse>""" </ModifyRuleResponse>"""
@ -774,7 +1036,7 @@ MODIFY_TARGET_GROUP_ATTRIBUTES_TEMPLATE = """<ModifyTargetGroupAttributesRespons
</Attributes> </Attributes>
</ModifyTargetGroupAttributesResult> </ModifyTargetGroupAttributesResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>70092c0e-f3a9-11e5-ae48-cff02092876b</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</ModifyTargetGroupAttributesResponse>""" </ModifyTargetGroupAttributesResponse>"""
@ -782,7 +1044,7 @@ REGISTER_TARGETS_TEMPLATE = """<RegisterTargetsResponse xmlns="http://elasticloa
<RegisterTargetsResult> <RegisterTargetsResult>
</RegisterTargetsResult> </RegisterTargetsResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>f9880f01-7852-629d-a6c3-3ae2-666a409287e6dc0c</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</RegisterTargetsResponse>""" </RegisterTargetsResponse>"""
@ -790,22 +1052,21 @@ DEREGISTER_TARGETS_TEMPLATE = """<DeregisterTargetsResponse xmlns="http://elasti
<DeregisterTargetsResult> <DeregisterTargetsResult>
</DeregisterTargetsResult> </DeregisterTargetsResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>f9880f01-7852-629d-a6c3-3ae2-666a409287e6dc0c</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeregisterTargetsResponse>""" </DeregisterTargetsResponse>"""
SET_LOAD_BALANCER_SSL_CERTIFICATE = """<SetLoadBalancerListenerSSLCertificateResponse xmlns="http://elasticloadbalan cing.amazonaws.com/doc/2015-12-01/"> SET_LOAD_BALANCER_SSL_CERTIFICATE = """<SetLoadBalancerListenerSSLCertificateResponse xmlns="http://elasticloadbalan cing.amazonaws.com/doc/2015-12-01/">
<SetLoadBalancerListenerSSLCertificateResult/> <SetLoadBalancerListenerSSLCertificateResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</SetLoadBalancerListenerSSLCertificateResponse>""" </SetLoadBalancerListenerSSLCertificateResponse>"""
DELETE_LOAD_BALANCER_LISTENERS = """<DeleteLoadBalancerListenersResponse xmlns="http://elasticloadbalan cing.amazonaws.com/doc/2015-12-01/"> DELETE_LOAD_BALANCER_LISTENERS = """<DeleteLoadBalancerListenersResponse xmlns="http://elasticloadbalan cing.amazonaws.com/doc/2015-12-01/">
<DeleteLoadBalancerListenersResult/> <DeleteLoadBalancerListenersResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeleteLoadBalancerListenersResponse>""" </DeleteLoadBalancerListenersResponse>"""
@ -837,7 +1098,7 @@ DESCRIBE_ATTRIBUTES_TEMPLATE = """<DescribeLoadBalancerAttributesResponse xmlns
</LoadBalancerAttributes> </LoadBalancerAttributes>
</DescribeLoadBalancerAttributesResult> </DescribeLoadBalancerAttributesResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeLoadBalancerAttributesResponse> </DescribeLoadBalancerAttributesResponse>
""" """
@ -871,7 +1132,7 @@ MODIFY_ATTRIBUTES_TEMPLATE = """<ModifyLoadBalancerAttributesResponse xmlns="htt
</LoadBalancerAttributes> </LoadBalancerAttributes>
</ModifyLoadBalancerAttributesResult> </ModifyLoadBalancerAttributesResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</ModifyLoadBalancerAttributesResponse> </ModifyLoadBalancerAttributesResponse>
""" """
@ -879,7 +1140,7 @@ MODIFY_ATTRIBUTES_TEMPLATE = """<ModifyLoadBalancerAttributesResponse xmlns="htt
CREATE_LOAD_BALANCER_POLICY_TEMPLATE = """<CreateLoadBalancerPolicyResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> CREATE_LOAD_BALANCER_POLICY_TEMPLATE = """<CreateLoadBalancerPolicyResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<CreateLoadBalancerPolicyResult/> <CreateLoadBalancerPolicyResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</CreateLoadBalancerPolicyResponse> </CreateLoadBalancerPolicyResponse>
""" """
@ -887,7 +1148,7 @@ CREATE_LOAD_BALANCER_POLICY_TEMPLATE = """<CreateLoadBalancerPolicyResponse xmln
SET_LOAD_BALANCER_POLICIES_OF_LISTENER_TEMPLATE = """<SetLoadBalancerPoliciesOfListenerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> SET_LOAD_BALANCER_POLICIES_OF_LISTENER_TEMPLATE = """<SetLoadBalancerPoliciesOfListenerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<SetLoadBalancerPoliciesOfListenerResult/> <SetLoadBalancerPoliciesOfListenerResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>07b1ecbc-1100-11e3-acaf-dd7edEXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</SetLoadBalancerPoliciesOfListenerResponse> </SetLoadBalancerPoliciesOfListenerResponse>
""" """
@ -895,7 +1156,7 @@ SET_LOAD_BALANCER_POLICIES_OF_LISTENER_TEMPLATE = """<SetLoadBalancerPoliciesOfL
SET_LOAD_BALANCER_POLICIES_FOR_BACKEND_SERVER_TEMPLATE = """<SetLoadBalancerPoliciesForBackendServerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/"> SET_LOAD_BALANCER_POLICIES_FOR_BACKEND_SERVER_TEMPLATE = """<SetLoadBalancerPoliciesForBackendServerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<SetLoadBalancerPoliciesForBackendServerResult/> <SetLoadBalancerPoliciesForBackendServerResult/>
<ResponseMetadata> <ResponseMetadata>
<RequestId>0eb9b381-dde0-11e2-8d78-6ddbaEXAMPLE</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</SetLoadBalancerPoliciesForBackendServerResponse> </SetLoadBalancerPoliciesForBackendServerResponse>
""" """
@ -918,7 +1179,7 @@ DESCRIBE_TARGET_HEALTH_TEMPLATE = """<DescribeTargetHealthResponse xmlns="http:/
</TargetHealthDescriptions> </TargetHealthDescriptions>
</DescribeTargetHealthResult> </DescribeTargetHealthResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>c534f810-f389-11e5-9192-3fff33344cfa</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DescribeTargetHealthResponse>""" </DescribeTargetHealthResponse>"""
@ -955,6 +1216,186 @@ SET_RULE_PRIORITIES_TEMPLATE = """<SetRulePrioritiesResponse xmlns="http://elast
</Rules> </Rules>
</SetRulePrioritiesResult> </SetRulePrioritiesResult>
<ResponseMetadata> <ResponseMetadata>
<RequestId>4d7a8036-f3a7-11e5-9c02-8fd20490d5a6</RequestId> <RequestId>{{ request_id }}</RequestId>
</ResponseMetadata> </ResponseMetadata>
</SetRulePrioritiesResponse>""" </SetRulePrioritiesResponse>"""
DESCRIBE_LIMITS_TEMPLATE = """<DescribeAccountLimitsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DescribeAccountLimitsResult>
<Limits>
{% for key, value in limits.items() %}
<member>
<Name>{{ key }}</Name>
<Max>{{ value }}</Max>
</member>
{% endfor %}
</Limits>
</DescribeAccountLimitsResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</DescribeAccountLimitsResponse>"""
DESCRIBE_SSL_POLICIES_TEMPLATE = """<DescribeSSLPoliciesResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DescribeSSLPoliciesResult>
<SslPolicies>
{% for policy in policies %}
<member>
<Name>{{ policy['name'] }}</Name>
<Ciphers>
{% for cipher in policy['ciphers'] %}
<member>
<Name>{{ cipher['name'] }}</Name>
<Priority>{{ cipher['priority'] }}</Priority>
</member>
{% endfor %}
</Ciphers>
<SslProtocols>
{% for proto in policy['ssl_protocols'] %}
<member>{{ proto }}</member>
{% endfor %}
</SslProtocols>
</member>
{% endfor %}
</SslPolicies>
</DescribeSSLPoliciesResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</DescribeSSLPoliciesResponse>"""
SET_IP_ADDRESS_TYPE_TEMPLATE = """<SetIpAddressTypeResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<SetIpAddressTypeResult>
<IpAddressType>{{ ip_type }}</IpAddressType>
</SetIpAddressTypeResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</SetIpAddressTypeResponse>"""
SET_SECURITY_GROUPS_TEMPLATE = """<SetSecurityGroupsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<SetSecurityGroupsResult>
<SecurityGroupIds>
{% for group in sec_groups %}
<member>{{ group }}</member>
{% endfor %}
</SecurityGroupIds>
</SetSecurityGroupsResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</SetSecurityGroupsResponse>"""
SET_SUBNETS_TEMPLATE = """<SetSubnetsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<SetSubnetsResult>
<AvailabilityZones>
{% for zone_id, subnet_id in subnets %}
<member>
<SubnetId>{{ subnet_id }}</SubnetId>
<ZoneName>{{ zone_id }}</ZoneName>
</member>
{% endfor %}
</AvailabilityZones>
</SetSubnetsResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</SetSubnetsResponse>"""
MODIFY_LOADBALANCER_ATTRS_TEMPLATE = """<ModifyLoadBalancerAttributesResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<ModifyLoadBalancerAttributesResult>
<Attributes>
{% for key, value in attrs.items() %}
<member>
{% if value == None %}<Value />{% else %}<Value>{{ value }}</Value>{% endif %}
<Key>{{ key }}</Key>
</member>
{% endfor %}
</Attributes>
</ModifyLoadBalancerAttributesResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</ModifyLoadBalancerAttributesResponse>"""
DESCRIBE_LOADBALANCER_ATTRS_TEMPLATE = """<DescribeLoadBalancerAttributesResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<DescribeLoadBalancerAttributesResult>
<Attributes>
{% for key, value in attrs.items() %}
<member>
{% if value == None %}<Value />{% else %}<Value>{{ value }}</Value>{% endif %}
<Key>{{ key }}</Key>
</member>
{% endfor %}
</Attributes>
</DescribeLoadBalancerAttributesResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</DescribeLoadBalancerAttributesResponse>"""
MODIFY_TARGET_GROUP_TEMPLATE = """<ModifyTargetGroupResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<ModifyTargetGroupResult>
<TargetGroups>
<member>
<TargetGroupArn>{{ target_group.arn }}</TargetGroupArn>
<TargetGroupName>{{ target_group.name }}</TargetGroupName>
<Protocol>{{ target_group.protocol }}</Protocol>
<Port>{{ target_group.port }}</Port>
<VpcId>{{ target_group.vpc_id }}</VpcId>
<HealthCheckProtocol>{{ target_group.healthcheck_protocol }}</HealthCheckProtocol>
<HealthCheckPort>{{ target_group.healthcheck_port }}</HealthCheckPort>
<HealthCheckPath>{{ target_group.healthcheck_path }}</HealthCheckPath>
<HealthCheckIntervalSeconds>{{ target_group.healthcheck_interval_seconds }}</HealthCheckIntervalSeconds>
<HealthCheckTimeoutSeconds>{{ target_group.healthcheck_timeout_seconds }}</HealthCheckTimeoutSeconds>
<HealthyThresholdCount>{{ target_group.healthy_threshold_count }}</HealthyThresholdCount>
<UnhealthyThresholdCount>{{ target_group.unhealthy_threshold_count }}</UnhealthyThresholdCount>
<Matcher>
<HttpCode>{{ target_group.http_status_codes }}</HttpCode>
</Matcher>
<LoadBalancerArns>
{% for load_balancer_arn in target_group.load_balancer_arns %}
<member>{{ load_balancer_arn }}</member>
{% endfor %}
</LoadBalancerArns>
</member>
</TargetGroups>
</ModifyTargetGroupResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</ModifyTargetGroupResponse>"""
MODIFY_LISTENER_TEMPLATE = """<ModifyListenerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
<ModifyListenerResult>
<Listeners>
<member>
<LoadBalancerArn>{{ listener.load_balancer_arn }}</LoadBalancerArn>
<Protocol>{{ listener.protocol }}</Protocol>
{% if listener.certificates %}
<Certificates>
{% for cert in listener.certificates %}
<member>
<CertificateArn>{{ cert }}</CertificateArn>
</member>
{% endfor %}
</Certificates>
{% endif %}
<Port>{{ listener.port }}</Port>
<SslPolicy>{{ listener.ssl_policy }}</SslPolicy>
<ListenerArn>{{ listener.arn }}</ListenerArn>
<DefaultActions>
{% for action in listener.default_actions %}
<member>
<Type>{{ action.type }}</Type>
<TargetGroupArn>{{ action.target_group_arn }}</TargetGroupArn>
</member>
{% endfor %}
</DefaultActions>
</member>
</Listeners>
</ModifyListenerResult>
<ResponseMetadata>
<RequestId>{{ request_id }}</RequestId>
</ResponseMetadata>
</ModifyListenerResponse>"""

View File

@ -5,7 +5,8 @@ from botocore.exceptions import ClientError
from nose.tools import assert_raises from nose.tools import assert_raises
import sure # noqa import sure # noqa
from moto import mock_elbv2, mock_ec2 from moto import mock_elbv2, mock_ec2, mock_acm
from moto.elbv2 import elbv2_backends
@mock_elbv2 @mock_elbv2
@ -1030,3 +1031,372 @@ def test_describe_invalid_target_group():
# Check error raises correctly # Check error raises correctly
with assert_raises(ClientError): with assert_raises(ClientError):
conn.describe_target_groups(Names=['invalid']) conn.describe_target_groups(Names=['invalid'])
@mock_elbv2
def test_describe_account_limits():
client = boto3.client('elbv2', region_name='eu-central-1')
resp = client.describe_account_limits()
resp['Limits'][0].should.contain('Name')
resp['Limits'][0].should.contain('Max')
@mock_elbv2
def test_describe_ssl_policies():
client = boto3.client('elbv2', region_name='eu-central-1')
resp = client.describe_ssl_policies()
len(resp['SslPolicies']).should.equal(5)
resp = client.describe_ssl_policies(Names=['ELBSecurityPolicy-TLS-1-2-2017-01', 'ELBSecurityPolicy-2016-08'])
len(resp['SslPolicies']).should.equal(2)
@mock_elbv2
@mock_ec2
def test_set_ip_address_type():
client = boto3.client('elbv2', region_name='us-east-1')
ec2 = boto3.resource('ec2', region_name='us-east-1')
security_group = ec2.create_security_group(
GroupName='a-security-group', Description='First One')
vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default')
subnet1 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1a')
subnet2 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1b')
response = client.create_load_balancer(
Name='my-lb',
Subnets=[subnet1.id, subnet2.id],
SecurityGroups=[security_group.id],
Scheme='internal',
Tags=[{'Key': 'key_name', 'Value': 'a_value'}])
arn = response['LoadBalancers'][0]['LoadBalancerArn']
# Internal LBs cant be dualstack yet
with assert_raises(ClientError):
client.set_ip_address_type(
LoadBalancerArn=arn,
IpAddressType='dualstack'
)
# Create internet facing one
response = client.create_load_balancer(
Name='my-lb2',
Subnets=[subnet1.id, subnet2.id],
SecurityGroups=[security_group.id],
Scheme='internet-facing',
Tags=[{'Key': 'key_name', 'Value': 'a_value'}])
arn = response['LoadBalancers'][0]['LoadBalancerArn']
client.set_ip_address_type(
LoadBalancerArn=arn,
IpAddressType='dualstack'
)
@mock_elbv2
@mock_ec2
def test_set_security_groups():
client = boto3.client('elbv2', region_name='us-east-1')
ec2 = boto3.resource('ec2', region_name='us-east-1')
security_group = ec2.create_security_group(
GroupName='a-security-group', Description='First One')
security_group2 = ec2.create_security_group(
GroupName='b-security-group', Description='Second One')
vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default')
subnet1 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1a')
subnet2 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1b')
response = client.create_load_balancer(
Name='my-lb',
Subnets=[subnet1.id, subnet2.id],
SecurityGroups=[security_group.id],
Scheme='internal',
Tags=[{'Key': 'key_name', 'Value': 'a_value'}])
arn = response['LoadBalancers'][0]['LoadBalancerArn']
client.set_security_groups(
LoadBalancerArn=arn,
SecurityGroups=[security_group.id, security_group2.id]
)
resp = client.describe_load_balancers(LoadBalancerArns=[arn])
len(resp['LoadBalancers'][0]['SecurityGroups']).should.equal(2)
with assert_raises(ClientError):
client.set_security_groups(
LoadBalancerArn=arn,
SecurityGroups=['non_existant']
)
@mock_elbv2
@mock_ec2
def test_set_subnets():
client = boto3.client('elbv2', region_name='us-east-1')
ec2 = boto3.resource('ec2', region_name='us-east-1')
security_group = ec2.create_security_group(
GroupName='a-security-group', Description='First One')
vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default')
subnet1 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1a')
subnet2 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1b')
subnet3 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1c')
response = client.create_load_balancer(
Name='my-lb',
Subnets=[subnet1.id, subnet2.id],
SecurityGroups=[security_group.id],
Scheme='internal',
Tags=[{'Key': 'key_name', 'Value': 'a_value'}])
arn = response['LoadBalancers'][0]['LoadBalancerArn']
client.set_subnets(
LoadBalancerArn=arn,
Subnets=[subnet1.id, subnet2.id, subnet3.id]
)
resp = client.describe_load_balancers(LoadBalancerArns=[arn])
len(resp['LoadBalancers'][0]['AvailabilityZones']).should.equal(3)
# Only 1 AZ
with assert_raises(ClientError):
client.set_subnets(
LoadBalancerArn=arn,
Subnets=[subnet1.id]
)
# Multiple subnets in same AZ
with assert_raises(ClientError):
client.set_subnets(
LoadBalancerArn=arn,
Subnets=[subnet1.id, subnet2.id, subnet2.id]
)
@mock_elbv2
@mock_ec2
def test_set_subnets():
client = boto3.client('elbv2', region_name='us-east-1')
ec2 = boto3.resource('ec2', region_name='us-east-1')
security_group = ec2.create_security_group(
GroupName='a-security-group', Description='First One')
vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default')
subnet1 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1a')
subnet2 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='us-east-1b')
response = client.create_load_balancer(
Name='my-lb',
Subnets=[subnet1.id, subnet2.id],
SecurityGroups=[security_group.id],
Scheme='internal',
Tags=[{'Key': 'key_name', 'Value': 'a_value'}])
arn = response['LoadBalancers'][0]['LoadBalancerArn']
client.modify_load_balancer_attributes(
LoadBalancerArn=arn,
Attributes=[{'Key': 'idle_timeout.timeout_seconds', 'Value': '600'}]
)
# Check its 600 not 60
response = client.describe_load_balancer_attributes(
LoadBalancerArn=arn
)
idle_timeout = list(filter(lambda item: item['Key'] == 'idle_timeout.timeout_seconds', response['Attributes']))[0]
idle_timeout['Value'].should.equal('600')
@mock_elbv2
@mock_ec2
def test_modify_target_group():
client = boto3.client('elbv2', region_name='us-east-1')
ec2 = boto3.resource('ec2', region_name='us-east-1')
vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default')
response = client.create_target_group(
Name='a-target',
Protocol='HTTP',
Port=8080,
VpcId=vpc.id,
HealthCheckProtocol='HTTP',
HealthCheckPort='8080',
HealthCheckPath='/',
HealthCheckIntervalSeconds=5,
HealthCheckTimeoutSeconds=5,
HealthyThresholdCount=5,
UnhealthyThresholdCount=2,
Matcher={'HttpCode': '200'})
arn = response.get('TargetGroups')[0]['TargetGroupArn']
client.modify_target_group(
TargetGroupArn=arn,
HealthCheckProtocol='HTTPS',
HealthCheckPort='8081',
HealthCheckPath='/status',
HealthCheckIntervalSeconds=10,
HealthCheckTimeoutSeconds=10,
HealthyThresholdCount=10,
UnhealthyThresholdCount=4,
Matcher={'HttpCode': '200-399'}
)
response = client.describe_target_groups(
TargetGroupArns=[arn]
)
response['TargetGroups'][0]['Matcher']['HttpCode'].should.equal('200-399')
response['TargetGroups'][0]['HealthCheckIntervalSeconds'].should.equal(10)
response['TargetGroups'][0]['HealthCheckPath'].should.equal('/status')
response['TargetGroups'][0]['HealthCheckPort'].should.equal('8081')
response['TargetGroups'][0]['HealthCheckProtocol'].should.equal('HTTPS')
response['TargetGroups'][0]['HealthCheckTimeoutSeconds'].should.equal(10)
response['TargetGroups'][0]['HealthyThresholdCount'].should.equal(10)
response['TargetGroups'][0]['UnhealthyThresholdCount'].should.equal(4)
@mock_elbv2
@mock_ec2
@mock_acm
def test_modify_listener_http_to_https():
client = boto3.client('elbv2', region_name='eu-central-1')
acm = boto3.client('acm', region_name='eu-central-1')
ec2 = boto3.resource('ec2', region_name='eu-central-1')
security_group = ec2.create_security_group(
GroupName='a-security-group', Description='First One')
vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default')
subnet1 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='eu-central-1a')
subnet2 = ec2.create_subnet(
VpcId=vpc.id,
CidrBlock='172.28.7.192/26',
AvailabilityZone='eu-central-1b')
response = client.create_load_balancer(
Name='my-lb',
Subnets=[subnet1.id, subnet2.id],
SecurityGroups=[security_group.id],
Scheme='internal',
Tags=[{'Key': 'key_name', 'Value': 'a_value'}])
load_balancer_arn = response.get('LoadBalancers')[0].get('LoadBalancerArn')
response = client.create_target_group(
Name='a-target',
Protocol='HTTP',
Port=8080,
VpcId=vpc.id,
HealthCheckProtocol='HTTP',
HealthCheckPort='8080',
HealthCheckPath='/',
HealthCheckIntervalSeconds=5,
HealthCheckTimeoutSeconds=5,
HealthyThresholdCount=5,
UnhealthyThresholdCount=2,
Matcher={'HttpCode': '200'})
target_group = response.get('TargetGroups')[0]
target_group_arn = target_group['TargetGroupArn']
# Plain HTTP listener
response = client.create_listener(
LoadBalancerArn=load_balancer_arn,
Protocol='HTTP',
Port=80,
DefaultActions=[{'Type': 'forward', 'TargetGroupArn': target_group_arn}]
)
listener_arn = response['Listeners'][0]['ListenerArn']
response = acm.request_certificate(
DomainName='google.com',
SubjectAlternativeNames=['google.com', 'www.google.com', 'mail.google.com'],
)
google_arn = response['CertificateArn']
response = acm.request_certificate(
DomainName='yahoo.com',
SubjectAlternativeNames=['yahoo.com', 'www.yahoo.com', 'mail.yahoo.com'],
)
yahoo_arn = response['CertificateArn']
response = client.modify_listener(
ListenerArn=listener_arn,
Port=443,
Protocol='HTTPS',
SslPolicy='ELBSecurityPolicy-TLS-1-2-2017-01',
Certificates=[
{'CertificateArn': google_arn, 'IsDefault': False},
{'CertificateArn': yahoo_arn, 'IsDefault': True}
],
DefaultActions=[
{'Type': 'forward', 'TargetGroupArn': target_group_arn}
]
)
response['Listeners'][0]['Port'].should.equal(443)
response['Listeners'][0]['Protocol'].should.equal('HTTPS')
response['Listeners'][0]['SslPolicy'].should.equal('ELBSecurityPolicy-TLS-1-2-2017-01')
len(response['Listeners'][0]['Certificates']).should.equal(2)
# Check default cert
listener = elbv2_backends['eu-central-1'].load_balancers[load_balancer_arn].listeners[listener_arn]
listener.certificate.should.equal(yahoo_arn)
# No default cert
with assert_raises(ClientError):
client.modify_listener(
ListenerArn=listener_arn,
Port=443,
Protocol='HTTPS',
SslPolicy='ELBSecurityPolicy-TLS-1-2-2017-01',
Certificates=[
{'CertificateArn': google_arn, 'IsDefault': False}
],
DefaultActions=[
{'Type': 'forward', 'TargetGroupArn': target_group_arn}
]
)
# Bad cert
with assert_raises(ClientError):
client.modify_listener(
ListenerArn=listener_arn,
Port=443,
Protocol='HTTPS',
SslPolicy='ELBSecurityPolicy-TLS-1-2-2017-01',
Certificates=[
{'CertificateArn': 'lalala', 'IsDefault': True}
],
DefaultActions=[
{'Type': 'forward', 'TargetGroupArn': target_group_arn}
]
)