From af28e0ac6cfd68a118f0468cee7e358ed2ba5bce Mon Sep 17 00:00:00 2001 From: Imre Jonk Date: Thu, 15 Jul 2021 15:18:11 +0200 Subject: [PATCH] Allow IPv6 with NetworkInterfaceIPConfiguration The ip_configurations parameter of the azure_rm_networkinterface module did not allow specifying the IP version, causing the Azure REST API to default to IPv4. Trying to add a public IPv6 address to the network interface would cause this error: ``` Error creating or updating network interface mynic - Azure Error: IPVersionForPublicIpAndNicIpConfigurationMustMatch Message: IP version for publicIPAddress '/subscriptions/[..]/resourceGroups/ansible/providers/Microsoft.Network/publicIPAddresses/mypublicipv6address', version 'IPv6' and network interface ipConfiguration '/subscriptions/[..]/resourceGroups/ansible/providers/Microsoft.Network/networkInterfaces/mynic/ipConfigurations/myipv6config', version 'IPv4' must match. ``` The Azure Python SDK however does allow for a parameter called `private_ip_address_version` [0]. This commit implements that parameter for the azure_rm_networkinterface module. [1] https://docs.microsoft.com/en-us/python/api/azure-mgmt-network/azure.mgmt.network.v2020_06_01.models.networkinterfaceipconfiguration?view=azure-python --- plugins/modules/azure_rm_networkinterface.py | 17 +++- .../modules/azure_rm_networkinterface_info.py | 2 +- .../azure_rm_networkinterface/tasks/main.yml | 93 +++++++++++++++++-- 3 files changed, 103 insertions(+), 9 deletions(-) diff --git a/plugins/modules/azure_rm_networkinterface.py b/plugins/modules/azure_rm_networkinterface.py index 6fd98e33d..0a9f28b3f 100644 --- a/plugins/modules/azure_rm_networkinterface.py +++ b/plugins/modules/azure_rm_networkinterface.py @@ -121,6 +121,13 @@ private_ip_address: description: - Private IP address for the IP configuration. + private_ip_address_version: + description: + - The version of the IP configuration. + choices: + - IPv4 + - IPv6 + default: IPv4 private_ip_allocation_method: description: - Private IP allocation method. @@ -374,6 +381,11 @@ - Private IP address for the IP configuration. type: str sample: "10.1.0.10" + private_ip_address_version: + description: + - The version of the IP configuration. + type: str + sample: "IPv4" private_ip_allocation_method: description: - Private IP allocation method. @@ -474,9 +486,10 @@ def nic_to_dict(nic): dict( name=config.name, private_ip_address=config.private_ip_address, + private_ip_address_version=config.private_ip_address_version, private_ip_allocation_method=config.private_ip_allocation_method, subnet=subnet_to_dict(config.subnet), - primary=config.primary, + primary=config.primary if config.primary else False, load_balancer_backend_address_pools=([item.id for item in config.load_balancer_backend_address_pools] if config.load_balancer_backend_address_pools else None), public_ip_address=dict( @@ -518,6 +531,7 @@ def nic_to_dict(nic): ip_configuration_spec = dict( name=dict(type='str', required=True), private_ip_address=dict(type='str'), + private_ip_address_version=dict(type='str', choices=['IPv4', 'IPv6'], default='IPv4'), private_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static'], default='Dynamic'), public_ip_address_name=dict(type='str', aliases=['public_ip_address', 'public_ip_name']), public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static'], default='Dynamic'), @@ -741,6 +755,7 @@ def exec_module(self, **kwargs): self.network_models.NetworkInterfaceIPConfiguration( private_ip_allocation_method=ip_config.get('private_ip_allocation_method'), private_ip_address=ip_config.get('private_ip_address'), + private_ip_address_version=ip_config.get('private_ip_address_version'), name=ip_config.get('name'), subnet=subnet, public_ip_address=self.get_or_create_public_ip_address(ip_config), diff --git a/plugins/modules/azure_rm_networkinterface_info.py b/plugins/modules/azure_rm_networkinterface_info.py index 4e1bf9cf3..f6662ea24 100644 --- a/plugins/modules/azure_rm_networkinterface_info.py +++ b/plugins/modules/azure_rm_networkinterface_info.py @@ -217,7 +217,7 @@ def nic_to_dict(nic): name=config.name, private_ip_address=config.private_ip_address, private_ip_allocation_method=config.private_ip_allocation_method, - primary=config.primary, + primary=config.primary if config.primary else False, load_balancer_backend_address_pools=([item.id for item in config.load_balancer_backend_address_pools] if config.load_balancer_backend_address_pools else None), public_ip_address=config.public_ip_address.id if config.public_ip_address else None, diff --git a/tests/integration/targets/azure_rm_networkinterface/tasks/main.yml b/tests/integration/targets/azure_rm_networkinterface/tasks/main.yml index 44a27b2b3..0d603097a 100644 --- a/tests/integration/targets/azure_rm_networkinterface/tasks/main.yml +++ b/tests/integration/targets/azure_rm_networkinterface/tasks/main.yml @@ -10,31 +10,47 @@ azure_rm_virtualnetwork: resource_group: "{{ resource_group_secondary }}" name: "tn{{ rpfx }}" - address_prefixes: "10.10.0.0/16" + address_prefixes: ["10.10.0.0/16", "fdae:f296:2787::/48"] register: vn - name: Add subnet azure_rm_subnet: resource_group: "{{ resource_group_secondary }}" name: "tn{{ rpfx }}" - address_prefix: "10.10.0.0/24" + address_prefixes_cidr: ["10.10.0.0/24", "fdae:f296:2787::/64"] virtual_network: "tn{{ rpfx }}" -- name: create public ip +- name: Create public IP addresses azure_rm_publicipaddress: - name: "pip{{ rpfx }}" + name: '{{ item.name }}' resource_group: '{{ resource_group }}' + sku: 'standard' + allocation_method: 'static' + version: '{{ item.version }}' + loop: + - name: 'pip{{ rpfx }}' + version: 'ipv4' + - name: 'tn{{ rpfx }}' + version: 'ipv4' + - name: 'pip{{ rpfx }}v6' + version: 'ipv6' + - name: 'tn{{ rpfx }}v6' + version: 'ipv6' - name: create load balancer with multiple parameters azure_rm_loadbalancer: resource_group: '{{ resource_group }}' name: "lb{{ rpfx }}" + sku: 'Standard' frontend_ip_configurations: - name: frontendipconf0 public_ip_address: "pip{{ rpfx }}" + - name: frontendipconf1 + public_ip_address: "pip{{ rpfx }}v6" backend_address_pools: - name: backendaddrpool0 - name: backendaddrpool1 + - name: backendaddrpool2 probes: - name: prob0 port: 80 @@ -45,6 +61,12 @@ frontend_port_range_start: 80 frontend_port_range_end: 81 backend_port: 8080 + - name: inboundnatpool1 + frontend_ip_configuration_name: frontendipconf1 + protocol: Tcp + frontend_port_range_start: 80 + frontend_port_range_end: 81 + backend_port: 8080 load_balancing_rules: - name: lbrbalancingrule0 frontend_ip_configuration: frontendipconf0 @@ -52,6 +74,12 @@ frontend_port: 80 backend_port: 80 probe: prob0 + - name: lbrbalancingrule1 + frontend_ip_configuration: frontendipconf1 + backend_address_pool: backendaddrpool2 + frontend_port: 80 + backend_port: 80 + probe: prob0 register: lb - name: Create most simple NIC with virtual_network id (check mode) @@ -239,6 +267,13 @@ - "{{ lb.state.backend_address_pools[0].id }}" - name: backendaddrpool1 load_balancer: "lb{{ rpfx }}" + - name: ipconfig2 + public_ip_name: "tn{{ rpfx }}v6" + private_ip_address_version: 'IPv6' + load_balancer_backend_address_pools: + - "{{ lb.state.backend_address_pools[2].id }}" + - name: backendaddrpool2 + load_balancer: "lb{{ rpfx }}" register: output - assert: @@ -272,6 +307,13 @@ - "{{ lb.state.backend_address_pools[0].id }}" - name: backendaddrpool1 load_balancer: "lb{{ rpfx }}" + - name: ipconfig2 + public_ip_name: "tn{{ rpfx }}v6" + private_ip_address_version: 'IPv6' + load_balancer_backend_address_pools: + - "{{ lb.state.backend_address_pools[2].id }}" + - name: backendaddrpool2 + load_balancer: "lb{{ rpfx }}" register: output - assert: @@ -288,7 +330,7 @@ that: - "facts.networkinterfaces | length == 1" - facts.networkinterfaces[0].id == output.state.id - - "facts.networkinterfaces[0].ip_configurations | length == 2" + - "facts.networkinterfaces[0].ip_configurations | length == 3" - 'facts.networkinterfaces[0].security_group.endswith("tn{{ rpfx }}sg")' - facts.networkinterfaces[0].enable_accelerated_networking - facts.networkinterfaces[0].enable_ip_forwarding @@ -513,11 +555,22 @@ name: "lb{{ rpfx }}" state: absent -- name: delete public ip +- name: delete public ip addresses azure_rm_publicipaddress: - name: "pip{{ rpfx }}" + name: "{{ item }}" resource_group: '{{ resource_group }}' state: absent + register: output + loop: + - 'pip{{ rpfx }}' + - 'pip{{ rpfx }}v6' + - 'tn{{ rpfx }}' + - 'tn{{ rpfx }}v6' + +- assert: + that: + - output.changed + - output.results | length == 4 - name: Delete the NIC azure_rm_networkinterface: @@ -556,3 +609,29 @@ name: "{{ applicationsecuritygroup_name2 }}" state: absent register: output + +- name: Delete network security groups + azure_rm_securitygroup: + resource_group: '{{ resource_group }}' + name: '{{ item }}' + state: 'absent' + register: output + loop: + - '{{ nic_name1 }}' + - 'tn{{ rpfx }}sg' + +- assert: + that: + - output.changed + - output.results | length == 2 + +- name: Delete virtual network + azure_rm_virtualnetwork: + resource_group: '{{ resource_group_secondary }}' + name: 'tn{{ rpfx }}' + state: 'absent' + register: output + +- assert: + that: + - output.changed