Repository: ansible/ansible-modules-core

Issue:
rds module sets Postgres to listen on port 3306 if not specified
##### Issue Type:

Bug Report
##### Ansible Version:

``` bash
[dvaida@scat Atlassian-Stash-Ansible]$ ansible --version
ansible 1.9 (devel ef9cb19976) last updated 2014/12/02 17:29:39 (GMT +200)
  lib/ansible/modules/core: (detached HEAD 63e81cfc2e) last updated 2014/10/30 15:43:29 (GMT +200)
  lib/ansible/modules/extras: (detached HEAD a0df36c6ab) last updated 2014/10/30 15:43:35 (GMT +200)
  v2/ansible/modules/core: (detached HEAD cb69744bce) last updated 2014/10/30 15:43:42 (GMT +200)
  v2/ansible/modules/extras: (detached HEAD 8a4f07eecd) last updated 2014/10/30 15:43:54 (GMT +200)
  configured module search path = None
[dvaida@scat Atlassian-Stash-Ansible]$
```
##### Environment:

FC19
##### Summary:

When the 'port' parameter is not specified, the rds module creates the Postgres instance listening on port 3306 (MySQL).
If the 'port' is set in the playbook to '5432', the DB instance is created correctly.
##### Steps To Reproduce:

```
- name: adding the RDS instance
    local_action:
      module: rds
      backup_retention: 14
      backup_window: 03:00-04:00
      command: create
      db_engine: postgres
      db_name: "{{ db_name }}" 
      engine_version: 9.3.5
      instance_name: "{{ db_instance_name }}"
      instance_type: db.t2.small
      maint_window: Sat:02:00-Sat:03:00
      size: 5
      subnet: "{{ db_subnet }}" 
      vpc_security_groups: "{{ private_postgres_sg_creation.group_id }}"
      username: "{{ db_master_username }}"
      password: "{{ db_master_password }}"
      region: "{{ region }}" 
      wait: yes
      wait_timeout: 1800
    register: rds_instance
```
##### Expected Results:

DB instance gets created and listens on correct port.
##### Actual Results:

Postgres RDS DB listens on port 3306.



Discussion:
I don't see this as a bug.  The doc states that the default port is 3306 as I assume that 3306 is the most popular.  If you're using a different database then you need to explicitly specify the port as a parameter.  

Changing the default of a parameter based on another parameter sounds like asking for trouble.

mysql default is 3306, postgres is 5432. be cool to have the module default to the app specific default based on db_engine: value.

http://www.postgresql.org/docs/8.3/static/app-postgres.html


Resolving patch:
diff --git a/cloud/amazon/rds.py b/cloud/amazon/rds.py
--- a/cloud/amazon/rds.py
+++ b/cloud/amazon/rds.py
@@ -112,12 +112,14 @@
     default: null
   port:
     description:
-      - Port number that the DB instance uses for connections.  Defaults to 3306 for mysql. Must be changed to 1521 for Oracle, 1433 for SQL Server, 5432 for PostgreSQL. Used only when command=create or command=replicate.
+      - Port number that the DB instance uses for connections. Used only when command=create or command=replicate.
+      - Prior to 2.0 it always defaults to null and the API would use 3306, it had to be set to other DB default values when not using MySql.
+        Starting at 2.0 it auotmaticaly defaults to what is expected for each c(db_engine).
     required: false
-    default: null
+    default: 3306 for mysql, 1521 for Oracle, 1433 for SQL Server, 5432 for PostgreSQL.
   upgrade:
     description:
-      - Indicates that minor version upgrades should be applied automatically. Used only when command=create or command=replicate. 
+      - Indicates that minor version upgrades should be applied automatically. Used only when command=create or command=replicate.
     required: false
     default: no
     choices: [ "yes", "no" ]
@@ -289,6 +291,12 @@
 except ImportError:
     has_rds2 = False
 
+DEFAULT_PORTS= {
+    'mysql': 3306,
+    'oracle': 1521,
+    'sqlserver': 1433,
+    'postgres': 5432,
+}
 
 class RDSException(Exception):
     def __init__(self, exc):
@@ -317,7 +325,7 @@ def get_db_instance(self, instancename):
             return None
 
     def get_db_snapshot(self, snapshotid):
-        try: 
+        try:
             return RDSSnapshot(self.connection.get_all_dbsnapshots(snapshot_id=snapshotid)[0])
         except boto.exception.BotoServerError, e:
             return None
@@ -994,7 +1002,7 @@ def main():
             parameter_group   = dict(required=False),
             license_model     = dict(choices=['license-included', 'bring-your-own-license', 'general-public-license', 'postgresql-license'], required=False),
             multi_zone        = dict(type='bool', default=False),
-            iops              = dict(required=False), 
+            iops              = dict(required=False),
             security_groups   = dict(required=False),
             vpc_security_groups = dict(type='list', required=False),
             port              = dict(required=False),
@@ -1002,7 +1010,7 @@ def main():
             option_group      = dict(required=False),
             maint_window      = dict(required=False),
             backup_window     = dict(required=False),
-            backup_retention  = dict(required=False), 
+            backup_retention  = dict(required=False),
             zone              = dict(aliases=['aws_zone', 'ec2_zone'], required=False),
             subnet            = dict(required=False),
             wait              = dict(type='bool', default=False),
@@ -1040,6 +1048,14 @@ def main():
     if not region:
         module.fail_json(msg="Region not specified. Unable to determine region from EC2_REGION.")
 
+    # set port to per db defaults if not specified
+    if module.params['port'] is None and module.params['command'] in ['create', 'replicate']:
+        if '-' in module.params['db_engine']:
+            engine = module.params['db_engine'].split('-')[0]
+        else:
+            engine = module.params['db_engine']
+        module.params['port'] = DEFAULT_PORTS[engine.lower()]
+
     # connect to the rds endpoint
     if has_rds2:
         conn = RDS2Connection(module, region, **aws_connect_params)
@@ -1047,7 +1063,7 @@ def main():
         conn = RDSConnection(module, region, **aws_connect_params)
 
     invocations[module.params.get('command')](module, conn)
-        
+
 # import module snippets
 from ansible.module_utils.basic import *
 from ansible.module_utils.ec2 import *


Test patch: