Repository: ansible/ansible

Issue:
ec2_group - Using SG's from peered VPC's
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
ec2_group

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.1.0
  config file = 
  configured module search path = Default w/o overrides
```
install: sudo pip install -U git+https://github.com/ansible/ansible.git@v2.2.1.0-0.2.rc2 --upgrade --ignore-installed six

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
default ansible.cfg

##### 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.
-->
OS X El Capitan 10.11.6
Multi VPC AWS environment.  Peers between VPC's w/appropriate routing between them

##### SUMMARY
<!--- Explain the problem briefly -->
ec2_group does not allow group_name to use groups via group name from other peered VPC's.  This worked in v1.9.6 and v2.0.2.  It appears to be due to some additional conditions that were added on 7/27/16.  If I revert this change, it works as expected.

https://github.com/ansible/ansible/commit/04199140c5f089db8215aee4842d5987cf12e28d

Using group_id with the name of the security group in a different VPC works but is not idempotent.  It will create the rule if it's new but will fail if it already exists.

##### 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.
-->
Attempt to use a AWS security group name from another VPC with required peering present using group_name:
```
- name: Provision Security Groups
  ec2_group:
    name: MyGroup
    description: MyDesc
    region: us-east-1
    vpc_id: vpc-xxxxxxxx
    rules:
       - proto: tcp
          from_port: 22
          to_port: 22
          group_name: <Other_VPC_SG_NAME>
```

Attempt to use a AWS security group name from another VPC with required peering present using group_id:
```
- name: Provision Security Groups
  ec2_group:
    name: MyGroup
    description: MyDesc
    region: us-east-1
    vpc_id: vpc-xxxxxxxx
    rules:
       - proto: tcp
          from_port: 22
          to_port: 22
          group_id: <Other_VPC_SG_NAME>
```
<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Translate group name to group ID (sg-xxxxxxxx) and update rule with the security group ID of the other VPC's security group.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
The group in the peered VPC is not found and an attempt to create a new group in the current VPC is executed.  In my case, this fails due to "no description"
<!--- Paste verbatim command output between quotes below -->
Message using group_name with security group name from a different VPC
```
"msg": "group <PeeredVPCGroupName> will be automatically created by rule {'to_port': 22, 'from_port': 22, 'group_name': '<PeeredVPCGroupName>', 'proto': 'tcp'} and no description was provided"
```

Message using group_id with security group name from a different VPC if the rule exists.  If the rule does not exist, it is added as expected.
```
    "module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/t8/vdrxm90s1ps41pghp7wxn8n80000gp/T/ansible_pJu0pZ/ansible_module_ec2_group.py\", line 479, in <module>\n    main()\n  File \"/var/folders/t8/vdrxm90s1ps41pghp7wxn8n80000gp/T/ansible_pJu0pZ/ansible_module_ec2_group.py\", line 374, in main\n    group.authorize(rule['proto'], rule['from_port'], rule['to_port'], thisip, grantGroup)\n  File \"/Library/Python/2.7/site-packages/boto-2.38.0-py2.7.egg/boto/ec2/securitygroup.py\", line 203, in authorize\n    dry_run=dry_run)\n  File \"/Library/Python/2.7/site-packages/boto-2.38.0-py2.7.egg/boto/ec2/connection.py\", line 3191, in authorize_security_group\n    params, verb='POST')\n  File \"/Library/Python/2.7/site-packages/boto-2.38.0-py2.7.egg/boto/connection.py\", line 1227, in get_status\n    raise self.ResponseError(response.status, response.reason, body)\nboto.exception.EC2ResponseError: EC2ResponseError: 400 Bad Request\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response><Errors><Error><Code>InvalidPermission.Duplicate</Code><Message>the specified rule \"peer: sg-xxxxxxxx, TCP, from port: 22, to port: 22, ALLOW\" already exists</Message></Error></Errors><RequestID>b9ec5eee-4a86-49d7-90b8-86bfbf2ba21b</RequestID></Response>\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE"
```



Discussion:
I'm experiencing the same thing. It detects the group just fine either by the group's exact name or by its ID when using `group_id`. However, it fails with the error below because it appears to be trying to create that group - even though it found the group.

Ansible version 2.2.0.0

Vars:
```
  ssh_ingress_rules:  
    - proto: tcp
       from_port: 0
       to_port: 65535
       group_id: "sg-ebb4d54e" ## Security Group from peered VPC
     - proto: tcp
       from_port: 0
       to_port: 65535
       group_name: "bootstrap-a-{{ app_env }}"
```
Playbook:
```
   - name: vpc SSH Security Group
      ec2_group:
        name: 'ssh-{{ vpc }}'
        description: 'ssh-{{ vpc }}'
        vpc_id: '{{ vpc_id_found }}'
        region: '{{ region }}'
        rules: '{{ ssh_ingress_rules }}'
```

Fails with the following error:

```
task path: /Users/me/src/ansible-infrastructure/playbooks/my_appy.ml:48
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: <Response><Errors><Error><Code>InvalidPermission.Duplicate</Code><Message>the specified rule "peer: sg-ebb4d54e, TCP, from port: 0, to port: 65535, ALLOW" already exists</Message></Error></Errors><RequestID>9ae3bc33-3e9f-433a-a51c-ea43df7eea47</RequestID></Response>
fatal: [127.0.0.1]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/ql/w7g6tb392mndtdk71gllj0040000gp/T/ansible_0FRqV5/ansible_module_ec2_group.py\", line 478, in <module>\n    main()\n  File \"/var/folders/ql/w7g6tb392mndtdk71gllj0040000gp/T/ansible_0FRqV5/ansible_module_ec2_group.py\", line 373, in main\n    group.authorize(rule['proto'], rule['from_port'], rule['to_port'], thisip, grantGroup)\n  File \"/Library/Python/2.7/site-packages/boto/ec2/securitygroup.py\", line 203, in authorize\n    dry_run=dry_run)\n  File \"/Library/Python/2.7/site-packages/boto/ec2/connection.py\", line 3191, in authorize_security_group\n    params, verb='POST')\n  File \"/Library/Python/2.7/site-packages/boto/connection.py\", line 1226, in get_status\n    raise self.ResponseError(response.status, response.reason, body)\nboto.exception.EC2ResponseError: EC2ResponseError: 400 Bad Request\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response><Errors><Error><Code>InvalidPermission.Duplicate</Code><Message>the specified rule \"peer: sg-ebb4d54e, TCP, from port: 0, to port: 65535, ALLOW\" already exists</Message></Error></Errors><RequestID>9ae3bc33-3e9f-433a-a51c-ea43df7eea47</RequestID></Response>\n", "module_stdout": "", "msg": "MODULE FAILURE"}
	to retry, use: --limit @/Users/me/.ansible-retry/my_app.retry

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=8    changed=1    unreachable=0    failed=1
```
cc @adq
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/ec2_group.py b/lib/ansible/modules/cloud/amazon/ec2_group.py
--- a/lib/ansible/modules/cloud/amazon/ec2_group.py
+++ b/lib/ansible/modules/cloud/amazon/ec2_group.py
@@ -385,7 +385,7 @@ def get_target_from_rule(module, client, rule, name, group, groups, vpc_id):
             group_id = group['GroupId']
             groups[group_id] = group
             groups[group_name] = group
-        elif group_name in groups and (vpc_id is None or groups[group_name]['VpcId'] == vpc_id):
+        elif group_name in groups:
             group_id = groups[group_name]['GroupId']
         else:
             if not rule.get('group_desc', '').strip():


Test patch: