From fff5fb2077d095b87b734636dcd0b0e9ecb195a2 Mon Sep 17 00:00:00 2001 From: Yuwei Zhou Date: Thu, 23 Aug 2018 06:24:57 +0800 Subject: [PATCH] Add route table and route module (#41175) * add route module * add test * add table * add route table * fix dict * fix * fix * route table accept no name * add default * fix * fix * fix * fix pep * support route table * fix line ending * fix pep * fix * fix * set the default to 'None' * make return value only id * camel and snake * set test alias * change facts line ending * change test * fix * add default * fix * fix line break * remove unsafe args * fix comment * fix --- .../modules/cloud/azure/azure_rm_route.py | 219 ++++++++++++++++++ .../cloud/azure/azure_rm_routetable.py | 200 ++++++++++++++++ .../cloud/azure/azure_rm_routetable_facts.py | 204 ++++++++++++++++ .../modules/cloud/azure/azure_rm_subnet.py | 36 ++- .../targets/azure_rm_routetable/aliases | 3 + .../targets/azure_rm_routetable/meta/main.yml | 2 + .../azure_rm_routetable/tasks/main.yml | 183 +++++++++++++++ .../targets/azure_rm_subnet/tasks/main.yml | 8 + 8 files changed, 853 insertions(+), 2 deletions(-) create mode 100644 lib/ansible/modules/cloud/azure/azure_rm_route.py create mode 100644 lib/ansible/modules/cloud/azure/azure_rm_routetable.py create mode 100644 lib/ansible/modules/cloud/azure/azure_rm_routetable_facts.py create mode 100644 test/integration/targets/azure_rm_routetable/aliases create mode 100644 test/integration/targets/azure_rm_routetable/meta/main.yml create mode 100644 test/integration/targets/azure_rm_routetable/tasks/main.yml diff --git a/lib/ansible/modules/cloud/azure/azure_rm_route.py b/lib/ansible/modules/cloud/azure/azure_rm_route.py new file mode 100644 index 0000000000..f7ebd73e55 --- /dev/null +++ b/lib/ansible/modules/cloud/azure/azure_rm_route.py @@ -0,0 +1,219 @@ +#!/usr/bin/python +# +# Copyright (c) 2018 Yuwei Zhou, +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: azure_rm_route +version_added: "2.7" +short_description: Manage Azure route resource. +description: + - Create, update or delete a route. +options: + resource_group: + description: + - name of resource group. + required: true + name: + description: + - name of the route. + required: true + state: + description: + - Assert the state of the route. Use 'present' to create or update and + 'absent' to delete. + default: present + choices: + - absent + - present + address_prefix: + description: + - The destination CIDR to which the route applies. + next_hop_type: + description: + - The type of Azure hop the packet should be sent to. + choices: + - virtual_network_gateway + - vnet_local + - internet + - virtual_appliance + - none + default: 'none' + next_hop_ip_address: + description: + - The IP address packets should be forwarded to. + - Next hop values are only allowed in routes where the next hop type is VirtualAppliance. + route_table_name: + description: + - The name of the route table. + required: true + + +extends_documentation_fragment: + - azure + - azure_tags + +author: + - "Yuwei Zhou (@yuwzho)" + +''' + +EXAMPLES = ''' + - name: Create a route + azure_rm_route: + name: foobar + resource_group: Testing + address_prefix: 10.1.0.0/16 + next_hop_type: virtual_network_gateway + route_table_name: table + + - name: Delete a route + azure_rm_route: + name: foobar + resource_group: Testing + route_table_name: table + state: absent +''' +RETURN = ''' +id: + description: Current state of the route. + returned: success + type: str +''' + +try: + 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 +from ansible.module_utils.common.dict_transformations import _snake_to_camel + + +class AzureRMRoute(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + resource_group=dict(type='str', required=True), + name=dict(type='str', required=True), + state=dict(type='str', default='present', choices=['present', 'absent']), + address_prefix=dict(type='str'), + next_hop_type=dict(type='str', + choices=['virtual_network_gateway', + 'vnet_local', + 'internet', + 'virtual_appliance', + 'none'], + default='none'), + next_hop_ip_address=dict(type='str'), + route_table_name=dict(type='str', required=True) + ) + + required_if = [ + ('state', 'present', ['next_hop_type']) + ] + + self.resource_group = None + self.name = None + self.state = None + self.address_prefix = None + self.next_hop_type = None + self.next_hop_ip_address = None + self.route_table_name = None + + self.results = dict( + changed=False, + id=None + ) + + super(AzureRMRoute, self).__init__(self.module_arg_spec, + required_if=required_if, + supports_check_mode=True) + + def exec_module(self, **kwargs): + + for key in list(self.module_arg_spec.keys()): + setattr(self, key, kwargs[key]) + + result = dict() + changed = False + + self.next_hop_type = _snake_to_camel(self.next_hop_type, capitalize_first=True) + + result = self.get_route() + if self.state == 'absent' and result: + changed = True + if not self.check_mode: + self.delete_route() + elif self.state == 'present': + if not result: + changed = True # create new route + else: # check update + if result.next_hop_type != self.next_hop_type: + self.log('Update: {0} next_hop_type from {1} to {2}'.format(self.name, result.next_hop_type, self.next_hop_type)) + changed = True + if result.next_hop_ip_address != self.next_hop_ip_address: + self.log('Update: {0} next_hop_ip_address from {1} to {2}'.format(self.name, result.next_hop_ip_address, self.next_hop_ip_address)) + changed = True + if result.address_prefix != self.address_prefix: + self.log('Update: {0} address_prefix from {1} to {2}'.format(self.name, result.address_prefix, self.address_prefix)) + changed = True + if changed: + result = self.network_models.Route(name=self.name, + address_prefix=self.address_prefix, + next_hop_type=self.next_hop_type, + next_hop_ip_address=self.next_hop_ip_address) + if not self.check_mode: + result = self.create_or_update_route(result) + + self.results['id'] = result.id if result else None + self.results['changed'] = changed + return self.results + + def create_or_update_route(self, param): + try: + poller = self.network_client.routes.create_or_update(self.resource_group, self.route_table_name, self.name, param) + return self.get_poller_result(poller) + except Exception as exc: + self.fail("Error creating or updating route {0} - {1}".format(self.name, str(exc))) + + def delete_route(self): + try: + poller = self.network_client.routes.delete(self.resource_group, self.route_table_name, self.name) + result = self.get_poller_result(poller) + return result + except Exception as exc: + self.fail("Error deleting route {0} - {1}".format(self.name, str(exc))) + + def get_route(self): + try: + return self.network_client.routes.get(self.resource_group, self.route_table_name, self.name) + except CloudError as cloud_err: + # Return None iff the resource is not found + if cloud_err.status_code == 404: + self.log('{0}'.format(str(cloud_err))) + return None + self.fail('Error: failed to get resource {0} - {1}'.format(self.name, str(cloud_err))) + except Exception as exc: + self.fail('Error: failed to get resource {0} - {1}'.format(self.name, str(exc))) + + +def main(): + AzureRMRoute() + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/modules/cloud/azure/azure_rm_routetable.py b/lib/ansible/modules/cloud/azure/azure_rm_routetable.py new file mode 100644 index 0000000000..cd5830c18a --- /dev/null +++ b/lib/ansible/modules/cloud/azure/azure_rm_routetable.py @@ -0,0 +1,200 @@ +#!/usr/bin/python +# +# Copyright (c) 2018 Yuwei Zhou, +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: azure_rm_routetable +version_added: "2.7" +short_description: Manage Azure route table resource. +description: + - Create, update or delete a route table. +options: + resource_group: + description: + - name of resource group. + required: true + name: + description: + - name of the route table. + required: true + state: + description: + - Assert the state of the route table. Use 'present' to create or update and + 'absent' to delete. + default: present + choices: + - absent + - present + disable_bgp_route_propagation: + description: + - Specified whether to disable the routes learned by BGP on that route table. + type: bool + default: False + location: + description: + - Region of the resource. + - Derived from C(resource_group) if not specified + +extends_documentation_fragment: + - azure + - azure_tags + +author: + - "Yuwei Zhou (@yuwzho)" + +''' + +EXAMPLES = ''' + - name: Create a route table + azure_rm_routetable: + name: foobar + resource_group: Testing + disable_bgp_route_propagation: False + tags: + purpose: testing + + - name: Update the subnet (idempotent) + azure_rm_subnet: + name: subnet + virtual_network_name: virtualnetwork + resource_group: Testing + address_prefix_cidr: "10.1.0.0/16" + route_table: foobar + + - name: Delete a route table + azure_rm_routetable: + name: foobar + resource_group: Testing + state: absent +''' +RETURN = ''' +changed: + description: Whether the resource is changed. + returned: always + type: bool +id: + description: resource id. + returned: success + type: str +''' + +try: + 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, normalize_location_name + + +class AzureRMRouteTable(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + resource_group=dict(type='str', required=True), + name=dict(type='str', required=True), + state=dict(type='str', default='present', choices=['present', 'absent']), + location=dict(type='str'), + disable_bgp_route_propagation=dict(type='bool', default=False) + ) + + self.resource_group = None + self.name = None + self.state = None + self.location = None + self.tags = None + self.disable_bgp_route_propagation = None + + self.results = dict( + changed=False + ) + + super(AzureRMRouteTable, self).__init__(self.module_arg_spec, + supports_check_mode=True) + + def exec_module(self, **kwargs): + for key in list(self.module_arg_spec.keys()) + ['tags']: + setattr(self, key, kwargs[key]) + + resource_group = self.get_resource_group(self.resource_group) + if not self.location: + # Set default location + self.location = resource_group.location + self.location = normalize_location_name(self.location) + + result = dict() + changed = False + + result = self.get_table() + if self.state == 'absent' and result: + changed = True + if not self.check_mode: + self.delete_table() + elif self.state == 'present': + if not result: + changed = True # create new route table + else: # check update + update_tags, self.tags = self.update_tags(result.tags) + if update_tags: + changed = True + if self.disable_bgp_route_propagation != result.disable_bgp_route_propagation: + changed = True + + if changed: + result = self.network_models.RouteTable(location=self.location, + tags=self.tags, + disable_bgp_route_propagation=self.disable_bgp_route_propagation) + if not self.check_mode: + result = self.create_or_update_table(result) + + self.results['id'] = result.id if result else None + self.results['changed'] = changed + return self.results + + def create_or_update_table(self, param): + try: + poller = self.network_client.route_tables.create_or_update(self.resource_group, self.name, param) + return self.get_poller_result(poller) + except Exception as exc: + self.fail("Error creating or updating route table {0} - {1}".format(self.name, str(exc))) + + def delete_table(self): + try: + poller = self.network_client.route_tables.delete(self.resource_group, self.name) + result = self.get_poller_result(poller) + return result + except Exception as exc: + self.fail("Error deleting virtual network {0} - {1}".format(self.name, str(exc))) + + def get_table(self): + try: + return self.network_client.route_tables.get(self.resource_group, self.name) + except CloudError as cloud_err: + # Return None iff the resource is not found + if cloud_err.status_code == 404: + self.log('{0}'.format(str(cloud_err))) + return None + self.fail('Error: failed to get resource {0} - {1}'.format(self.name, str(cloud_err))) + except Exception as exc: + self.fail('Error: failed to get resource {0} - {1}'.format(self.name, str(exc))) + + +def main(): + AzureRMRouteTable() + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/modules/cloud/azure/azure_rm_routetable_facts.py b/lib/ansible/modules/cloud/azure/azure_rm_routetable_facts.py new file mode 100644 index 0000000000..7ef3c1d842 --- /dev/null +++ b/lib/ansible/modules/cloud/azure/azure_rm_routetable_facts.py @@ -0,0 +1,204 @@ +#!/usr/bin/python +# +# Copyright (c) 2018 Yuwei Zhou, +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: azure_rm_routetable_facts + +version_added: "2.7" + +short_description: Get route table facts. + +description: + - Get facts for a specific route table or all route table in a resource group or subscription. + +options: + name: + description: + - Limit results to a specific route table. + resource_group: + description: + - Limit results in a specific resource group. + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + +extends_documentation_fragment: + - azure + +author: + - "Yuwei Zhou (@yuwzho)" + +''' + +EXAMPLES = ''' + - name: Get facts for one route table + azure_rm_routetable_facts: + name: Testing + resource_group: foo + + - name: Get facts for all route tables + azure_rm_routetable_facts: + resource_group: foo + + - name: Get facts by tags + azure_rm_routetable_facts: + tags: + - testing + - foo:bar +''' +RETURN = ''' +id: + description: Resource id. + returned: success + type: str +name: + description: Name of the resource. + returned: success + type: str +resource_group: + description: Resource group of the route table. + returned: success + type: str +disable_bgp_route_propagation: + description: Whether the routes learned by BGP on that route table disabled. + returned: success + type: bool +tags: + description: Tags of the route table. + returned: success + type: list +routes: + description: Current routes of the route table. + returned: success + type: list + sample: [ + { + "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/Testing/providers/Microsoft.Network/routeTables/foobar/routes/route", + "name": "route", + "resource_group": "Testing", + "routeTables": "foobar", + "address_prefix": "192.0.0.1", + "next_hop_type": "virtual_networkGateway" + } + ] +''' + +try: + from msrestazure.azure_exceptions import CloudError +except: + # This is handled in azure_rm_common + pass + +from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict +from ansible.module_utils.common.dict_transformations import _camel_to_snake + + +def route_to_dict(route): + id_dict = azure_id_to_dict(route.id) + return dict( + id=route.id, + name=route.name, + resource_group=id_dict.get('resourceGroups'), + route_table_name=id_dict.get('routeTables'), + address_prefix=route.address_prefix, + next_hop_type=_camel_to_snake(route.next_hop_type), + next_hop_ip_address=route.next_hop_ip_address + ) + + +def instance_to_dict(table): + return dict( + id=table.id, + name=table.name, + resource_group=azure_id_to_dict(table.id).get('resourceGroups'), + location=table.location, + routes=[route_to_dict(i) for i in table.routes] if table.routes else [], + disable_bgp_route_propagation=table.disable_bgp_route_propagation, + tags=table.tags + ) + + +class AzureRMRouteTableFacts(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + name=dict(type='str'), + resource_group=dict(type='str'), + tags=dict(type='list') + ) + + self.results = dict( + changed=False, + route_tables=[] + ) + + self.name = None + self.resource_group = None + self.tags = None + + super(AzureRMRouteTableFacts, self).__init__(self.module_arg_spec, + supports_tags=False, + facts_module=True) + + def exec_module(self, **kwargs): + + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + response = [] + if self.name: + response = self.get_item() + elif self.resource_group: + response = self.list_items() + else: + response = self.list_all_items() + + self.results['route_tables'] = [instance_to_dict(x) for x in response if self.has_tags(x.tags, self.tags)] + return self.results + + def get_item(self): + self.log('Get route table for {0}-{1}'.format(self.resource_group, self.name)) + try: + item = self.network_client.route_tables.get(self.resource_group, self.name) + return [item] + except CloudError: + pass + return [] + + def list_items(self): + self.log('List all items in resource group') + try: + return self.network_client.route_tables.list(self.resource_group) + except CloudError as exc: + self.fail("Failed to list items - {0}".format(str(exc))) + return [] + + def list_all_items(self): + self.log("List all items in subscription") + try: + return self.network_client.route_tables.list_all() + except CloudError as exc: + self.fail("Failed to list all items - {0}".format(str(exc))) + return [] + + +def main(): + AzureRMRouteTableFacts() + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/modules/cloud/azure/azure_rm_subnet.py b/lib/ansible/modules/cloud/azure/azure_rm_subnet.py index 62753f9e63..a600481750 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_subnet.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_subnet.py @@ -61,6 +61,13 @@ options: required: true aliases: - virtual_network + route_table: + description: + - The reference of the RouteTable resource. + - It can accept both a str or a dict. + - The str can be the name or resource id of the route table. + - The dict can contains C(name) and C(resource_group) of the route_table. + version_added: "2.7" extends_documentation_fragment: - azure @@ -89,6 +96,7 @@ EXAMPLES = ''' security_group: name: secgroupfoo resource_group: Testing1 + route_table: route - name: Delete a subnet azure_rm_subnet: @@ -149,11 +157,18 @@ def subnet_to_dict(subnet): provisioning_state=subnet.provisioning_state, address_prefix=subnet.address_prefix, network_security_group=dict(), + route_table=dict() ) if subnet.network_security_group: id_keys = azure_id_to_dict(subnet.network_security_group.id) result['network_security_group']['id'] = subnet.network_security_group.id result['network_security_group']['name'] = id_keys['networkSecurityGroups'] + result['network_security_group']['resource_group'] = id_keys['resourceGroups'] + if subnet.route_table: + id_keys = azure_id_to_dict(subnet.route_table.id) + result['route_table']['id'] = subnet.route_table.id + result['route_table']['name'] = id_keys['routeTables'] + result['route_table']['resource_group'] = id_keys['resourceGroups'] return result @@ -167,7 +182,8 @@ class AzureRMSubnet(AzureRMModuleBase): state=dict(type='str', default='present', choices=['present', 'absent']), virtual_network_name=dict(type='str', required=True, aliases=['virtual_network']), address_prefix_cidr=dict(type='str', aliases=['address_prefix']), - security_group=dict(type='raw', aliases=['security_group_name']) + security_group=dict(type='raw', aliases=['security_group_name']), + route_table=dict(type='raw') ) required_if = [ @@ -185,6 +201,7 @@ class AzureRMSubnet(AzureRMModuleBase): self.virtual_network_name = None self.address_prefix_cidr = None self.security_group = None + self.route_table = None super(AzureRMSubnet, self).__init__(self.module_arg_spec, supports_check_mode=True, @@ -204,6 +221,14 @@ class AzureRMSubnet(AzureRMModuleBase): if self.security_group: nsg = self.parse_nsg() + if self.route_table: + route_table = self.parse_resource_to_dict(self.route_table) + self.route_table = format_resource_id(val=route_table['name'], + subscription_id=route_table['subscription_id'], + namespace='Microsoft.Network', + types='routeTables', + resource_group=route_table['resource_group']) + results = dict() changed = False @@ -228,6 +253,10 @@ class AzureRMSubnet(AzureRMModuleBase): changed = True results['network_security_group']['id'] = nsg.get('id') results['network_security_group']['name'] = nsg.get('name') + if self.route_table != results['route_table'].get('id'): + changed = True + results['route_table']['id'] = self.route_table + self.log("CHANGED: subnet {0} route_table to {1}".format(self.name, route_table['name'])) elif self.state == 'absent': changed = True except CloudError: @@ -249,7 +278,8 @@ class AzureRMSubnet(AzureRMModuleBase): ) if nsg: subnet.network_security_group = self.network_models.NetworkSecurityGroup(id=nsg.get('id')) - + if self.route_table: + subnet.route_table = self.network_models.RouteTable(id=self.route_table) else: # update subnet self.log('Updating subnet {0}'.format(self.name)) @@ -258,6 +288,8 @@ class AzureRMSubnet(AzureRMModuleBase): ) if results['network_security_group'].get('id'): subnet.network_security_group = self.network_models.NetworkSecurityGroup(results['network_security_group'].get('id')) + if self.route_table: + subnet.route_table = self.network_models.RouteTable(id=self.route_table) self.results['state'] = self.create_or_update_subnet(subnet) elif self.state == 'absent' and changed: diff --git a/test/integration/targets/azure_rm_routetable/aliases b/test/integration/targets/azure_rm_routetable/aliases new file mode 100644 index 0000000000..239e365779 --- /dev/null +++ b/test/integration/targets/azure_rm_routetable/aliases @@ -0,0 +1,3 @@ +cloud/azure +shippable/azure/group4 +destructive diff --git a/test/integration/targets/azure_rm_routetable/meta/main.yml b/test/integration/targets/azure_rm_routetable/meta/main.yml new file mode 100644 index 0000000000..95e1952f98 --- /dev/null +++ b/test/integration/targets/azure_rm_routetable/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_azure diff --git a/test/integration/targets/azure_rm_routetable/tasks/main.yml b/test/integration/targets/azure_rm_routetable/tasks/main.yml new file mode 100644 index 0000000000..40c4159eac --- /dev/null +++ b/test/integration/targets/azure_rm_routetable/tasks/main.yml @@ -0,0 +1,183 @@ +- name: Prepare random number + set_fact: + name: "table{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" + route_name: "route{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" + run_once: yes + +- name: Create a route table (check mode) + azure_rm_routetable: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + tags: + purpose: testing + check_mode: yes + register: output + +- assert: + that: + - not output.id + - output.changed + +- name: Create a route table + azure_rm_routetable: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + tags: + purpose: testing + register: output + +- assert: + that: + - output.changed + - output.id + +- name: Create a route table (idemponent) + azure_rm_routetable: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + tags: + purpose: testing + register: output + +- assert: + that: + - not output.changed + +- name: Get facts of the table + azure_rm_routetable_facts: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + register: output + +- assert: + that: + - "output.route_tables | length == 1" + - "output.route_tables[0].routes | length == 0" + +- name: Create route (check mode) + azure_rm_route: + name: "{{ route_name }}" + resource_group: "{{ resource_group }}" + next_hop_type: virtual_network_gateway + address_prefix: "10.1.0.0/16" + route_table_name: "{{ name }}" + check_mode: yes + register: output + +- assert: + that: + - output.changed + - not output.id + +- name: Create route + azure_rm_route: + name: "{{ route_name }}" + resource_group: "{{ resource_group }}" + next_hop_type: virtual_network_gateway + address_prefix: "10.1.0.0/16" + route_table_name: "{{ name }}" + register: output + +- assert: + that: + - output.changed + - output.id + +- name: Create route (idemponent) + azure_rm_route: + name: "{{ route_name }}" + resource_group: "{{ resource_group }}" + next_hop_type: virtual_network_gateway + address_prefix: "10.1.0.0/16" + route_table_name: "{{ name }}" + register: output + +- assert: + that: + - not output.changed + +- name: update route + azure_rm_route: + name: "{{ route_name }}" + resource_group: "{{ resource_group }}" + next_hop_type: virtual_network_gateway + address_prefix: "10.1.0.0/24" + route_table_name: "{{ name }}" + register: output + +- assert: + that: + - output.changed + +- name: Get facts of the table + azure_rm_routetable_facts: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + register: output + +- assert: + that: + - "output.route_tables | length == 1" + - "output.route_tables[0].routes | length == 1" + - output.route_tables[0].routes[0].address_prefix == '10.1.0.0/24' + +- name: Delete route (check mode) + azure_rm_route: + name: "{{ route_name }}" + resource_group: "{{ resource_group }}" + route_table_name: "{{ name }}" + state: absent + check_mode: yes + +- name: Delete route + azure_rm_route: + name: "{{ route_name }}" + resource_group: "{{ resource_group }}" + state: absent + route_table_name: "{{ name }}" + register: output + +- assert: + that: + - output.changed + +- name: Delete route (idemponent) + azure_rm_route: + name: "{{ route_name }}" + resource_group: "{{ resource_group }}" + state: absent + route_table_name: "{{ name }}" + register: output + +- assert: + that: + - not output.changed + +- name: Delete route table (check mode) + azure_rm_routetable: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + state: absent + check_mode: yes + +- name: Delete route table + azure_rm_routetable: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + state: absent + register: output + +- assert: + that: + - output.changed + +- name: Delete route table (idemponent) + azure_rm_routetable: + name: "{{ name }}" + resource_group: "{{ resource_group }}" + state: absent + register: output + +- assert: + that: + - not output.changed diff --git a/test/integration/targets/azure_rm_subnet/tasks/main.yml b/test/integration/targets/azure_rm_subnet/tasks/main.yml index 32ad0670d9..b6735a4430 100644 --- a/test/integration/targets/azure_rm_subnet/tasks/main.yml +++ b/test/integration/targets/azure_rm_subnet/tasks/main.yml @@ -12,6 +12,12 @@ delete: on-exit resource_group: "{{ resource_group }}" +- name: Create route table + azure_rm_routetable: + name: routetableforsubnet + resource_group: "{{ resource_group }}" + register: route_table + - name: Remove subnet azure_rm_subnet: state: absent @@ -87,6 +93,7 @@ virtual_network_name: My_Virtual_Network resource_group: "{{ resource_group }}" address_prefix_cidr: "10.1.0.0/16" + route_table: "{{ route_table.id }}" security_group: name: secgroupfoo resource_group: "{{ resource_group_secondary }}" @@ -106,6 +113,7 @@ virtual_network_name: My_Virtual_Network resource_group: "{{ resource_group }}" address_prefix_cidr: "10.1.0.0/16" + route_table: "{{ route_table.id }}" security_group: "{{ nsg.state.id }}" tags: testing: testing