From 169994caa4f87c9a069f8944e06a2becf29e75d4 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 24 Mar 2021 15:25:36 +0100 Subject: [PATCH 1/5] rds_instance: Add purge_security_groups feature for vpc_security_groups_ids. * Fixes: #385 --- plugins/modules/rds_instance.py | 38 +++++++++++-- .../tasks/test_vpc_security_groups.yml | 56 ++++++++++++++++++- 2 files changed, 86 insertions(+), 8 deletions(-) diff --git a/plugins/modules/rds_instance.py b/plugins/modules/rds_instance.py index 0dd763c369f..ba8433c4bd6 100644 --- a/plugins/modules/rds_instance.py +++ b/plugins/modules/rds_instance.py @@ -416,6 +416,13 @@ - A list of EC2 VPC security groups to associate with the DB cluster. type: list elements: str + purge_security_groups: + description: + - Set to False to retain any enabled security groups that aren't specified in the task and are associated with the instance. + - Can be applied to I(vpc_security_group_ids) and I(db_security_groups) + type: bool + default: True + version_added: 1.5.0 ''' EXAMPLES = r''' @@ -451,6 +458,15 @@ id: "{{ instance_id }}" state: absent final_snapshot_identifier: "{{ snapshot_id }}" + +- name: Add a new security group without purge + community.aws.rds_instance: + id: "{{ instance_id }}" + state: present + vpc_security_group_ids: + - sg-0be17ba10c9286b0b + purge_security_groups: false + register: result ''' RETURN = r''' @@ -752,6 +768,7 @@ except ImportError: pass # caught by AnsibleAWSModule + from ansible.module_utils._text import to_text from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict from ansible.module_utils.six import string_types @@ -861,6 +878,7 @@ def get_options_with_changing_values(client, module, parameters): port = module.params['port'] apply_immediately = parameters.pop('ApplyImmediately', None) cloudwatch_logs_enabled = module.params['enable_cloudwatch_logs_exports'] + purge_security_groups = module.params['purge_security_groups'] if port: parameters['DBPortNumber'] = port @@ -872,7 +890,7 @@ def get_options_with_changing_values(client, module, parameters): parameters.pop('Iops', None) instance = get_instance(client, module, instance_id) - updated_parameters = get_changing_options_with_inconsistent_keys(parameters, instance, purge_cloudwatch_logs) + updated_parameters = get_changing_options_with_inconsistent_keys(parameters, instance, purge_cloudwatch_logs, purge_security_groups) updated_parameters.update(get_changing_options_with_consistent_keys(parameters, instance)) parameters = updated_parameters @@ -884,7 +902,7 @@ def get_options_with_changing_values(client, module, parameters): parameters['DBInstanceIdentifier'] = instance_id if apply_immediately is not None: parameters['ApplyImmediately'] = apply_immediately - + return parameters @@ -909,8 +927,8 @@ def get_current_attributes_with_inconsistent_keys(instance): else: options['ProcessorFeatures'] = instance.get('ProcessorFeatures', {}) options['OptionGroupName'] = [g['OptionGroupName'] for g in instance['OptionGroupMemberships']] - options['DBSecurityGroups'] = [sg['DBSecurityGroupName'] for sg in instance['DBSecurityGroups'] if sg['Status'] in ['adding', 'active']] - options['VpcSecurityGroupIds'] = [sg['VpcSecurityGroupId'] for sg in instance['VpcSecurityGroups'] if sg['Status'] in ['adding', 'active']] + options['DBSecurityGroups'] = [sg['DBSecurityGroupName'] for sg in instance['DBSecurityGroups']] if sg['Status'] in ['adding', 'active']] + options['VpcSecurityGroupIds'] = [sg['VpcSecurityGroupId'] for sg in instance['VpcSecurityGroups']] if sg['Status'] in ['adding', 'active']] options['DBParameterGroupName'] = [parameter_group['DBParameterGroupName'] for parameter_group in instance['DBParameterGroups']] options['AllowMajorVersionUpgrade'] = None options['EnableIAMDatabaseAuthentication'] = instance['IAMDatabaseAuthenticationEnabled'] @@ -922,7 +940,7 @@ def get_current_attributes_with_inconsistent_keys(instance): return options -def get_changing_options_with_inconsistent_keys(modify_params, instance, purge_cloudwatch_logs): +def get_changing_options_with_inconsistent_keys(modify_params, instance, purge_cloudwatch_logs, purge_security_groups): changing_params = {} current_options = get_current_attributes_with_inconsistent_keys(instance) @@ -938,7 +956,9 @@ def get_changing_options_with_inconsistent_keys(modify_params, instance, purge_c # TODO: allow other purge_option module parameters rather than just checking for things to add if isinstance(current_option, list): if isinstance(desired_option, list): - if set(desired_option) <= set(current_option): + if set(desired_option) < set(current_option): + if (option == 'DBSecurityGroups' or option == 'VpcSecurityGroupIds') and purge_security_groups: + changing_params[option] = desired_option continue elif isinstance(desired_option, string_types): if desired_option in current_option: @@ -958,6 +978,11 @@ def get_changing_options_with_inconsistent_keys(modify_params, instance, purge_c format_option['DisableLogTypes'] = list(current_option.difference(desired_option)) if format_option['EnableLogTypes'] or format_option['DisableLogTypes']: changing_params[option] = format_option + elif option == 'DBSecurityGroups' or option == 'VpcSecurityGroupIds': + if purge_security_groups: + changing_params[option] = desired_option + else: + changing_params[option] = list(set(current_option) | set(desired_option)) else: changing_params[option] = desired_option @@ -1082,6 +1107,7 @@ def main(): purge_tags=dict(type='bool', default=True), read_replica=dict(type='bool'), wait=dict(type='bool', default=True), + purge_security_groups=dict(type='bool', default=True), ) parameter_options = dict( diff --git a/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml b/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml index f481b71fd72..f71c6af2fc9 100644 --- a/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml +++ b/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml @@ -73,18 +73,70 @@ that: - result.changed - "result.db_instance_identifier == '{{ instance_id }}'" + - "result.vpc_security_groups | selectattr('status', 'in', ['active', 'adding']) | list | length == 2" - - name: Add a new security group + - name: Add a new security group without purge (check_mode) rds_instance: id: "{{ instance_id }}" state: present vpc_security_group_ids: - "{{ sgs_result.results.2.group_id }}" + apply_immediately: true + purge_security_groups: false + check_mode: true register: result - assert: that: - result.changed + - "result.db_instance_identifier == '{{ instance_id }}'" + + - name: Add a new security group without purge + rds_instance: + id: "{{ instance_id }}" + state: present + vpc_security_group_ids: + - "{{ sgs_result.results.2.group_id }}" + apply_immediately: true + purge_security_groups: false + register: result + + - assert: + that: + - result.changed + - "result.db_instance_identifier == '{{ instance_id }}'" + - "result.vpc_security_groups | selectattr('status', 'in', ['active', 'adding']) | list | length == 3" + + - name: Add a new security group without purge (test idempotence) + rds_instance: + id: "{{ instance_id }}" + state: present + vpc_security_group_ids: + - "{{ sgs_result.results.2.group_id }}" + apply_immediately: true + purge_security_groups: false + register: result + + - assert: + that: + - not result.changed + - "result.db_instance_identifier == '{{ instance_id }}'" + + - name: Add a security group with purge + rds_instance: + id: "{{ instance_id }}" + state: present + vpc_security_group_ids: + - "{{ sgs_result.results.2.group_id }}" + apply_immediately: true + register: result + + - assert: + that: + - result.changed + - "result.db_instance_identifier == '{{ instance_id }}'" + - "result.vpc_security_groups | selectattr('status', 'in', ['active', 'adding']) | list | length == 1" + - "result.vpc_security_groups | selectattr('status', 'equalto', 'removing') | list | length == 2" always: @@ -127,7 +179,7 @@ - {"cidr": "10.122.122.160/28", "zone": "{{ aws_region }}c"} - {"cidr": "10.122.122.176/28", "zone": "{{ aws_region }}d"} - - name: create a VPC + - name: Delete VPC ec2_vpc_net: name: "{{ resource_prefix }}-vpc" state: absent From 294452238e2cf29f48d6066d19c014cd894dbc70 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Thu, 25 Mar 2021 19:34:17 +0100 Subject: [PATCH 2/5] * Fix syntax error * Sanity fix Signed-off-by: Alina Buzachis --- plugins/modules/rds_instance.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/modules/rds_instance.py b/plugins/modules/rds_instance.py index ba8433c4bd6..0c7fe155303 100644 --- a/plugins/modules/rds_instance.py +++ b/plugins/modules/rds_instance.py @@ -902,7 +902,7 @@ def get_options_with_changing_values(client, module, parameters): parameters['DBInstanceIdentifier'] = instance_id if apply_immediately is not None: parameters['ApplyImmediately'] = apply_immediately - + return parameters @@ -927,8 +927,8 @@ def get_current_attributes_with_inconsistent_keys(instance): else: options['ProcessorFeatures'] = instance.get('ProcessorFeatures', {}) options['OptionGroupName'] = [g['OptionGroupName'] for g in instance['OptionGroupMemberships']] - options['DBSecurityGroups'] = [sg['DBSecurityGroupName'] for sg in instance['DBSecurityGroups']] if sg['Status'] in ['adding', 'active']] - options['VpcSecurityGroupIds'] = [sg['VpcSecurityGroupId'] for sg in instance['VpcSecurityGroups']] if sg['Status'] in ['adding', 'active']] + options['DBSecurityGroups'] = [sg['DBSecurityGroupName'] for sg in instance['DBSecurityGroups'] if sg['Status'] in ['adding', 'active']] + options['VpcSecurityGroupIds'] = [sg['VpcSecurityGroupId'] for sg in instance['VpcSecurityGroups'] if sg['Status'] in ['adding', 'active']] options['DBParameterGroupName'] = [parameter_group['DBParameterGroupName'] for parameter_group in instance['DBParameterGroups']] options['AllowMajorVersionUpgrade'] = None options['EnableIAMDatabaseAuthentication'] = instance['IAMDatabaseAuthenticationEnabled'] From f4263be49abf230a8f3b2b0a4e20e5b9d80e4907 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Tue, 30 Mar 2021 13:39:29 +0200 Subject: [PATCH 3/5] * Address reviewer's comments * Add changelog Signed-off-by: Alina Buzachis --- .../fragments/500-rds_instance-purge-sg-option.yml | 2 ++ plugins/modules/rds_instance.py | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/500-rds_instance-purge-sg-option.yml diff --git a/changelogs/fragments/500-rds_instance-purge-sg-option.yml b/changelogs/fragments/500-rds_instance-purge-sg-option.yml new file mode 100644 index 00000000000..77c103cf399 --- /dev/null +++ b/changelogs/fragments/500-rds_instance-purge-sg-option.yml @@ -0,0 +1,2 @@ +minor_changes: +- rds_instance - new ``purge_security_groups`` parameter (https://github.com/ansible-collections/community.aws/issues/385). diff --git a/plugins/modules/rds_instance.py b/plugins/modules/rds_instance.py index 0c7fe155303..0dae125889b 100644 --- a/plugins/modules/rds_instance.py +++ b/plugins/modules/rds_instance.py @@ -956,9 +956,12 @@ def get_changing_options_with_inconsistent_keys(modify_params, instance, purge_c # TODO: allow other purge_option module parameters rather than just checking for things to add if isinstance(current_option, list): if isinstance(desired_option, list): - if set(desired_option) < set(current_option): - if (option == 'DBSecurityGroups' or option == 'VpcSecurityGroupIds') and purge_security_groups: - changing_params[option] = desired_option + if ( + set(desired_option) < set(current_option) and + option in ('DBSecurityGroups', 'VpcSecurityGroupIds',) and purge_security_groups + ): + changing_params[option] = desired_option + elif set(desired_option) <= set(current_option): continue elif isinstance(desired_option, string_types): if desired_option in current_option: @@ -978,7 +981,7 @@ def get_changing_options_with_inconsistent_keys(modify_params, instance, purge_c format_option['DisableLogTypes'] = list(current_option.difference(desired_option)) if format_option['EnableLogTypes'] or format_option['DisableLogTypes']: changing_params[option] = format_option - elif option == 'DBSecurityGroups' or option == 'VpcSecurityGroupIds': + elif option in ('DBSecurityGroups', 'VpcSecurityGroupIds',): if purge_security_groups: changing_params[option] = desired_option else: From c736fdaf490c631b83970bf6ac56521f387010c7 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 7 Apr 2021 12:58:24 +0200 Subject: [PATCH 4/5] Whitespace linting --- .../targets/rds_instance/tasks/test_vpc_security_groups.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml b/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml index f71c6af2fc9..13d2b6486fc 100644 --- a/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml +++ b/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml @@ -90,7 +90,6 @@ that: - result.changed - "result.db_instance_identifier == '{{ instance_id }}'" - - name: Add a new security group without purge rds_instance: id: "{{ instance_id }}" @@ -106,7 +105,6 @@ - result.changed - "result.db_instance_identifier == '{{ instance_id }}'" - "result.vpc_security_groups | selectattr('status', 'in', ['active', 'adding']) | list | length == 3" - - name: Add a new security group without purge (test idempotence) rds_instance: id: "{{ instance_id }}" From 8d2de3ef99626c958fa501ff6a6884d84ca2297d Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 7 Apr 2021 13:03:26 +0200 Subject: [PATCH 5/5] Whitespace linting --- .../targets/rds_instance/tasks/test_vpc_security_groups.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml b/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml index 13d2b6486fc..940ce5b0fae 100644 --- a/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml +++ b/tests/integration/targets/rds_instance/tasks/test_vpc_security_groups.yml @@ -90,6 +90,7 @@ that: - result.changed - "result.db_instance_identifier == '{{ instance_id }}'" + - name: Add a new security group without purge rds_instance: id: "{{ instance_id }}" @@ -105,6 +106,7 @@ - result.changed - "result.db_instance_identifier == '{{ instance_id }}'" - "result.vpc_security_groups | selectattr('status', 'in', ['active', 'adding']) | list | length == 3" + - name: Add a new security group without purge (test idempotence) rds_instance: id: "{{ instance_id }}" @@ -119,7 +121,7 @@ that: - not result.changed - "result.db_instance_identifier == '{{ instance_id }}'" - + - name: Add a security group with purge rds_instance: id: "{{ instance_id }}"