implement mocking for lb policies

This commit is contained in:
Andrew Harris 2015-07-14 23:54:58 +00:00
parent 7f2abc41a5
commit bbb021d06d
3 changed files with 340 additions and 9 deletions

View File

@ -8,6 +8,12 @@ from boto.ec2.elb.attributes import (
AccessLogAttribute,
CrossZoneLoadBalancingAttribute,
)
from boto.ec2.elb.policies import (
Policies,
AppCookieStickinessPolicy,
LBCookieStickinessPolicy,
OtherPolicy,
)
from moto.core import BaseBackend
@ -27,6 +33,19 @@ class FakeListener(object):
self.instance_port = instance_port
self.protocol = protocol.upper()
self.ssl_certificate_id = ssl_certificate_id
self.policy_names = []
def __repr__(self):
return "FakeListener(lbp: %s, inp: %s, pro: %s, cid: %s, policies: %s)" % (self.load_balancer_port, self.instance_port, self.protocol, self.ssl_certificate_id, self.policy_names)
class FakeBackend(object):
def __init__(self, instance_port):
self.instance_port = instance_port
self.policy_names = []
def __repr__(self):
return "FakeBackend(inp: %s, policies: %s)" % (self.instance_port, self.policy_names)
class FakeLoadBalancer(object):
@ -36,7 +55,12 @@ class FakeLoadBalancer(object):
self.instance_ids = []
self.zones = zones
self.listeners = []
self.backends = []
self.attributes = FakeLoadBalancer.get_default_attributes()
self.policies = Policies()
self.policies.other_policies = []
self.policies.app_cookie_stickiness_policies = []
self.policies.lb_cookie_stickiness_policies = []
for protocol, lb_port, instance_port, ssl_certificate_id in ports:
listener = FakeListener(
@ -46,6 +70,13 @@ class FakeLoadBalancer(object):
ssl_certificate_id=ssl_certificate_id
)
self.listeners.append(listener)
# it is unclear per the AWS documentation as to when or how backend
# information gets set, so let's guess and set it here *shrug*
backend = FakeBackend(
instance_port = instance_port,
)
self.backends.append(backend)
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
@ -103,7 +134,6 @@ class FakeLoadBalancer(object):
return attributes
class ELBBackend(BaseBackend):
def __init__(self):
@ -201,6 +231,37 @@ class ELBBackend(BaseBackend):
load_balancer.attributes.connecting_settings = attribute
return load_balancer
def create_lb_other_policy(self, load_balancer_name, other_policy):
load_balancer = self.get_load_balancer(load_balancer_name)
load_balancer.policies.other_policies.append(other_policy)
return load_balancer
def create_app_cookie_stickiness_policy(self, load_balancer_name, policy):
load_balancer = self.get_load_balancer(load_balancer_name)
load_balancer.policies.app_cookie_stickiness_policies.append(policy)
return load_balancer
def create_lb_cookie_stickiness_policy(self, load_balancer_name, policy):
load_balancer = self.get_load_balancer(load_balancer_name)
load_balancer.policies.lb_cookie_stickiness_policies.append(policy)
return load_balancer
def set_load_balancer_policies_of_backend_server(self, load_balancer_name, instance_port, policies):
load_balancer = self.get_load_balancer(load_balancer_name)
backend = [b for b in load_balancer.backends if int(b.instance_port) == instance_port][0]
backend_idx = load_balancer.backends.index(backend)
backend.policy_names = policies
load_balancer.backends[backend_idx] = backend
return load_balancer
def set_load_balancer_policies_of_listener(self, load_balancer_name, load_balancer_port, policies):
load_balancer = self.get_load_balancer(load_balancer_name)
listener = [l for l in load_balancer.listeners if int(l.load_balancer_port) == load_balancer_port][0]
listener_idx = load_balancer.listeners.index(listener)
listener.policy_names = policies
load_balancer.listeners[listener_idx] = listener
return load_balancer
elb_backends = {}
for region in boto.ec2.elb.regions():

View File

@ -5,6 +5,12 @@ from boto.ec2.elb.attributes import (
AccessLogAttribute,
CrossZoneLoadBalancingAttribute,
)
from boto.ec2.elb.policies import (
Policies,
AppCookieStickinessPolicy,
LBCookieStickinessPolicy,
OtherPolicy,
)
from moto.core.responses import BaseResponse
from .models import elb_backends
@ -177,6 +183,101 @@ class ELBResponse(BaseResponse):
template = self.response_template(MODIFY_ATTRIBUTES_TEMPLATE)
return template.render(attributes=load_balancer.attributes)
def create_load_balancer_policy(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
load_balancer = self.elb_backend.describe_load_balancers(load_balancer_name)[0]
other_policy = OtherPolicy()
policy_name = [value[0] for key, value in self.querystring.items() if "PolicyName" in key][0]
other_policy.policy_name = policy_name
self.elb_backend.create_lb_other_policy(load_balancer_name, other_policy)
template = self.response_template(CREATE_LOAD_BALANCER_POLICY_TEMPLATE)
return template.render()
def create_app_cookie_stickiness_policy(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
load_balancer = self.elb_backend.describe_load_balancers(load_balancer_name)[0]
policy = AppCookieStickinessPolicy()
policy_name = [value[0] for key, value in self.querystring.items() if "PolicyName" in key][0]
policy.policy_name = policy_name
cookie_name = [value[0] for key, value in self.querystring.items() if "CookieName" in key][0]
policy.cookie_name = cookie_name
self.elb_backend.create_app_cookie_stickiness_policy(load_balancer_name, policy)
template = self.response_template(CREATE_LOAD_BALANCER_POLICY_TEMPLATE)
return template.render()
def create_lbcookie_stickiness_policy(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
load_balancer = self.elb_backend.describe_load_balancers(load_balancer_name)[0]
policy = AppCookieStickinessPolicy()
policy_name = [value[0] for key, value in self.querystring.items() if "PolicyName" in key][0]
policy.policy_name = policy_name
cookie_expirations = [value[0] for key, value in self.querystring.items() if "CookieExpirationPeriod" in key]
if cookie_expirations:
policy.cookie_expiration_period = long(cookie_expirations[0])
else:
policy.cookie_expiration_period = None
self.elb_backend.create_lb_cookie_stickiness_policy(load_balancer_name, policy)
template = self.response_template(CREATE_LOAD_BALANCER_POLICY_TEMPLATE)
return template.render()
def set_load_balancer_policies_of_listener(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
load_balancer = self.elb_backend.describe_load_balancers(load_balancer_name)[0]
load_balancer_port = int(self.querystring.get('LoadBalancerPort')[0])
mb_listener = [l for l in load_balancer.listeners if int(l.load_balancer_port) == load_balancer_port]
if mb_listener:
policies = []
policy_index = 1
while True:
try:
policy = self.querystring['PolicyNames.member.{0}'.format(policy_index)][0]
except KeyError:
break
policy_index += 1
policies.append(str(policy))
self.elb_backend.set_load_balancer_policies_of_listener(load_balancer_name, load_balancer_port, policies)
# else: explode?
template = self.response_template(SET_LOAD_BALANCER_POLICIES_OF_LISTENER_TEMPLATE)
return template.render()
def set_load_balancer_policies_for_backend_server(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
load_balancer = self.elb_backend.describe_load_balancers(load_balancer_name)[0]
instance_port = int(self.querystring.get('InstancePort')[0])
mb_backend = [b for b in load_balancer.backends if int(b.instance_port) == instance_port]
if mb_backend:
policies = []
policy_index = 1
while True:
try:
policy = self.querystring['PolicyNames.member.{0}'.format(policy_index)][0]
except KeyError:
break
policy_index += 1
policies.append(str(policy))
self.elb_backend.set_load_balancer_policies_of_backend_server(load_balancer_name, instance_port, policies)
# else: explode?
template = self.response_template(SET_LOAD_BALANCER_POLICIES_FOR_BACKEND_SERVER_TEMPLATE)
return template.render()
def describe_instance_health(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
instance_ids = [value[0] for key, value in self.querystring.items() if "Instances.member" in key]
@ -223,7 +324,9 @@ DESCRIBE_LOAD_BALANCERS_TEMPLATE = """<DescribeLoadBalancersResponse xmlns="http
{% for listener in load_balancer.listeners %}
<member>
<PolicyNames>
<member>AWSConsolePolicy-1</member>
{% for policy_name in listener.policy_names %}
<member>{{ policy_name }}</member>
{% endfor %}
</PolicyNames>
<Listener>
<Protocol>{{ listener.protocol }}</Protocol>
@ -243,14 +346,35 @@ DESCRIBE_LOAD_BALANCERS_TEMPLATE = """<DescribeLoadBalancersResponse xmlns="http
{% endfor %}
</Instances>
<Policies>
<AppCookieStickinessPolicies/>
<OtherPolicies/>
<AppCookieStickinessPolicies>
{% if load_balancer.policies.app_cookie_stickiness_policies %}
{% for policy in load_balancer.policies.app_cookie_stickiness_policies %}
<member>
<CookieName>{{ policy.cookie_name }}</CookieName>
<PolicyName>{{ policy.policy_name }}</PolicyName>
</member>
{% endfor %}
{% endif %}
</AppCookieStickinessPolicies>
<LBCookieStickinessPolicies>
<member>
<PolicyName>AWSConsolePolicy-1</PolicyName>
<CookieExpirationPeriod>30</CookieExpirationPeriod>
</member>
{% if load_balancer.policies.lb_cookie_stickiness_policies %}
{% for policy in load_balancer.policies.lb_cookie_stickiness_policies %}
<member>
{% if policy.cookie_expiration_period %}
<CookieExpirationPeriod>{{ policy.cookie_expiration_period }}</CookieExpirationPeriod>
{% endif %}
<PolicyName>{{ policy.policy_name }}</PolicyName>
</member>
{% endfor %}
{% endif %}
</LBCookieStickinessPolicies>
<OtherPolicies>
{% if load_balancer.policies.other_policies %}
{% for policy in load_balancer.policies.other_policies %}
<member>{{ policy.policy_name }}</member>
{% endfor %}
{% endif %}
</OtherPolicies>
</Policies>
<AvailabilityZones>
{% for zone in load_balancer.zones %}
@ -261,7 +385,22 @@ DESCRIBE_LOAD_BALANCERS_TEMPLATE = """<DescribeLoadBalancersResponse xmlns="http
<CanonicalHostedZoneNameID>Z3ZONEID</CanonicalHostedZoneNameID>
<Scheme>internet-facing</Scheme>
<DNSName>tests.us-east-1.elb.amazonaws.com</DNSName>
<BackendServerDescriptions/>
<BackendServerDescriptions>
{% for backend in load_balancer.backends %}
<member>
{% if backend.instance_port %}
<InstancePort>{{ backend.instance_port }}</InstancePort>
{% endif %}
{% if backend.policy_names %}
<PolicyNames>
{% for policy in backend.policy_names %}
<member>{{ policy }}</member>
{% endfor %}
</PolicyNames>
{% endif %}
</member>
{% endfor %}
</BackendServerDescriptions>
<Subnets>
</Subnets>
</member>
@ -381,6 +520,30 @@ MODIFY_ATTRIBUTES_TEMPLATE = """<ModifyLoadBalancerAttributesResponse xmlns="htt
</ModifyLoadBalancerAttributesResponse>
"""
CREATE_LOAD_BALANCER_POLICY_TEMPLATE = """<CreateLoadBalancerPolicyResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<CreateLoadBalancerPolicyResult/>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</CreateLoadBalancerPolicyResponse>
"""
SET_LOAD_BALANCER_POLICIES_OF_LISTENER_TEMPLATE = """<SetLoadBalancerPoliciesOfListenerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<SetLoadBalancerPoliciesOfListenerResult/>
<ResponseMetadata>
<RequestId>07b1ecbc-1100-11e3-acaf-dd7edEXAMPLE</RequestId>
</ResponseMetadata>
</SetLoadBalancerPoliciesOfListenerResponse>
"""
SET_LOAD_BALANCER_POLICIES_FOR_BACKEND_SERVER_TEMPLATE = """<SetLoadBalancerPoliciesForBackendServerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<SetLoadBalancerPoliciesForBackendServerResult/>
<ResponseMetadata>
<RequestId>0eb9b381-dde0-11e2-8d78-6ddbaEXAMPLE</RequestId>
</ResponseMetadata>
</SetLoadBalancerPoliciesForBackendServerResponse>
"""
DESCRIBE_INSTANCE_HEALTH_TEMPLATE = """<DescribeInstanceHealthResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DescribeInstanceHealthResult>
<InstanceStates>

View File

@ -7,6 +7,12 @@ from boto.ec2.elb.attributes import (
ConnectionDrainingAttribute,
AccessLogAttribute,
)
from boto.ec2.elb.policies import (
Policies,
AppCookieStickinessPolicy,
LBCookieStickinessPolicy,
OtherPolicy,
)
import sure # noqa
from moto import mock_elb, mock_ec2
@ -315,6 +321,107 @@ def test_connection_settings_attribute():
attributes = lb.get_attributes(force=True)
attributes.connecting_settings.idle_timeout.should.equal(60)
@mock_elb
def test_create_lb_cookie_stickiness_policy():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
cookie_expiration_period = 60
policy_name = "LBCookieStickinessPolicy"
lb.create_cookie_stickiness_policy(cookie_expiration_period, policy_name)
lb = conn.get_all_load_balancers()[0]
# There appears to be a quirk about boto, whereby it returns a unicode
# string for cookie_expiration_period, despite being stated in
# documentation to be a long.
#
# To work around that, this value is converted to a long and checked.
cookie_expiration_period_response_str = lb.policies.lb_cookie_stickiness_policies[0].cookie_expiration_period
long(cookie_expiration_period_response_str).should.equal(cookie_expiration_period)
lb.policies.lb_cookie_stickiness_policies[0].policy_name.should.equal(policy_name)
@mock_elb
def test_create_lb_cookie_stickiness_policy_no_expiry():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
policy_name = "LBCookieStickinessPolicy"
lb.create_cookie_stickiness_policy(None, policy_name)
lb = conn.get_all_load_balancers()[0]
lb.policies.lb_cookie_stickiness_policies[0].cookie_expiration_period.should.be.none
lb.policies.lb_cookie_stickiness_policies[0].policy_name.should.equal(policy_name)
@mock_elb
def test_create_app_cookie_stickiness_policy():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
cookie_name = "my-stickiness-policy"
policy_name = "AppCookieStickinessPolicy"
lb.create_app_cookie_stickiness_policy(cookie_name, policy_name)
lb = conn.get_all_load_balancers()[0]
lb.policies.app_cookie_stickiness_policies[0].cookie_name.should.equal(cookie_name)
lb.policies.app_cookie_stickiness_policies[0].policy_name.should.equal(policy_name)
@mock_elb
def test_create_lb_policy():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
policy_name = "ProxyPolicy"
lb.create_lb_policy(policy_name, 'ProxyProtocolPolicyType', {'ProxyProtocol': True})
lb = conn.get_all_load_balancers()[0]
lb.policies.other_policies[0].policy_name.should.equal(policy_name)
@mock_elb
def test_set_policies_of_listener():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
listener_port = 80
policy_name = "my-stickiness-policy"
# boto docs currently state that zero or one policy may be associated
# with a given listener
# in a real flow, it is necessary first to create a policy,
# then to set that policy to the listener
lb.create_cookie_stickiness_policy(None, policy_name)
lb.set_policies_of_listener(listener_port, [policy_name])
lb = conn.get_all_load_balancers()[0]
print lb.listeners
print lb.backends
listener = lb.listeners[0]
listener.load_balancer_port.should.equal(listener_port)
# by contrast to a backend, a listener stores only policy name strings
listener.policy_names[0].should.equal(policy_name)
@mock_elb
def test_set_policies_of_backend_server():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
instance_port = 8080
policy_name = "ProxyPolicy"
# in a real flow, it is necessary first to create a policy,
# then to set that policy to the backend
lb.create_lb_policy(policy_name, 'ProxyProtocolPolicyType', {'ProxyProtocol': True})
lb.set_policies_of_backend_server(instance_port, [policy_name])
lb = conn.get_all_load_balancers()[0]
backend = lb.backends[0]
backend.instance_port.should.equal(instance_port)
# by contrast to a listener, a backend stores OtherPolicy objects
backend.policies[0].policy_name.should.equal(policy_name)
@mock_ec2
@mock_elb