Skip to content

Commit

Permalink
rds_cluster: add support for removing cluster from global db (ansible…
Browse files Browse the repository at this point in the history
…-collections#1705)

rds_cluster: add support for removing cluster from global db

SUMMARY

add support for removing cluster from global db

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

rds_cluster
ADDITIONAL INFORMATION

Reviewed-by: Alina Buzachis
Reviewed-by: Mandar Kulkarni <[email protected]>
Reviewed-by: GomathiselviS
Reviewed-by: Helen Bailey <[email protected]>
Reviewed-by: Jill R
  • Loading branch information
mandar242 authored and alinabuzachis committed Oct 2, 2023
1 parent 7aa5b83 commit 3d0a3b6
Show file tree
Hide file tree
Showing 8 changed files with 375 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- rds_cluster - Add support for removing cluster from global db (https://github.com/ansible-collections/amazon.aws/pull/1705).
2 changes: 2 additions & 0 deletions plugins/module_utils/rds.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ def get_rds_method_attribute(method_name, module):
waiter = "role_disassociated"
elif method_name == "promote_read_replica":
waiter = "read_replica_promoted"
elif method_name == "db_cluster_promoting":
waiter = "db_cluster_promoting"
else:
waiter = "db_instance_available"
# Handle retry codes
Expand Down
18 changes: 18 additions & 0 deletions plugins/module_utils/waiters.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,19 @@
rds_data = {
"version": 2,
"waiters": {
"DBClusterPromoting": {
"delay": 5,
"maxAttempts": 60,
"operation": "DescribeDBClusters",
"acceptors": [
{
"state": "success",
"matcher": "pathAll",
"argument": "DBClusters[].Status",
"expected": "promoting",
},
],
},
"DBInstanceStopped": {
"delay": 20,
"maxAttempts": 60,
Expand Down Expand Up @@ -911,6 +924,11 @@ def route53_model(name):
elbv2_model("LoadBalancersDeleted"),
core_waiter.NormalizedOperationMethod(elbv2.describe_load_balancers),
),
("RDS", "db_cluster_promoting"): lambda rds: core_waiter.Waiter(
"db_cluster_promoting",
rds_model("DBClusterPromoting"),
core_waiter.NormalizedOperationMethod(rds.describe_db_clusters),
),
("RDS", "db_instance_stopped"): lambda rds: core_waiter.Waiter(
"db_instance_stopped",
rds_model("DBInstanceStopped"),
Expand Down
85 changes: 84 additions & 1 deletion plugins/modules/rds_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,13 @@
aliases:
- maintenance_window
type: str
remove_from_global_db:
description:
- If set to C(true), the cluster will be removed from global DB.
- Parameters I(global_cluster_identifier), I(db_cluster_identifier) must be specified when I(remove_from_global_db=true).
type: bool
required: False
version_added: 6.5.0
replication_source_identifier:
description:
- The Amazon Resource Name (ARN) of the source DB instance or DB cluster if this DB cluster is created as a Read Replica.
Expand Down Expand Up @@ -463,6 +470,42 @@
engine: aurora-postgresql
state: present
db_instance_class: 'db.t3.medium'
- name: Remove a cluster from global DB (do not delete)
amazon.aws.rds_cluster:
db_cluster_identifier: '{{ cluster_id }}'
global_cluster_identifier: '{{ global_cluster_id }}'
remove_from_global_db: true
- name: Remove a cluster from global DB and Delete without creating a final snapshot
amazon.aws.rds_cluster:
engine: aurora
password: "{{ password }}"
username: "{{ username }}"
cluster_id: "{{ cluster_id }}"
skip_final_snapshot: true
remove_from_global_db: true
wait: true
state: absent
- name: Update cluster port and WAIT for remove secondary DB cluster from global DB to complete
amazon.aws.rds_cluster:
db_cluster_identifier: "{{ secondary_cluster_name }}"
global_cluster_identifier: "{{ global_cluster_name }}"
remove_from_global_db: true
state: present
port: 3389
region: "{{ secondary_cluster_region }}"
- name: Update cluster port and DO NOT WAIT for remove secondary DB cluster from global DB to complete
amazon.aws.rds_cluster:
db_cluster_identifier: "{{ secondary_cluster_name }}"
global_cluster_identifier: "{{ global_cluster_name }}"
remove_from_global_db: true
state: present
port: 3389
region: "{{ secondary_cluster_region }}"
wait: false
"""

RETURN = r"""
Expand Down Expand Up @@ -1102,6 +1145,33 @@ def ensure_present(cluster, parameters, method_name, method_options_name):
return changed


def handle_remove_from_global_db(module, cluster):
global_cluster_id = module.params.get("global_cluster_identifier")
db_cluster_id = module.params.get("db_cluster_identifier")
db_cluster_arn = cluster["DBClusterArn"]

if module.check_mode:
return True

try:
client.remove_from_global_cluster(DbClusterIdentifier=db_cluster_arn, GlobalClusterIdentifier=global_cluster_id)
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
module.fail_json_aws(
e, msg=f"Failed to remove cluster {db_cluster_id} from global DB cluster {global_cluster_id}."
)

# for replica cluster - wait for cluster to change status from 'available' to 'promoting'
# only replica/secondary clusters have "GlobalWriteForwardingStatus" field
if "GlobalWriteForwardingStatus" in cluster:
wait_for_cluster_status(client, module, db_cluster_id, "db_cluster_promoting")

# if wait=true, wait for db cluster remove from global db operation to complete
if module.params.get("wait"):
wait_for_cluster_status(client, module, db_cluster_id, "cluster_available")

return True


def main():
global module
global client
Expand Down Expand Up @@ -1154,6 +1224,7 @@ def main():
port=dict(type="int"),
preferred_backup_window=dict(aliases=["backup_window"]),
preferred_maintenance_window=dict(aliases=["maintenance_window"]),
remove_from_global_db=dict(type="bool"),
replication_source_identifier=dict(aliases=["replication_src_id"]),
restore_to_time=dict(),
restore_type=dict(choices=["full-copy", "copy-on-write"]),
Expand Down Expand Up @@ -1190,6 +1261,7 @@ def main():
required_if=[
["creation_source", "snapshot", ["snapshot_identifier", "engine"]],
["creation_source", "s3", required_by_s3_creation_source],
["remove_from_global_db", True, ["global_cluster_identifier", "db_cluster_identifier"]],
],
mutually_exclusive=[
["s3_bucket_name", "source_db_cluster_identifier", "snapshot_identifier"],
Expand Down Expand Up @@ -1244,12 +1316,17 @@ def main():
msg="skip_final_snapshot is False but all of the following are missing: final_snapshot_identifier"
)

parameters = arg_spec_to_rds_params(dict((k, module.params[k]) for k in module.params if k in parameter_options))
changed = False

parameters = arg_spec_to_rds_params(dict((k, module.params[k]) for k in module.params if k in parameter_options))
method_name, method_options_name = get_rds_method_attribute_name(cluster)

if method_name:
if method_name == "delete_db_cluster":
if cluster and module.params.get("remove_from_global_db"):
if cluster["Engine"] in ["aurora", "aurora-mysql", "aurora-postgresql"]:
changed = handle_remove_from_global_db(module, cluster)

call_method(client, module, method_name, eval(method_options_name)(parameters))
changed = True
else:
Expand All @@ -1260,6 +1337,12 @@ def main():
else:
cluster_id = module.params["db_cluster_identifier"]

if cluster_id and get_cluster(cluster_id) and module.params.get("remove_from_global_db"):
if cluster["Engine"] in ["aurora", "aurora-mysql", "aurora-postgresql"]:
if changed:
wait_for_cluster_status(client, module, cluster_id, "cluster_available")
changed |= handle_remove_from_global_db(module, cluster)

result = camel_dict_to_snake_dict(get_cluster(cluster_id))

if result:
Expand Down
1 change: 1 addition & 0 deletions tests/integration/requirements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
collections:
- ansible.windows
- ansible.utils # ipv6 filter
- amazon.cloud # used by integration tests - rds_cluster_modify
17 changes: 17 additions & 0 deletions tests/integration/targets/rds_cluster_modify/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,20 @@ new_cluster_id: ansible-test-cluster-{{ tiny_prefix }}-new
new_port: 1155
new_password: test-rds_password-new
new_db_parameter_group_name: ansible-test-db-parameter-group-{{ tiny_prefix }}-new

test_engine: aurora-mysql
test_engine_version: 8.0
test_instance_class: db.r5.large

# Global cluster parameters ================================
test_global_cluster_name: ansible-test-global-{{ tiny_prefix }}

# Primary cluster parameters ================================
test_primary_cluster_name: ansible-test-primary-{{ tiny_prefix }}
test_primary_cluster_region: us-west-2
test_primary_cluster_instance_name: ansible-test-instance-primary-{{ tiny_prefix }}

# Replica cluster parameters ================================
test_replica_cluster_name: ansible-test-replica-{{ tiny_prefix }}
test_replica_cluster_region: eu-north-1
test_replica_cluster_instance_name: ansible-test-instance-replica-{{ tiny_prefix }}
6 changes: 6 additions & 0 deletions tests/integration/targets/rds_cluster_modify/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
secret_key: '{{ aws_secret_key }}'
session_token: '{{ security_token | default(omit) }}'
block:

# Disabled: Below tests require use of more than 1 region, not supported by CI at the moment
# Tests have been ran, tested, and verified locally on us-west-2 (primary), eu-north-1 (replica)
# - name: Run tests for testing remove cluster from global db
# import_tasks: remove_from_global_db.yaml

- name: Ensure the resource doesn't exist
rds_cluster:
id: '{{ cluster_id }}'
Expand Down
Loading

0 comments on commit 3d0a3b6

Please sign in to comment.