Repository: ansible/ansible

Issue:
Modules for AWS ElastiCache are not working in cn-north-1
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
`elasticache_subnet_group` and `elasticache`

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0.0
  config file = 
  configured module search path = Default w/o overrides
  python version = 2.7.12 (default, Nov 19 2016, 06:48:10) [GCC 5.4.0 20160609]
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
Xubuntu 16.04

##### SUMMARY
<!--- Explain the problem briefly -->
Aws elasticache modules are not working in `cn-north-1`, the same commands works fine in `eu-west-1`. Aws cli works fine in both regions.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
Run module `elasticache_subnet_group` in `cn-north-1`. I have the same behaviour for playbook and single command.

<!--- Paste example playbooks or commands between quotes below -->
- Example of not working command ( [output](https://gist.github.com/sszwed/dd857ede3079055b77f8885493d1159b) ) :

```
ansible -c local -i localhost, localhost -m elasticache_subnet_group -a "description='Subnet group for Redis' name=redis state=present subnets=subnet-aaaaaaaa,subnet-bbbbbbbb region=cn-north-1 profile=china" -vvvv
```

- Example of working command ( [output](https://gist.github.com/sszwed/f2b2e9d64f73c608e9120e1321b75fd8) ):
```
ansible -c local -i localhost, localhost -m elasticache_subnet_group -a "description='Subnet group for Redis' name=redis state=present subnets=subnet-cccccccc,subnet-dddddddd region=eu-west-1 profile=ireland" -vvvv
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Module works for all regions.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
In region where command works it takes 2-3 seconds to create subnet group. In `cn-north-1` it takes about a minute to fail.
<!--- Paste verbatim command output between quotes below -->
```
No config file found; using defaults
Set default localhost to localhost
Loading callback plugin minimal of type stdout, v2.0 from /usr/local/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc
META: ran handlers
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/cloud/amazon/elasticache_subnet_group.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: sszwed
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763 `" && echo ansible-tmp-1493119113.83-14610261905763="` echo /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763 `" ) && sleep 0'
<localhost> PUT /tmp/tmp3G1P22 TO /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/elasticache_subnet_group.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/ /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/elasticache_subnet_group.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/elasticache_subnet_group.py; rm -rf "/home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/" > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py", line 160, in <module>
    main()
  File "/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py", line 129, in main
    matching_groups = conn.describe_cache_subnet_groups(group_name, max_records=100)
  File "/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py", line 851, in describe_cache_subnet_groups
    path='/', params=params)
  File "/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py", line 1658, in _make_request
    path='/', params=params)
  File "/usr/local/lib/python2.7/dist-packages/boto/connection.py", line 1116, in make_request
    return self._mexe(http_request)
  File "/usr/local/lib/python2.7/dist-packages/boto/connection.py", line 1030, in _mexe
    raise ex
socket.gaierror: [Errno -2] Name or service not known

localhost | FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py\", line 160, in <module>\n    main()\n  File \"/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py\", line 129, in main\n    matching_groups = conn.describe_cache_subnet_groups(group_name, max_records=100)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py\", line 851, in describe_cache_subnet_groups\n    path='/', params=params)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py\", line 1658, in _make_request\n    path='/', params=params)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/connection.py\", line 1116, in make_request\n    return self._mexe(http_request)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/connection.py\", line 1030, in _mexe\n    raise ex\nsocket.gaierror: [Errno -2] Name or service not known\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 0
}
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/elasticache.py b/lib/ansible/modules/cloud/amazon/elasticache.py
--- a/lib/ansible/modules/cloud/amazon/elasticache.py
+++ b/lib/ansible/modules/cloud/amazon/elasticache.py
@@ -146,8 +146,7 @@
 
 try:
     import boto
-    from boto.elasticache.layer1 import ElastiCacheConnection
-    from boto.regioninfo import RegionInfo
+    from boto.elasticache import connect_to_region
     HAS_BOTO = True
 except ImportError:
     HAS_BOTO = False
@@ -430,10 +429,8 @@ def _requires_destroy_and_create(self):
     def _get_elasticache_connection(self):
         """Get an elasticache connection"""
         try:
-            endpoint = "elasticache.%s.amazonaws.com" % self.region
-            connect_region = RegionInfo(name=self.region, endpoint=endpoint)
-            return ElastiCacheConnection(
-                region=connect_region,
+            return connect_to_region(
+                region_name=self.region,
                 **self.aws_connect_kwargs
             )
         except boto.exception.NoAuthHandlerFound as e:


Test patch: