From 78109359fc8da054b897a2becc83f8ed0d45e666 Mon Sep 17 00:00:00 2001 From: Prem Karat Date: Wed, 9 Feb 2022 08:27:07 +0530 Subject: [PATCH 01/13] vpc support for ansible includes client sdk and ansile module TODO: ansible spec validator Resolves issue#64 Signed-off-by: Prem Karat --- plugins/module_utils/prism/subnets.py | 17 +++ plugins/module_utils/prism/vpcs.py | 68 +++++++++- plugins/modules/ntnx_vpcs.py | 185 ++++++++++++++++++++++++++ 3 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 plugins/modules/ntnx_vpcs.py diff --git a/plugins/module_utils/prism/subnets.py b/plugins/module_utils/prism/subnets.py index 4a6d3303e..7c294fbf6 100644 --- a/plugins/module_utils/prism/subnets.py +++ b/plugins/module_utils/prism/subnets.py @@ -141,3 +141,20 @@ def _get_default_dhcp_spec(self): "tftp_server_name": "", } ) + + +##### Helper functions ##### + + +def get_subnet_uuid(config, module): + if "name" in config or "subnet_name" in config: + subnet = Subnet(module) + name = config.get("name") or config.get("subnet_name") + uuid = subnet.get_uuid(name) + if not uuid: + error = "Subnet {0} not found.".format(name) + return None, error + elif "uuid" in config or "subnet_uuid" in config: + uuid = config.get("uuid") or config.get("subnet_uuid") + + return uuid, None diff --git a/plugins/module_utils/prism/vpcs.py b/plugins/module_utils/prism/vpcs.py index 27ee844e9..226716242 100644 --- a/plugins/module_utils/prism/vpcs.py +++ b/plugins/module_utils/prism/vpcs.py @@ -7,6 +7,7 @@ from copy import deepcopy from .prism import Prism +from .subnets import get_subnet_uuid class Vpc(Prism): @@ -14,19 +15,76 @@ def __init__(self, module): resource_type = "/vpcs" super(Vpc, self).__init__(module, resource_type=resource_type) self.build_spec_methods = { - # TODO. This is a Map of - # ansible attirbute and corresponding API spec generation method - # Example: method name should start with _build_spec_ - # name: _build_spec_name + "name": self._build_spec_name, + "external_subnets": self._build_spec_external_subnet, + "routable_ips": self._build_spec_routable_ips, + "dns_servers": self._build_dns_servers } def _get_default_spec(self): return deepcopy( { - # TODO: Default API spec + "api_version": "3.1.0", + "metadata": { + "kind": "vpc", + "categories": {}, + }, + "spec": { + "name": None, + "resources": { + "common_domain_name_server_ip_list": [], + "external_subnet_list": [], + "externally_routable_prefix_list": [] + } + } } ) + def _build_spec_name(self, payload, name): + payload["spec"]["name"] = name + return payload, None + + def _build_spec_external_subnet(self, payload, subnets): + external_subnets = [] + for subnet in subnets: + uuid, error = get_subnet_uuid(subnet, self.module) + if error: + return None, error + subnet_ref_spec = self._get_external_subnet_ref_spec(uuid) + external_subnets.append(subnet_ref_spec) + + payload["spec"]["external_subnet_list"] = external_subnets + return payload, None + + def _build_spec_routable_ips(self, payload, ips): + routable_ips = [] + for ip in ips: + routable_ip_ref_spec = self._get_routable_ip_spec( + ip["network_ip"], ip["network_prefix"] + ) + routable_ips.append(routable_ip_ref_spec) + + payload["spec"]["externally_routable_prefix_list"] = routable_ips + return payload, None + + def _build_dns_servers(self, payload, dns_servers): + payload["spec"]["common_domain_name_server_ip_list"] = dns_servers + return payload, None + + def _get_external_subnet_ref_spec(self, uuid): + return deepcopy( + { + "external_subnet_reference": {"kind": "subnet", "uuid": uuid} + } + ) + + def _get_routable_ip_spec(self, ip, prefix): + return deepcopy( + { + "ip": ip, + "prefix_length": prefix + } + ) ##### Helper functions ##### diff --git a/plugins/modules/ntnx_vpcs.py b/plugins/modules/ntnx_vpcs.py new file mode 100644 index 000000000..7ca7ee869 --- /dev/null +++ b/plugins/modules/ntnx_vpcs.py @@ -0,0 +1,185 @@ +#!/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 + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: ntnx_vpcs +short_description: vpcs module which suports vpc CRUD operations +version_added: 1.0.0 +description: 'Create, Update, Delete vpcs' +options: + nutanix_host: + description: + - PC hostname or IP address + type: str + required: true + nutanix_port: + description: + - PC port + type: str + default: 9440 + required: false + nutanix_username: + description: + - PC username + type: str + required: true + nutanix_password: + description: + - PC password; + required: true + type: str + validate_certs: + description: + - Set value to C(False) to skip validation for self signed certificates + - This is not recommended for production setup + type: bool + default: true + state: + description: + - Specify state of vpc + - If C(state) is set to C(present) then vpc is created. + - >- + If C(state) is set to C(absent) and if the vpc exists, then + vpc is removed. + choices: + - present + - absent + type: str + default: present + wait: + description: Wait for vpc CRUD operation to complete. + type: bool + required: false + default: True + name: + description: vpc Name + required: False + type: str + vpc_uuid: + description: vpc UUID + type: str + + #TODO here should be additional arguments documentation + +""" + +EXAMPLES = r""" +# TODO +""" + +RETURN = r""" +# TODO +""" + +from ..module_utils.base_module import BaseModule # noqa: E402 +from ..module_utils.prism.tasks import Task # noqa: E402 +from ..module_utils.prism.vpcs import Vpc # noqa: E402 +from ..module_utils.utils import remove_param_with_none_value # noqa: E402 + + +def get_module_spec(): + module_args = dict( + # TODO: Ansible module spec and spec validation + ) + + return module_args + + +def create_vpc(module, result): + vpc = Vpc(module) + spec, error = vpc.get_spec() + if error: + result["error"] = error + module.fail_json(msg="Failed generating vpc spec", **result) + + if module.check_mode: + result["response"] = spec + return + + resp, status = vpc.create(spec) + if status["error"]: + result["error"] = status["error"] + result["response"] = resp + module.fail_json(msg="Failed creating vpc", **result) + + vpc_uuid = resp["metadata"]["uuid"] + result["changed"] = True + result["response"] = resp + result["vpc_uuid"] = vpc_uuid + result["task_uuid"] = resp["status"]["execution_context"]["task_uuid"] + + if module.params.get("wait"): + wait_for_task_completion(module, result) + resp, tmp = vpc.read(vpc_uuid) + result["response"] = resp + + +def delete_vpc(module, result): + vpc_uuid = module.params["vpc_uuid"] + if not vpc_uuid: + result["error"] = "Missing parameter vpc_uuid in playbook" + module.fail_json(msg="Failed deleting vpc", **result) + + vpc = Vpc(module) + resp, status = vpc.delete(vpc_uuid) + if status["error"]: + result["error"] = status["error"] + result["response"] = resp + module.fail_json(msg="Failed deleting vpc", **result) + + result["changed"] = True + result["response"] = resp + result["vpc_uuid"] = vpc_uuid + result["task_uuid"] = resp["status"]["execution_context"]["task_uuid"] + + if module.params.get("wait"): + wait_for_task_completion(module, result) + + +def wait_for_task_completion(module, result): + task = Task(module) + task_uuid = result["task_uuid"] + resp, status = task.wait_for_completion(task_uuid) + result["response"] = resp + if status["error"]: + result["error"] = status["error"] + result["response"] = resp + module.fail_json(msg="Failed creating vpc", **result) + + +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, + "task_uuid": None, + } + state = module.params["state"] + if state == "present": + create_vpc(module, result) + elif state == "absent": + delete_vpc(module, result) + + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == "__main__": + main() + From 4c7d096a0f5b195f796846754cdf3a3c95c065e2 Mon Sep 17 00:00:00 2001 From: Prem Karat Date: Wed, 9 Feb 2022 08:49:52 +0530 Subject: [PATCH 02/13] fixing black issues Signed-off-by: Prem Karat --- plugins/module_utils/prism/vpcs.py | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/plugins/module_utils/prism/vpcs.py b/plugins/module_utils/prism/vpcs.py index 226716242..ec278c201 100644 --- a/plugins/module_utils/prism/vpcs.py +++ b/plugins/module_utils/prism/vpcs.py @@ -18,7 +18,7 @@ def __init__(self, module): "name": self._build_spec_name, "external_subnets": self._build_spec_external_subnet, "routable_ips": self._build_spec_routable_ips, - "dns_servers": self._build_dns_servers + "dns_servers": self._build_dns_servers, } def _get_default_spec(self): @@ -34,9 +34,9 @@ def _get_default_spec(self): "resources": { "common_domain_name_server_ip_list": [], "external_subnet_list": [], - "externally_routable_prefix_list": [] - } - } + "externally_routable_prefix_list": [], + }, + }, } ) @@ -72,19 +72,11 @@ def _build_dns_servers(self, payload, dns_servers): return payload, None def _get_external_subnet_ref_spec(self, uuid): - return deepcopy( - { - "external_subnet_reference": {"kind": "subnet", "uuid": uuid} - } - ) + return deepcopy({"external_subnet_reference": {"kind": "subnet", "uuid": uuid}}) def _get_routable_ip_spec(self, ip, prefix): - return deepcopy( - { - "ip": ip, - "prefix_length": prefix - } - ) + return deepcopy({"ip": ip, "prefix_length": prefix}) + ##### Helper functions ##### From c9707d588dec414d944fe2657352339a6fbf84b2 Mon Sep 17 00:00:00 2001 From: Gevorg-Khachatryaan Date: Wed, 9 Feb 2022 14:31:25 +0400 Subject: [PATCH 03/13] #70 module arguments for vpcs --- plugins/modules/ntnx_vpcs.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/plugins/modules/ntnx_vpcs.py b/plugins/modules/ntnx_vpcs.py index 7ca7ee869..c62db4e3a 100644 --- a/plugins/modules/ntnx_vpcs.py +++ b/plugins/modules/ntnx_vpcs.py @@ -85,8 +85,22 @@ def get_module_spec(): + external_subnets_spec = dict( + subnet_name=dict(type="str"), subnet_uuid=dict(type="str") + ) + routable_ips_spec = dict( + network_ip=dict(type="str"), network_prefix=dict(type="str") + ) module_args = dict( - # TODO: Ansible module spec and spec validation + name=dict(type="str", required=True), + external_subnets=dict( + type="list", + elements="dict", + options=external_subnets_spec, + mutually_exclusive=[("subnet_name", "subnet_uuid")], + ), + routable_ips=dict(type="list", elements="dict", options=routable_ips_spec), + dns_servers=dict(type="list", elements="str"), ) return module_args @@ -155,10 +169,7 @@ def wait_for_task_completion(module, result): def run_module(): - module = BaseModule( - argument_spec=get_module_spec(), - supports_check_mode=True - ) + module = BaseModule(argument_spec=get_module_spec(), supports_check_mode=True) remove_param_with_none_value(module.params) result = { "changed": False, @@ -182,4 +193,3 @@ def main(): if __name__ == "__main__": main() - From 9fbeb51b5666c2d2c683c3fe68daff82f9803cf5 Mon Sep 17 00:00:00 2001 From: Gevorg-Khachatryaan Date: Wed, 9 Feb 2022 14:32:55 +0400 Subject: [PATCH 04/13] #71 fixes for spec generation --- plugins/module_utils/prism/vpcs.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/plugins/module_utils/prism/vpcs.py b/plugins/module_utils/prism/vpcs.py index ec278c201..ee579e855 100644 --- a/plugins/module_utils/prism/vpcs.py +++ b/plugins/module_utils/prism/vpcs.py @@ -7,7 +7,6 @@ from copy import deepcopy from .prism import Prism -from .subnets import get_subnet_uuid class Vpc(Prism): @@ -25,10 +24,7 @@ def _get_default_spec(self): return deepcopy( { "api_version": "3.1.0", - "metadata": { - "kind": "vpc", - "categories": {}, - }, + "metadata": {"kind": "vpc", "categories": {}}, "spec": { "name": None, "resources": { @@ -45,6 +41,8 @@ def _build_spec_name(self, payload, name): return payload, None def _build_spec_external_subnet(self, payload, subnets): + from .subnets import get_subnet_uuid + external_subnets = [] for subnet in subnets: uuid, error = get_subnet_uuid(subnet, self.module) @@ -53,7 +51,7 @@ def _build_spec_external_subnet(self, payload, subnets): subnet_ref_spec = self._get_external_subnet_ref_spec(uuid) external_subnets.append(subnet_ref_spec) - payload["spec"]["external_subnet_list"] = external_subnets + payload["spec"]["resources"]["external_subnet_list"] = external_subnets return payload, None def _build_spec_routable_ips(self, payload, ips): @@ -64,11 +62,11 @@ def _build_spec_routable_ips(self, payload, ips): ) routable_ips.append(routable_ip_ref_spec) - payload["spec"]["externally_routable_prefix_list"] = routable_ips + payload["spec"]["resources"]["externally_routable_prefix_list"] = routable_ips return payload, None def _build_dns_servers(self, payload, dns_servers): - payload["spec"]["common_domain_name_server_ip_list"] = dns_servers + payload["spec"]["resources"]["common_domain_name_server_ip_list"] = dns_servers return payload, None def _get_external_subnet_ref_spec(self, uuid): @@ -91,3 +89,4 @@ def get_vpc_uuid(config, module): return None, error elif "uuid" in config["vpc"]: uuid = config["vpc"]["uuid"] + return uuid, None From 0a6486e62a0fb5d614c8ed3ee2287d84964e993c Mon Sep 17 00:00:00 2001 From: alaa-bish Date: Thu, 10 Feb 2022 08:08:21 +0000 Subject: [PATCH 05/13] Add integration test: Github issue 76 --- .../nutanix_vpcs/tasks/create_vpcs.yml | 114 ++++++++++++++++++ .../targets/nutanix_vpcs/tasks/main.yml | 3 + .../targets/nutanix_vpcs/vars/main.yml | 13 ++ 3 files changed, 130 insertions(+) create mode 100644 tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml create mode 100644 tests/integration/targets/nutanix_vpcs/tasks/main.yml create mode 100644 tests/integration/targets/nutanix_vpcs/vars/main.yml diff --git a/tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml b/tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml new file mode 100644 index 000000000..39f00cb1c --- /dev/null +++ b/tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml @@ -0,0 +1,114 @@ +- name: create VPC + ntnx_vpcs: + validate_certs: False + state: present + nutanix_host: "{{ IP }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + name: MinVPC + external_subnets: + - subnet_name: "{{external_subnet.subnet_name}}" + register: result + ignore_errors: True + +- name: Creation Status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + fail_msg: " Unable to create Min vpc " + success_msg: " Min vpc created successfully " + +- set_fact: + todelete: "{{ todelete + [ result.vpc_uuid ] }}" + +- debug: + var: result + +- name: create VPC with routable_ips + ntnx_vpcs: + validate_certs: False + state: present + nutanix_host: "{{ IP }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + name: vpc_with_routable_ips + external_subnets: + - subnet_name: "{{external_subnet.subnet_name}}" + routable_ips: + - network_ip: "{{routable_ips.network_ip}}" + network_prefix: "{{routable_ips.network_prefix}}" + register: result + ignore_errors: True +- name: Creation Status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + fail_msg: " Unable to create vpc with routable_ips " + success_msg: " vpc with routable_ips created successfully " + +- set_fact: + todelete: "{{ todelete + [ result.vpc_uuid ] }}" + + +- name: create VPC with dns_servers + ntnx_vpcs: + validate_certs: False + state: present + nutanix_host: "{{ IP }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + name: vpc_with_dns_servers + external_subnets: + - subnet_name: "{{external_subnet.subnet_name}}" + register: result + ignore_errors: True +- name: Creation Status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + fail_msg: " Unable to create vpc with dns_servers " + success_msg: " vpc with dns_servers created successfully " + +- set_fact: + todelete: "{{ todelete + [ result.vpc_uuid ] }}" + + + +- name: create VPC with All specfactions + ntnx_vpcs: + validate_certs: False + state: present + nutanix_host: "{{ IP }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + name: vpc_with_add_specfactions + external_subnets: + - subnet_name: "{{external_subnet.subnet_name}}" + register: result + ignore_errors: True +- name: Creation Status + assert: + that: + - result.response is defined + - result.response.status.state == 'COMPLETE' + fail_msg: " Unable to create vpc all specfactions " + success_msg: " vpc with all specfactions created successfully " + +- set_fact: + todelete: "{{ todelete + [ result.vpc_uuid ] }}" + + +- name: Delete all Created vpcs + ntnx_vpcs: + state: absent + nutanix_host: "{{ IP }}" + nutanix_username: "{{ username }}" + nutanix_password: "{{ password }}" + validate_certs: false + vpc_uuid: "{{ item }}" + register: result + loop: "{{ todelete }}" + ignore_errors: True \ No newline at end of file diff --git a/tests/integration/targets/nutanix_vpcs/tasks/main.yml b/tests/integration/targets/nutanix_vpcs/tasks/main.yml new file mode 100644 index 000000000..767da5e3a --- /dev/null +++ b/tests/integration/targets/nutanix_vpcs/tasks/main.yml @@ -0,0 +1,3 @@ +- block: + - import_tasks: "create_vpcs.yml" + diff --git a/tests/integration/targets/nutanix_vpcs/vars/main.yml b/tests/integration/targets/nutanix_vpcs/vars/main.yml new file mode 100644 index 000000000..616271eef --- /dev/null +++ b/tests/integration/targets/nutanix_vpcs/vars/main.yml @@ -0,0 +1,13 @@ +IP: 10.44.76.88 +username: admin +password: Nutanix.123 +external_subnet: + subnet_name: ext_115 + subnet_uuiid: +dns_servers: + - 8.8.8.8 + - 8.8.4.4 +routable_ips: + network_ip: 192.168.2.0 + network_prefix: 24 +todelete: [] \ No newline at end of file From 5b229a46b119e3baffa0a80000cc20efd7a367a0 Mon Sep 17 00:00:00 2001 From: alaa-bish Date: Thu, 10 Feb 2022 08:13:45 +0000 Subject: [PATCH 06/13] Change network prefix type :Github issue 80 --- plugins/modules/ntnx_vpcs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/ntnx_vpcs.py b/plugins/modules/ntnx_vpcs.py index c62db4e3a..60c4f9c75 100644 --- a/plugins/modules/ntnx_vpcs.py +++ b/plugins/modules/ntnx_vpcs.py @@ -89,7 +89,7 @@ def get_module_spec(): subnet_name=dict(type="str"), subnet_uuid=dict(type="str") ) routable_ips_spec = dict( - network_ip=dict(type="str"), network_prefix=dict(type="str") + network_ip=dict(type="str"), network_prefix=dict(type="int") ) module_args = dict( name=dict(type="str", required=True), From 8c11a24cb0d6c3a72da5b9a35a70225ea4dc49bd Mon Sep 17 00:00:00 2001 From: alaa-bish Date: Thu, 10 Feb 2022 07:05:53 +0000 Subject: [PATCH 07/13] Fix sanity and add doc: Gihub issue 78 --- nutanix-ncp-1.0.0.tar.gz | Bin 0 -> 42789 bytes plugins/module_utils/prism/subnets.py | 2 +- plugins/modules/ntnx_vpcs.py | 39 +++++++++++++++++++++----- scripts/create_module.py | 4 +-- 4 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 nutanix-ncp-1.0.0.tar.gz diff --git a/nutanix-ncp-1.0.0.tar.gz b/nutanix-ncp-1.0.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5fa11720209e0b29bea3d72a2e659414ebd863d9 GIT binary patch literal 42789 zcmV(lK=i*KiwFo1xddVY|88}3VQy)7EpB6QEio=IE-)^1VR8WMy<2nJNSY|v&-fKM zte&t`L(u?lAXV*-R>`U=ow6m3B)g`<;b0|zgoHLpa0pVe+Q$+5x)0|Papq+=c4Hp* zf6XtLpRnI0Gm!v6O1`P8rlsyEOF$y8-~E=)_l^#~J2*RU{WZ^~fA} {lvXUHTV( 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%0DK_pE^ugSAxSAEA@xqw(3arE(Gf0NUUsaI@ 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 N{|78%+M59A0|1=?T0j5* literal 0 HcmV?d00001 diff --git a/plugins/module_utils/prism/subnets.py b/plugins/module_utils/prism/subnets.py index 1d110be7a..bbd64161a 100644 --- a/plugins/module_utils/prism/subnets.py +++ b/plugins/module_utils/prism/subnets.py @@ -140,7 +140,7 @@ def _get_default_dhcp_spec(self): ) -##### Helper functions ##### +# Helper functions def get_subnet_uuid(config, module): diff --git a/plugins/modules/ntnx_vpcs.py b/plugins/modules/ntnx_vpcs.py index c62db4e3a..1acfc1d15 100644 --- a/plugins/modules/ntnx_vpcs.py +++ b/plugins/modules/ntnx_vpcs.py @@ -60,14 +60,39 @@ default: True name: description: vpc Name - required: False + required: True type: str - vpc_uuid: - description: vpc UUID - type: str - - #TODO here should be additional arguments documentation - + dns_servers: + description: List of DNS servers IPs + type: list + elements: str + routable_ips: + description: Address space within the VPC which can talk externally without NAT. These are in effect when No-NAT External subnet is used. + type: list + elements: dict + suboptions: + network_ip: + description: ip address + type: str + network_prefix: + description: Subnet ip address prefix length + type: int + external_subnets: + description: A subnet with external connectivity + type: list + elements: dict + suboptions: + subnet_uuid: + description: Subnet UUID + type: str + subnet_name: + description: Subnet Name + type: str +author: + - Prem Karat (@premkarat) + - Gevorg Khachatryan (@Gevorg-Khachatryan-97) + - Alaa Bishtawi (@alaa-bish) + - Dina AbuHijleh (@dina-abuhijleh) """ EXAMPLES = r""" diff --git a/scripts/create_module.py b/scripts/create_module.py index f81cb7324..6b6548de5 100644 --- a/scripts/create_module.py +++ b/scripts/create_module.py @@ -217,14 +217,14 @@ def _get_default_spec(self): def create_module(name): - with open("plugins/modules/ntnx_{0}s.py".format(name), "w") as f: + with open("plugins/modules/ntnx_{0}s.py".format(name), "wb") as f: f.write( module_content.replace("object", name.lower()).replace( "Object", name.capitalize() ) ) - with open("plugins/module_utils/prism/{0}s.py".format(name), "w") as f: + with open("plugins/module_utils/prism/{0}s.py".format(name), "wb") as f: f.write( object_content.replace("object", name.lower()).replace( "Object", name.capitalize() From e6eb480c86c1c7f277de275694860ee2f4dd6628 Mon Sep 17 00:00:00 2001 From: alaa-bish Date: Thu, 10 Feb 2022 07:05:53 +0000 Subject: [PATCH 08/13] Fix sanity and add doc: Gihub issue 78 --- plugins/module_utils/prism/subnets.py | 2 +- plugins/modules/ntnx_vpcs.py | 39 ++++++++++++++++++++++----- scripts/create_module.py | 4 +-- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/plugins/module_utils/prism/subnets.py b/plugins/module_utils/prism/subnets.py index 1d110be7a..bbd64161a 100644 --- a/plugins/module_utils/prism/subnets.py +++ b/plugins/module_utils/prism/subnets.py @@ -140,7 +140,7 @@ def _get_default_dhcp_spec(self): ) -##### Helper functions ##### +# Helper functions def get_subnet_uuid(config, module): diff --git a/plugins/modules/ntnx_vpcs.py b/plugins/modules/ntnx_vpcs.py index c62db4e3a..1acfc1d15 100644 --- a/plugins/modules/ntnx_vpcs.py +++ b/plugins/modules/ntnx_vpcs.py @@ -60,14 +60,39 @@ default: True name: description: vpc Name - required: False + required: True type: str - vpc_uuid: - description: vpc UUID - type: str - - #TODO here should be additional arguments documentation - + dns_servers: + description: List of DNS servers IPs + type: list + elements: str + routable_ips: + description: Address space within the VPC which can talk externally without NAT. These are in effect when No-NAT External subnet is used. + type: list + elements: dict + suboptions: + network_ip: + description: ip address + type: str + network_prefix: + description: Subnet ip address prefix length + type: int + external_subnets: + description: A subnet with external connectivity + type: list + elements: dict + suboptions: + subnet_uuid: + description: Subnet UUID + type: str + subnet_name: + description: Subnet Name + type: str +author: + - Prem Karat (@premkarat) + - Gevorg Khachatryan (@Gevorg-Khachatryan-97) + - Alaa Bishtawi (@alaa-bish) + - Dina AbuHijleh (@dina-abuhijleh) """ EXAMPLES = r""" diff --git a/scripts/create_module.py b/scripts/create_module.py index f81cb7324..6b6548de5 100644 --- a/scripts/create_module.py +++ b/scripts/create_module.py @@ -217,14 +217,14 @@ def _get_default_spec(self): def create_module(name): - with open("plugins/modules/ntnx_{0}s.py".format(name), "w") as f: + with open("plugins/modules/ntnx_{0}s.py".format(name), "wb") as f: f.write( module_content.replace("object", name.lower()).replace( "Object", name.capitalize() ) ) - with open("plugins/module_utils/prism/{0}s.py".format(name), "w") as f: + with open("plugins/module_utils/prism/{0}s.py".format(name), "wb") as f: f.write( object_content.replace("object", name.lower()).replace( "Object", name.capitalize() From 2c0a4d5992f1382950b5a310915c89596f52d140 Mon Sep 17 00:00:00 2001 From: Gevorg-Khachatryaan Date: Thu, 10 Feb 2022 13:41:47 +0400 Subject: [PATCH 09/13] #71 fixes for dns_server spec --- plugins/module_utils/prism/vpcs.py | 4 +++- plugins/modules/ntnx_vpcs.py | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/plugins/module_utils/prism/vpcs.py b/plugins/module_utils/prism/vpcs.py index 2bec2dd30..1be60cf2c 100644 --- a/plugins/module_utils/prism/vpcs.py +++ b/plugins/module_utils/prism/vpcs.py @@ -66,7 +66,9 @@ def _build_spec_routable_ips(self, payload, ips): return payload, None def _build_dns_servers(self, payload, dns_servers): - payload["spec"]["resources"]["common_domain_name_server_ip_list"] = dns_servers + payload["spec"]["resources"]["common_domain_name_server_ip_list"] = [ + {"ip": i} for i in dns_servers + ] return payload, None def _get_external_subnet_ref_spec(self, uuid): diff --git a/plugins/modules/ntnx_vpcs.py b/plugins/modules/ntnx_vpcs.py index 1acfc1d15..179ce41f8 100644 --- a/plugins/modules/ntnx_vpcs.py +++ b/plugins/modules/ntnx_vpcs.py @@ -60,7 +60,9 @@ default: True name: description: vpc Name - required: True + type: str + vpc_uuid: + description: vpc uuid type: str dns_servers: description: List of DNS servers IPs @@ -117,7 +119,8 @@ def get_module_spec(): network_ip=dict(type="str"), network_prefix=dict(type="str") ) module_args = dict( - name=dict(type="str", required=True), + name=dict(type="str"), + vpc_uuid=dict(type="str"), external_subnets=dict( type="list", elements="dict", @@ -194,7 +197,14 @@ def wait_for_task_completion(module, result): def run_module(): - module = BaseModule(argument_spec=get_module_spec(), supports_check_mode=True) + module = BaseModule( + argument_spec=get_module_spec(), + supports_check_mode=True, + required_if=[ + ("state", "present", ("name",)), + ("state", "absent", ("vpc_uuid",)), + ], + ) remove_param_with_none_value(module.params) result = { "changed": False, From f19a5914fbad2f4ff6b8c1562a323e29a39a3a1e Mon Sep 17 00:00:00 2001 From: Gevorg-Khachatryaan Date: Thu, 10 Feb 2022 13:45:44 +0400 Subject: [PATCH 10/13] delete wrong files --- nutanix-ncp-1.0.0.tar.gz | Bin 42789 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 nutanix-ncp-1.0.0.tar.gz diff --git a/nutanix-ncp-1.0.0.tar.gz b/nutanix-ncp-1.0.0.tar.gz deleted file mode 100644 index 5fa11720209e0b29bea3d72a2e659414ebd863d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42789 zcmV(lK=i*KiwFo1xddVY|88}3VQy)7EpB6QEio=IE-)^1VR8WMy<2nJNSY|v&-fKM zte&t`L(u?lAXV*-R>`U=ow6m3B)g`<;b0|zgoHLpa0pVe+Q$+5x)0|Papq+=c4Hp* zf6XtLpRnI0Gm!v6O1`P8rlsyEOF$y8-~E=)_l^#~J2*RU{WZ^~fA} {lvXUHTV( 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%0DK_pE^ugSAxSAEA@xqw(3arE(Gf0NUUsaI@ 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 N{|78%+M59A0|1=?T0j5* From 88b6414c4ee620cfaea942558cee1edc89857c5f Mon Sep 17 00:00:00 2001 From: alaa-bish Date: Thu, 10 Feb 2022 10:19:29 +0000 Subject: [PATCH 11/13] Add dns_server integration test : Github issue 76 --- .../targets/nutanix_vpcs/tasks/create_vpcs.yml | 10 +++++----- tests/integration/targets/nutanix_vpcs/vars/main.yml | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml b/tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml index 39f00cb1c..428ac02f0 100644 --- a/tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml +++ b/tests/integration/targets/nutanix_vpcs/tasks/create_vpcs.yml @@ -1,4 +1,4 @@ -- name: create VPC +- name: create Min VPC ntnx_vpcs: validate_certs: False state: present @@ -22,8 +22,6 @@ - set_fact: todelete: "{{ todelete + [ result.vpc_uuid ] }}" -- debug: - var: result - name: create VPC with routable_ips ntnx_vpcs: @@ -40,6 +38,7 @@ network_prefix: "{{routable_ips.network_prefix}}" register: result ignore_errors: True + - name: Creation Status assert: that: @@ -62,6 +61,7 @@ name: vpc_with_dns_servers external_subnets: - subnet_name: "{{external_subnet.subnet_name}}" + dns_servers: "{{dns_servers}}" register: result ignore_errors: True - name: Creation Status @@ -76,7 +76,6 @@ todelete: "{{ todelete + [ result.vpc_uuid ] }}" - - name: create VPC with All specfactions ntnx_vpcs: validate_certs: False @@ -87,6 +86,7 @@ name: vpc_with_add_specfactions external_subnets: - subnet_name: "{{external_subnet.subnet_name}}" + dns_servers: "{{dns_servers}}" register: result ignore_errors: True - name: Creation Status @@ -111,4 +111,4 @@ vpc_uuid: "{{ item }}" register: result loop: "{{ todelete }}" - ignore_errors: True \ No newline at end of file + ignore_errors: True diff --git a/tests/integration/targets/nutanix_vpcs/vars/main.yml b/tests/integration/targets/nutanix_vpcs/vars/main.yml index 616271eef..dd2f74cc0 100644 --- a/tests/integration/targets/nutanix_vpcs/vars/main.yml +++ b/tests/integration/targets/nutanix_vpcs/vars/main.yml @@ -2,12 +2,12 @@ IP: 10.44.76.88 username: admin password: Nutanix.123 external_subnet: - subnet_name: ext_115 - subnet_uuiid: + subnet_name: ET_2 + subnet_uuiid: 57959f75-6b21-431c-b76b-516447d52621 dns_servers: - 8.8.8.8 - 8.8.4.4 routable_ips: network_ip: 192.168.2.0 network_prefix: 24 -todelete: [] \ No newline at end of file +todelete: [] From d1db84ffed2b84a89b3cb65baad929ab9bdd3bc8 Mon Sep 17 00:00:00 2001 From: Gevorg-Khachatryaan Date: Thu, 10 Feb 2022 15:21:12 +0400 Subject: [PATCH 12/13] #85 added test cases for some functions --- .../unit/plugins/module_utils/test_entity.py | 71 ++++++++++++++++--- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/tests/unit/plugins/module_utils/test_entity.py b/tests/unit/plugins/module_utils/test_entity.py index ea921e80c..33f2a19f9 100644 --- a/tests/unit/plugins/module_utils/test_entity.py +++ b/tests/unit/plugins/module_utils/test_entity.py @@ -39,9 +39,12 @@ def _fetch_url(url, method, data=None, **kwargs): "status": {"state": "succeeded"}, "status_code": 200, "request": {"method": method, "url": url, "data": data}, + "entities": [ + {"spec": {"name": "test_name"}, "metadata": {"uuid": "test_uuid"}} + ], } - return response + return response, 200 def exit_json(*args, **kwargs): @@ -59,6 +62,10 @@ class TestEntity(ModuleTestCase): def setUp(self): self.module = Module() Entity._fetch_url = MagicMock(side_effect=_fetch_url) + Entity._get_default_spec = MagicMock(side_effect=lambda: {}) + Entity.build_spec_methods = { + "test_param": lambda s, v: ({"test_param": v}, None) + } self.entity = Entity(self.module, resource_type="/test") self.module.exit_json = MagicMock(side_effect=exit_json) self.module.fail_json = MagicMock(side_effect=fail_json) @@ -66,7 +73,7 @@ def setUp(self): def test_create_action(self): data = {} req = {"method": "POST", "url": "https://99.99.99.99:9999/test", "data": data} - result = self.entity.create(data) + result, status = self.entity.create(data) self.assertEqual(result["request"], req) def test_negative_create_action(self): @@ -75,14 +82,14 @@ def test_negative_create_action(self): entity = Entity(self.module, resource_type="") req = {"method": "POST", "url": "https://None/", "data": data} - result = entity.create(data) + result, status = entity.create(data) self.assertEqual(result["request"], req) self.assertEqual(entity.headers.get("Authorization"), None) def test_update_action(self): data = {} req = {"method": "PUT", "url": "https://99.99.99.99:9999/test", "data": data} - result = self.entity.update(data) + result, status = self.entity.update(data) self.assertEqual(result["request"], req) def test_negative_update_action(self): @@ -91,7 +98,7 @@ def test_negative_update_action(self): entity = Entity(self.module, resource_type="") req = {"method": "PUT", "url": "https://None/", "data": data} - result = entity.update(data) + result, status = entity.update(data) self.assertEqual(result["request"], req) self.assertEqual(entity.headers.get("Authorization"), None) @@ -102,7 +109,7 @@ def test_list_action(self): "url": "https://99.99.99.99:9999/test/list", "data": data, } - result = self.entity.list(data) + result, status = self.entity.list(data) self.assertEqual(result["request"], req) def test_negative_list_action(self): @@ -111,7 +118,27 @@ def test_negative_list_action(self): entity = Entity(self.module, resource_type="") req = {"method": "POST", "url": "https://None//list", "data": data} - result = entity.list(data) + result, status = entity.list(data) + self.assertEqual(result["request"], req) + self.assertEqual(entity.headers.get("Authorization"), None) + + def test_raed_action(self): + uuid = "test_uuid" + req = { + "method": "GET", + "url": "https://99.99.99.99:9999/test/{0}".format(uuid), + "data": None, + } + result, status = self.entity.read(uuid=uuid) + self.assertEqual(result["request"], req) + + def test_negative_read_action(self): + data = None + self.module.params = {} + entity = Entity(self.module, resource_type="") + + req = {"method": "GET", "url": "https://None/", "data": data} + result, status = entity.read(data) self.assertEqual(result["request"], req) self.assertEqual(entity.headers.get("Authorization"), None) @@ -122,7 +149,7 @@ def test_delete_action(self): "url": "https://99.99.99.99:9999/test/{0}".format(uuid), "data": None, } - result = self.entity.delete(uuid=uuid) + result, status = self.entity.delete(uuid=uuid) self.assertEqual(result["request"], req) def test_negative_delete_action(self): @@ -131,7 +158,7 @@ def test_negative_delete_action(self): entity = Entity(self.module, resource_type="") req = {"method": "DELETE", "url": "https://None/", "data": data} - result = entity.delete(data) + result, status = entity.delete(data) self.assertEqual(result["request"], req) self.assertEqual(entity.headers.get("Authorization"), None) @@ -174,3 +201,29 @@ def test_build_headers(self): generated_headers = self.entity._build_headers(self.module, additional_headers) self.assertEqual(actual_headers, generated_headers) + + def test_get_uuid(self): + name = "test_name" + result = self.entity.get_uuid(name=name) + self.assertEqual(result, "test_uuid") + + def test_negative_get_uuid(self): + name = "wrong_test_name" + result = self.entity.get_uuid(name=name) + self.assertEqual(result, None) + + def test_get_spec(self): + result = self.entity.get_spec() + self.assertEqual(result, ({}, None)) + + def test_build_spec_methods(self): + self.module.params = {"test_param": "test_value"} + entity = Entity(self.module, resource_type="/test") + result = entity.get_spec() + self.assertEqual(result, ({"test_param": "test_value"}, None)) + + def test_negative_build_spec_methods(self): + self.module.params = {"wrong_param": "test_value"} + entity = Entity(self.module, resource_type="/test") + result = entity.get_spec() + self.assertNotEqual(result, ({"wrong_param": "test_value"}, None)) From c167ce1b3c3c66a8e0c656cca7c65ec3ff784368 Mon Sep 17 00:00:00 2001 From: Gevorg-Khachatryaan Date: Thu, 10 Feb 2022 15:24:00 +0400 Subject: [PATCH 13/13] #85 update unit-tests job to skip mocked function --- .github/workflows/unit_testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit_testing.yml b/.github/workflows/unit_testing.yml index 5c7b90a59..8d088cfbc 100644 --- a/.github/workflows/unit_testing.yml +++ b/.github/workflows/unit_testing.yml @@ -66,7 +66,7 @@ jobs: run: | cd /home/${USER}/.ansible/collections/ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} ansible-test units --docker default --python ${{ matrix.python-version }} --coverage -v - ansible-test coverage report --include */plugins/* --omit */utils.py* > coverage.txt + ansible-test coverage report --include */plugins/* --omit */utils.py,_fetch_url* > coverage.txt - name: Code Coverage Check run: | cd /home/${USER}/.ansible/collections/ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}