From 84ac980f95847273ba4ce27e0e2572159c293afe Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Wed, 29 Jun 2022 15:43:33 +0530 Subject: [PATCH 1/9] Add static routes module spec --- plugins/modules/ntnx_static_routes.py | 76 +++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 plugins/modules/ntnx_static_routes.py diff --git a/plugins/modules/ntnx_static_routes.py b/plugins/modules/ntnx_static_routes.py new file mode 100644 index 000000000..3b58a3d2b --- /dev/null +++ b/plugins/modules/ntnx_static_routes.py @@ -0,0 +1,76 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Prem Karat +# 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 +from email.policy import default + +__metaclass__ = type + +DOCUMENTATION = r""" +""" +EXAMPLES = r""" +""" + +RETURN = r""" +""" + +from ..module_utils.base_module import BaseModule # noqa: E402 +from ..module_utils.prism.tasks import Task # noqa: E402 +from ..module_utils.utils import remove_param_with_none_value # noqa: E402 + + +def get_module_spec(): + mutually_exclusive = [("name", "uuid")] + + entity_by_spec = dict(name=dict(type="str"), uuid=dict(type="str")) + + nexthop_spec = dict( + subnet = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False), + vpn = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False) + ) + static_route_spec = dict( + destination = dict(type="str", required=True), + next_hop = dict( + type = "dict", + options=nexthop_spec, + required=True + ) + ) + module_args = dict( + static_routes_list = dict( + type="dict", + options=static_route_spec, + required=False + ), + remove_all_routes = dict(type="str", required=False, default=False) + ) + return module_args + + +def update_static_routes(module, result): + pass + +def run_module(): + module = BaseModule( + argument_spec=get_module_spec(), + supports_check_mode=True, + ) + remove_param_with_none_value(module.params) + result = { + "changed": False, + "error": None, + "response": None, + "vpc_uuid": None, + } + update_static_routes(module, result) + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == "__main__": + main() From c028d97c2c7a76382e449e994fc4969e59066ead Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Fri, 1 Jul 2022 16:06:24 +0530 Subject: [PATCH 2/9] Static routes update module --- plugins/module_utils/prism/static_routes.py | 96 +++++++++++++++++++ plugins/module_utils/prism/vpn_connections.py | 32 +++++++ plugins/modules/ntnx_static_routes.py | 63 ++++++++++-- 3 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 plugins/module_utils/prism/static_routes.py create mode 100644 plugins/module_utils/prism/vpn_connections.py diff --git a/plugins/module_utils/prism/static_routes.py b/plugins/module_utils/prism/static_routes.py new file mode 100644 index 000000000..1336dc14e --- /dev/null +++ b/plugins/module_utils/prism/static_routes.py @@ -0,0 +1,96 @@ +# This file is part of Ansible +# 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 + +from copy import deepcopy + +from .subnets import get_subnet_uuid +from .vpn_connections import get_vpn_connection_uuid +from .prism import Prism + + +class StaticRoutes(Prism): + default_route_dest = "0.0.0.0/0" + + def __init__(self, module): + resource_type = "/vpcs" + super(StaticRoutes, self).__init__(module, resource_type=resource_type) + self.build_spec_methods = { + "static_routes_list": self._build_spec_static_routes_list, + "remove_all_routes": self._build_spec_remove_all_routes + } + + def update_static_routes(self, data, vpc_uuid): + return self.update(data=data, uuid=vpc_uuid, endpoint="route_tables") + + def get_static_routes(self, vpc_uuid): + return self.read(uuid=vpc_uuid, endpoint="route_tables") + + def _get_default_spec(self): + return deepcopy( + { + "metadata":{ + "kind": "vpc_route_table" + }, + "spec":{ + "resources":{ + "static_routes_list": [], + "default_route_nexthop": None + } + } + + } + ) + + def _build_default_route_spec(self, payload, next_hop): + if payload["spec"]["resources"].get("default_route_nexthop"): + error = "More than one default routes are not allowed" + return None, error + payload["spec"]["resources"]["default_route_nexthop"] = next_hop + return payload, None + + def _build_spec_static_routes_list(self, payload, inp_static_routes): + if payload["spec"]["resources"].get("default_route_nexthop"): + payload["spec"]["resources"]["default_route_nexthop"] = None + static_routes_list = [] + for route in inp_static_routes: + next_hop = {} + if route["next_hop"].get("external_subnet_ref"): + subnet_ref = route["next_hop"]["external_subnet_ref"] + uuid, err = get_subnet_uuid(subnet_ref, self.module) + if err: + return None, err + next_hop["external_subnet_reference"] = { + "kind": "subnet", + "uuid" : uuid + } + elif route["next_hop"].get("vpn_connection_ref"): + vpn_ref = route["next_hop"]["vpn_connection_ref"] + uuid, err = get_vpn_connection_uuid(self.module, vpn_ref) + if err: + return None, err + next_hop["vpn_connection_reference"] = { + "kind": "vpn_connection", + "uuid" : uuid + } + + if route["destination"] == self.default_route_dest: + _, err = self._build_default_route_spec(payload, next_hop) + if err: + return None, err + else: + static_routes_list.append({ + "nexthop" : next_hop, + "destination": route["destination"] + }) + + payload["spec"]["resources"]["static_routes_list"] = static_routes_list + return payload, None + + def _build_spec_remove_all_routes(self, payload, remove_all_routes): + if remove_all_routes: + payload["spec"]["resources"].pop("default_route_nexthop") + payload["spec"]["resources"]["static_routes_list"] = [] + return payload, None \ No newline at end of file diff --git a/plugins/module_utils/prism/vpn_connections.py b/plugins/module_utils/prism/vpn_connections.py new file mode 100644 index 000000000..b47ea2567 --- /dev/null +++ b/plugins/module_utils/prism/vpn_connections.py @@ -0,0 +1,32 @@ +# This file is part of Ansible +# 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 + +from .prism import Prism + + +class VpnConnection(Prism): + def __init__(self, module): + resource_type = "/vpn_connections" + super(VpnConnection, self).__init__(module, resource_type=resource_type) + +# Helper functions + + +def get_vpn_connection_uuid(module, config): + if "name" in config: + vpn_obj = VpnConnection(module) + name = config.get("name") + uuid = vpn_obj.get_uuid(name) + if not uuid: + error = "VPN connection {0} not found.".format(name) + return None, error + elif "uuid" in config: + uuid = config.get("uuid") + else: + error = "Config {0} doesn't have name or uuid key".format(config) + None, error + + return uuid, None diff --git a/plugins/modules/ntnx_static_routes.py b/plugins/modules/ntnx_static_routes.py index 3b58a3d2b..fcc641763 100644 --- a/plugins/modules/ntnx_static_routes.py +++ b/plugins/modules/ntnx_static_routes.py @@ -4,7 +4,6 @@ # Copyright: (c) 2021, Prem Karat # 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 -from email.policy import default __metaclass__ = type @@ -18,39 +17,89 @@ from ..module_utils.base_module import BaseModule # noqa: E402 from ..module_utils.prism.tasks import Task # noqa: E402 +from ..module_utils.prism.static_routes import StaticRoutes +from ..module_utils import utils from ..module_utils.utils import remove_param_with_none_value # noqa: E402 + def get_module_spec(): mutually_exclusive = [("name", "uuid")] entity_by_spec = dict(name=dict(type="str"), uuid=dict(type="str")) nexthop_spec = dict( - subnet = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False), - vpn = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False) + external_subnet_ref = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False), + vpn_connection_ref = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False) ) static_route_spec = dict( destination = dict(type="str", required=True), next_hop = dict( type = "dict", options=nexthop_spec, - required=True + required=True, + mutually_exclusive = [("external_subnet_ref", "vpn_connection_ref")] ) ) module_args = dict( + vpc_uuid = dict(type="str", required=True), static_routes_list = dict( - type="dict", + type="list", + elements="dict", options=static_route_spec, required=False ), - remove_all_routes = dict(type="str", required=False, default=False) + remove_all_routes = dict(type="bool", required=False, default=False) ) return module_args def update_static_routes(module, result): - pass + static_routes = StaticRoutes(module) + vpc_uuid = module.params["vpc_uuid"] + curr_routes = static_routes.get_static_routes(vpc_uuid) + result["response"] = curr_routes + result["vpc_uuid"] = vpc_uuid + + # status and spec have field name different schema for default static routes + if curr_routes["status"]["resources"].get("default_route"): + curr_routes["status"]["resources"]["default_route_nexthop"] = curr_routes["status"]["resources"]["default_route"]["nexthop"] + + utils.strip_extra_attrs_from_status(curr_routes["status"], curr_routes["spec"]) + curr_routes["spec"] = curr_routes.pop("status") + + # new spec for updating static routes + update_spec, err = static_routes.get_spec(curr_routes) + if err: + result["error"] = err + module.fail_json(msg="Failed generating static routes update spec", **result) + + if update_spec == curr_routes: + result["skipped"] = True + module.exit_json( + msg="Nothing to update" + ) + + if module.check_mode: + result["response"] = update_spec + result["params"] = module.params + result["current_spec"] = curr_routes + return + + # update static routes + resp = static_routes.update_static_routes(update_spec, vpc_uuid) + task_uuid = resp["status"]["execution_context"]["task_uuid"] + + # wait for static routes update to finish + if module.params.get("wait"): + task = Task(module) + task.wait_for_completion(task_uuid) + # get the current static routes + resp = static_routes.get_static_routes(vpc_uuid) + + result["changed"] = True + result["response"] = resp + def run_module(): module = BaseModule( From 67dfa2a68cb2046cbb87e77e3c3fa776fda9d273 Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Fri, 1 Jul 2022 16:19:42 +0530 Subject: [PATCH 3/9] Info module for static routes --- plugins/modules/ntnx_static_routes_info.py | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 plugins/modules/ntnx_static_routes_info.py diff --git a/plugins/modules/ntnx_static_routes_info.py b/plugins/modules/ntnx_static_routes_info.py new file mode 100644 index 000000000..a9d4be8f2 --- /dev/null +++ b/plugins/modules/ntnx_static_routes_info.py @@ -0,0 +1,49 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Prem Karat +# 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 + +from ..module_utils.base_module import BaseModule +from ..module_utils.prism.static_routes import StaticRoutes + +__metaclass__ = type + +DOCUMENTATION = r""" +""" +EXAMPLES = r""" +""" +RETURN = r""" +""" + + +def get_module_spec(): + + module_args = dict( + vpc_uuid=dict(type="str", required=True), + ) + + return module_args + + +def run_module(): + module = BaseModule( + argument_spec=get_module_spec(), + supports_check_mode=False, + ) + result = {"changed": False, "error": None, "response": None} + + vpc_uuid = module.params["vpc_uuid"] + static_routes = StaticRoutes(module) + result["response"] = static_routes.get_static_routes(vpc_uuid) + result["vpc_uuid"] = vpc_uuid + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == "__main__": + main() From 0a456b99f3c407f0061f86775c07655077785a16 Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Fri, 1 Jul 2022 18:29:06 +0530 Subject: [PATCH 4/9] tests for static routes --- meta/runtime.yml | 2 + plugins/module_utils/prism/static_routes.py | 6 +- .../targets/ntnx_static_routes/meta/main.yml | 2 + .../ntnx_static_routes/tasks/create.yml | 134 ++++++++++++++++++ .../targets/ntnx_static_routes/tasks/main.yml | 9 ++ .../ntnx_static_routes_info/meta/main.yml | 2 + .../ntnx_static_routes_info/tasks/info.yml | 71 ++++++++++ .../ntnx_static_routes_info/tasks/main.yml | 9 ++ .../targets/prepare_env/vars/main.yml | 8 +- 9 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 tests/integration/targets/ntnx_static_routes/meta/main.yml create mode 100644 tests/integration/targets/ntnx_static_routes/tasks/create.yml create mode 100644 tests/integration/targets/ntnx_static_routes/tasks/main.yml create mode 100644 tests/integration/targets/ntnx_static_routes_info/meta/main.yml create mode 100644 tests/integration/targets/ntnx_static_routes_info/tasks/info.yml create mode 100644 tests/integration/targets/ntnx_static_routes_info/tasks/main.yml diff --git a/meta/runtime.yml b/meta/runtime.yml index da1a8c2a9..7ae4d9725 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -11,6 +11,7 @@ action_groups: - ntnx_vms_clone - ntnx_vms - ntnx_vpcs + - ntnx_static_routes - ntnx_floating_ips_info - ntnx_images_info - ntnx_image_placement_policies_info @@ -18,6 +19,7 @@ action_groups: - ntnx_subnets_info - ntnx_vms_info - ntnx_vpcs_info + - ntnx_static_routes_info - ntnx_foundation_aos_packages_info - ntnx_foundation_bmc_ipmi_config - ntnx_foundation_discover_nodes_info diff --git a/plugins/module_utils/prism/static_routes.py b/plugins/module_utils/prism/static_routes.py index 1336dc14e..5fcfcfbea 100644 --- a/plugins/module_utils/prism/static_routes.py +++ b/plugins/module_utils/prism/static_routes.py @@ -52,8 +52,9 @@ def _build_default_route_spec(self, payload, next_hop): return payload, None def _build_spec_static_routes_list(self, payload, inp_static_routes): + # since static route list has to be overriden if payload["spec"]["resources"].get("default_route_nexthop"): - payload["spec"]["resources"]["default_route_nexthop"] = None + payload["spec"]["resources"].pop("default_route_nexthop") static_routes_list = [] for route in inp_static_routes: next_hop = {} @@ -91,6 +92,7 @@ def _build_spec_static_routes_list(self, payload, inp_static_routes): def _build_spec_remove_all_routes(self, payload, remove_all_routes): if remove_all_routes: - payload["spec"]["resources"].pop("default_route_nexthop") + if payload["spec"]["resources"].get("default_route_nexthop"): + payload["spec"]["resources"].pop("default_route_nexthop") payload["spec"]["resources"]["static_routes_list"] = [] return payload, None \ No newline at end of file diff --git a/tests/integration/targets/ntnx_static_routes/meta/main.yml b/tests/integration/targets/ntnx_static_routes/meta/main.yml new file mode 100644 index 000000000..e4f447d3a --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - prepare_env diff --git a/tests/integration/targets/ntnx_static_routes/tasks/create.yml b/tests/integration/targets/ntnx_static_routes/tasks/create.yml new file mode 100644 index 000000000..c64acc2d3 --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes/tasks/create.yml @@ -0,0 +1,134 @@ +- debug: + msg: Start testing static routes update tests + +- name: Add default static route and external nat static route to the vpc route table + ntnx_static_routes: + vpc_uuid: "{{ vpc.uuid }}" + static_routes_list: + - destination: "0.0.0.0/0" + next_hop: + external_subnet_ref: + name: "{{ external_nat_subnet.name }}" + - destination: "10.2.2.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + - destination: "10.2.3.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + register: result + +- name: Update static routes list Status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + - result.changed == true + - result.response.status.resources.static_routes_list[0]["is_active"] == true + - result.response.status.resources.static_routes_list[0]["destination"] == "10.2.2.0/24" + - result.response.status.resources.static_routes_list[0]["nexthop"]["external_subnet_reference"]["name"] == "{{ external_nat_subnet.name }}" + - result.response.status.resources.static_routes_list[1]["is_active"] == true + - result.response.status.resources.static_routes_list[1]["destination"] == "10.2.3.0/24" + - result.response.status.resources.static_routes_list[1]["nexthop"]["external_subnet_reference"]["name"] == "{{ external_nat_subnet.name }}" + - result.response.status.resources.default_route["is_active"] == true + - result.response.status.resources.default_route["destination"] == "0.0.0.0/0" + - result.response.status.resources.default_route["nexthop"]["external_subnet_reference"]["name"] == "{{ external_nat_subnet.name }}" + + fail_msg: 'Fail: Unable to update static routes of vpc' + success_msg: 'Succes: static routes updated succesfully' + +########################################################################################################### + +- name: Idempotency check + ntnx_static_routes: + vpc_uuid: "{{ vpc.uuid }}" + static_routes_list: + - destination: "0.0.0.0/0" + next_hop: + external_subnet_ref: + name: "{{ external_nat_subnet.name }}" + - destination: "10.2.2.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + - destination: "10.2.3.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + register: result + +- name: check idempotency status + assert: + that: + - result.changed == false + - result.failed == false + - "'Nothing to update' in result.msg" + fail_msg: "Static routes" + success_msg: "Static routes update skipped succesfully due to no changes in spec" + +########################################################################################################### + +- name: Override existing static routes + ntnx_static_routes: + vpc_uuid: "{{ vpc.uuid }}" + static_routes_list: + - destination: "10.2.4.0/24" + next_hop: + external_subnet_ref: + name: "{{ external_nat_subnet.name }}" + register: result + +- name: Update static routes list Status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + - result.changed == true + - result.response.status.resources.static_routes_list[0]["is_active"] == true + - result.response.status.resources.static_routes_list[0]["destination"] == "10.2.4.0/24" + - result.response.status.resources.static_routes_list[0]["nexthop"]["external_subnet_reference"]["name"] == "{{ external_nat_subnet.name }}" + fail_msg: "Static routes overriding failed" + success_msg: "Static routes overriden successfully" + +########################################################################################################### + +- name: Netgative scenario of cretaing multiple default routes + ntnx_static_routes: + vpc_uuid: "{{ vpc.uuid }}" + static_routes_list: + - destination: "0.0.0.0/0" + next_hop: + external_subnet_ref: + name: "{{ external_nat_subnet.name }}" + - destination: "0.0.0.0/0" + next_hop: + external_subnet_ref: + name: "{{ external_nat_subnet.name }}" + register: result + ignore_errors: true + +- name: Update static routes list Status + assert: + that: + - result.changed == false + - result.failed == true + fail_msg: "Static routes updated successfully" + success_msg: "Static routes update failed successfully" + +########################################################################################################### +- name: remove all routes + ntnx_static_routes: + vpc_uuid: "{{ vpc.uuid }}" + remove_all_routes: true + register: result + +- name: Remove all routes status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + - result.changed == true + - result.response.status.resources.static_routes_list == [] + fail_msg: "Static routes remove failed" + success_msg: "Static routes removed successfully" diff --git a/tests/integration/targets/ntnx_static_routes/tasks/main.yml b/tests/integration/targets/ntnx_static_routes/tasks/main.yml new file mode 100644 index 000000000..b19cfc1ec --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- module_defaults: + group/nutanix.ncp.ntnx: + nutanix_host: "{{ ip }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + validate_certs: "{{ validate_certs }}" + block: + - import_tasks: "create.yml" diff --git a/tests/integration/targets/ntnx_static_routes_info/meta/main.yml b/tests/integration/targets/ntnx_static_routes_info/meta/main.yml new file mode 100644 index 000000000..e4f447d3a --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes_info/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - prepare_env diff --git a/tests/integration/targets/ntnx_static_routes_info/tasks/info.yml b/tests/integration/targets/ntnx_static_routes_info/tasks/info.yml new file mode 100644 index 000000000..f0c4100cb --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes_info/tasks/info.yml @@ -0,0 +1,71 @@ +- debug: + msg: Start testing static routes info tests + +- name: create new static routes + ntnx_static_routes: + vpc_uuid: "{{ vpc.uuid }}" + static_routes_list: + - destination: "0.0.0.0/0" + next_hop: + external_subnet_ref: + name: "{{ external_nat_subnet.name }}" + - destination: "10.2.2.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + - destination: "10.2.3.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + register: result + +- name: Update static routes list Status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + - result.changed == true + fail_msg: 'Fail: Unable to update static routes of vpc' + success_msg: 'Succes: static routes updated succesfully' + +########################################################################################################### + +- name: get all static routes + ntnx_static_routes_info: + vpc_uuid: "{{ vpc.uuid }}" + register: result + +- name: check info module response + assert: + that: + - result.response is defined + - result.changed == false + - result.response.status.resources.static_routes_list[0]["is_active"] == true + - result.response.status.resources.static_routes_list[0]["destination"] == "10.2.2.0/24" + - result.response.status.resources.static_routes_list[0]["nexthop"]["external_subnet_reference"]["name"] == "{{ external_nat_subnet.name }}" + - result.response.status.resources.static_routes_list[1]["is_active"] == true + - result.response.status.resources.static_routes_list[1]["destination"] == "10.2.3.0/24" + - result.response.status.resources.static_routes_list[1]["nexthop"]["external_subnet_reference"]["name"] == "{{ external_nat_subnet.name }}" + - result.response.status.resources.default_route["is_active"] == true + - result.response.status.resources.default_route["destination"] == "0.0.0.0/0" + - result.response.status.resources.default_route["nexthop"]["external_subnet_reference"]["name"] == "{{ external_nat_subnet.name }}" + + fail_msg: 'Fail: Unable to get static routes for vpc' + success_msg: 'Succes' + +########################################################################################################### + +- name: remove all routes for cleanup + ntnx_static_routes: + vpc_uuid: "{{ vpc.uuid }}" + remove_all_routes: true + register: result + ignore_errors: true + +- name: Remove all routes status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + - result.changed == true + - result.response.status.resources.static_routes_list == [] diff --git a/tests/integration/targets/ntnx_static_routes_info/tasks/main.yml b/tests/integration/targets/ntnx_static_routes_info/tasks/main.yml new file mode 100644 index 000000000..3364b30c6 --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes_info/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- module_defaults: + group/nutanix.ncp.ntnx: + nutanix_host: "{{ ip }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + validate_certs: "{{ validate_certs }}" + block: + - import_tasks: "info.yml" diff --git a/tests/integration/targets/prepare_env/vars/main.yml b/tests/integration/targets/prepare_env/vars/main.yml index 401a4052d..6811ac056 100644 --- a/tests/integration/targets/prepare_env/vars/main.yml +++ b/tests/integration/targets/prepare_env/vars/main.yml @@ -8,12 +8,12 @@ disk_image: centos: "CentOS-7-cloudinit" cluster: - name: auto_cluster_prod_1a87d3b4b507 - uuid: 0005e298-1741-9353-3507-ac1f6b60292f + name: auto_cluster_prod_f34ce3677ecf + uuid: "0005e2ae-ac79-ed3f-185b-ac1f6b6f97e2" virtual_switch: name: vs0 - uuid: 7a88a08c-cc4c-44ef-b8c6-a0e8e970311f + uuid: 25738b38-41f1-498c-89bc-2a868951bc6c external_nat_subnets: name: integration_test_Ext-Nat vlan_id: 103 @@ -35,4 +35,4 @@ overlay_subnet: network_ip: 192.168.1.0 network_prefix: 24 gateway_ip: 192.168.1.1 - private_ip: 192.168.1.13 + private_ip: 192.168.1.13 \ No newline at end of file From b1b202ebb63932a7bb4aa2523acb7f5f83219043 Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Fri, 1 Jul 2022 18:36:42 +0530 Subject: [PATCH 5/9] Sanity fixes --- README.md | 2 + plugins/module_utils/prism/static_routes.py | 35 +++++------ plugins/module_utils/prism/vpn_connections.py | 1 + plugins/modules/ntnx_static_routes.py | 60 +++++++++++-------- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 183696812..512c7864b 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,8 @@ ansible-playbook examples/iaas/iaas.yml | ntnx_image_placement_policies_info | List existing image placement policies. | | ntnx_pbrs | Create or delete a PBR. | | ntnx_pbrs_info | List existing PBRs. | +| ntnx_static_routes | Update static routes of a vpc. | +| ntnx_static_routes_info | List existing static routes of a vpc. | | ntnx_subnets | Create or delete a Subnet. | | ntnx_subnets_info | List existing Subnets. | | ntnx_vms | Create or delete a VM. | diff --git a/plugins/module_utils/prism/static_routes.py b/plugins/module_utils/prism/static_routes.py index 5fcfcfbea..c0acb195c 100644 --- a/plugins/module_utils/prism/static_routes.py +++ b/plugins/module_utils/prism/static_routes.py @@ -19,28 +19,25 @@ def __init__(self, module): super(StaticRoutes, self).__init__(module, resource_type=resource_type) self.build_spec_methods = { "static_routes_list": self._build_spec_static_routes_list, - "remove_all_routes": self._build_spec_remove_all_routes + "remove_all_routes": self._build_spec_remove_all_routes, } def update_static_routes(self, data, vpc_uuid): return self.update(data=data, uuid=vpc_uuid, endpoint="route_tables") - + def get_static_routes(self, vpc_uuid): return self.read(uuid=vpc_uuid, endpoint="route_tables") - + def _get_default_spec(self): return deepcopy( { - "metadata":{ - "kind": "vpc_route_table" - }, - "spec":{ - "resources":{ + "metadata": {"kind": "vpc_route_table"}, + "spec": { + "resources": { "static_routes_list": [], - "default_route_nexthop": None + "default_route_nexthop": None, } - } - + }, } ) @@ -63,10 +60,7 @@ def _build_spec_static_routes_list(self, payload, inp_static_routes): uuid, err = get_subnet_uuid(subnet_ref, self.module) if err: return None, err - next_hop["external_subnet_reference"] = { - "kind": "subnet", - "uuid" : uuid - } + next_hop["external_subnet_reference"] = {"kind": "subnet", "uuid": uuid} elif route["next_hop"].get("vpn_connection_ref"): vpn_ref = route["next_hop"]["vpn_connection_ref"] uuid, err = get_vpn_connection_uuid(self.module, vpn_ref) @@ -74,7 +68,7 @@ def _build_spec_static_routes_list(self, payload, inp_static_routes): return None, err next_hop["vpn_connection_reference"] = { "kind": "vpn_connection", - "uuid" : uuid + "uuid": uuid, } if route["destination"] == self.default_route_dest: @@ -82,10 +76,9 @@ def _build_spec_static_routes_list(self, payload, inp_static_routes): if err: return None, err else: - static_routes_list.append({ - "nexthop" : next_hop, - "destination": route["destination"] - }) + static_routes_list.append( + {"nexthop": next_hop, "destination": route["destination"]} + ) payload["spec"]["resources"]["static_routes_list"] = static_routes_list return payload, None @@ -95,4 +88,4 @@ def _build_spec_remove_all_routes(self, payload, remove_all_routes): if payload["spec"]["resources"].get("default_route_nexthop"): payload["spec"]["resources"].pop("default_route_nexthop") payload["spec"]["resources"]["static_routes_list"] = [] - return payload, None \ No newline at end of file + return payload, None diff --git a/plugins/module_utils/prism/vpn_connections.py b/plugins/module_utils/prism/vpn_connections.py index b47ea2567..c382e07ce 100644 --- a/plugins/module_utils/prism/vpn_connections.py +++ b/plugins/module_utils/prism/vpn_connections.py @@ -12,6 +12,7 @@ def __init__(self, module): resource_type = "/vpn_connections" super(VpnConnection, self).__init__(module, resource_type=resource_type) + # Helper functions diff --git a/plugins/modules/ntnx_static_routes.py b/plugins/modules/ntnx_static_routes.py index fcc641763..15942e7d1 100644 --- a/plugins/modules/ntnx_static_routes.py +++ b/plugins/modules/ntnx_static_routes.py @@ -16,11 +16,12 @@ """ from ..module_utils.base_module import BaseModule # noqa: E402 +from ..module_utils.prism.static_routes import StaticRoutes # noqa: E402 from ..module_utils.prism.tasks import Task # noqa: E402 -from ..module_utils.prism.static_routes import StaticRoutes -from ..module_utils import utils -from ..module_utils.utils import remove_param_with_none_value # noqa: E402 - +from ..module_utils.utils import ( # noqa: E402 + remove_param_with_none_value, + strip_extra_attrs_from_status, +) def get_module_spec(): @@ -29,27 +30,34 @@ def get_module_spec(): entity_by_spec = dict(name=dict(type="str"), uuid=dict(type="str")) nexthop_spec = dict( - external_subnet_ref = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False), - vpn_connection_ref = dict(type="dict", options=entity_by_spec, mutually_exclusive=mutually_exclusive, required=False) + external_subnet_ref=dict( + type="dict", + options=entity_by_spec, + mutually_exclusive=mutually_exclusive, + required=False, + ), + vpn_connection_ref=dict( + type="dict", + options=entity_by_spec, + mutually_exclusive=mutually_exclusive, + required=False, + ), ) static_route_spec = dict( - destination = dict(type="str", required=True), - next_hop = dict( - type = "dict", + destination=dict(type="str", required=True), + next_hop=dict( + type="dict", options=nexthop_spec, required=True, - mutually_exclusive = [("external_subnet_ref", "vpn_connection_ref")] - ) - ) + mutually_exclusive=[("external_subnet_ref", "vpn_connection_ref")], + ), + ) module_args = dict( - vpc_uuid = dict(type="str", required=True), - static_routes_list = dict( - type="list", - elements="dict", - options=static_route_spec, - required=False + vpc_uuid=dict(type="str", required=True), + static_routes_list=dict( + type="list", elements="dict", options=static_route_spec, required=False ), - remove_all_routes = dict(type="bool", required=False, default=False) + remove_all_routes=dict(type="bool", required=False, default=False), ) return module_args @@ -63,11 +71,13 @@ def update_static_routes(module, result): # status and spec have field name different schema for default static routes if curr_routes["status"]["resources"].get("default_route"): - curr_routes["status"]["resources"]["default_route_nexthop"] = curr_routes["status"]["resources"]["default_route"]["nexthop"] - - utils.strip_extra_attrs_from_status(curr_routes["status"], curr_routes["spec"]) + curr_routes["status"]["resources"]["default_route_nexthop"] = curr_routes[ + "status" + ]["resources"]["default_route"]["nexthop"] + + strip_extra_attrs_from_status(curr_routes["status"], curr_routes["spec"]) curr_routes["spec"] = curr_routes.pop("status") - + # new spec for updating static routes update_spec, err = static_routes.get_spec(curr_routes) if err: @@ -76,9 +86,7 @@ def update_static_routes(module, result): if update_spec == curr_routes: result["skipped"] = True - module.exit_json( - msg="Nothing to update" - ) + module.exit_json(msg="Nothing to update") if module.check_mode: result["response"] = update_spec From ed99488f10f77deb54841088fa2b11a6e5f7d99d Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Fri, 1 Jul 2022 19:49:41 +0530 Subject: [PATCH 6/9] Doc fixes --- plugins/modules/ntnx_static_routes.py | 253 +++++++++++++++++++++ plugins/modules/ntnx_static_routes_info.py | 159 ++++++++++++- 2 files changed, 408 insertions(+), 4 deletions(-) diff --git a/plugins/modules/ntnx_static_routes.py b/plugins/modules/ntnx_static_routes.py index 15942e7d1..fa6a64756 100644 --- a/plugins/modules/ntnx_static_routes.py +++ b/plugins/modules/ntnx_static_routes.py @@ -8,11 +8,262 @@ __metaclass__ = type DOCUMENTATION = r""" +module: ntnx_static_routes +short_description: module for create/update static routes of vpc +version_added: 1.0.0 +description: "Create/Update static routes of vpc" +options: + wait: + description: Wait for the create/update operations to complete. + type: bool + required: false + default: True + vpc_uuid: + description: vpc uuid whose static routes has to be created/updated + required: true + type: str + remove_all_routes: + description: + - set this flag to remove all static routes + - this will only remove all static routes except local and dynamic routes + - mutually_exclusive with C(static_routes_list) + type: bool + required: false + default: false + static_routes_list: + description: + - list of static routes to be overriden in vpc. + - mutually exclusive with C(remove_all_routes) + - required incase remove_all_categories is not given + - default static route can be mentioned in this with destination - 0.0.0.0/0 + - Only one default static route is allowed + required: false + type: list + elements: dict + suboptions: + destination: + description: + - destination prefix eg. 10.2.3.0/24 + - for defaut static route give 0.0.0.0/0 + required: true + type: str + next_hop: + description: + - info about next hop in static route + type: dict + required: true + suboptions: + vpn_connection_ref: + description: + - vpn connection reference + - mutually exclusive with C(external_subnet_ref) + type: dict + required: false + suboptions: + name: + description: + - vpn connection Name + - Mutually exclusive with C(uuid) + type: str + required: false + uuid: + description: + - vpn connection UUID + - Mutually exclusive with C(name) + type: str + required: false + external_subnet_ref: + description: + - external subnet reference + - mutually exclusive with C(vpn_connection_ref) + type: dict + required: false + suboptions: + name: + description: + - subnet connection Name + - Mutually exclusive with C(uuid) + type: str + required: false + uuid: + description: + - subnet connection UUID + - Mutually exclusive with C(name) + type: str + required: false +extends_documentation_fragment: + - nutanix.ncp.ntnx_credentials + - nutanix.ncp.ntnx_operations +author: + - Prem Karat (@premkarat) + - Pradeepsingh Bhati (@bhati-pradeep) """ EXAMPLES = r""" +- name: create static routes and default static routes with external nat subnet + ntnx_static_routes: + nutanix_host: "{{ ip }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + validate_certs: False + vpc_uuid: "{{ vpc.uuid }}" + static_routes_list: + - destination: "0.0.0.0/0" + next_hop: + external_subnet_ref: + name: "{{ external_nat_subnet.name }}" + - destination: "10.2.2.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + - destination: "10.2.3.0/24" + next_hop: + external_subnet_ref: + uuid: "{{ external_nat_subnet.uuid }}" + register: result + +- name: remove all routes excluding dynamic and local routes + ntnx_static_routes: + nutanix_host: "{{ ip }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + validate_certs: False + vpc_uuid: "{{ vpc.uuid }}" + remove_all_routes: true + register: result """ RETURN = r""" +api_version: + description: API Version of the Nutanix v3 API framework. + returned: always + type: str + sample: "3.1" +metadata: + description: The vpc_route_table kind metadata + returned: always + type: dict + sample: { + "categories": {}, + "categories_mapping": {}, + "creation_time": "2022-07-01T08:20:39Z", + "kind": "vpc_route_table", + "last_update_time": "2022-07-01T10:30:41Z", + "owner_reference": { + "kind": "user", + "name": "admin", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "spec_hash": "00000000000000000000000000000000000000000000000000", + "spec_version": 8, + "uuid": "528323ee-7c89-sb65-68a7-a66c0c4fc9d5" + } +spec: + description: An intentful representation of a vpc static routes spec + returned: always + type: dict + sample: { + "name": "Route Table for vpc", + "resources": { + "default_route_nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "uuid": "ace7f19a-a1a9-43ca-a11a-cbac200044b7" + } + }, + "static_routes_list": [ + { + "destination": "10.2.2.0/24", + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "uuid": "ace7f19a-a1a9-43ca-c11a-9bac200044b7" + } + } + }, + { + "destination": "10.2.3.0/24", + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "uuid": "ace7f19a-d1a9-43ca-a11a-9bac200044b7" + } + } + } + ] + } + } +status: + description: An intentful representation of a vpc static routes status + returned: always + type: dict + sample: { + "execution_context": { + "task_uuid": [ + "bc6bdb00-18b3-sdab-8b03-701db6856e7f" + ] + }, + "resources": { + "default_route": { + "destination": "0.0.0.0/0", + "is_active": true, + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "name": "no-nat", + "uuid": "ace7f19a-a1a9-43ca-a11a-9bac200044b7" + } + }, + "priority": 23455 + }, + "dynamic_routes_list": [], + "local_routes_list": [ + { + "destination": "xx.xx.xx.xx/24", + "is_active": true, + "nexthop": { + "local_subnet_reference": { + "kind": "subnet", + "name": "integration_test_overlay_subnet", + "uuid": "974234b1-3fd1-4525-adeb-bce069696d2e" + } + }, + "priority": 65534 + } + ], + "static_routes_list": [ + { + "destination": "10.2.2.0/24", + "is_active": true, + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "name": "no-nat", + "uuid": "ave7f19a-a1a9-43ca-a11a-9bac200044b7" + } + }, + "priority": 23455 + }, + { + "destination": "10.2.3.0/24", + "is_active": true, + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "name": "no-nat", + "uuid": "cce7f19a-a1a9-43ca-a11a-9bac200044b7" + } + }, + "priority": 23455 + } + ] + }, + "state": "COMPLETE" + } +vpc_uuid: + description: vpc uuid + returned: always + type: str + sample: "00000000-0000-0000-0000-000000000000" """ from ..module_utils.base_module import BaseModule # noqa: E402 @@ -113,6 +364,8 @@ def run_module(): module = BaseModule( argument_spec=get_module_spec(), supports_check_mode=True, + required_one_of=[("static_routes_list", "remove_all_routes")], + mutually_exclusive=[("static_routes_list", "remove_all_routes")], ) remove_param_with_none_value(module.params) result = { diff --git a/plugins/modules/ntnx_static_routes_info.py b/plugins/modules/ntnx_static_routes_info.py index a9d4be8f2..0c724b35e 100644 --- a/plugins/modules/ntnx_static_routes_info.py +++ b/plugins/modules/ntnx_static_routes_info.py @@ -5,18 +5,169 @@ # 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 -from ..module_utils.base_module import BaseModule -from ..module_utils.prism.static_routes import StaticRoutes - __metaclass__ = type DOCUMENTATION = r""" +--- +module: ntnx_static_routes_info +short_description: static routes info module +version_added: 1.0.0 +description: 'Get static routes info for a vpc' +options: + vpc_uuid: + description: + - vpc UUID whose static routes needs to be fetched + type: str +extends_documentation_fragment: + - nutanix.ncp.ntnx_credentials + - nutanix.ncp.ntnx_operations +author: + - Prem Karat (@premkarat) + - Pradeepsingh Bhati (@bhati-pradeep) """ EXAMPLES = r""" +- name: get all static routes for a vpc + ntnx_static_routes_info: + vpc_uuid: "{{ vpc.uuid }}" + register: result """ RETURN = r""" +api_version: + description: API Version of the Nutanix v3 API framework. + returned: always + type: str + sample: "3.1" +metadata: + description: The vpc_route_table kind metadata + returned: always + type: dict + sample: { + "categories": {}, + "categories_mapping": {}, + "creation_time": "2022-07-01T08:20:39Z", + "kind": "vpc_route_table", + "last_update_time": "2022-07-01T10:30:41Z", + "owner_reference": { + "kind": "user", + "name": "admin", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "spec_hash": "00000000000000000000000000000000000000000000000000", + "spec_version": 8, + "uuid": "528323ee-7c89-sb65-68a7-a66c0c4fc9d5" + } +spec: + description: An intentful representation of a vpc static routes spec + returned: always + type: dict + sample: { + "name": "Route Table for vpc", + "resources": { + "default_route_nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "uuid": "ace7f19a-a1a9-43ca-a11a-cbac200044b7" + } + }, + "static_routes_list": [ + { + "destination": "10.2.2.0/24", + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "uuid": "ace7f19a-a1a9-43ca-c11a-9bac200044b7" + } + } + }, + { + "destination": "10.2.3.0/24", + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "uuid": "ace7f19a-d1a9-43ca-a11a-9bac200044b7" + } + } + } + ] + } + } +status: + description: An intentful representation of a vpc static routes status + returned: always + type: dict + sample: { + "execution_context": { + "task_uuid": [ + "bc6bdb00-18b3-sdab-8b03-701db6856e7f" + ] + }, + "resources": { + "default_route": { + "destination": "0.0.0.0/0", + "is_active": true, + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "name": "no-nat", + "uuid": "ace7f19a-a1a9-43ca-a11a-9bac200044b7" + } + }, + "priority": 23455 + }, + "dynamic_routes_list": [], + "local_routes_list": [ + { + "destination": "xx.xx.xx.xx/24", + "is_active": true, + "nexthop": { + "local_subnet_reference": { + "kind": "subnet", + "name": "integration_test_overlay_subnet", + "uuid": "974234b1-3fd1-4525-adeb-bce069696d2e" + } + }, + "priority": 65534 + } + ], + "static_routes_list": [ + { + "destination": "10.2.2.0/24", + "is_active": true, + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "name": "no-nat", + "uuid": "ave7f19a-a1a9-43ca-a11a-9bac200044b7" + } + }, + "priority": 23455 + }, + { + "destination": "10.2.3.0/24", + "is_active": true, + "nexthop": { + "external_subnet_reference": { + "kind": "subnet", + "name": "no-nat", + "uuid": "cce7f19a-a1a9-43ca-a11a-9bac200044b7" + } + }, + "priority": 23455 + } + ] + }, + "state": "COMPLETE" + } +vpc_uuid: + description: vpc uuid + returned: always + type: str + sample: "00000000-0000-0000-0000-000000000000" """ +from ..module_utils.base_module import BaseModule # noqa: E402 +from ..module_utils.prism.static_routes import StaticRoutes # noqa: E402 + def get_module_spec(): @@ -32,7 +183,7 @@ def run_module(): argument_spec=get_module_spec(), supports_check_mode=False, ) - result = {"changed": False, "error": None, "response": None} + result = {"changed": False, "error": None, "response": None, "vpc_uuid": None} vpc_uuid = module.params["vpc_uuid"] static_routes = StaticRoutes(module) From de45a735f44ef337b10d42161fbce24d61033e30 Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Mon, 4 Jul 2022 12:03:44 +0530 Subject: [PATCH 7/9] minor fix --- plugins/module_utils/prism/static_routes.py | 4 ++-- plugins/modules/ntnx_static_routes.py | 12 ++++++------ .../targets/ntnx_static_routes/tasks/create.yml | 8 ++++---- .../targets/ntnx_static_routes_info/tasks/info.yml | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/module_utils/prism/static_routes.py b/plugins/module_utils/prism/static_routes.py index c0acb195c..3d31fdf3a 100644 --- a/plugins/module_utils/prism/static_routes.py +++ b/plugins/module_utils/prism/static_routes.py @@ -18,7 +18,7 @@ def __init__(self, module): resource_type = "/vpcs" super(StaticRoutes, self).__init__(module, resource_type=resource_type) self.build_spec_methods = { - "static_routes_list": self._build_spec_static_routes_list, + "static_routes": self._build_spec_static_routes, "remove_all_routes": self._build_spec_remove_all_routes, } @@ -48,7 +48,7 @@ def _build_default_route_spec(self, payload, next_hop): payload["spec"]["resources"]["default_route_nexthop"] = next_hop return payload, None - def _build_spec_static_routes_list(self, payload, inp_static_routes): + def _build_spec_static_routes(self, payload, inp_static_routes): # since static route list has to be overriden if payload["spec"]["resources"].get("default_route_nexthop"): payload["spec"]["resources"].pop("default_route_nexthop") diff --git a/plugins/modules/ntnx_static_routes.py b/plugins/modules/ntnx_static_routes.py index fa6a64756..b54c38fc9 100644 --- a/plugins/modules/ntnx_static_routes.py +++ b/plugins/modules/ntnx_static_routes.py @@ -26,11 +26,11 @@ description: - set this flag to remove all static routes - this will only remove all static routes except local and dynamic routes - - mutually_exclusive with C(static_routes_list) + - mutually_exclusive with C(static_routes) type: bool required: false default: false - static_routes_list: + static_routes: description: - list of static routes to be overriden in vpc. - mutually exclusive with C(remove_all_routes) @@ -106,7 +106,7 @@ nutanix_password: "{{ password }}" validate_certs: False vpc_uuid: "{{ vpc.uuid }}" - static_routes_list: + static_routes: - destination: "0.0.0.0/0" next_hop: external_subnet_ref: @@ -305,7 +305,7 @@ def get_module_spec(): ) module_args = dict( vpc_uuid=dict(type="str", required=True), - static_routes_list=dict( + static_routes=dict( type="list", elements="dict", options=static_route_spec, required=False ), remove_all_routes=dict(type="bool", required=False, default=False), @@ -364,8 +364,8 @@ def run_module(): module = BaseModule( argument_spec=get_module_spec(), supports_check_mode=True, - required_one_of=[("static_routes_list", "remove_all_routes")], - mutually_exclusive=[("static_routes_list", "remove_all_routes")], + required_one_of=[("static_routes", "remove_all_routes")], + mutually_exclusive=[("static_routes", "remove_all_routes")], ) remove_param_with_none_value(module.params) result = { diff --git a/tests/integration/targets/ntnx_static_routes/tasks/create.yml b/tests/integration/targets/ntnx_static_routes/tasks/create.yml index c64acc2d3..5d3bbfb65 100644 --- a/tests/integration/targets/ntnx_static_routes/tasks/create.yml +++ b/tests/integration/targets/ntnx_static_routes/tasks/create.yml @@ -4,7 +4,7 @@ - name: Add default static route and external nat static route to the vpc route table ntnx_static_routes: vpc_uuid: "{{ vpc.uuid }}" - static_routes_list: + static_routes: - destination: "0.0.0.0/0" next_hop: external_subnet_ref: @@ -43,7 +43,7 @@ - name: Idempotency check ntnx_static_routes: vpc_uuid: "{{ vpc.uuid }}" - static_routes_list: + static_routes: - destination: "0.0.0.0/0" next_hop: external_subnet_ref: @@ -72,7 +72,7 @@ - name: Override existing static routes ntnx_static_routes: vpc_uuid: "{{ vpc.uuid }}" - static_routes_list: + static_routes: - destination: "10.2.4.0/24" next_hop: external_subnet_ref: @@ -96,7 +96,7 @@ - name: Netgative scenario of cretaing multiple default routes ntnx_static_routes: vpc_uuid: "{{ vpc.uuid }}" - static_routes_list: + static_routes: - destination: "0.0.0.0/0" next_hop: external_subnet_ref: diff --git a/tests/integration/targets/ntnx_static_routes_info/tasks/info.yml b/tests/integration/targets/ntnx_static_routes_info/tasks/info.yml index f0c4100cb..8eda760ab 100644 --- a/tests/integration/targets/ntnx_static_routes_info/tasks/info.yml +++ b/tests/integration/targets/ntnx_static_routes_info/tasks/info.yml @@ -4,7 +4,7 @@ - name: create new static routes ntnx_static_routes: vpc_uuid: "{{ vpc.uuid }}" - static_routes_list: + static_routes: - destination: "0.0.0.0/0" next_hop: external_subnet_ref: From 33c39a07112f558704cc94fd10456aa423069bd2 Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Mon, 4 Jul 2022 12:17:05 +0530 Subject: [PATCH 8/9] make vpc parent class for static routes --- plugins/module_utils/prism/static_routes.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/module_utils/prism/static_routes.py b/plugins/module_utils/prism/static_routes.py index 3d31fdf3a..39b403ae7 100644 --- a/plugins/module_utils/prism/static_routes.py +++ b/plugins/module_utils/prism/static_routes.py @@ -8,15 +8,14 @@ from .subnets import get_subnet_uuid from .vpn_connections import get_vpn_connection_uuid -from .prism import Prism +from .vpcs import Vpc -class StaticRoutes(Prism): +class StaticRoutes(Vpc): default_route_dest = "0.0.0.0/0" def __init__(self, module): - resource_type = "/vpcs" - super(StaticRoutes, self).__init__(module, resource_type=resource_type) + super(StaticRoutes, self).__init__(module) self.build_spec_methods = { "static_routes": self._build_spec_static_routes, "remove_all_routes": self._build_spec_remove_all_routes, From 8730c10793e23253ff415fcd1e86bb35c69b0cf0 Mon Sep 17 00:00:00 2001 From: Pradeepsingh Bhati Date: Mon, 4 Jul 2022 12:21:33 +0530 Subject: [PATCH 9/9] Disable static routes test --- tests/integration/targets/ntnx_static_routes/aliases | 1 + tests/integration/targets/ntnx_static_routes_info/aliases | 1 + 2 files changed, 2 insertions(+) create mode 100644 tests/integration/targets/ntnx_static_routes/aliases create mode 100644 tests/integration/targets/ntnx_static_routes_info/aliases diff --git a/tests/integration/targets/ntnx_static_routes/aliases b/tests/integration/targets/ntnx_static_routes/aliases new file mode 100644 index 000000000..7a68b11da --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes/aliases @@ -0,0 +1 @@ +disabled diff --git a/tests/integration/targets/ntnx_static_routes_info/aliases b/tests/integration/targets/ntnx_static_routes_info/aliases new file mode 100644 index 000000000..7a68b11da --- /dev/null +++ b/tests/integration/targets/ntnx_static_routes_info/aliases @@ -0,0 +1 @@ +disabled