From e07bce003c1b5ea8b9bf785bbef53052dbe14042 Mon Sep 17 00:00:00 2001 From: Toshiya Kawasaki Date: Thu, 17 Aug 2017 03:10:26 +0900 Subject: [PATCH] add set_rule_priorities to elbv2 --- moto/elbv2/exceptions.py | 8 +++++ moto/elbv2/models.py | 36 ++++++++++++++++++++- moto/elbv2/responses.py | 46 ++++++++++++++++++++++++++ tests/test_elbv2/test_elbv2.py | 59 +++++++++++++++++++++------------- 4 files changed, 126 insertions(+), 23 deletions(-) diff --git a/moto/elbv2/exceptions.py b/moto/elbv2/exceptions.py index 705aa9622..569fa7eed 100644 --- a/moto/elbv2/exceptions.py +++ b/moto/elbv2/exceptions.py @@ -158,3 +158,11 @@ class RuleNotFoundError(ELBClientError): super(RuleNotFoundError, self).__init__( "RuleNotFound", "The specified rule does not exist.") + + +class DuplicatePriorityError(ELBClientError): + + def __init__(self, invalid_value): + super(DuplicatePriorityError, self).__init__( + "ValidationError", + "Priority '%s' was provided multiple times" % invalid_value) diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py index c51b6a561..398a63481 100644 --- a/moto/elbv2/models.py +++ b/moto/elbv2/models.py @@ -20,7 +20,8 @@ from .exceptions import ( InvalidActionTypeError, ActionTargetGroupNotFoundError, InvalidDescribeRulesRequest, - RuleNotFoundError + RuleNotFoundError, + DuplicatePriorityError ) @@ -471,6 +472,39 @@ class ELBv2Backend(BaseBackend): targets = target_group.targets.values() return [target_group.health_for(target) for target in targets] + def set_rule_priorities(self, rule_priorities): + # validate + priorities = [rule_priority['priority'] for rule_priority in rule_priorities] + for priority in set(priorities): + if priorities.count(priority) > 1: + raise DuplicatePriorityError(priority) + + # validate + for rule_priority in rule_priorities: + given_rule_arn = rule_priority['rule_arn'] + priority = rule_priority['priority'] + _given_rules = self.describe_rules(listener_arn=None, rule_arns=[given_rule_arn]) + if not _given_rules: + raise RuleNotFoundError() + given_rule = _given_rules[0] + listeners = self.describe_listeners(None, [given_rule.listener_arn]) + listener = listeners[0] + for rule_in_listener in listener.rules: + if rule_in_listener.priority == priority: + raise PriorityInUseError() + # modify + modified_rules = [] + for rule_priority in rule_priorities: + given_rule_arn = rule_priority['rule_arn'] + priority = rule_priority['priority'] + _given_rules = self.describe_rules(listener_arn=None, rule_arns=[given_rule_arn]) + if not _given_rules: + raise RuleNotFoundError() + given_rule = _given_rules[0] + given_rule.priority = priority + modified_rules.append(given_rule) + return modified_rules + elbv2_backends = {} for region in ec2_backends.keys(): diff --git a/moto/elbv2/responses.py b/moto/elbv2/responses.py index 2e5f1e299..a798d1e41 100644 --- a/moto/elbv2/responses.py +++ b/moto/elbv2/responses.py @@ -255,6 +255,14 @@ class ELBV2Response(BaseResponse): template = self.response_template(DESCRIBE_TARGET_HEALTH_TEMPLATE) return template.render(target_health_descriptions=target_health_descriptions) + def set_rule_priorities(self): + rule_priorities = self._get_list_prefix('RulePriorities.member') + for rule_priority in rule_priorities: + rule_priority['priority'] = int(rule_priority['priority']) + rules = self.elbv2_backend.set_rule_priorities(rule_priorities) + template = self.response_template(SET_RULE_PRIORITIES_TEMPLATE) + return template.render(rules=rules) + def add_tags(self): resource_arns = self._get_multi_param('ResourceArns.member') @@ -896,3 +904,41 @@ DESCRIBE_TARGET_HEALTH_TEMPLATE = """ + + + {% for rule in rules %} + + {{ "true" if rule.is_default else "false" }} + + {% for condition in rule.conditions %} + + {{ condition["field"] }} + + {% for value in condition["values"] %} + {{ value }} + {% endfor %} + + + {% endfor %} + + {{ rule.priority }} + + {% for action in rule.actions %} + + {{ action["type"] }} + {{ action["target_group_arn"] }} + + {% endfor %} + + {{ rule.arn }} + + {% endfor %} + + + + 4d7a8036-f3a7-11e5-9c02-8fd20490d5a6 + +""" diff --git a/tests/test_elbv2/test_elbv2.py b/tests/test_elbv2/test_elbv2.py index 0911ff4a1..d4220d4c8 100644 --- a/tests/test_elbv2/test_elbv2.py +++ b/tests/test_elbv2/test_elbv2.py @@ -612,6 +612,27 @@ def test_create_listener_rules(): }] ) + # test for PriorityInUse + host2 = 'yyy.example.com' + with assert_raises(ClientError): + r = conn.create_rule( + ListenerArn=http_listener_arn, + Priority=priority, + Conditions=[{ + 'Field': 'host-header', + 'Values': [ host ] + }, + { + 'Field': 'path-pattern', + 'Values': [ path_pattern ] + }], + Actions=[{ + 'TargetGroupArn': target_group.get('TargetGroupArn'), + 'Type': 'forward' + }] + ) + + # test for describe listeners obtained_rules = conn.describe_rules(ListenerArn=http_listener_arn) len(obtained_rules['Rules']).should.equal(3) @@ -619,6 +640,7 @@ def test_create_listener_rules(): priorities.should.equal(['50', '100', 'default']) first_rule = obtained_rules['Rules'][0] + second_rule = obtained_rules['Rules'][1] obtained_rules = conn.describe_rules(RuleArns=[first_rule['RuleArn']]) obtained_rules['Rules'].should.equal([first_rule]) @@ -638,7 +660,7 @@ def test_create_listener_rules(): RuleArns=[first_rule['RuleArn']] ) - # modify + # modify rule new_host = 'new.example.com' new_path_pattern = 'new_path' modified_rule = conn.modify_rule( @@ -660,10 +682,23 @@ def test_create_listener_rules(): rules = conn.describe_rules(ListenerArn=http_listener_arn) modified_rule.should.equal(rules['Rules'][0]) + # modify priority + conn.set_rule_priorities( + RulePriorities=[ + {'RuleArn': first_rule['RuleArn'], 'Priority': int(first_rule['Priority']) - 1} + ] + ) + with assert_raises(ClientError): + conn.set_rule_priorities( + RulePriorities=[ + {'RuleArn': first_rule['RuleArn'], 'Priority': 999}, + {'RuleArn': second_rule['RuleArn'], 'Priority': 999} + ] + ) + # delete arn = first_rule['RuleArn'] conn.delete_rule(RuleArn=arn) - # TODO: describe rule and ensure rule is removed # test for invalid action type safe_priority = 2 @@ -706,26 +741,6 @@ def test_create_listener_rules(): }] ) - # test for PriorityInUse - host2 = 'yyy.example.com' - with assert_raises(ClientError): - r = conn.create_rule( - ListenerArn=http_listener_arn, - Priority=priority, - Conditions=[{ - 'Field': 'host-header', - 'Values': [ host ] - }, - { - 'Field': 'path-pattern', - 'Values': [ path_pattern ] - }], - Actions=[{ - 'TargetGroupArn': target_group.get('TargetGroupArn'), - 'Type': 'forward' - }] - ) - # test for invalid condition field_name safe_priority = 2 with assert_raises(ClientError):