Repository: ansible/ansible

Issue:
Redshift module - bug in cluster delete
##### ISSUE TYPE

 - Bug Report

##### COMPONENT NAME

redshift module

##### ANSIBLE VERSION

```
ansible 2.3.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609]
```

##### CONFIGURATION

N/A

##### OS / ENVIRONMENT

N/A

##### SUMMARY

Deleting a Redshift cluster fails with an error

##### STEPS TO REPRODUCE

```yaml
- name: Delete the Redshift cluster
  redshift:
    command: "delete"
    region: "eu-west-1"
    identifier: "my_database_cluster"
```

##### EXPECTED RESULTS

The cluster should be deleted

##### ACTUAL RESULTS

```
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_lnv2tks5/ansible_module_redshift.py", line 506, in <module>
    main()
  File "/tmp/ansible_lnv2tks5/ansible_module_redshift.py", line 494, in main
    (changed, cluster) = delete_cluster(module, conn)
  File "/tmp/ansible_lnv2tks5/ansible_module_redshift.py", line 353, in delete_cluster
    redshift.delete_custer(
AttributeError: 'RedshiftConnection' object has no attribute 'delete_custer'

fatal: [127.0.0.1]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_lnv2tks5/ansible_module_redshift.py\", line 506, in <module>\n    main()\n  File \"/tmp/ansible_lnv2tks5/ansible_module_redshift.py\", line 494, in main\n    (changed, cluster) = delete_cluster(module, conn)\n  File \"/tmp/ansible_lnv2tks5/ansible_module_redshift.py\", line 353, in delete_cluster\n    redshift.delete_custer(\nAttributeError: 'RedshiftConnection' object has no attribute 'delete_custer'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 0
}
```



Discussion:
This seems to be caused by a typo (`delete_custer` -> `delete_cluster`).

Once this is fixed, another error pops up: `FinalClusterSnapshotIdentifier is required unless SkipFinalClusterSnapshot is specified.` 

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/redshift.py b/lib/ansible/modules/cloud/amazon/redshift.py
--- a/lib/ansible/modules/cloud/amazon/redshift.py
+++ b/lib/ansible/modules/cloud/amazon/redshift.py
@@ -80,6 +80,19 @@
       - VPC security group
     aliases: ['vpc_security_groups']
     default: null
+  skip_final_cluster_snapshot:
+    description:
+      - skip a final snapshot before deleting the cluster. Used only when command=delete.
+    aliases: ['skip_final_snapshot']
+    default: false
+    version_added: "2.4"
+  final_cluster_snapshot_identifier:
+    description:
+      - identifier of the final snapshot to be created before deleting the cluster. If this parameter is provided,
+        final_cluster_snapshot_identifier must be false. Used only when command=delete.
+    aliases: ['final_snapshot_id']
+    default: null
+    version_added: "2.4"
   preferred_maintenance_window:
     description:
       - maintenance window
@@ -149,6 +162,13 @@
     identifier=new_cluster
     username=cluster_admin
     password=1nsecure
+
+# Cluster delete example
+- redshift:
+    command: delete
+    identifier: new_cluster
+    skip_final_cluster_snapshot: true
+    wait: true
 '''
 
 RETURN = '''
@@ -327,12 +347,18 @@ def delete_cluster(module, redshift):
     redshift: authenticated redshift connection object
     """
 
-    identifier   = module.params.get('identifier')
-    wait         = module.params.get('wait')
+    identifier = module.params.get('identifier')
+    wait = module.params.get('wait')
     wait_timeout = module.params.get('wait_timeout')
+    skip_final_cluster_snapshot = module.params.get('skip_final_cluster_snapshot')
+    final_cluster_snapshot_identifier = module.params.get('final_cluster_snapshot_identifier')
 
     try:
-        redshift.delete_custer( identifier )
+        redshift.delete_cluster(
+            identifier,
+            skip_final_cluster_snapshot,
+            final_cluster_snapshot_identifier
+        )
     except boto.exception.JSONResponseError as e:
         module.fail_json(msg=str(e))
 
@@ -422,6 +448,8 @@ def main():
         cluster_type                        = dict(choices=['multi-node', 'single-node', ], default='single-node'),
         cluster_security_groups             = dict(aliases=['security_groups'], type='list'),
         vpc_security_group_ids              = dict(aliases=['vpc_security_groups'], type='list'),
+        skip_final_cluster_snapshot         = dict(aliases=['skip_final_snapshot'], type='bool', default=False),
+        final_cluster_snapshot_identifier   = dict(aliases=['final_snapshot_id'], required=False),
         cluster_subnet_group_name           = dict(aliases=['subnet']),
         availability_zone                   = dict(aliases=['aws_zone', 'zone']),
         preferred_maintenance_window        = dict(aliases=['maintance_window', 'maint_window']),
@@ -437,11 +465,16 @@ def main():
         new_cluster_identifier              = dict(aliases=['new_identifier']),
         wait                                = dict(type='bool', default=False),
         wait_timeout                        = dict(type='int', default=300),
-    )
-    )
+    ))
+
+    required_if = [
+        ('command', 'delete', ['skip_final_cluster_snapshot']),
+        ('skip_final_cluster_snapshot', False, ['final_cluster_snapshot_identifier'])
+    ]
 
     module = AnsibleModule(
         argument_spec=argument_spec,
+        required_if=required_if
     )
 
     if not HAS_BOTO:


Test patch: