diff --git a/changelogs/fragments/188-httprequestmethodconfig-keyerror.yaml b/changelogs/fragments/188-httprequestmethodconfig-keyerror.yaml new file mode 100644 index 00000000000..5b7ac63aec4 --- /dev/null +++ b/changelogs/fragments/188-httprequestmethodconfig-keyerror.yaml @@ -0,0 +1,5 @@ +--- +bugfixes: + - module_utils/elbv2 - add logic to compare_rules to suit Values list nested within dicts unique to each field type. + Fixes issue (https://github.com/ansible-collections/amazon.aws/issues/187) + - module_utils/elbv2 - Requires 1.16.57 as minimum boto3 version. diff --git a/plugins/module_utils/elbv2.py b/plugins/module_utils/elbv2.py index 8ae12e01172..2124a61a68c 100644 --- a/plugins/module_utils/elbv2.py +++ b/plugins/module_utils/elbv2.py @@ -51,6 +51,9 @@ def __init__(self, connection, module): else: self.elb_attributes = None + if not self.module.boto3_at_least('1.16.57'): + self.module.fail_json(msg="elbv2 requires boto3 >= 1.16.57") + def wait_for_status(self, elb_arn): """ Wait for load balancer to reach 'active' status @@ -719,11 +722,46 @@ def _compare_condition(self, current_conditions, condition): condition_found = False for current_condition in current_conditions: - if current_condition.get('SourceIpConfig'): + # host-header: current_condition includes both HostHeaderConfig AND Values while + # condition can be defined with either HostHeaderConfig OR Values. Only use + # HostHeaderConfig['Values'] comparison if both conditions includes HostHeaderConfig. + if current_condition.get('HostHeaderConfig') and condition.get('HostHeaderConfig'): + if (current_condition['Field'] == condition['Field'] and + sorted(current_condition['HostHeaderConfig']['Values']) == sorted(condition['HostHeaderConfig']['Values'])): + condition_found = True + break + elif current_condition.get('HttpHeaderConfig'): + if (current_condition['Field'] == condition['Field'] and + sorted(current_condition['HttpHeaderConfig']['Values']) == sorted(condition['HttpHeaderConfig']['Values']) and + current_condition['HttpHeaderConfig']['HttpHeaderName'] == condition['HttpHeaderConfig']['HttpHeaderName']): + condition_found = True + break + elif current_condition.get('HttpRequestMethodConfig'): + if (current_condition['Field'] == condition['Field'] and + sorted(current_condition['HttpRequestMethodConfig']['Values']) == sorted(condition['HttpRequestMethodConfig']['Values'])): + condition_found = True + break + # path-pattern: current_condition includes both PathPatternConfig AND Values while + # condition can be defined with either PathPatternConfig OR Values. Only use + # PathPatternConfig['Values'] comparison if both conditions includes PathPatternConfig. + elif current_condition.get('PathPatternConfig') and condition.get('PathPatternConfig'): + if (current_condition['Field'] == condition['Field'] and + sorted(current_condition['PathPatternConfig']['Values']) == sorted(condition['PathPatternConfig']['Values'])): + condition_found = True + break + elif current_condition.get('QueryStringConfig'): + # QueryString Values is not sorted as it is the only list of dicts (not strings). + if (current_condition['Field'] == condition['Field'] and + current_condition['QueryStringConfig']['Values'] == condition['QueryStringConfig']['Values']): + condition_found = True + break + elif current_condition.get('SourceIpConfig'): if (current_condition['Field'] == condition['Field'] and - current_condition['SourceIpConfig']['Values'][0] == condition['SourceIpConfig']['Values'][0]): + sorted(current_condition['SourceIpConfig']['Values']) == sorted(condition['SourceIpConfig']['Values'])): condition_found = True break + # Not all fields are required to have Values list nested within a *Config dict + # e.g. fields host-header/path-pattern can directly list Values elif current_condition['Field'] == condition['Field'] and sorted(current_condition['Values']) == sorted(condition['Values']): condition_found = True break