From 9e182cf0e7a44179bcde4ba5c0dd9180147480bf Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 22 Jul 2022 12:14:17 +0200 Subject: [PATCH] More work on ELBv2 module_utils (#940) More work on ELBv2 module_utils SUMMARY Refactors LB creation and makes sure that ip_address_type is set on creation (bug found when working on fixing NLB tests) Fixes bug with DefaultAction comparisons Extends tests for _prune_ForwardConfig Extends tests for _prune_secrets Fixes KeyError bug uncovered when extending tests for _prune_secrets ISSUE TYPE Bugfix Pull Request COMPONENT NAME plugins/module_utils/elbv2.py ADDITIONAL INFORMATION Fixes: ansible-collections/community.aws#604 See also: ansible-collections/community.aws#1365 Reviewed-by: Alina Buzachis --- changelogs/fragments/604-elb_network_lb.yml | 6 + plugins/module_utils/elbv2.py | 237 ++++++++++++------ plugins/module_utils/waiters.py | 125 +++++++++ .../elb_classic_lb/tasks/https_listeners.yml | 3 + tests/unit/module_utils/elbv2/test_prune.py | 182 ++++++++++++++ tests/unit/module_utils/test_elbv2.py | 14 -- 6 files changed, 480 insertions(+), 87 deletions(-) create mode 100644 changelogs/fragments/604-elb_network_lb.yml create mode 100644 tests/unit/module_utils/elbv2/test_prune.py diff --git a/changelogs/fragments/604-elb_network_lb.yml b/changelogs/fragments/604-elb_network_lb.yml new file mode 100644 index 00000000000..0564261bb78 --- /dev/null +++ b/changelogs/fragments/604-elb_network_lb.yml @@ -0,0 +1,6 @@ +bugfixes: +- module_utils/elbv2 - improvements to idempotency when comparing listeners (https://github.com/ansible-collections/community.aws/issues/604). +- module_utils/elbv2 - fixes ``KeyError`` when using ``UseExistingClientSecret`` rather than ``ClientSecret`` (https://github.com/ansible-collections/amazon.aws/pull/940). +minor_changes: +- module_utils/elbv2 - ensures that ``ip_address_type`` is set on creation rather than re-setting it after creation (https://github.com/ansible-collections/amazon.aws/pull/940). +- module_utils/elbv2 - uses new waiters with retries for temporary failures (https://github.com/ansible-collections/amazon.aws/pull/940). diff --git a/plugins/module_utils/elbv2.py b/plugins/module_utils/elbv2.py index bd86ddf1b84..5a654db9933 100644 --- a/plugins/module_utils/elbv2.py +++ b/plugins/module_utils/elbv2.py @@ -19,6 +19,54 @@ from .elb_utils import convert_tg_name_to_arn from .elb_utils import get_elb from .elb_utils import get_elb_listener +from .waiters import get_waiter + + +def _simple_forward_config_arn(config, parent_arn): + config = deepcopy(config) + + stickiness = config.pop('TargetGroupStickinessConfig', {'Enabled': False}) + # Stickiness options set, non default value + if stickiness != {'Enabled': False}: + return False + + target_groups = config.pop('TargetGroups', []) + + # non-default config left over, probably invalid + if config: + return False + # Multiple TGS, not simple + if len(target_groups) > 1: + return False + + if not target_groups: + # with no TGs defined, but an ARN set, this is one of the minimum possible configs + return parent_arn or False + + target_group = target_groups[0] + # We don't care about the weight with a single TG + target_group.pop('Weight', None) + + target_group_arn = target_group.pop('TargetGroupArn', None) + + # non-default config left over + if target_group: + return False + + # We didn't find an ARN + if not (target_group_arn or parent_arn): + return False + + # Only one + if not parent_arn: + return target_group_arn + if not target_group_arn: + return parent_arn + + if parent_arn != target_group_arn: + return False + + return target_group_arn # ForwardConfig may be optional if we've got a single TargetGroupArn entry @@ -31,21 +79,16 @@ def _prune_ForwardConfig(action): return action if "ForwardConfig" not in action: return action - # Where we have multiple TGs, action['TargetGroupArn'] shouldn't be set - if "TargetGroupArn" not in action: - return action - # This is the same as having TargetGroupArn set - equivalent_action = { - 'TargetGroupStickinessConfig': {'Enabled': False}, - 'TargetGroups': [{"TargetGroupArn": action["TargetGroupArn"], "Weight": 1}], - } - if action["ForwardConfig"] != equivalent_action: + parent_arn = action.get('TargetGroupArn', None) + arn = _simple_forward_config_arn(action["ForwardConfig"], parent_arn) + if not arn: return action # Remove the redundant ForwardConfig newAction = action.copy() del(newAction["ForwardConfig"]) + newAction["TargetGroupArn"] = arn return newAction @@ -53,8 +96,13 @@ def _prune_ForwardConfig(action): # or the module will always see the new and current actions as different # and try to apply the same config def _prune_secret(action): - if action['Type'] == 'authenticate-oidc': - action['AuthenticateOidcConfig'].pop('ClientSecret') + if action['Type'] != 'authenticate-oidc': + return action + + action['AuthenticateOidcConfig'].pop('ClientSecret', None) + if action['AuthenticateOidcConfig'].get('UseExistingClientSecret', False): + action['AuthenticateOidcConfig'].pop('UseExistingClientSecret') + return action @@ -75,22 +123,47 @@ def __init__(self, connection, module): self.subnet_mappings = module.params.get("subnet_mappings") self.subnets = module.params.get("subnets") self.deletion_protection = module.params.get("deletion_protection") + self.elb_ip_addr_type = module.params.get("ip_address_type") self.wait = module.params.get("wait") if module.params.get("tags") is not None: self.tags = ansible_dict_to_boto3_tag_list(module.params.get("tags")) else: self.tags = None + self.purge_tags = module.params.get("purge_tags") self.elb = get_elb(connection, module, self.name) if self.elb is not None: self.elb_attributes = self.get_elb_attributes() - self.elb['tags'] = self.get_elb_tags() self.elb_ip_addr_type = self.get_elb_ip_address_type() + self.elb['tags'] = self.get_elb_tags() else: self.elb_attributes = None - self.elb_ip_addr_type = None + + def wait_for_ip_type(self, elb_arn, ip_type): + """ + Wait for load balancer to reach 'active' status + + :param elb_arn: The load balancer ARN + :return: + """ + + if not self.wait: + return + + waiter_names = { + 'ipv4': 'load_balancer_ip_address_type_ipv4', + 'dualstack': 'load_balancer_ip_address_type_dualstack', + } + if ip_type not in waiter_names: + return + + try: + waiter = get_waiter(self.connection, waiter_names.get(ip_type)) + waiter.wait(LoadBalancerArns=[elb_arn]) + except (BotoCoreError, ClientError) as e: + self.module.fail_json_aws(e) def wait_for_status(self, elb_arn): """ @@ -100,8 +173,28 @@ def wait_for_status(self, elb_arn): :return: """ + if not self.wait: + return + try: - waiter = self.connection.get_waiter('load_balancer_available') + waiter = get_waiter(self.connection, 'load_balancer_available') + waiter.wait(LoadBalancerArns=[elb_arn]) + except (BotoCoreError, ClientError) as e: + self.module.fail_json_aws(e) + + def wait_for_deletion(self, elb_arn): + """ + Wait for load balancer to reach 'active' status + + :param elb_arn: The load balancer ARN + :return: + """ + + if not self.wait: + return + + try: + waiter = get_waiter(self.connection, 'load_balancers_deleted') waiter.wait(LoadBalancerArns=[elb_arn]) except (BotoCoreError, ClientError) as e: self.module.fail_json_aws(e) @@ -200,6 +293,8 @@ def delete(self): except (BotoCoreError, ClientError) as e: self.module.fail_json_aws(e) + self.wait_for_deletion(self.elb['LoadBalancerArn']) + self.changed = True def compare_subnets(self): @@ -264,15 +359,57 @@ def modify_ip_address_type(self, ip_addr_type): Modify ELB ip address type :return: """ - if self.elb_ip_addr_type != ip_addr_type: - try: - AWSRetry.jittered_backoff()( - self.connection.set_ip_address_type - )(LoadBalancerArn=self.elb['LoadBalancerArn'], IpAddressType=ip_addr_type) - except (BotoCoreError, ClientError) as e: - self.module.fail_json_aws(e) + if ip_addr_type is None: + return + if self.elb_ip_addr_type == ip_addr_type: + return + + try: + AWSRetry.jittered_backoff()( + self.connection.set_ip_address_type + )(LoadBalancerArn=self.elb['LoadBalancerArn'], IpAddressType=ip_addr_type) + except (BotoCoreError, ClientError) as e: + self.module.fail_json_aws(e) + + self.changed = True + self.wait_for_ip_type(self.elb['LoadBalancerArn'], ip_addr_type) + def _elb_create_params(self): + # Required parameters + params = dict() + params['Name'] = self.name + params['Type'] = self.type + + # Other parameters + if self.elb_ip_addr_type is not None: + params['IpAddressType'] = self.elb_ip_addr_type + if self.subnets is not None: + params['Subnets'] = self.subnets + if self.subnet_mappings is not None: + params['SubnetMappings'] = self.subnet_mappings + if self.tags: + params['Tags'] = self.tags + # Scheme isn't supported for GatewayLBs, so we won't add it here, even though we don't + # support them yet. + + return params + + def create_elb(self): + """ + Create a load balancer + :return: + """ + + params = self._elb_create_params() + + try: + self.elb = AWSRetry.jittered_backoff()(self.connection.create_load_balancer)(**params)['LoadBalancers'][0] self.changed = True + self.new_load_balancer = True + except (BotoCoreError, ClientError) as e: + self.module.fail_json_aws(e) + + self.wait_for_status(self.elb['LoadBalancerArn']) class ApplicationLoadBalancer(ElasticLoadBalancerV2): @@ -314,37 +451,14 @@ def __init__(self, connection, connection_ec2, module): if self.elb is not None and self.elb['Type'] != 'application': self.module.fail_json(msg="The load balancer type you are trying to manage is not application. Try elb_network_lb module instead.") - def create_elb(self): - """ - Create a load balancer - :return: - """ + def _elb_create_params(self): + params = super()._elb_create_params() - # Required parameters - params = dict() - params['Name'] = self.name - params['Type'] = self.type - - # Other parameters - if self.subnets is not None: - params['Subnets'] = self.subnets - if self.subnet_mappings is not None: - params['SubnetMappings'] = self.subnet_mappings if self.security_groups is not None: params['SecurityGroups'] = self.security_groups params['Scheme'] = self.scheme - if self.tags: - params['Tags'] = self.tags - - try: - self.elb = AWSRetry.jittered_backoff()(self.connection.create_load_balancer)(**params)['LoadBalancers'][0] - self.changed = True - self.new_load_balancer = True - except (BotoCoreError, ClientError) as e: - self.module.fail_json_aws(e) - if self.wait: - self.wait_for_status(self.elb['LoadBalancerArn']) + return params def compare_elb_attributes(self): """ @@ -485,35 +599,12 @@ def __init__(self, connection, connection_ec2, module): if self.elb is not None and self.elb['Type'] != 'network': self.module.fail_json(msg="The load balancer type you are trying to manage is not network. Try elb_application_lb module instead.") - def create_elb(self): - """ - Create a load balancer - :return: - """ + def _elb_create_params(self): + params = super()._elb_create_params() - # Required parameters - params = dict() - params['Name'] = self.name - params['Type'] = self.type - - # Other parameters - if self.subnets is not None: - params['Subnets'] = self.subnets - if self.subnet_mappings is not None: - params['SubnetMappings'] = self.subnet_mappings params['Scheme'] = self.scheme - if self.tags: - params['Tags'] = self.tags - - try: - self.elb = AWSRetry.jittered_backoff()(self.connection.create_load_balancer)(**params)['LoadBalancers'][0] - self.changed = True - self.new_load_balancer = True - except (BotoCoreError, ClientError) as e: - self.module.fail_json_aws(e) - if self.wait: - self.wait_for_status(self.elb['LoadBalancerArn']) + return params def modify_elb_attributes(self): """ diff --git a/plugins/module_utils/waiters.py b/plugins/module_utils/waiters.py index 2256a642ef1..078894cb673 100644 --- a/plugins/module_utils/waiters.py +++ b/plugins/module_utils/waiters.py @@ -631,6 +631,102 @@ } } +elbv2_data = { + "version": 2, + "waiters": { + "LoadBalancerAvailable": { + "delay": 15, + "operation": "DescribeLoadBalancers", + "maxAttempts": 40, + "acceptors": [ + { + "state": "success", + "matcher": "pathAll", + "argument": "LoadBalancers[].State.Code", + "expected": "active" + }, + { + "state": "retry", + "matcher": "pathAny", + "argument": "LoadBalancers[].State.Code", + "expected": "provisioning" + }, + { + "state": "retry", + "matcher": "error", + "expected": "LoadBalancerNotFound" + } + ] + }, + "LoadBalancerIpAddressTypeIpv4": { + "delay": 15, + "operation": "DescribeLoadBalancers", + "maxAttempts": 40, + "acceptors": [ + { + "state": "success", + "matcher": "pathAll", + "argument": "LoadBalancers[].IpAddressType", + "expected": "ipv4" + }, + { + "state": "retry", + "matcher": "pathAny", + "argument": "LoadBalancers[].IpAddressType", + "expected": "dualstack" + }, + { + "state": "failure", + "matcher": "error", + "expected": "LoadBalancerNotFound" + } + ] + }, + "LoadBalancerIpAddressTypeDualStack": { + "delay": 15, + "operation": "DescribeLoadBalancers", + "maxAttempts": 40, + "acceptors": [ + { + "state": "success", + "matcher": "pathAll", + "argument": "LoadBalancers[].IpAddressType", + "expected": "dualstack" + }, + { + "state": "retry", + "matcher": "pathAny", + "argument": "LoadBalancers[].IpAddressType", + "expected": "ipv4" + }, + { + "state": "failure", + "matcher": "error", + "expected": "LoadBalancerNotFound" + } + ] + }, + "LoadBalancersDeleted": { + "delay": 15, + "operation": "DescribeLoadBalancers", + "maxAttempts": 40, + "acceptors": [ + { + "state": "retry", + "matcher": "pathAll", + "argument": "LoadBalancers[].State.Code", + "expected": "active" + }, + { + "matcher": "error", + "expected": "LoadBalancerNotFound", + "state": "success" + } + ] + }, + } +} + rds_data = { "version": 2, @@ -805,6 +901,11 @@ def eks_model(name): return eks_models.get_waiter(name) +def elbv2_model(name): + elbv2_models = core_waiter.WaiterModel(waiter_config=_inject_limit_retries(elbv2_data)) + return elbv2_models.get_waiter(name) + + def elb_model(name): elb_models = core_waiter.WaiterModel(waiter_config=_inject_limit_retries(elb_data)) return elb_models.get_waiter(name) @@ -1037,6 +1138,30 @@ def route53_model(name): core_waiter.NormalizedOperationMethod( elb.describe_load_balancers )), + ('ElasticLoadBalancingv2', 'load_balancer_available'): lambda elbv2: core_waiter.Waiter( + 'load_balancer_available', + elbv2_model('LoadBalancerAvailable'), + core_waiter.NormalizedOperationMethod( + elbv2.describe_load_balancers + )), + ('ElasticLoadBalancingv2', 'load_balancer_ip_address_type_ipv4'): lambda elbv2: core_waiter.Waiter( + 'load_balancer_ip_address_type_ipv4', + elbv2_model('LoadBalancerIpAddressTypeIpv4'), + core_waiter.NormalizedOperationMethod( + elbv2.describe_load_balancers + )), + ('ElasticLoadBalancingv2', 'load_balancer_ip_address_type_dualstack'): lambda elbv2: core_waiter.Waiter( + 'load_balancers_ip_address_type_dualstack', + elbv2_model('LoadBalancerIpAddressTypeDualStack'), + core_waiter.NormalizedOperationMethod( + elbv2.describe_load_balancers + )), + ('ElasticLoadBalancingv2', 'load_balancers_deleted'): lambda elbv2: core_waiter.Waiter( + 'load_balancers_deleted', + elbv2_model('LoadBalancersDeleted'), + core_waiter.NormalizedOperationMethod( + elbv2.describe_load_balancers + )), ('RDS', 'db_instance_stopped'): lambda rds: core_waiter.Waiter( 'db_instance_stopped', rds_model('DBInstanceStopped'), diff --git a/tests/integration/targets/elb_classic_lb/tasks/https_listeners.yml b/tests/integration/targets/elb_classic_lb/tasks/https_listeners.yml index 99cfdf749fd..3ab12ab2aab 100644 --- a/tests/integration/targets/elb_classic_lb/tasks/https_listeners.yml +++ b/tests/integration/targets/elb_classic_lb/tasks/https_listeners.yml @@ -119,6 +119,9 @@ community.aws.aws_acm: certificate_arn: '{{ cert_arn }}' state: absent + # AWS doesn't always cleanup the associations properly + # https://repost.aws/questions/QU63csgGNEQl2M--xCdy-oxw/cant-delete-certificate-because-there-are-dangling-load-balancer-resources + ignore_errors: True register: delete_result - assert: that: diff --git a/tests/unit/module_utils/elbv2/test_prune.py b/tests/unit/module_utils/elbv2/test_prune.py new file mode 100644 index 00000000000..3a80bf58df8 --- /dev/null +++ b/tests/unit/module_utils/elbv2/test_prune.py @@ -0,0 +1,182 @@ +# +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import pytest + +from ansible_collections.amazon.aws.plugins.module_utils import elbv2 + +example_arn = 'arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/nlb-123456789abc/abcdef0123456789' +example_arn2 = 'arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/nlb-0123456789ab/0123456789abcdef' + +one_action = [ + dict( + ForwardConfig=dict( + TargetGroupStickinessConfig=dict(Enabled=False), + TargetGroups=[ + dict(TargetGroupArn=example_arn, Weight=1), + ] + ), + TargetGroupArn=example_arn, Type='forward', + ) +] + +one_action_two_tg = [ + dict( + ForwardConfig=dict( + TargetGroupStickinessConfig=dict(Enabled=False), + TargetGroups=[ + dict(TargetGroupArn=example_arn, Weight=1), + dict(TargetGroupArn=example_arn2, Weight=1), + ] + ), + TargetGroupArn=example_arn, Type='forward', + ) +] + +simplified_action = dict(Type='forward', TargetGroupArn=example_arn) +# Examples of various minimalistic actions which are all the same +simple_actions = [ + dict(Type='forward', TargetGroupArn=example_arn), + + dict(Type='forward', TargetGroupArn=example_arn, ForwardConfig=dict(TargetGroups=[dict(TargetGroupArn=example_arn)])), + dict(Type='forward', ForwardConfig=dict(TargetGroups=[dict(TargetGroupArn=example_arn)])), + dict(Type='forward', TargetGroupArn=example_arn, ForwardConfig=dict(TargetGroups=[dict(TargetGroupArn=example_arn, Weight=1)])), + dict(Type='forward', ForwardConfig=dict(TargetGroups=[dict(TargetGroupArn=example_arn, Weight=1)])), + dict(Type='forward', TargetGroupArn=example_arn, ForwardConfig=dict(TargetGroups=[dict(TargetGroupArn=example_arn, Weight=42)])), + dict(Type='forward', ForwardConfig=dict(TargetGroups=[dict(TargetGroupArn=example_arn, Weight=42)])), + + dict(Type='forward', TargetGroupArn=example_arn, ForwardConfig=dict(TargetGroupStickinessConfig=dict(Enabled=False), + TargetGroups=[dict(TargetGroupArn=example_arn)])), + dict(Type='forward', ForwardConfig=dict(TargetGroupStickinessConfig=dict(Enabled=False), TargetGroups=[dict(TargetGroupArn=example_arn)])), + dict(Type='forward', TargetGroupArn=example_arn, ForwardConfig=dict(TargetGroupStickinessConfig=dict(Enabled=False), + TargetGroups=[dict(TargetGroupArn=example_arn, Weight=1)])), + dict(Type='forward', ForwardConfig=dict(TargetGroupStickinessConfig=dict(Enabled=False), TargetGroups=[dict(TargetGroupArn=example_arn, Weight=1)])), + dict(Type='forward', TargetGroupArn=example_arn, ForwardConfig=dict(TargetGroupStickinessConfig=dict(Enabled=False), + TargetGroups=[dict(TargetGroupArn=example_arn, Weight=42)])), + dict(Type='forward', ForwardConfig=dict(TargetGroupStickinessConfig=dict(Enabled=False), TargetGroups=[dict(TargetGroupArn=example_arn, Weight=42)])), +] + +# Test that _prune_ForwardConfig() doesn't mangle things we don't expect +complex_actions = [ + # Non-Forwarding + dict( + Type='authenticate-oidc', TargetGroupArn=example_arn, + AuthenticateOidcConfig=dict( + Issuer='https://idp.ansible.test/oidc-config', + AuthorizationEndpoint='https://idp.ansible.test/authz', + TokenEndpoint='https://idp.ansible.test/token', + UserInfoEndpoint='https://idp.ansible.test/user', + ClientId='ExampleClient', + UseExistingClientSecret=False, + ), + ), + dict( + Type='redirect', + RedirectConfig=dict(Protocol='HTTPS', Port=443, Host='redirect.ansible.test', Path='/', StatusCode='HTTP_302'), + ), + # Multiple TGs + dict( + TargetGroupArn=example_arn, Type='forward', + ForwardConfig=dict( + TargetGroupStickinessConfig=dict(Enabled=False), + TargetGroups=[ + dict(TargetGroupArn=example_arn, Weight=1), + dict(TargetGroupArn=example_arn2, Weight=1), + ] + ), + ), + # Sticky-Sessions + dict( + Type='forward', TargetGroupArn=example_arn, + ForwardConfig=dict( + TargetGroupStickinessConfig=dict(Enabled=True, DurationSeconds=3600), + TargetGroups=[dict(TargetGroupArn=example_arn)] + ) + ), +] + +simplified_oidc_action = dict( + Type='authenticate-oidc', TargetGroupArn=example_arn, + AuthenticateOidcConfig=dict( + Issuer='https://idp.ansible.test/oidc-config', + AuthorizationEndpoint='https://idp.ansible.test/authz', + TokenEndpoint='https://idp.ansible.test/token', + UserInfoEndpoint='https://idp.ansible.test/user', + ClientId='ExampleClient', + ), +) +oidc_actions = [ + dict( + Type='authenticate-oidc', TargetGroupArn=example_arn, + AuthenticateOidcConfig=dict( + Issuer='https://idp.ansible.test/oidc-config', + AuthorizationEndpoint='https://idp.ansible.test/authz', + TokenEndpoint='https://idp.ansible.test/token', + UserInfoEndpoint='https://idp.ansible.test/user', + ClientId='ExampleClient', + UseExistingClientSecret=True, + ), + ), + dict( + Type='authenticate-oidc', TargetGroupArn=example_arn, + AuthenticateOidcConfig=dict( + Issuer='https://idp.ansible.test/oidc-config', + AuthorizationEndpoint='https://idp.ansible.test/authz', + TokenEndpoint='https://idp.ansible.test/token', + UserInfoEndpoint='https://idp.ansible.test/user', + ClientId='ExampleClient', + ClientSecret='MyVerySecretString', + ), + ), +] + + +#### + + +# Original tests +def test__prune_secret(): + assert elbv2._prune_secret(one_action[0]) == one_action[0] + + +def test__prune_ForwardConfig(): + expectation = {"TargetGroupArn": example_arn, "Type": "forward"} + pruned_config = elbv2._prune_ForwardConfig(one_action[0]) + assert pruned_config == expectation + + # https://github.com/ansible-collections/community.aws/issues/1089 + pruned_config = elbv2._prune_ForwardConfig(one_action_two_tg[0]) + assert pruned_config == one_action_two_tg[0] + + +#### + + +@pytest.mark.parametrize("action", simple_actions) +def test__prune_ForwardConfig_simplifiable_actions(action): + pruned_config = elbv2._prune_ForwardConfig(action) + assert pruned_config == simplified_action + + +@pytest.mark.parametrize("action", complex_actions) +def test__prune_ForwardConfig_non_simplifiable_actions(action): + pruned_config = elbv2._prune_ForwardConfig(action) + assert pruned_config == action + + +@pytest.mark.parametrize("action", oidc_actions) +def test__prune_secret_simplifiable_actions(action): + pruned_config = elbv2._prune_secret(action) + assert pruned_config == simplified_oidc_action + + +@pytest.mark.parametrize("action", complex_actions) +def test__prune_secret_non_simplifiable_actions(action): + pruned_config = elbv2._prune_secret(action) + assert pruned_config == action diff --git a/tests/unit/module_utils/test_elbv2.py b/tests/unit/module_utils/test_elbv2.py index c827bf41542..7fe70b1b2a7 100644 --- a/tests/unit/module_utils/test_elbv2.py +++ b/tests/unit/module_utils/test_elbv2.py @@ -47,20 +47,6 @@ ] -def test__prune_ForwardConfig(): - expectation = { - "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:966509639900:targetgroup/my-tg-58045486/5b231e04f663ae21", - "Type": "forward", - } - assert elbv2._prune_ForwardConfig(one_action[0]) == expectation - # https://github.com/ansible-collections/community.aws/issues/1089 - assert elbv2._prune_ForwardConfig(one_action_two_tg[0]) == one_action_two_tg[0] - - -def _prune_secret(): - assert elbv2._prune_secret(one_action[0]) == one_action[0] - - def _sort_actions_one_entry(): assert elbv2._sort_actions(one_action) == one_action