Repository: ansible/ansible

Issue:
Increase Azure network interface provisioning flexibility
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
-->

##### ISSUE TYPE
Feature Idea
<!--- Pick one below and delete the rest -->
 - Bug Report
 - Feature Idea
 - Documentation Report

##### COMPONENT NAME
azure_rm_networkinterface
<!---
Name of the module, plugin, task or feature
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
N/A
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, 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.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->

##### SUMMARY
The current implementation of the azure_rm_networkinterface does not allow to create a NIC in a resource group R and connect it to a virtual network in a different resource group X. The implementation is assuming that both are in the same resource group and lacks configuration of a separate resource group where the virtual network lives in.

In contrast to that this is already possible with the azure_rm_virtualmachine module which offers a dedicated option `virtual_network_resource_group` for that purpose



<!--- Explain the problem briefly -->

##### 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.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: Create a network interface that connects to a vnet in a different resource group
  azure_rm_networkinterface:
        name: nic001
        resource_group: Testing
        virtual_network_name: vnet001
        virtual_network_resource_group: TestingNet
        subnet_name: subnet001
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Once implemented, it should be possible to connect NICs to virtual networks in different resource groups, as it's currently already possible with the azure_rm_virtualmachine module

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```

```



Discussion:
Files identified in the description:
* [lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @haroldwongms @nitzmahone @trstringer @xscript @yuwzho @zikalino
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Documentation should be updated. @zikalino will work on it.

Resolving patch:
diff --git a/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py b/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py
--- a/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py
+++ b/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py
@@ -50,6 +50,15 @@
         description:
             - Valid azure location. Defaults to location of the resource group.
         default: resource_group location
+        required: false
+    virtual_network_resource_group:
+        description:
+        - The resource group of I(virtual_network_name).
+        - If not set then this is the same resource group as I(resource_group).
+        - This can be used to specify the resource group of a virtual network that is in another resource group
+          than the network interface.
+        - If I(virtual_network_name) is specified as a virtual network id, this parameter is ignored.
+        version_added: 2.6
     virtual_network_name:
         description:
             - Name or id of an existing virtual network with which the network interface will be associated. Required
@@ -366,6 +375,7 @@ def __init__(self):
             public_ip_address_name=dict(type='str', aliases=['public_ip_address', 'public_ip_name']),
             public_ip=dict(type='bool', default=True),
             subnet_name=dict(type='str', aliases=['subnet']),
+            virtual_network_resource_group=dict(type='str'),
             virtual_network_name=dict(type='str', aliases=['virtual_network']),
             public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static'], default='Dynamic'),
             ip_configurations=dict(type='list', default=None, elements='dict', options=ip_configuration_spec),
@@ -386,6 +396,7 @@ def __init__(self):
         self.public_ip_address_name = None
         self.public_ip = None
         self.subnet_name = None
+        self.virtual_network_resource_group = None
         self.virtual_network_name = None
         self.public_ip_allocation_method = None
         self.state = None
@@ -422,7 +433,10 @@ def exec_module(self, **kwargs):
         # parse the virtual network resource group and name
         virtual_network_dict = parse_resource_id(self.virtual_network_name)
         virtual_network_name = virtual_network_dict.get('name')
-        virtual_network_resource_group = virtual_network_dict.get('resource_group', self.resource_group)
+        virtual_network_resource_group = virtual_network_dict.get('resource_group', self.virtual_network_resource_group)
+
+        if virtual_network_resource_group is None:
+            virtual_network_resource_group = self.resource_group
 
         if self.state == 'present' and not self.ip_configurations:
             # construct the ip_configurations array for compatiable


Test patch:
diff --git a/test/integration/targets/azure_rm_networkinterface/tasks/main.yml b/test/integration/targets/azure_rm_networkinterface/tasks/main.yml
--- a/test/integration/targets/azure_rm_networkinterface/tasks/main.yml
+++ b/test/integration/targets/azure_rm_networkinterface/tasks/main.yml
@@ -28,6 +28,24 @@
     that:
       - output.changed
 
+- name: Create NIC using virtual_network_resource_group parameter
+  azure_rm_networkinterface:
+      resource_group: "{{ resource_group }}"
+      name: testnic001rg
+      virtual_network: testnic001
+      virtual_network_resource_group: "{{ resource_group_secondary }}"
+      subnet: testnic001
+      public_ip_name: testnic001
+      public_ip_allocation_method: Static
+      security_group: testnic001
+  register: output
+
+- name: Delete NIC
+  azure_rm_networkinterface:
+      resource_group: "{{ resource_group }}"
+      name: testnic001rg
+      state: absent
+  
 - name: Create NIC
   azure_rm_networkinterface:
       resource_group: "{{ resource_group }}"