diff --git a/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py b/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py index 4239d21d37b..6ed75795a4f 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_networkinterface.py @@ -158,6 +158,11 @@ options: - Whether the ip configuration is the primary one in the list. type: bool default: 'no' + application_security_groups: + description: + - List of application security groups in which the IP configuration is included. + - Element of the list could be a resource id of application security group, or dict of C(resource_group) and C(name). + version_added: 2.8 version_added: 2.5 enable_accelerated_networking: description: @@ -355,13 +360,13 @@ state: ''' try: - from msrestazure.tools import parse_resource_id, resource_id + from msrestazure.tools import parse_resource_id, resource_id, is_valid_resource_id from msrestazure.azure_exceptions import CloudError except ImportError: # This is handled in azure_rm_common pass -from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict, normalize_location_name +from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict, normalize_location_name, format_resource_id from ansible.module_utils._text import to_native @@ -389,7 +394,9 @@ def nic_to_dict(nic): id=config.public_ip_address.id, name=azure_id_to_dict(config.public_ip_address.id).get('publicIPAddresses'), public_ip_allocation_method=config.public_ip_address.public_ip_allocation_method - ) if config.public_ip_address else None + ) if config.public_ip_address else None, + application_security_groups=([asg.id for asg in config.application_security_groups] + if config.application_security_groups else None) ) for config in nic.ip_configurations ] return dict( @@ -426,7 +433,8 @@ ip_configuration_spec = dict( 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'), load_balancer_backend_address_pools=dict(type='list'), - primary=dict(type='bool', default=False) + primary=dict(type='bool', default=False), + application_security_groups=dict(type='list', elements='raw') ) @@ -512,6 +520,25 @@ class AzureRMNetworkInterface(AzureRMModuleBase): # if not set the security group name, use nic name for default self.security_group = self.parse_resource_to_dict(self.security_group or self.name) + # if application security groups set, convert to resource id format + if self.ip_configurations: + for config in self.ip_configurations: + if config.get('application_security_groups'): + asgs = [] + for asg in config['application_security_groups']: + asg_resource_id = asg + if isinstance(asg, str) and (not is_valid_resource_id(asg)): + asg = self.parse_resource_to_dict(asg) + if isinstance(asg, dict): + asg_resource_id = format_resource_id(val=asg['name'], + subscription_id=self.subscription_id, + namespace='Microsoft.Network', + types='applicationSecurityGroups', + resource_group=asg['resource_group']) + asgs.append(asg_resource_id) + if len(asgs) > 0: + config['application_security_groups'] = asgs + if self.state == 'present' and not self.ip_configurations: # construct the ip_configurations array for compatible self.deprecate('Setting ip_configuration flatten is deprecated and will be removed.' @@ -631,7 +658,10 @@ class AzureRMNetworkInterface(AzureRMModuleBase): load_balancer_backend_address_pools=([self.network_models.BackendAddressPool(id=self.backend_addr_pool_id(bap_id)) for bap_id in ip_config.get('load_balancer_backend_address_pools')] if ip_config.get('load_balancer_backend_address_pools') else None), - primary=ip_config.get('primary') + primary=ip_config.get('primary'), + application_security_groups=([self.network_models.ApplicationSecurityGroup(id=asg_id) + for asg_id in ip_config.get('application_security_groups')] + if ip_config.get('application_security_groups') else None) ) for ip_config in self.ip_configurations ] @@ -736,6 +766,8 @@ class AzureRMNetworkInterface(AzureRMModuleBase): load_balancer_backend_address_pools=(set([to_native(self.backend_addr_pool_id(id)) for id in item.get('load_balancer_backend_address_pools')]) if item.get('load_balancer_backend_address_pools') else None), + application_security_groups=(set([to_native(asg_id) for asg_id in item.get('application_security_groups')]) + if item.get('application_security_groups') else None), name=to_native(item.get('name')) )) for item in raw] return set(configurations) diff --git a/lib/ansible/modules/cloud/azure/azure_rm_networkinterface_facts.py b/lib/ansible/modules/cloud/azure/azure_rm_networkinterface_facts.py index a3fcd5cff7d..3ccf8e96bd6 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_networkinterface_facts.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_networkinterface_facts.py @@ -156,6 +156,10 @@ networkinterfaces: primary: description: - Whether the ip configuration is the primary one in the list. + application_security_groups: + description: + - List of Application security groups. + sample: /subscriptions//resourceGroups//providers/Microsoft.Network/applicationSecurityGroups/myASG enable_accelerated_networking: description: - Specifies whether the network interface should be created with the accelerated networking feature or not @@ -217,7 +221,9 @@ def nic_to_dict(nic): 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, - public_ip_allocation_method=config.public_ip_address.public_ip_allocation_method if config.public_ip_address else None + public_ip_allocation_method=config.public_ip_address.public_ip_allocation_method if config.public_ip_address else None, + application_security_groups=([asg.id for asg in config.application_security_groups] + if config.application_security_groups else None) ) for config in nic.ip_configurations ] config = nic.ip_configurations[0] if len(nic.ip_configurations) > 0 else None diff --git a/test/integration/targets/azure_rm_applicationsecuritygroup/aliases b/test/integration/targets/azure_rm_applicationsecuritygroup/aliases deleted file mode 100644 index 1f8f08b0999..00000000000 --- a/test/integration/targets/azure_rm_applicationsecuritygroup/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/azure -shippable/azure/group4 -destructive \ No newline at end of file diff --git a/test/integration/targets/azure_rm_applicationsecuritygroup/meta/main.yml b/test/integration/targets/azure_rm_applicationsecuritygroup/meta/main.yml deleted file mode 100644 index 95e1952f989..00000000000 --- a/test/integration/targets/azure_rm_applicationsecuritygroup/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - setup_azure diff --git a/test/integration/targets/azure_rm_applicationsecuritygroup/tasks/main.yml b/test/integration/targets/azure_rm_applicationsecuritygroup/tasks/main.yml deleted file mode 100644 index 0a619a5e74d..00000000000 --- a/test/integration/targets/azure_rm_applicationsecuritygroup/tasks/main.yml +++ /dev/null @@ -1,85 +0,0 @@ -- name: Prepare random number - set_fact: - name: "asg{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" - run_once: yes - - -- name: Create application security group(check mode) - azure_rm_applicationsecuritygroup: - resource_group: "{{ resource_group }}" - name: "{{ name }}" - tags: - testing: testing - check_mode: yes - register: output - -- name: Assert check mode creation - assert: - that: - - output.changed - -- name: Create application security group - azure_rm_applicationsecuritygroup: - resource_group: "{{ resource_group }}" - name: "{{ name }}" - tags: - testing: testing - register: output - -- name: Assert the application security group is well created - assert: - that: - - output.changed - - output.id != '' - -- name: Create application security group (idempotent) - azure_rm_applicationsecuritygroup: - resource_group: "{{ resource_group }}" - name: "{{ name }}" - tags: - testing: testing - register: output - -- name: Assert idempotent - assert: - that: - - not output.changed - -- name: Update application security group - azure_rm_applicationsecuritygroup: - resource_group: "{{ resource_group }}" - name: "{{ name }}" - tags: - testing: testing - foo: bar - register: output - -- name: Assert Update - assert: - that: - - output.changed - -- name: Delete the application security group (check mode) - azure_rm_applicationsecuritygroup: - resource_group: "{{ resource_group }}" - name: "{{ name }}" - state: absent - check_mode: yes - register: output - -- name: Assert delete check mode - assert: - that: - - output.changed - -- name: Delete the application security group - azure_rm_applicationsecuritygroup: - resource_group: "{{ resource_group }}" - name: "{{ name }}" - state: absent - register: output - -- name: Assert the deletion - assert: - that: - - output.changed diff --git a/test/integration/targets/azure_rm_networkinterface/aliases b/test/integration/targets/azure_rm_networkinterface/aliases index fadef3afa88..67f86756772 100644 --- a/test/integration/targets/azure_rm_networkinterface/aliases +++ b/test/integration/targets/azure_rm_networkinterface/aliases @@ -1,3 +1,4 @@ cloud/azure shippable/azure/group5 destructive +azure_rm_applicationsecuritygroup \ No newline at end of file diff --git a/test/integration/targets/azure_rm_networkinterface/tasks/main.yml b/test/integration/targets/azure_rm_networkinterface/tasks/main.yml index fe30de20a44..5d5b0b443f7 100644 --- a/test/integration/targets/azure_rm_networkinterface/tasks/main.yml +++ b/test/integration/targets/azure_rm_networkinterface/tasks/main.yml @@ -1,6 +1,9 @@ - name: Prepare random number set_fact: rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" + applicationsecuritygroup_name1: "asg{{ resource_group | hash('md5') | truncate(5, True, '') }}{{ 1000 | random }}" + applicationsecuritygroup_name2: "asg{{ resource_group | hash('md5') | truncate(5, True, '') }}{{ 1000 | random }}" + nic_name1: "nic1{{ resource_group | hash('md5') | truncate(5, True, '') }}{{ 1000 | random }}" run_once: yes - name: Create virtual network @@ -319,6 +322,139 @@ - output.state.ip_configurations[0].public_ip_address.name == "tn{{ rpfx }}" - output.state.enable_accelerated_networking +- name: Create application security group(check mode) + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group }}" + name: "{{ applicationsecuritygroup_name1 }}" + tags: + testing: testing + check_mode: yes + register: output + +- name: Assert check mode creation + assert: + that: + - output.changed + +- name: Create Application security group + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group }}" + name: "{{ applicationsecuritygroup_name1 }}" + tags: + testing: testing + register: output + +- name: Assert application security group creation + assert: + that: + - output.changed + - output.id != '' + +- name: Create application security group (idempotent) + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group }}" + name: "{{ applicationsecuritygroup_name1 }}" + tags: + testing: testing + register: output + +- name: Assert idempotent + assert: + that: + - not output.changed + +- name: Update application security group + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group }}" + name: "{{ applicationsecuritygroup_name1 }}" + tags: + testing: testing + foo: bar + register: output + +- name: Assert update + assert: + that: + - output.changed + +- name: Create Application security group in secondary resource group + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group_secondary }}" + name: "{{ applicationsecuritygroup_name2 }}" + register: asg + +- name: Create Nic with application security groups + azure_rm_networkinterface: + resource_group: "{{ resource_group }}" + name: "{{ nic_name1 }}" + virtual_network: "{{ vn.state.id }}" + subnet: "tn{{ rpfx }}" + create_with_security_group: True + public_ip: False + ip_configurations: + - name: ipconfig1 + application_security_groups: + - "{{ applicationsecuritygroup_name1 }}" + - "{{ asg.id }}" + primary: True + register: output + +- name: assert creation succeeded + assert: + that: + - output.changed + +- name: Create Nic with application security groups (idempotent) + azure_rm_networkinterface: + resource_group: "{{ resource_group }}" + name: "{{ nic_name1 }}" + virtual_network: "{{ vn.state.id }}" + subnet: "tn{{ rpfx }}" + create_with_security_group: True + public_ip: False + ip_configurations: + - name: ipconfig1 + application_security_groups: + - "{{ asg.id }}" + - "{{ applicationsecuritygroup_name1 }}" + primary: True + register: output + +- name: assert idempotent + assert: + that: + - not output.changed + +- name: Update Nic with application security groups + azure_rm_networkinterface: + resource_group: "{{ resource_group }}" + name: "{{ nic_name1 }}" + virtual_network: "{{ vn.state.id }}" + subnet: "tn{{ rpfx }}" + create_with_security_group: True + public_ip: False + ip_configurations: + - name: ipconfig1 + application_security_groups: + - "{{ applicationsecuritygroup_name1 }}" + primary: True + register: output + +- name: assert update succeeded + assert: + that: + - output.changed + +- name: Get fact of the new created NIC + azure_rm_networkinterface_facts: + resource_group: "{{ resource_group }}" + name: "{{ nic_name1 }}" + register: facts + +- assert: + that: + - "facts.networkinterfaces[0].ip_configurations[0].application_security_groups | length == 1" + - name: Delete the NIC (check mode) azure_rm_networkinterface: resource_group: "{{ resource_group }}" @@ -364,3 +500,41 @@ name: "pip{{ rpfx }}" resource_group: '{{ resource_group }}' state: absent + +- name: Delete the NIC + azure_rm_networkinterface: + resource_group: "{{ resource_group }}" + name: "{{ nic_name1 }}" + state: absent + +- name: Delete the application security group (check mode) + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group }}" + name: "{{ applicationsecuritygroup_name1 }}" + state: absent + check_mode: yes + register: output + +- name: Assert delete check mode + assert: + that: + - output.changed + +- name: Delete the application security group + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group }}" + name: "{{ applicationsecuritygroup_name1 }}" + state: absent + register: output + +- name: Assert the deletion + assert: + that: + - output.changed + +- name: Delete second application security group + azure_rm_applicationsecuritygroup: + resource_group: "{{ resource_group_secondary }}" + name: "{{ applicationsecuritygroup_name2 }}" + state: absent + register: output \ No newline at end of file