diff --git a/moto/elbv2/exceptions.py b/moto/elbv2/exceptions.py index c6e2256e8..e22820966 100644 --- a/moto/elbv2/exceptions.py +++ b/moto/elbv2/exceptions.py @@ -174,3 +174,12 @@ class InvalidTargetGroupNameError(ELBClientError): super(InvalidTargetGroupNameError, self).__init__( "ValidationError", msg ) + + +class InvalidModifyRuleArgumentsError(ELBClientError): + + def __init__(self): + super(InvalidModifyRuleArgumentsError, self).__init__( + "ValidationError", + "Either conditions or actions must be specified" + ) diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py index 0f3ee4518..9092084e6 100644 --- a/moto/elbv2/models.py +++ b/moto/elbv2/models.py @@ -23,7 +23,8 @@ from .exceptions import ( InvalidDescribeRulesRequest, RuleNotFoundError, DuplicatePriorityError, - InvalidTargetGroupNameError + InvalidTargetGroupNameError, + InvalidModifyRuleArgumentsError ) @@ -429,45 +430,50 @@ class ELBv2Backend(BaseBackend): raise ListenerNotFoundError() def modify_rule(self, rule_arn, conditions, actions): + # if conditions or actions is empty list, do not update the attributes + if not conditions and not actions: + raise InvalidModifyRuleArgumentsError() rules = self.describe_rules(listener_arn=None, rule_arns=[rule_arn]) if not rules: raise RuleNotFoundError() rule = rules[0] - # validate conditions - for condition in conditions: - field = condition['field'] - if field not in ['path-pattern', 'host-header']: - raise InvalidConditionFieldError(field) + if conditions: + for condition in conditions: + field = condition['field'] + if field not in ['path-pattern', 'host-header']: + raise InvalidConditionFieldError(field) - values = condition['values'] - if len(values) == 0: - raise InvalidConditionValueError('A condition value must be specified') - if len(values) > 1: - raise InvalidConditionValueError( - "The '%s' field contains too many values; the limit is '1'" % field - ) - - # TODO: check pattern of value for 'host-header' - # TODO: check pattern of value for 'path-pattern' + values = condition['values'] + if len(values) == 0: + raise InvalidConditionValueError('A condition value must be specified') + if len(values) > 1: + raise InvalidConditionValueError( + "The '%s' field contains too many values; the limit is '1'" % field + ) + # TODO: check pattern of value for 'host-header' + # TODO: check pattern of value for 'path-pattern' # validate Actions target_group_arns = [target_group.arn for target_group in self.target_groups.values()] - for i, action in enumerate(actions): - index = i + 1 - action_type = action['type'] - if action_type not in ['forward']: - raise InvalidActionTypeError(action_type, index) - action_target_group_arn = action['target_group_arn'] - if action_target_group_arn not in target_group_arns: - raise ActionTargetGroupNotFoundError(action_target_group_arn) + if actions: + for i, action in enumerate(actions): + index = i + 1 + action_type = action['type'] + if action_type not in ['forward']: + raise InvalidActionTypeError(action_type, index) + action_target_group_arn = action['target_group_arn'] + if action_target_group_arn not in target_group_arns: + raise ActionTargetGroupNotFoundError(action_target_group_arn) # TODO: check for error 'TooManyRegistrationsForTargetId' # TODO: check for error 'TooManyRules' # modify rule - rule.conditions = conditions - rule.actions = actions + if conditions: + rule.conditions = conditions + if actions: + rule.actions = actions return [rule] def register_targets(self, target_group_arn, instances): diff --git a/tests/test_elbv2/test_elbv2.py b/tests/test_elbv2/test_elbv2.py index 43d72b393..be3f484e0 100644 --- a/tests/test_elbv2/test_elbv2.py +++ b/tests/test_elbv2/test_elbv2.py @@ -731,7 +731,7 @@ def test_handle_listener_rules(): RuleArns=[first_rule['RuleArn']] ) - # modify rule + # modify rule partially new_host = 'new.example.com' new_path_pattern = 'new_path' modified_rule = conn.modify_rule( @@ -743,15 +743,15 @@ def test_handle_listener_rules(): { 'Field': 'path-pattern', 'Values': [ new_path_pattern ] - }], - Actions=[{ - 'TargetGroupArn': target_group.get('TargetGroupArn'), - 'Type': 'forward' }] - )['Rules'][0] + rules = conn.describe_rules(ListenerArn=http_listener_arn) - modified_rule.should.equal(rules['Rules'][0]) + obtained_rule = rules['Rules'][0] + modified_rule.should.equal(obtained_rule) + obtained_rule['Conditions'][0]['Values'][0].should.equal(new_host) + obtained_rule['Conditions'][1]['Values'][0].should.equal(new_path_pattern) + obtained_rule['Actions'][0]['TargetGroupArn'].should.equal(target_group.get('TargetGroupArn')) # modify priority conn.set_rule_priorities(