diff options
Diffstat (limited to 'tests')
76 files changed, 18495 insertions, 0 deletions
diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..d985dca --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,21 @@ +"""Main test module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s - %(name)-23s - %(levelname)-8s - %(message)s') +logging.captureWarnings(True) diff --git a/tests/data/__init__.py b/tests/data/__init__.py new file mode 100644 index 0000000..5b3f765 --- /dev/null +++ b/tests/data/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
\ No newline at end of file diff --git a/tests/data/bad.csar b/tests/data/bad.csar new file mode 100644 index 0000000..6a445b6 --- /dev/null +++ b/tests/data/bad.csar @@ -0,0 +1 @@ +bad is bad diff --git a/tests/data/bad_no_service.csar b/tests/data/bad_no_service.csar Binary files differnew file mode 100644 index 0000000..f0a0627 --- /dev/null +++ b/tests/data/bad_no_service.csar diff --git a/tests/data/csar.meta b/tests/data/csar.meta new file mode 100644 index 0000000..bc3359c --- /dev/null +++ b/tests/data/csar.meta @@ -0,0 +1,2 @@ +SDC-TOSCA-Meta-File-Version: 1.0 +SDC-TOSCA-Definitions-Version: 9.0 diff --git a/tests/data/service-Foo-template.yml b/tests/data/service-Foo-template.yml new file mode 100644 index 0000000..12ba4f4 --- /dev/null +++ b/tests/data/service-Foo-template.yml @@ -0,0 +1,1228 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 +metadata: + invariantUUID: 6a081157-7d17-4369-a1f2-099322bfa9bc + UUID: 862d4c8a-bb0e-40dc-ad4c-7768fc03530a + name: vFW-service + description: vFW-service + type: Service + category: Network L4+ + serviceType: '' + serviceRole: '' + serviceEcompNaming: true + ecompGeneratedNaming: true + namingPolicy: '' +imports: + - nodes: + file: nodes.yml + - datatypes: + file: data.yml + - capabilities: + file: capabilities.yml + - relationships: + file: relationships.yml + - groups: + file: groups.yml + - policies: + file: policies.yml + - service-vFW-service-interface: + file: service-VfwService-template-interface.yml + - resource-vFWCL_vPKG-vf: + file: resource-VfwclVpkgVf-template.yml + - resource-vFWCL_vPKG-vf-interface: + file: resource-VfwclVpkgVf-template-interface.yml + - resource-vFWCL_vFWSNK-vf: + file: resource-VfwclVfwsnkVf-template.yml + - resource-vFWCL_vFWSNK-vf-interface: + file: resource-VfwclVfwsnkVf-template-interface.yml +topology_template: + node_templates: + vFWCL_vPKG-vf 0: + type: org.openecomp.resource.vf.VfwclVpkgVf + metadata: + invariantUUID: 696c4c49-b5d2-4d6f-ac2d-be2cd09fc356 + UUID: 9530fa98-94ca-41c3-bb67-bae3f3dae4a2 + customizationUUID: a2e4b36f-bcea-4b22-a383-0d4dc0a7dd65 + version: '1.0' + name: vFWCL_vPKG-vf + description: vPacketGenerator function + type: VF + category: Application L4+ + subcategory: Firewall + resourceVendor: Generic-Vendor + resourceVendorRelease: '1.0' + resourceVendorModelNumber: '' + properties: + vf_module_id: vTrafficPNG + repo_url_blob: https://nexus.onap.org/content/sites/raw + unprotected_private_subnet_id: zdfw1fwl01_unprotected_sub + public_net_id: 715a1ca1-cbc6-4d00-84bb-0f8667a748ce + vfw_private_ip_0: 192.168.10.100 + onap_private_subnet_id: 51a5a838-7318-464d-858a-974bef8d49e3 + onap_private_net_cidr: 10.4.2.0/24 + image_name: ubuntu-14.04-daily + flavor_name: onap.medium + vnf_id: vPNG_Firewall_demo_app + vpg_name_0: zdfw1fwl01pgn01 + vpg_private_ip_1: 10.4.2.200 + vsn_private_ip_0: 192.168.20.250 + vpg_private_ip_0: 192.168.10.200 + protected_private_net_cidr: 192.168.20.0/24 + unprotected_private_net_cidr: 192.168.10.0/24 + nf_naming: + ecomp_generated_naming: true + onap_private_net_id: 715a1ca1-cbc6-4d00-84bb-0f8667a748ce + unprotected_private_net_id: zdfw1fwl01_unprotected + availability_zone_max_count: 1 + demo_artifacts_version: 1.2.0 + key_name: onap_key_LnHa + repo_url_artifacts: https://nexus.onap.org/content/groups/staging + install_script_version: 1.2.0-SNAPSHOT + cloud_env: openstack + vFWCL_vFWSNK-vf 0: + type: org.openecomp.resource.vf.VfwclVfwsnkVf + metadata: + invariantUUID: f37bfc8b-5d9f-4471-a799-1508f0d8fab5 + UUID: 1fb229a7-0bd9-4358-9072-60501374bcc2 + customizationUUID: 2b98b1f4-498c-4bc9-ab6c-b76af29cb981 + version: '1.0' + name: vFWCL_vFWSNK-vf + description: vFirewall et vSink functions + type: VF + category: Application L4+ + subcategory: Firewall + resourceVendor: Generic-Vendor + resourceVendorRelease: '1.0' + resourceVendorModelNumber: '' + properties: + vf_module_id: vFirewallCL + repo_url_blob: https://nexus.onap.org/content/sites/raw + vfw_private_ip_1: 192.168.20.100 + unprotected_private_subnet_id: zdfw1fwl01_unprotected_sub + public_net_id: 715a1ca1-cbc6-4d00-84bb-0f8667a748ce + vfw_private_ip_0: 192.168.10.100 + onap_private_subnet_id: 51a5a838-7318-464d-858a-974bef8d49e3 + vfw_private_ip_2: 10.4.2.201 + vfw_name_0: zdfw1fwl01fwl01 + onap_private_net_cidr: 10.4.2.0/24 + image_name: ubuntu-14.04-daily + flavor_name: onap.medium + dcae_collector_ip: 10.4.2.38 + vnf_id: vFirewall_demo_app + dcae_collector_port: '8080' + protected_private_subnet_id: zdfw1fwl01_protected_sub + vsn_private_ip_0: 192.168.20.250 + vsn_private_ip_1: 10.4.2.202 + vpg_private_ip_0: 192.168.10.200 + protected_private_net_cidr: 192.168.20.0/24 + unprotected_private_net_cidr: 192.168.10.0/24 + nf_naming: + ecomp_generated_naming: true + vsn_name_0: zdfw1fwl01snk01 + onap_private_net_id: 715a1ca1-cbc6-4d00-84bb-0f8667a748ce + unprotected_private_net_id: zdfw1fwl01_unprotected + availability_zone_max_count: 1 + demo_artifacts_version: 1.2.0 + key_name: onap_key_LnHa + repo_url_artifacts: https://nexus.onap.org/content/groups/staging + install_script_version: 1.2.0-SNAPSHOT + protected_private_net_id: zdfw1fwl01_protected + cloud_env: openstack + capabilities: + network.outgoing.bytes_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + end_point: + properties: + protocol: tcp + initiator: source + network_name: PRIVATE + secure: false + network.outgoing.bytes.rate_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + memory.usage_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.packets_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.read.requests_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + instance_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.latency_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + memory.resident_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outpoing.packets_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outgoing.bytes.rate_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.allocation_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.write.requests.rate_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.bytes.rate_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.bytes_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.iops_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.packets.rate_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + scalable_vfw: + properties: + min_instances: 1 + max_instances: 1 + network.incoming.packets_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.usage_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outgoing.bytes_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.usage_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.ephemeral.size_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.write.bytes.rate_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outpoing.packets_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + cpu.delta_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.write.bytes.rate_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.read.bytes_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.capacity_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.write.bytes_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.allocation_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.read.requests.rate_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.read.requests_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + vcpus_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.bytes_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.read.bytes_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.read.bytes.rate_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + endpoint_vfw: + properties: + secure: true + network.outgoing.packets.rate_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outgoing.packets.rate_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.read.bytes.rate_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.packets.rate_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.bytes.rate_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.write.requests_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + memory_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.write.requests_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.root.size_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outgoing.packets.rate_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.packets.rate_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.capacity_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outgoing.bytes_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outpoing.packets_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.packets_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.write.requests.rate_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.bytes_vfw_vfw_private_1_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.latency_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + cpu_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.iops_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.incoming.bytes.rate_vfw_vfw_private_2_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + disk.device.write.bytes_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + network.outgoing.bytes.rate_vfw_vfw_private_0_port: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + cpu_util_vfw: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + groups: + vfwcl_vfwsnkvf0..VfwclVfwsnkVf..base_vfw..module-0: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: VfwclVfwsnkVf..base_vfw..module-0 + vfModuleModelInvariantUUID: 0cf42138-9514-4667-af27-19e04eae09ea + vfModuleModelUUID: fd867a01-04a0-4733-a0dd-38293bcb5b1e + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: 14f54459-417e-4608-adf3-e173b25bf26c + properties: + min_vf_module_instances: 1 + vf_module_label: base_vfw + max_vf_module_instances: 1 + vfc_list: + vf_module_type: Base + vf_module_description: + initial_count: 1 + volume_group: false + availability_zone_count: + vfwcl_vpkgvf0..VfwclVpkgVf..base_vpkg..module-0: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: VfwclVpkgVf..base_vpkg..module-0 + vfModuleModelInvariantUUID: 8154de96-1f48-42ec-b8a0-9d2eb60cd6b3 + vfModuleModelUUID: d44761cf-c1e6-429f-8cbd-bd9923827965 + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: a567f92e-d8ac-4547-bd7e-958419df6b86 + properties: + min_vf_module_instances: 1 + vf_module_label: base_vpkg + max_vf_module_instances: 1 + vfc_list: + vf_module_type: Base + vf_module_description: + initial_count: 1 + volume_group: false + availability_zone_count: + substitution_mappings: + node_type: org.openecomp.service.VfwService + capabilities: + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.write.bytes_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.write.bytes_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.write.requests.rate_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.write.requests.rate_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.latency_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.latency_vfw + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.incoming.bytes_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.incoming.bytes_vpg_vpg_private_0_port + vfwcl_vpkgvf0.vpg.abstract_vpg.cpu_util_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.cpu_util_vpg + vfwcl_vfwsnkvf0.protected_private_network.attachment: + - vfwcl_vfwsnkvf0 + - protected_private_network.attachment + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.iops_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.iops_vfw + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.binding_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.binding_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.os_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.os_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.scalable_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.scalable_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.write.requests_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.write.requests_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_private_2_port + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.incoming.bytes_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.incoming.bytes_vfw_vfw_private_2_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.read.requests.rate_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.read.requests.rate_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.capacity_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.capacity_vfw + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.incoming.packets_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.incoming.packets_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.root.size_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.root.size_vfw + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.write.bytes_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.write.bytes_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.cpu_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.cpu_vsn + vfwcl_vfwsnkvf0.vfw.abstract_vfw.vcpus_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.vcpus_vfw + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.iops_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.iops_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.usage_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.usage_vfw + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.capacity_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.capacity_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.read.requests_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.read.requests_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.ephemeral.size_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.ephemeral.size_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.binding_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.binding_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.write.requests_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.write.requests_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.write.requests_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.write.requests_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.read.bytes_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.read.bytes_vfw + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.outgoing.bytes_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.outgoing.bytes_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.read.bytes.rate_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.read.bytes.rate_vfw + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.usage_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.usage_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.feature_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.feature_vsn + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.binding_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.binding_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.write.requests.rate_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.write.requests.rate_vsn + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.outgoing.packets.rate_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.outgoing.packets.rate_vsn_vsn_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.host_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.host_vfw + vfwcl_vfwsnkvf0.unprotected_private_network.feature: + - vfwcl_vfwsnkvf0 + - unprotected_private_network.feature + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.iops_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.iops_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.host_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.host_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.outgoing.bytes_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.outgoing.bytes_vfw_vfw_private_2_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.latency_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.latency_vpg + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.read.bytes_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.read.bytes_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.memory_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.memory_vsn + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.outgoing.packets.rate_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.outgoing.packets.rate_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.instance_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.instance_vfw + vfwcl_vfwsnkvf0.unprotected_private_network.end_point: + - vfwcl_vfwsnkvf0 + - unprotected_private_network.end_point + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.iops_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.iops_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.memory_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.memory_vfw + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.incoming.bytes.rate_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.incoming.bytes.rate_vsn_vsn_private_1_port + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.outpoing.packets_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.outpoing.packets_vsn_vsn_private_1_port + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.outpoing.packets_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.outpoing.packets_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_private_2_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.allocation_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.allocation_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.outgoing.bytes_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.outgoing.bytes_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.write.requests_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.write.requests_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.vcpus_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.vcpus_vpg + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.write.bytes_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.write.bytes_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.write.bytes.rate_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.write.bytes.rate_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.outpoing.packets_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.outpoing.packets_vfw_vfw_private_2_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.write.requests.rate_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.write.requests.rate_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.attachment_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.attachment_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.latency_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.latency_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.cpu_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.cpu_vpg + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.root.size_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.root.size_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.host_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.host_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.capacity_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.capacity_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.memory.resident_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.memory.resident_vfw + vfwcl_vpkgvf0.vpg.abstract_vpg.memory.resident_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.memory.resident_vpg + vfwcl_vpkgvf0.vpg.abstract_vpg.binding_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.binding_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.cpu_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.cpu_vfw + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.attachment_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.attachment_vsn_vsn_private_1_port + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.attachment_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.attachment_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.outgoing.bytes_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.outgoing.bytes_vfw_vfw_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.read.requests_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.read.requests_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.root.size_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.root.size_vsn + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.read.requests_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.read.requests_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.read.bytes.rate_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.read.bytes.rate_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.incoming.packets_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.incoming.packets_vfw_vfw_private_2_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.read.bytes.rate_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.read.bytes.rate_vpg + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.incoming.bytes_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.incoming.bytes_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.outgoing.packets.rate_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.outgoing.packets.rate_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.read.bytes.rate_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.read.bytes.rate_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.read.bytes_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.read.bytes_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.read.bytes_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.read.bytes_vpg + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.feature_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.feature_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.read.bytes_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.read.bytes_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.incoming.packets_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.incoming.packets_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.latency_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.latency_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.endpoint_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.endpoint_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.feature_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.feature_vfw_vfw_private_0_port + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.incoming.packets.rate_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.incoming.packets.rate_vsn_vsn_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.capacity_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.capacity_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.write.requests.rate_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.write.requests.rate_vfw + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.allocation_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.allocation_vsn + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.incoming.packets_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.incoming.packets_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.usage_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.usage_vfw + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.outgoing.packets.rate_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.outgoing.packets.rate_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.incoming.packets.rate_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.incoming.packets.rate_vfw_vfw_private_2_port + vfwcl_vpkgvf0.vpg.abstract_vpg.memory.usage_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.memory.usage_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.feature_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.feature_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.protected_private_network.feature: + - vfwcl_vfwsnkvf0 + - protected_private_network.feature + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.attachment_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.attachment_vfw_vfw_private_2_port + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.incoming.bytes.rate_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.incoming.bytes.rate_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.memory.usage_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.memory.usage_vsn + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.incoming.packets.rate_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.incoming.packets.rate_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.write.bytes_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.write.bytes_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.scalable_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.scalable_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.memory.usage_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.memory.usage_vfw + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.usage_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.usage_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.incoming.bytes_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.incoming.bytes_vfw_vfw_private_1_port + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.incoming.bytes.rate_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.incoming.bytes.rate_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.incoming.bytes_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.incoming.bytes_vsn_vsn_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.read.requests_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.read.requests_vpg + vfwcl_vpkgvf0.vpg.abstract_vpg.feature_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.feature_vpg + vfwcl_vfwsnkvf0.vfw.abstract_vfw.cpu_util_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.cpu_util_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.feature_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.feature_vfw_vfw_private_2_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.read.requests.rate_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.read.requests.rate_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.ephemeral.size_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.ephemeral.size_vsn + vfwcl_vfwsnkvf0.vfw.abstract_vfw.binding_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.binding_vfw + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.attachment_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.attachment_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.allocation_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.allocation_vfw + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.binding_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.binding_vsn_vsn_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.read.bytes.rate_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.read.bytes.rate_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.memory.resident_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.memory.resident_vsn + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.feature_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.feature_vpg_vpg_private_1_port + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.incoming.bytes_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.incoming.bytes_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.binding_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.binding_vsn + vfwcl_vfwsnkvf0.vfw.abstract_vfw.cpu.delta_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.cpu.delta_vfw + vfwcl_vpkgvf0.vpg.abstract_vpg.os_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.os_vpg + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.outpoing.packets_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.outpoing.packets_vsn_vsn_private_0_port + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.incoming.packets_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.incoming.packets_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.incoming.packets.rate_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.incoming.packets.rate_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.incoming.bytes.rate_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.incoming.bytes.rate_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.outgoing.bytes_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.outgoing.bytes_vsn_vsn_private_1_port + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.outpoing.packets_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.outpoing.packets_vpg_vpg_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.cpu.delta_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.cpu.delta_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.binding_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.binding_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.os_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.os_vfw + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.latency_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.latency_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.read.bytes.rate_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.read.bytes.rate_vsn + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.write.bytes.rate_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.write.bytes.rate_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.incoming.packets.rate_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.incoming.packets.rate_vfw_vfw_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.allocation_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.allocation_vpg + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.network.outgoing.bytes_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.network.outgoing.bytes_vpg_vpg_private_1_port + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.network.incoming.packets.rate_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.network.incoming.packets.rate_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_private_0_port + vfwcl_vpkgvf0.vpg.abstract_vpg.instance_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.instance_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.vcpus_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.vcpus_vsn + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.outgoing.bytes_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.outgoing.bytes_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.endpoint_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.endpoint_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.usage_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.usage_vsn + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.write.bytes.rate_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.write.bytes.rate_vfw + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.latency_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.latency_vsn + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_private_2_port + vfwcl_vpkgvf0.vpg.abstract_vpg.memory_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.memory_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.cpu.delta_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.cpu.delta_vsn + vfwcl_vfwsnkvf0.unprotected_private_network.attachment: + - vfwcl_vfwsnkvf0 + - unprotected_private_network.attachment + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.outpoing.packets_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.outpoing.packets_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.ephemeral.size_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.ephemeral.size_vfw + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.binding_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.binding_vfw_vfw_private_2_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.iops_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.iops_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.capacity_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.capacity_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.write.requests.rate_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.write.requests.rate_vpg + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.write.bytes.rate_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.write.bytes.rate_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.outpoing.packets_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.outpoing.packets_vfw_vfw_private_0_port + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.attachment_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.attachment_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.write.requests.rate_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.write.requests.rate_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.write.requests_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.write.requests_vpg + vfwcl_vfwsnkvf0.protected_private_network.link: + - vfwcl_vfwsnkvf0 + - protected_private_network.link + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.device.usage_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.device.usage_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.write.bytes.rate_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.write.bytes.rate_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.write.bytes.rate_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.write.bytes.rate_vsn + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.read.requests.rate_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.read.requests.rate_vfw + vfwcl_vfwsnkvf0.vfw.abstract_vfw.feature_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.feature_vfw + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.allocation_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.allocation_vsn + vfwcl_vfwsnkvf0.vsn.abstract_vsn.instance_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.instance_vsn + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.device.read.requests_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.device.read.requests_vfw + vfwcl_vfwsnkvf0.vsn.abstract_vsn.cpu_util_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.cpu_util_vsn + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.feature_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.feature_vsn_vsn_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.allocation_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.allocation_vpg + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.capacity_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.capacity_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.write.bytes_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.write.bytes_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.network.incoming.packets_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.network.incoming.packets_vsn_vsn_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.endpoint_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.endpoint_vpg + vfwcl_vfwsnkvf0.unprotected_private_network.link: + - vfwcl_vfwsnkvf0 + - unprotected_private_network.link + vfwcl_vpkgvf0.vpg.abstract_vpg.disk.iops_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.disk.iops_vpg + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.incoming.packets.rate_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.incoming.packets.rate_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.scalable_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.scalable_vsn + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.attachment_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.attachment_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.feature_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.feature_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.network.incoming.packets_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.network.incoming.packets_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.read.bytes_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.read.bytes_vsn + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.write.requests_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.write.requests_vfw + vfwcl_vfwsnkvf0.protected_private_network.end_point: + - vfwcl_vfwsnkvf0 + - protected_private_network.end_point + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.network.incoming.bytes_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.network.incoming.bytes_vfw_vfw_private_0_port + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.binding_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.binding_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.disk.write.bytes_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.disk.write.bytes_vfw + vfwcl_vfwsnkvf0.vsn.abstract_vsn.disk.device.read.requests_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.disk.device.read.requests_vsn + requirements: + vfwcl_vfwsnkvf0.vfw.abstract_vfw.local_storage_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.local_storage_vfw + vfwcl_vfwsnkvf0.protected_private_network.dependency: + - vfwcl_vfwsnkvf0 + - protected_private_network.dependency + vfwcl_vfwsnkvf0.unprotected_private_network.dependency: + - vfwcl_vfwsnkvf0 + - unprotected_private_network.dependency + vfwcl_vfwsnkvf0.vsn.abstract_vsn.dependency_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.dependency_vsn + vfwcl_vpkgvf0.vpg.abstract_vpg.local_storage_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.local_storage_vpg + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.link_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.link_vpg_vpg_private_1_port + vfwcl_vpkgvf0.vpg_vpg_private_1_port.abstract_vpg.dependency_vpg_vpg_private_1_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_1_port.abstract_vpg.dependency_vpg_vpg_private_1_port + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.link_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.link_vfw_vfw_private_2_port + vfwcl_vfwsnkvf0.vfw.abstract_vfw.dependency_vfw: + - vfwcl_vfwsnkvf0 + - vfw.abstract_vfw.dependency_vfw + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.dependency_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.dependency_vsn_vsn_private_0_port + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.link_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.link_vfw_vfw_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.link_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.link_vsn_vsn_private_1_port + vfwcl_vfwsnkvf0.vfw_vfw_private_2_port.abstract_vfw.dependency_vfw_vfw_private_2_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_2_port.abstract_vfw.dependency_vfw_vfw_private_2_port + vfwcl_vfwsnkvf0.vfw_vfw_private_0_port.abstract_vfw.dependency_vfw_vfw_private_0_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_0_port.abstract_vfw.dependency_vfw_vfw_private_0_port + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.dependency_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.dependency_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vsn.abstract_vsn.local_storage_vsn: + - vfwcl_vfwsnkvf0 + - vsn.abstract_vsn.local_storage_vsn + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.link_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.link_vfw_vfw_private_1_port + vfwcl_vfwsnkvf0.vsn_vsn_private_0_port.abstract_vsn.link_vsn_vsn_private_0_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_0_port.abstract_vsn.link_vsn_vsn_private_0_port + vfwcl_vpkgvf0.vpg_vpg_private_0_port.abstract_vpg.link_vpg_vpg_private_0_port: + - vfwcl_vpkgvf0 + - vpg_vpg_private_0_port.abstract_vpg.link_vpg_vpg_private_0_port + vfwcl_vfwsnkvf0.vsn_vsn_private_1_port.abstract_vsn.dependency_vsn_vsn_private_1_port: + - vfwcl_vfwsnkvf0 + - vsn_vsn_private_1_port.abstract_vsn.dependency_vsn_vsn_private_1_port + vfwcl_vfwsnkvf0.vfw_vfw_private_1_port.abstract_vfw.dependency_vfw_vfw_private_1_port: + - vfwcl_vfwsnkvf0 + - vfw_vfw_private_1_port.abstract_vfw.dependency_vfw_vfw_private_1_port + vfwcl_vpkgvf0.vpg.abstract_vpg.dependency_vpg: + - vfwcl_vpkgvf0 + - vpg.abstract_vpg.dependency_vpg diff --git a/tests/data/service-TestPnfVsp-template.yml b/tests/data/service-TestPnfVsp-template.yml new file mode 100644 index 0000000..b1ffa37 --- /dev/null +++ b/tests/data/service-TestPnfVsp-template.yml @@ -0,0 +1,146 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 +metadata: + invariantUUID: 25871897-1960-445b-8c4f-78111fab1e32 + UUID: fda7e33f-775d-496c-a2a9-76bb8814fed7 + name: test_service_pnf_vsp + description: service + type: Service + category: Network Service + serviceType: '' + serviceRole: '' + instantiationType: A-la-carte + serviceEcompNaming: true + ecompGeneratedNaming: true + namingPolicy: '' + environmentContext: General_Revenue-Bearing + serviceFunction: '' +imports: +- nodes: + file: nodes.yml +- datatypes: + file: data.yml +- capabilities: + file: capabilities.yml +- relationships: + file: relationships.yml +- groups: + file: groups.yml +- policies: + file: policies.yml +- annotations: + file: annotations.yml +- service-test_service_pnf_vsp-interface: + file: service-TestServicePnfVsp-template-interface.yml +- resource-test_pnf_vsp: + file: resource-TestPnfVsp-template.yml +- resource-test_pnf_vsp-interface: + file: resource-TestPnfVsp-template-interface.yml +topology_template: + inputs: + skip_post_instantiation_configuration: + default: true + type: boolean + required: false + controller_actor: + default: SO-REF-DATA + type: string + required: false + cds_model_version: + type: string + required: false + cds_model_name: + type: string + required: false + node_templates: + test_pnf_vsp 0: + type: org.openecomp.resource.pnf.TestPnfVsp + metadata: + invariantUUID: d52250cb-f4e4-4e16-880b-de0c3a9a3273 + UUID: 081bc1b2-0283-44f6-80a2-f0f3672fec05 + customizationUUID: dc0627b2-cdb6-40a7-8510-3ee70d98ce66 + version: '1.0' + name: test_pnf_vsp + description: PNF + type: PNF + category: Generic + subcategory: Abstract + resourceVendor: test-vendor + resourceVendorRelease: '1.0' + resourceVendorModelNumber: '' + properties: + skip_post_instantiation_configuration: false + controller_actor: CDS + sdnc_model_version: 2.0.0 + sdnc_artifact_name: vnf + sdnc_model_name: vSIM_CNF_CDS + capabilities: + pnfextcp_1.network.incoming.packets.rate: + properties: + name: network.incoming.packets.rate + pnfextcp_1.network.outgoing.packets.rate: + properties: + name: network.outgoing.packets.rate + pnfextcp_1.network.incoming.bytes: + properties: + name: network.incoming.bytes + pnfextcp_1.network.outgoing.bytes.rate: + properties: + name: network.outgoing.bytes.rate + pnfextcp_1.network.outpoing.packets: + properties: + name: network.outpoing.packets + pnfextcp_1.network.outgoing.bytes: + properties: + name: network.outgoing.bytes + pnfextcp_1.network.incoming.bytes.rate: + properties: + name: network.incoming.bytes.rate + pnfextcp_1.network.incoming.packets: + properties: + name: network.incoming.packets + substitution_mappings: + node_type: org.openecomp.service.TestServicePnfVsp8 + capabilities: + test_pnf_vsp0.pnfextcp_1.network.outpoing.packets: + - test_pnf_vsp 0 + - pnfextcp_1.network.outpoing.packets + test_pnf_vsp0.pnfextcp_1.feature: + - test_pnf_vsp 0 + - pnfextcp_1.feature + test_pnf_vsp0.pnfextcp_1.network.incoming.bytes: + - test_pnf_vsp 0 + - pnfextcp_1.network.incoming.bytes + test_pnf_vsp0.pnfextcp_1.network.incoming.packets: + - test_pnf_vsp 0 + - pnfextcp_1.network.incoming.packets + test_pnf_vsp0.pnfextcp_1.port_mirroring: + - test_pnf_vsp 0 + - pnfextcp_1.port_mirroring + test_pnf_vsp0.pnfextcp_1.network.incoming.packets.rate: + - test_pnf_vsp 0 + - pnfextcp_1.network.incoming.packets.rate + test_pnf_vsp0.pnfextcp_1.network.outgoing.bytes.rate: + - test_pnf_vsp 0 + - pnfextcp_1.network.outgoing.bytes.rate + test_pnf_vsp0.pnfextcp_1.network.incoming.bytes.rate: + - test_pnf_vsp 0 + - pnfextcp_1.network.incoming.bytes.rate + test_pnf_vsp0.pnfextcp_1.forwarder: + - test_pnf_vsp 0 + - pnfextcp_1.forwarder + test_pnf_vsp0.pnfextcp_1.network.outgoing.packets.rate: + - test_pnf_vsp 0 + - pnfextcp_1.network.outgoing.packets.rate + test_pnf_vsp0.pnfextcp_1.network.outgoing.bytes: + - test_pnf_vsp 0 + - pnfextcp_1.network.outgoing.bytes + requirements: + test_pnf_vsp0.pnfextcp_1.dependency: + - test_pnf_vsp 0 + - pnfextcp_1.dependency + test_pnf_vsp0.pnfextcp_1.binding: + - test_pnf_vsp 0 + - pnfextcp_1.binding + test_pnf_vsp0.pnfextcp_1.link: + - test_pnf_vsp 0 + - pnfextcp_1.link diff --git a/tests/data/service-TestServiceFyx-template.yml b/tests/data/service-TestServiceFyx-template.yml new file mode 100644 index 0000000..179ff43 --- /dev/null +++ b/tests/data/service-TestServiceFyx-template.yml @@ -0,0 +1,646 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 +metadata: + invariantUUID: 0ca2fd47-4f5b-4d0f-ad83-f458a0e6c4cd + UUID: 2ad116d1-5219-41de-b2ee-d00f100d7f00 + name: freeRadiusInnova_SERVICE123 + description: service + type: Service + category: Network Service + serviceType: '' + serviceRole: '' + instantiationType: A-la-carte + serviceEcompNaming: true + ecompGeneratedNaming: true + namingPolicy: '' + environmentContext: General_Revenue-Bearing + serviceFunction: '' +imports: +- nodes: + file: nodes.yml +- datatypes: + file: data.yml +- capabilities: + file: capabilities.yml +- relationships: + file: relationships.yml +- groups: + file: groups.yml +- policies: + file: policies.yml +- annotations: + file: annotations.yml +- service-freeRadiusInnova_SERVICE123-interface: + file: service-FreeradiusinnovaService123-template-interface.yml +- resource-NeutronNet: + file: resource-Neutronnet-template.yml +- resource-freeRadiusInnova_VF: + file: resource-FreeradiusinnovaVf-template.yml +- resource-freeRadiusInnova_VF-interface: + file: resource-FreeradiusinnovaVf-template-interface.yml +topology_template: + inputs: + skip_post_instantiation_configuration: + default: true + type: boolean + required: false + controller_actor: + default: SO-REF-DATA + type: string + required: false + cds_model_version: + type: string + required: false + cds_model_name: + type: string + required: false + node_templates: + NeutronNet 0: + type: org.openecomp.resource.vl.nodes.heat.network.neutron.Net + metadata: + invariantUUID: 4084c513-5149-456d-9be0-efc503058799 + UUID: e12cedf4-fd3f-4d76-ae2a-0368eaee40dc + customizationUUID: ae1df985-3313-4a8f-93e6-efbc71fd3938 + version: '1.0' + name: NeutronNet + description: Represents a network service with optional subnets and advanced configurations. + type: VL + category: Generic + subcategory: Network Elements + resourceVendor: ONAP (Tosca) + resourceVendorRelease: 1.0.0.wd03 + resourceVendorModelNumber: '' + properties: + dhcp_enabled: true + shared: false + ip_version: 4 + admin_state_up: true + capabilities: + end_point: + properties: + protocol: tcp + initiator: source + network_name: PRIVATE + secure: false + freeRadiusInnova_VF 0: + type: org.openecomp.resource.vf.FreeradiusinnovaVf + metadata: + invariantUUID: e7ba6a8b-ece2-4f4e-bd1a-0f5ca461eedc + UUID: e65f6295-82d1-4e34-8ce9-4df5a81f98a0 + customizationUUID: 674140ec-1aba-4c59-b775-9cb239fc5c70 + version: '1.0' + name: freeRadiusInnova_VF + description: VF + type: VF + category: Generic + subcategory: Abstract + resourceVendor: VNFVendor + resourceVendorRelease: '1.0' + resourceVendorModelNumber: '' + properties: + vf_module_id: FreeRadiusInnova-VF-module + freeRadius_image_name: ubuntu-16.04-daily + skip_post_instantiation_configuration: true + nf_naming: + ecomp_generated_naming: true + user_plane_net_name: user-plane-net, + multi_stage_design: 'false' + controller_actor: SO-REF-DATA + availability_zone_max_count: 1 + control_plane_net_name: control-plane-net + freeRadius_key_name: innova + freeRadius_flavor_name: onap.small + vnf_name: FreeRadiusInnova + freeRadius_pub_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCifYw9iPtGH/enR6rigILYu3djnyT+6g+bOnzSSNLVffDsU6QAv7i3Girc+JgXGjxCtWAzZTHx3qjniKixhIpyzt65J0RDeyZCS9WnMfOqkgIlj+85yxlQDLZdkS0xaQYzeqDEPsT6N0i+gxGWu52NxKYazVqyRXrqwiXZvOMyY4hcgtbNiWRy9Vqdkeippo/+3Jg2gawOz54fIF5zbWMqiJAALBCBl5w1LGTJIaJ+f6vQPq05kLKZOOs3zlfcUY5u1bEzulm/ZNyfhh3rrnJD20jCp8KETgg9sGHQdWdRkbsqT5AGeJQhwK47BEk7ckwZH3lmKwgRw8S/J604tpUh Generated-by-Nova + oam_plane_net_name: admin + freeRadius_name_0: FreeRadiusInnova-VM + vnf_id: FreeRadiusInnova-Id + capabilities: + abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_freeradius.cpu_util_freeRadius: + properties: + name: cpu_util + abstract_freeradius.memory.usage_freeRadius: + properties: + name: memory.usage + abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.incoming.bytes + abstract_freeradius.memory_freeRadius: + properties: + name: memory + abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_oam_port_0: + properties: + name: network.outgoing.packets.rate + abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.incoming.packets.rate + abstract_freeradius.disk.device.read.bytes.rate_freeRadius: + properties: + name: disk.device.read.bytes.rate + abstract_freeradius.disk.read.requests_freeRadius: + properties: + name: disk.read.requests + abstract_freeradius.disk.device.usage_freeRadius: + properties: + name: disk.device.usage + abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.incoming.packets + abstract_freeradius.scalable_freeRadius: + properties: + min_instances: 1 + max_instances: 1 + abstract_freeradius.disk.latency_freeRadius: + properties: + name: disk.latency + abstract_freeradius.disk.write.requests.rate_freeRadius: + properties: + name: disk.write.requests.rate + abstract_freeradius.disk.write.requests_freeRadius: + properties: + name: disk.write.requests + abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.incoming.bytes + abstract_freeradius.disk.device.write.bytes.rate_freeRadius: + properties: + name: disk.device.write.bytes.rate + abstract_freeradius.disk.device.iops_freeRadius: + properties: + name: disk.device.iops + abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.outpoing.packets + abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.incoming.packets + abstract_freeradius.disk.iops_freeRadius: + properties: + name: disk.iops + abstract_freeradius.disk.device.write.requests_freeRadius: + properties: + name: disk.device.write.requests + abstract_freeradius.disk.device.read.requests.rate_freeRadius: + properties: + name: disk.device.read.requests.rate + abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.incoming.bytes.rate + abstract_freeradius.disk.device.write.requests.rate_freeRadius: + properties: + name: disk.device.write.requests.rate + abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_oam_port_0: + properties: + name: network.outpoing.packets + abstract_freeradius.disk.device.write.bytes_freeRadius: + properties: + name: disk.device.write.bytes + abstract_freeradius.instance_freeRadius: + properties: + name: instance + abstract_freeradius.disk.device.capacity_freeRadius: + properties: + name: disk.device.capacity + abstract_freeradius.port_mirroring_freeRadius_freeRadius_oam_port_0: + properties: + connection_point: + network_role: + get_input: port_freeRadius_oam_port_0_network_role + nfc_naming_code: freeRadius + abstract_freeradius.disk.usage_freeRadius: + properties: + name: disk.usage + abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_oam_port_0: + properties: + name: network.outgoing.bytes + abstract_freeradius.disk.device.latency_freeRadius: + properties: + name: disk.device.latency + abstract_freeradius.disk.root.size_freeRadius: + properties: + name: disk.root.size + abstract_freeradius.disk.capacity_freeRadius: + properties: + name: disk.capacity + abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_oam_port_0: + properties: + name: network.incoming.bytes.rate + abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.incoming.bytes.rate + abstract_freeradius.memory.resident_freeRadius: + properties: + name: memory.resident + abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_oam_port_0: + properties: + name: network.incoming.packets.rate + abstract_freeradius.disk.write.bytes.rate_freeRadius: + properties: + name: disk.write.bytes.rate + abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.outgoing.bytes + abstract_freeradius.disk.device.read.bytes_freeRadius: + properties: + name: disk.device.read.bytes + abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_oam_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_freeradius.disk.allocation_freeRadius: + properties: + name: disk.allocation + abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.outgoing.packets.rate + abstract_freeradius.cpu.delta_freeRadius: + properties: + name: cpu.delta + abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.outgoing.packets.rate + abstract_freeradius.disk.read.bytes.rate_freeRadius: + properties: + name: disk.read.bytes.rate + abstract_freeradius.vcpus_freeRadius: + properties: + name: vcpus + abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_oam_port_0: + properties: + name: network.incoming.packets + abstract_freeradius.disk.device.allocation_freeRadius: + properties: + name: disk.device.allocation + abstract_freeradius.disk.write.bytes_freeRadius: + properties: + name: disk.write.bytes + abstract_freeradius.endpoint_freeRadius: + properties: + secure: true + abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.incoming.packets.rate + abstract_freeradius.disk.read.bytes_freeRadius: + properties: + name: disk.read.bytes + abstract_freeradius.cpu_freeRadius: + properties: + name: cpu + abstract_freeradius.port_mirroring_freeRadius_freeRadius_control_plane_port_0: + properties: + connection_point: + network_role: + get_input: port_freeRadius_control_plane_port_0_network_role + nfc_naming_code: freeRadius + abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_control_plane_port_0: + properties: + name: network.outpoing.packets + abstract_freeradius.disk.device.read.requests_freeRadius: + properties: + name: disk.device.read.requests + abstract_freeradius.port_mirroring_freeRadius_freeRadius_user_plane_port_0: + properties: + connection_point: + network_role: + get_input: port_freeRadius_user_plane_port_0_network_role + nfc_naming_code: freeRadius + abstract_freeradius.disk.ephemeral.size_freeRadius: + properties: + name: disk.ephemeral.size + abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_oam_port_0: + properties: + name: network.incoming.bytes + abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_user_plane_port_0: + properties: + name: network.outgoing.bytes + groups: + freeradiusinnova_vf0..FreeradiusinnovaVf..base_freeRadiusInnova..module-0: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: FreeradiusinnovaVf..base_freeRadiusInnova..module-0 + vfModuleModelInvariantUUID: bd638287-e1a0-47d0-a0b1-825a4ad23fef + vfModuleModelUUID: 9bc52324-3e35-4795-9181-804a4eee0806 + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: 0a633c1a-c122-4e0a-8ed6-233ac56c132f + properties: + min_vf_module_instances: 1 + vf_module_label: base_freeRadiusInnova + max_vf_module_instances: 1 + vf_module_type: Base + isBase: true + initial_count: 1 + volume_group: false + substitution_mappings: + node_type: org.openecomp.service.FreeradiusinnovaService123 + capabilities: + freeradiusinnova_vf0.abstract_freeradius.disk.latency_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.latency_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.usage_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.usage_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.read.bytes_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.read.bytes_freeRadius + freeradiusinnova_vf0.abstract_freeradius.os_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.os_freeRadius + freeradiusinnova_vf0.abstract_freeradius.attachment_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.attachment_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.feature_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.feature_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.device.read.bytes_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.read.bytes_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.device.latency_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.latency_freeRadius + freeradiusinnova_vf0.abstract_freeradius.binding_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.binding_freeRadius + freeradiusinnova_vf0.abstract_freeradius.binding_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.binding_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.forwarder_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.forwarder_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.disk.device.usage_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.usage_freeRadius + freeradiusinnova_vf0.abstract_freeradius.endpoint_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.endpoint_freeRadius + freeradiusinnova_vf0.abstract_freeradius.port_mirroring_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.port_mirroring_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.cpu.delta_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.cpu.delta_freeRadius + freeradiusinnova_vf0.abstract_freeradius.feature_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.feature_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.disk.write.bytes_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.write.bytes_freeRadius + freeradiusinnova_vf0.abstract_freeradius.forwarder_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.forwarder_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.disk.device.write.bytes_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.write.bytes_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.device.write.requests.rate_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.write.requests.rate_freeRadius + freeradiusinnova_vf0.abstract_freeradius.host_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.host_freeRadius + freeradiusinnova_vf0.abstract_freeradius.attachment_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.attachment_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.disk.device.write.bytes.rate_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.write.bytes.rate_freeRadius + neutronnet0.end_point: + - NeutronNet 0 + - end_point + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.cpu_util_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.cpu_util_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_oam_port_0 + neutronnet0.attachment: + - NeutronNet 0 + - attachment + freeradiusinnova_vf0.abstract_freeradius.disk.device.iops_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.iops_freeRadius + freeradiusinnova_vf0.freeradius_control_plane_security_group.feature: + - freeRadiusInnova_VF 0 + - freeradius_control_plane_security_group.feature + freeradiusinnova_vf0.freeradius_user_plane_security_group.feature: + - freeRadiusInnova_VF 0 + - freeradius_user_plane_security_group.feature + freeradiusinnova_vf0.abstract_freeradius.disk.capacity_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.capacity_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_oam_port_0 + neutronnet0.link: + - NeutronNet 0 + - link + freeradiusinnova_vf0.abstract_freeradius.disk.write.bytes.rate_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.write.bytes.rate_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.device.read.requests_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.read.requests_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.bytes_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.vcpus_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.vcpus_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.bytes.rate_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.disk.device.allocation_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.allocation_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.device.read.requests.rate_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.read.requests.rate_freeRadius + freeradiusinnova_vf0.abstract_freeradius.attachment_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.attachment_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.memory_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.memory_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.device.write.requests_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.write.requests_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.read.bytes.rate_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.read.bytes.rate_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.root.size_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.root.size_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.allocation_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.allocation_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.packets_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.disk.device.capacity_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.capacity_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_user_plane_port_0 + neutronnet0.feature: + - NeutronNet 0 + - feature + freeradiusinnova_vf0.abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.port_mirroring_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.port_mirroring_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.instance_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.instance_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.write.requests.rate_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.write.requests.rate_freeRadius + freeradiusinnova_vf0.abstract_freeradius.memory.resident_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.memory.resident_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.write.requests_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.write.requests_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.forwarder_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.forwarder_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.packets.rate_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.binding_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.binding_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.binding_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.binding_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.packets.rate_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outpoing.packets_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.outgoing.bytes.rate_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.scalable_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.scalable_freeRadius + freeradiusinnova_vf0.abstract_freeradius.feature_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.feature_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.freeradius_oam_security_group.feature: + - freeRadiusInnova_VF 0 + - freeradius_oam_security_group.feature + freeradiusinnova_vf0.abstract_freeradius.feature_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.feature_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.port_mirroring_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.port_mirroring_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.disk.device.read.bytes.rate_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.device.read.bytes.rate_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.read.requests_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.read.requests_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.iops_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.iops_freeRadius + freeradiusinnova_vf0.abstract_freeradius.memory.usage_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.memory.usage_freeRadius + freeradiusinnova_vf0.abstract_freeradius.disk.ephemeral.size_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.disk.ephemeral.size_freeRadius + freeradiusinnova_vf0.abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.network.incoming.bytes_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.cpu_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.cpu_freeRadius + requirements: + freeradiusinnova_vf0.abstract_freeradius.dependency_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.dependency_freeRadius_freeRadius_user_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.dependency_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.dependency_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.abstract_freeradius.link_freeRadius_freeRadius_oam_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.link_freeRadius_freeRadius_oam_port_0 + freeradiusinnova_vf0.freeradius_control_plane_security_group.port: + - freeRadiusInnova_VF 0 + - freeradius_control_plane_security_group.port + freeradiusinnova_vf0.freeradius_oam_security_group.dependency: + - freeRadiusInnova_VF 0 + - freeradius_oam_security_group.dependency + freeradiusinnova_vf0.freeradius_control_plane_security_group.dependency: + - freeRadiusInnova_VF 0 + - freeradius_control_plane_security_group.dependency + neutronnet0.dependency: + - NeutronNet 0 + - dependency + freeradiusinnova_vf0.freeradius_user_plane_security_group.port: + - freeRadiusInnova_VF 0 + - freeradius_user_plane_security_group.port + freeradiusinnova_vf0.freeradius_user_plane_security_group.dependency: + - freeRadiusInnova_VF 0 + - freeradius_user_plane_security_group.dependency + freeradiusinnova_vf0.abstract_freeradius.dependency_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.dependency_freeRadius + freeradiusinnova_vf0.abstract_freeradius.dependency_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.dependency_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.link_freeRadius_freeRadius_control_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.link_freeRadius_freeRadius_control_plane_port_0 + freeradiusinnova_vf0.abstract_freeradius.local_storage_freeRadius: + - freeRadiusInnova_VF 0 + - abstract_freeradius.local_storage_freeRadius + freeradiusinnova_vf0.freeradius_oam_security_group.port: + - freeRadiusInnova_VF 0 + - freeradius_oam_security_group.port + freeradiusinnova_vf0.abstract_freeradius.link_freeRadius_freeRadius_user_plane_port_0: + - freeRadiusInnova_VF 0 + - abstract_freeradius.link_freeRadius_freeRadius_user_plane_port_0
\ No newline at end of file diff --git a/tests/data/service-Ubuntu16-template.yml b/tests/data/service-Ubuntu16-template.yml new file mode 100644 index 0000000..63cee88 --- /dev/null +++ b/tests/data/service-Ubuntu16-template.yml @@ -0,0 +1,543 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 +metadata: + invariantUUID: d65b4e82-06e7-424a-8944-284558b94ff4 + UUID: b54a8c68-d520-42c3-8f8e-08f3866f4fc1 + name: ubuntu16 + description: ubuntu16 + type: Service + category: Network Service + serviceType: '' + serviceRole: '' + instantiationType: A-la-carte + serviceEcompNaming: true + ecompGeneratedNaming: true + namingPolicy: '' + environmentContext: General_Revenue-Bearing +imports: +- nodes: + file: nodes.yml +- datatypes: + file: data.yml +- capabilities: + file: capabilities.yml +- relationships: + file: relationships.yml +- groups: + file: groups.yml +- policies: + file: policies.yml +- annotations: + file: annotations.yml +- service-ubuntu16-interface: + file: service-Ubuntu16-template-interface.yml +- resource-ubuntu16_VF: + file: resource-Ubuntu16Vf-template.yml +- resource-ubuntu16_VF-interface: + file: resource-Ubuntu16Vf-template-interface.yml +topology_template: + node_templates: + ubuntu16_VF 0: + type: org.openecomp.resource.vf.Ubuntu16Vf + metadata: + invariantUUID: 712e6e88-404e-49cb-99db-19460b29c2ac + UUID: dc4f02bb-f318-49c4-bd70-2a1ee95b439a + customizationUUID: 1066c03b-0aab-43b3-a661-7543de231e7c + version: '1.0' + name: ubuntu16_VF + description: VF + type: VF + category: Generic + subcategory: Abstract + resourceVendor: Generic-Vendor + resourceVendorRelease: '1.0' + resourceVendorModelNumber: '' + properties: + vf_module_id: Ubuntu16-VF-module + ubuntu16_name_0: ubuntu16 + nf_naming: + ecomp_generated_naming: true + ubuntu16_flavor_name: onap.small + multi_stage_design: false + ubuntu16_pub_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDY15cdBmIs2XOpe4EiFCsaY6bmUmK/GysMoLl4UG51JCfJwvwoWCoA+6mDIbymZxhxq9IGxilp/yTA6WQ9s/5pBag1cUMJmFuda9PjOkXl04jgqh5tR6I+GZ97AvCg93KAECis5ubSqw1xOCj4utfEUtPoF1OuzqM/lE5mY4N6VKXn+fT7pCD6cifBEs6JHhVNvs5OLLp/tO8Pa3kKYQOdyS0xc3rh+t2lrzvKUSWGZbX+dLiFiEpjsUL3tDqzkEMNUn4pdv69OJuzWHCxRWPfdrY9Wg0j3mJesP29EBht+w+EC9/kBKq+1VKdmsXUXAcjEvjovVL8l1BrX3BY0R8D imported-openssh-key + availability_zone_max_count: 1 + vnf_id: Ubuntu16-VNF + vnf_name: Ubuntu16-VNF-name + ubuntu16_image_name: ubuntu-16.04-daily + admin_plane_net_name: admin + ubuntu16_key_name: cleouverte + capabilities: + abstract_ubuntu16.port_mirroring_ubuntu16_ubuntu16_admin_plane_port: + properties: + connection_point: + network_role: + get_input: port_ubuntu16_admin_plane_port_network_role + nfc_naming_code: ubuntu16 + abstract_ubuntu16.cpu_util_ubuntu16: + properties: + unit: '%' + description: Average CPU utilization + type: Gauge + category: compute + abstract_ubuntu16.network.outpoing.packets_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: packet + description: Number of outgoing packets + type: Cumulative + category: network + abstract_ubuntu16.disk.device.read.bytes.rate_ubuntu16: + properties: + unit: B/s + description: Average rate of reads + type: Gauge + category: disk + abstract_ubuntu16.endpoint_ubuntu16: + properties: + secure: true + abstract_ubuntu16.disk.ephemeral.size_ubuntu16: + properties: + unit: GB + description: Size of ephemeral disk + type: Gauge + category: compute + abstract_ubuntu16.disk.write.bytes_ubuntu16: + properties: + unit: B + description: Volume of writes + type: Cumulative + category: compute + abstract_ubuntu16.cpu.delta_ubuntu16: + properties: + unit: ns + description: CPU time used since previous datapoint + type: Delta + category: compute + abstract_ubuntu16.network.incoming.bytes.rate_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: B/s + description: Average rate of incoming bytes + type: Gauge + category: network + abstract_ubuntu16.network.incoming.bytes_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: B + description: Number of incoming bytes + type: Cumulative + category: network + abstract_ubuntu16.disk.write.requests.rate_ubuntu16: + properties: + unit: request/s + description: Average rate of write requests + type: Gauge + category: compute + abstract_ubuntu16.memory_ubuntu16: + properties: + unit: MB + description: Volume of RAM allocated to the instance + type: Gauge + category: compute + abstract_ubuntu16.disk.root.size_ubuntu16: + properties: + unit: GB + description: Size of root disk + type: Gauge + category: compute + abstract_ubuntu16.disk.device.usage_ubuntu16: + properties: + unit: B + description: The physical size in bytes of the image container on the host per device + type: Gauge + category: disk + abstract_ubuntu16.disk.write.requests_ubuntu16: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: compute + abstract_ubuntu16.disk.device.read.bytes_ubuntu16: + properties: + unit: B + description: Volume of reads + type: Cumulative + category: disk + abstract_ubuntu16.vcpus_ubuntu16: + properties: + unit: vcpu + description: Number of virtual CPUs allocated to the instance + type: Gauge + category: compute + abstract_ubuntu16.network.incoming.packets.rate_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: packet/s + description: Average rate of incoming packets + type: Gauge + category: network + abstract_ubuntu16.network.incoming.packets_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: packet + description: Number of incoming packets + type: Cumulative + category: network + abstract_ubuntu16.disk.read.bytes_ubuntu16: + properties: + unit: B + description: Volume of reads + type: Cumulative + category: compute + abstract_ubuntu16.disk.latency_ubuntu16: + properties: + unit: ms + description: Average disk latency + type: Gauge + category: disk + abstract_ubuntu16.disk.device.read.requests.rate_ubuntu16: + properties: + unit: request/s + description: Average rate of read requests + type: Gauge + category: disk + abstract_ubuntu16.network.outgoing.bytes_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: B + description: Number of outgoing bytes + type: Cumulative + category: network + abstract_ubuntu16.scalable_ubuntu16: + properties: + max_instances: 1 + min_instances: 1 + abstract_ubuntu16.disk.device.write.requests.rate_ubuntu16: + properties: + unit: request/s + description: Average rate of write requests + type: Gauge + category: disk + abstract_ubuntu16.disk.device.allocation_ubuntu16: + properties: + unit: B + description: The amount of disk per device occupied by the instance on the host machine + type: Gauge + category: disk + abstract_ubuntu16.disk.device.write.bytes_ubuntu16: + properties: + unit: B + description: Volume of writes + type: Cumulative + category: disk + abstract_ubuntu16.disk.device.capacity_ubuntu16: + properties: + unit: B + description: The amount of disk per device that the instance can see + type: Gauge + category: disk + abstract_ubuntu16.disk.device.latency_ubuntu16: + properties: + unit: ms + description: Average disk latency per device + type: Gauge + category: disk + abstract_ubuntu16.disk.write.bytes.rate_ubuntu16: + properties: + unit: B/s + description: Average rate of writes + type: Gauge + category: compute + abstract_ubuntu16.instance_ubuntu16: + properties: + unit: instance + description: Existence of instance + type: Gauge + category: compute + abstract_ubuntu16.disk.iops_ubuntu16: + properties: + unit: count/s + description: Average disk iops + type: Gauge + category: disk + abstract_ubuntu16.disk.capacity_ubuntu16: + properties: + unit: B + description: The amount of disk that the instance can see + type: Gauge + category: disk + abstract_ubuntu16.memory.resident_ubuntu16: + properties: + unit: MB + description: Volume of RAM used by the instance on the physical machine + type: Gauge + category: compute + abstract_ubuntu16.disk.allocation_ubuntu16: + properties: + unit: B + description: The amount of disk occupied by the instance on the host machine + type: Gauge + category: disk + abstract_ubuntu16.network.outgoing.packets.rate_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: packet/s + description: Average rate of outgoing packets + type: Gauge + category: network + abstract_ubuntu16.disk.read.requests_ubuntu16: + properties: + unit: request + description: Number of read requests + type: Cumulative + category: compute + abstract_ubuntu16.network.outgoing.bytes.rate_ubuntu16_ubuntu16_admin_plane_port: + properties: + unit: B/s + description: Average rate of outgoing bytes + type: Gauge + category: network + abstract_ubuntu16.cpu_ubuntu16: + properties: + unit: ns + description: CPU time used + type: Cumulative + category: compute + abstract_ubuntu16.disk.device.iops_ubuntu16: + properties: + unit: count/s + description: Average disk iops per device + type: Gauge + category: disk + abstract_ubuntu16.disk.device.read.requests_ubuntu16: + properties: + unit: request + description: Number of read requests + type: Cumulative + category: disk + abstract_ubuntu16.memory.usage_ubuntu16: + properties: + unit: MB + description: Volume of RAM used by the instance from the amount of its allocated memory + type: Gauge + category: compute + abstract_ubuntu16.disk.usage_ubuntu16: + properties: + unit: B + description: The physical size in bytes of the image container on the host + type: Gauge + category: disk + abstract_ubuntu16.disk.device.write.bytes.rate_ubuntu16: + properties: + unit: B/s + description: Average rate of writes + type: Gauge + category: disk + abstract_ubuntu16.disk.read.bytes.rate_ubuntu16: + properties: + unit: B/s + description: Average rate of reads + type: Gauge + category: compute + abstract_ubuntu16.disk.device.write.requests_ubuntu16: + properties: + unit: request + description: Number of write requests + type: Cumulative + category: disk + groups: + ubuntu16_vf0..Ubuntu16Vf..base_ubuntu16..module-0: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: Ubuntu16Vf..base_ubuntu16..module-0 + vfModuleModelInvariantUUID: f47c3a9b-6a5f-4d1a-8a0b-b7f56ebb9a90 + vfModuleModelUUID: ed041b38-63fc-486d-9d4d-4e2531bc7e54 + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: d946ea06-ec4b-4ed2-921a-117e1379b913 + properties: + min_vf_module_instances: 1 + vf_module_label: base_ubuntu16 + max_vf_module_instances: 1 + vf_module_type: Base + isBase: true + initial_count: 1 + volume_group: false + substitution_mappings: + node_type: org.openecomp.service.Ubuntu16 + capabilities: + ubuntu16_vf0.abstract_ubuntu16.disk.device.write.bytes_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.write.bytes_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.memory.resident_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.memory.resident_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.forwarder_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.forwarder_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.binding_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.binding_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.vcpus_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.vcpus_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.latency_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.latency_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.latency_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.latency_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.read.bytes_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.read.bytes_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.network.outgoing.bytes.rate_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.outgoing.bytes.rate_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.device.usage_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.usage_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.cpu.delta_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.cpu.delta_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.endpoint_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.endpoint_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.read.bytes_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.read.bytes_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.write.requests_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.write.requests_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.network.outgoing.bytes_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.outgoing.bytes_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.capacity_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.capacity_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.attachment_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.attachment_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.network.incoming.bytes.rate_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.incoming.bytes.rate_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.device.iops_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.iops_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.capacity_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.capacity_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.write.bytes.rate_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.write.bytes.rate_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.write.requests.rate_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.write.requests.rate_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.feature_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.feature_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.port_mirroring_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.port_mirroring_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.write.requests.rate_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.write.requests.rate_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.root.size_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.root.size_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.allocation_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.allocation_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.feature_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.feature_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.read.bytes.rate_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.read.bytes.rate_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.read.requests_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.read.requests_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.network.incoming.packets.rate_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.incoming.packets.rate_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.ubuntu16_admin_security_group.feature: + - ubuntu16_vf0 + - ubuntu16_admin_security_group.feature + ubuntu16_vf0.abstract_ubuntu16.host_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.host_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.write.bytes_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.write.bytes_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.memory_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.memory_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.cpu_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.cpu_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.usage_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.usage_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.cpu_util_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.cpu_util_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.write.requests_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.write.requests_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.os_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.os_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.network.outgoing.packets.rate_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.outgoing.packets.rate_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.ephemeral.size_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.ephemeral.size_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.network.outpoing.packets_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.outpoing.packets_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.device.write.bytes.rate_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.write.bytes.rate_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.binding_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.binding_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.read.requests_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.read.requests_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.memory.usage_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.memory.usage_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.read.bytes.rate_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.read.bytes.rate_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.disk.device.allocation_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.allocation_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.scalable_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.scalable_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.network.incoming.bytes_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.incoming.bytes_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.device.read.requests.rate_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.device.read.requests.rate_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.instance_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.instance_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.network.incoming.packets_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.network.incoming.packets_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.disk.iops_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.disk.iops_ubuntu16 + requirements: + ubuntu16_vf0.ubuntu16_admin_security_group.port: + - ubuntu16_vf0 + - ubuntu16_admin_security_group.port + ubuntu16_vf0.abstract_ubuntu16.local_storage_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.local_storage_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.dependency_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.dependency_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.abstract_ubuntu16.dependency_ubuntu16: + - ubuntu16_vf0 + - abstract_ubuntu16.dependency_ubuntu16 + ubuntu16_vf0.abstract_ubuntu16.link_ubuntu16_ubuntu16_admin_plane_port: + - ubuntu16_vf0 + - abstract_ubuntu16.link_ubuntu16_ubuntu16_admin_plane_port + ubuntu16_vf0.ubuntu16_admin_security_group.dependency: + - ubuntu16_vf0 + - ubuntu16_admin_security_group.dependency diff --git a/tests/data/service-VfwcdsService-template.yml b/tests/data/service-VfwcdsService-template.yml new file mode 100644 index 0000000..15e0beb --- /dev/null +++ b/tests/data/service-VfwcdsService-template.yml @@ -0,0 +1,1439 @@ +tosca_definitions_version: tosca_simple_yaml_1_1 +metadata: + invariantUUID: 40f5261c-38dd-4e7b-9ef4-4af383982efe + UUID: 7227d3dc-fa6c-470c-b752-9879395e3560 + name: vfwcds_SERVICE + description: service + type: Service + category: Network Service + serviceType: '' + serviceRole: '' + instantiationType: Macro + serviceEcompNaming: true + ecompGeneratedNaming: true + namingPolicy: '' + environmentContext: General_Revenue-Bearing + serviceFunction: '' +imports: +- nodes: + file: nodes.yml +- datatypes: + file: data.yml +- capabilities: + file: capabilities.yml +- relationships: + file: relationships.yml +- groups: + file: groups.yml +- policies: + file: policies.yml +- annotations: + file: annotations.yml +- service-vfwcds_SERVICE-interface: + file: service-VfwcdsService-template-interface.yml +- resource-vfwcds_VF: + file: resource-VfwcdsVf-template.yml +- resource-vfwcds_VF-interface: + file: resource-VfwcdsVf-template-interface.yml +topology_template: + inputs: + skip_post_instantiation_configuration: + default: true + type: boolean + required: false + controller_actor: + default: SO-REF-DATA + type: string + required: false + cds_model_version: + type: string + required: false + cds_model_name: + type: string + required: false + node_templates: + vfwcds_VF 0: + type: org.openecomp.resource.vf.VfwcdsVf + metadata: + invariantUUID: 1d96a236-7c64-4bfe-9eeb-5026e060e6cd + UUID: 8726a1fd-e84e-4477-bffb-319defb84b76 + customizationUUID: eabe78af-3a24-45ed-a50a-24ad778d0bac + version: '1.0' + name: vfwcds_VF + description: VF + type: VF + category: Generic + subcategory: Abstract + resourceVendor: VNFVendor + resourceVendorRelease: '1.0' + resourceVendorModelNumber: '' + properties: + vf_module_id: vFirewallCL + skip_post_instantiation_configuration: false + controller_actor: CDS + vsn_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested) + vfw_int_private2_ip_0: 192.168.20.100 + int_private1_subnet_id: zdfw1fwl01_unprotected_sub + public_net_id: PUT THE PUBLIC NETWORK ID HERE + vnf_name: vFW_NextGen + onap_private_subnet_id: PUT THE ONAP PRIVATE NETWORK NAME HERE + vsn_int_private2_ip_0: 192.168.20.250 + sec_group: PUT THE ONAP SECURITY GROUP HERE + vfw_name_0: zdfw1fwl01fwl01 + nexus_artifact_repo: https://nexus.onap.org + onap_private_net_cidr: 10.0.0.0/16 + vpg_onap_private_ip_0: 10.0.100.2 + dcae_collector_ip: 10.0.4.1 + vsn_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404) + vnf_id: vSink_demo_app + vpg_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested) + dcae_collector_port: '30417' + vfw_int_private2_floating_ip: 192.168.10.200 + vpg_name_0: zdfw1fwl01pgn01 + int_private2_subnet_id: zdfw1fwl01_protected_sub + int_private2_net_cidr: 192.168.20.0/24 + nf_naming: + ecomp_generated_naming: true + vsn_name_0: zdfw1fwl01snk01 + multi_stage_design: 'false' + vpg_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404) + onap_private_net_id: PUT THE ONAP PRIVATE NETWORK NAME HERE + availability_zone_max_count: 1 + sdnc_artifact_name: vfwcds + vsn_onap_private_ip_0: 10.0.100.3 + vfw_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested) + demo_artifacts_version: 1.6.0-SNAPSHOT + pub_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQXYJYYi3/OUZXUiCYWdtc7K0m5C0dJKVxPG0eI8EWZrEHYdfYe6WoTSDJCww+1qlBSpA5ac/Ba4Wn9vh+lR1vtUKkyIC/nrYb90ReUd385Glkgzrfh5HdR5y5S2cL/Frh86lAn9r6b3iWTJD8wBwXFyoe1S2nMTOIuG4RPNvfmyCTYVh8XTCCE8HPvh3xv2r4egawG1P4Q4UDwk+hDBXThY2KS8M5/8EMyxHV0ImpLbpYCTBA6KYDIRtqmgS6iKyy8v2D1aSY5mc9J0T5t9S2Gv+VZQNWQDDKNFnxqYaAo1uEoq/i1q63XC5AD3ckXb2VT6dp23BQMdDfbHyUWfJN + key_name: vfw_key + vfw_int_private1_ip_0: 192.168.10.100 + sdnc_model_version: 1.0.0 + int_private1_net_cidr: 192.168.10.0/24 + install_script_version: 1.6.0-SNAPSHOT + vfw_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404) + vfw_onap_private_ip_0: 10.0.100.1 + vpg_int_private1_ip_0: 192.168.10.200 + int_private2_net_id: zdfw1fwl01_protected + cloud_env: PUT openstack OR rackspace HERE + sdnc_model_name: vFW-CDS + int_private1_net_id: zdfw1fwl01_unprotected + capabilities: + abstract_vfw.cpu_vfw: + properties: + name: cpu + abstract_vpg.memory.resident_vpg: + properties: + name: memory.resident + abstract_vfw.disk.device.read.requests_vfw: + properties: + name: disk.device.read.requests + abstract_vpg.disk.write.bytes_vpg: + properties: + name: disk.write.bytes + abstract_vsn.disk.device.write.requests.rate_vsn: + properties: + name: disk.device.write.requests.rate + abstract_vpg.disk.usage_vpg: + properties: + name: disk.usage + abstract_vfw.network.outpoing.packets_vfw_vfw_int_private1_port_0: + properties: + name: network.outpoing.packets + abstract_vfw.disk.device.latency_vfw: + properties: + name: disk.device.latency + abstract_vfw.network.outpoing.packets_vfw_vfw_int_private2_port_0: + properties: + name: network.outpoing.packets + abstract_vfw.network.outpoing.packets_vfw_vfw_onap_private_port_0: + properties: + name: network.outpoing.packets + abstract_vsn.disk.device.write.bytes_vsn: + properties: + name: disk.device.write.bytes + abstract_vfw.disk.read.requests_vfw: + properties: + name: disk.read.requests + abstract_vsn.memory.resident_vsn: + properties: + name: memory.resident + abstract_vfw.network.incoming.bytes_vfw_vfw_int_private1_port_0: + properties: + name: network.incoming.bytes + abstract_vfw.network.incoming.bytes_vfw_vfw_int_private2_port_0: + properties: + name: network.incoming.bytes + abstract_vfw.memory_vfw: + properties: + name: memory + abstract_vsn.disk.device.read.requests.rate_vsn: + properties: + name: disk.device.read.requests.rate + abstract_vfw.disk.device.allocation_vfw: + properties: + name: disk.device.allocation + abstract_vsn.network.outgoing.packets.rate_vsn_vsn_int_private2_port_0: + properties: + name: network.outgoing.packets.rate + abstract_vfw.disk.root.size_vfw: + properties: + name: disk.root.size + abstract_vpg.network.incoming.packets_vpg_vpg_int_private1_port_0: + properties: + name: network.incoming.packets + abstract_vpg.network.outpoing.packets_vpg_vpg_onap_private_port_0: + properties: + name: network.outpoing.packets + abstract_vpg.memory.usage_vpg: + properties: + name: memory.usage + abstract_vfw.disk.capacity_vfw: + properties: + name: disk.capacity + abstract_vfw.disk.allocation_vfw: + properties: + name: disk.allocation + abstract_vpg.disk.iops_vpg: + properties: + name: disk.iops + abstract_vpg.disk.device.capacity_vpg: + properties: + name: disk.device.capacity + abstract_vsn.scalable_vsn: + properties: + max_instances: 1 + min_instances: 1 + abstract_vsn.network.incoming.packets.rate_vsn_vsn_int_private2_port_0: + properties: + name: network.incoming.packets.rate + abstract_vpg.disk.write.requests.rate_vpg: + properties: + name: disk.write.requests.rate + abstract_vsn.disk.read.bytes_vsn: + properties: + name: disk.read.bytes + abstract_vsn.network.incoming.bytes.rate_vsn_vsn_onap_private_port_0: + properties: + name: network.incoming.bytes.rate + abstract_vfw.disk.device.iops_vfw: + properties: + name: disk.device.iops + abstract_vsn.disk.device.write.requests_vsn: + properties: + name: disk.device.write.requests + abstract_vfw.disk.write.requests_vfw: + properties: + name: disk.write.requests + abstract_vpg.network.outgoing.bytes_vpg_vpg_int_private1_port_0: + properties: + name: network.outgoing.bytes + abstract_vsn.disk.device.allocation_vsn: + properties: + name: disk.device.allocation + abstract_vpg.disk.read.bytes_vpg: + properties: + name: disk.read.bytes + abstract_vsn.disk.ephemeral.size_vsn: + properties: + name: disk.ephemeral.size + abstract_vsn.cpu_vsn: + properties: + name: cpu + abstract_vpg.network.outgoing.packets.rate_vpg_vpg_onap_private_port_0: + properties: + name: network.outgoing.packets.rate + abstract_vpg.network.incoming.packets.rate_vpg_vpg_int_private1_port_0: + properties: + name: network.incoming.packets.rate + abstract_vsn.disk.write.bytes_vsn: + properties: + name: disk.write.bytes + abstract_vfw.network.incoming.packets.rate_vfw_vfw_int_private2_port_0: + properties: + name: network.incoming.packets.rate + abstract_vpg.disk.device.read.bytes_vpg: + properties: + name: disk.device.read.bytes + int_private1_network.end_point: + properties: + protocol: tcp + initiator: source + network_name: PRIVATE + secure: false + abstract_vfw.network.incoming.bytes.rate_vfw_vfw_int_private2_port_0: + properties: + name: network.incoming.bytes.rate + abstract_vfw.network.outgoing.bytes_vfw_vfw_onap_private_port_0: + properties: + name: network.outgoing.bytes + abstract_vpg.disk.capacity_vpg: + properties: + name: disk.capacity + abstract_vfw.network.outgoing.packets.rate_vfw_vfw_onap_private_port_0: + properties: + name: network.outgoing.packets.rate + abstract_vpg.disk.device.read.bytes.rate_vpg: + properties: + name: disk.device.read.bytes.rate + abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_onap_private_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_vfw.disk.usage_vfw: + properties: + name: disk.usage + abstract_vsn.disk.device.latency_vsn: + properties: + name: disk.device.latency + abstract_vpg.scalable_vpg: + properties: + max_instances: 1 + min_instances: 1 + abstract_vsn.instance_vsn: + properties: + name: instance + abstract_vpg.disk.device.allocation_vpg: + properties: + name: disk.device.allocation + abstract_vsn.disk.write.requests_vsn: + properties: + name: disk.write.requests + abstract_vfw.disk.write.bytes_vfw: + properties: + name: disk.write.bytes + abstract_vsn.disk.device.read.bytes.rate_vsn: + properties: + name: disk.device.read.bytes.rate + abstract_vsn.vcpus_vsn: + properties: + name: vcpus + abstract_vfw.disk.device.write.bytes_vfw: + properties: + name: disk.device.write.bytes + abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_onap_private_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_vfw.network.incoming.packets.rate_vfw_vfw_onap_private_port_0: + properties: + name: network.incoming.packets.rate + abstract_vsn.cpu.delta_vsn: + properties: + name: cpu.delta + abstract_vfw.memory.resident_vfw: + properties: + name: memory.resident + abstract_vpg.disk.device.iops_vpg: + properties: + name: disk.device.iops + abstract_vsn.cpu_util_vsn: + properties: + name: cpu_util + abstract_vpg.network.incoming.packets.rate_vpg_vpg_onap_private_port_0: + properties: + name: network.incoming.packets.rate + abstract_vpg.network.outgoing.packets.rate_vpg_vpg_int_private1_port_0: + properties: + name: network.outgoing.packets.rate + abstract_vpg.disk.latency_vpg: + properties: + name: disk.latency + abstract_vsn.port_mirroring_vsn_vsn_onap_private_port_0: + properties: + connection_point: + network_role: + get_input: port_vsn_onap_private_port_0_network_role + nfc_naming_code: vsn + abstract_vpg.instance_vpg: + properties: + name: instance + abstract_vfw.network.incoming.bytes_vfw_vfw_onap_private_port_0: + properties: + name: network.incoming.bytes + abstract_vpg.port_mirroring_vpg_vpg_onap_private_port_0: + properties: + connection_point: + network_role: + get_input: port_vpg_onap_private_port_0_network_role + nfc_naming_code: vpg + abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_int_private2_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_vfw.network.outgoing.packets.rate_vfw_vfw_int_private2_port_0: + properties: + name: network.outgoing.packets.rate + abstract_vfw.port_mirroring_vfw_vfw_onap_private_port_0: + properties: + connection_point: + network_role: + get_input: port_vfw_onap_private_port_0_network_role + nfc_naming_code: vfw + abstract_vfw.network.incoming.bytes.rate_vfw_vfw_onap_private_port_0: + properties: + name: network.incoming.bytes.rate + abstract_vpg.network.incoming.packets_vpg_vpg_onap_private_port_0: + properties: + name: network.incoming.packets + abstract_vsn.disk.allocation_vsn: + properties: + name: disk.allocation + abstract_vsn.disk.capacity_vsn: + properties: + name: disk.capacity + abstract_vpg.network.incoming.bytes_vpg_vpg_int_private1_port_0: + properties: + name: network.incoming.bytes + abstract_vpg.disk.allocation_vpg: + properties: + name: disk.allocation + abstract_vsn.disk.device.capacity_vsn: + properties: + name: disk.device.capacity + abstract_vfw.disk.device.read.requests.rate_vfw: + properties: + name: disk.device.read.requests.rate + abstract_vsn.disk.root.size_vsn: + properties: + name: disk.root.size + abstract_vsn.disk.usage_vsn: + properties: + name: disk.usage + abstract_vsn.disk.write.bytes.rate_vsn: + properties: + name: disk.write.bytes.rate + abstract_vsn.network.outgoing.bytes_vsn_vsn_int_private2_port_0: + properties: + name: network.outgoing.bytes + abstract_vsn.endpoint_vsn: + properties: + secure: true + abstract_vpg.disk.read.bytes.rate_vpg: + properties: + name: disk.read.bytes.rate + abstract_vpg.disk.device.read.requests_vpg: + properties: + name: disk.device.read.requests + abstract_vsn.network.outgoing.bytes_vsn_vsn_onap_private_port_0: + properties: + name: network.outgoing.bytes + abstract_vfw.disk.ephemeral.size_vfw: + properties: + name: disk.ephemeral.size + abstract_vpg.network.incoming.bytes.rate_vpg_vpg_onap_private_port_0: + properties: + name: network.incoming.bytes.rate + abstract_vpg.network.incoming.bytes.rate_vpg_vpg_int_private1_port_0: + properties: + name: network.incoming.bytes.rate + abstract_vpg.disk.read.requests_vpg: + properties: + name: disk.read.requests + abstract_vfw.network.incoming.packets_vfw_vfw_onap_private_port_0: + properties: + name: network.incoming.packets + abstract_vsn.disk.device.write.bytes.rate_vsn: + properties: + name: disk.device.write.bytes.rate + abstract_vpg.network.incoming.bytes_vpg_vpg_onap_private_port_0: + properties: + name: network.incoming.bytes + abstract_vpg.disk.device.write.bytes_vpg: + properties: + name: disk.device.write.bytes + abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_int_private1_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_vsn.memory.usage_vsn: + properties: + name: memory.usage + abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_int_private2_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_vsn.network.incoming.packets_vsn_vsn_int_private2_port_0: + properties: + name: network.incoming.packets + abstract_vsn.disk.device.iops_vsn: + properties: + name: disk.device.iops + abstract_vfw.network.incoming.packets_vfw_vfw_int_private1_port_0: + properties: + name: network.incoming.packets + abstract_vpg.disk.device.write.bytes.rate_vpg: + properties: + name: disk.device.write.bytes.rate + abstract_vsn.disk.device.read.bytes_vsn: + properties: + name: disk.device.read.bytes + abstract_vfw.disk.latency_vfw: + properties: + name: disk.latency + abstract_vsn.disk.read.requests_vsn: + properties: + name: disk.read.requests + abstract_vpg.endpoint_vpg: + properties: + secure: true + abstract_vsn.network.incoming.bytes.rate_vsn_vsn_int_private2_port_0: + properties: + name: network.incoming.bytes.rate + abstract_vsn.disk.device.read.requests_vsn: + properties: + name: disk.device.read.requests + abstract_vsn.memory_vsn: + properties: + name: memory + abstract_vfw.disk.device.read.bytes.rate_vfw: + properties: + name: disk.device.read.bytes.rate + abstract_vfw.disk.device.read.bytes_vfw: + properties: + name: disk.device.read.bytes + abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_int_private1_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_vsn.network.incoming.packets.rate_vsn_vsn_onap_private_port_0: + properties: + name: network.incoming.packets.rate + abstract_vfw.network.outgoing.packets.rate_vfw_vfw_int_private1_port_0: + properties: + name: network.outgoing.packets.rate + abstract_vfw.disk.read.bytes_vfw: + properties: + name: disk.read.bytes + abstract_vfw.disk.read.bytes.rate_vfw: + properties: + name: disk.read.bytes.rate + abstract_vfw.endpoint_vfw: + properties: + secure: true + abstract_vfw.disk.device.write.requests_vfw: + properties: + name: disk.device.write.requests + int_private2_network.end_point: + properties: + protocol: tcp + initiator: source + network_name: PRIVATE + secure: false + abstract_vpg.cpu_util_vpg: + properties: + name: cpu_util + abstract_vfw.network.outgoing.bytes_vfw_vfw_int_private2_port_0: + properties: + name: network.outgoing.bytes + abstract_vpg.vcpus_vpg: + properties: + name: vcpus + abstract_vpg.cpu_vpg: + properties: + name: cpu + abstract_vsn.network.incoming.packets_vsn_vsn_onap_private_port_0: + properties: + name: network.incoming.packets + abstract_vpg.network.outpoing.packets_vpg_vpg_int_private1_port_0: + properties: + name: network.outpoing.packets + abstract_vfw.disk.write.requests.rate_vfw: + properties: + name: disk.write.requests.rate + abstract_vpg.disk.root.size_vpg: + properties: + name: disk.root.size + abstract_vsn.disk.write.requests.rate_vsn: + properties: + name: disk.write.requests.rate + abstract_vpg.disk.device.usage_vpg: + properties: + name: disk.device.usage + abstract_vpg.disk.device.write.requests.rate_vpg: + properties: + name: disk.device.write.requests.rate + abstract_vfw.disk.device.capacity_vfw: + properties: + name: disk.device.capacity + abstract_vsn.network.outgoing.packets.rate_vsn_vsn_onap_private_port_0: + properties: + name: network.outgoing.packets.rate + abstract_vfw.network.incoming.packets.rate_vfw_vfw_int_private1_port_0: + properties: + name: network.incoming.packets.rate + abstract_vfw.network.incoming.bytes.rate_vfw_vfw_int_private1_port_0: + properties: + name: network.incoming.bytes.rate + abstract_vfw.cpu_util_vfw: + properties: + name: cpu_util + abstract_vfw.cpu.delta_vfw: + properties: + name: cpu.delta + abstract_vfw.vcpus_vfw: + properties: + name: vcpus + abstract_vsn.disk.iops_vsn: + properties: + name: disk.iops + abstract_vfw.disk.iops_vfw: + properties: + name: disk.iops + abstract_vfw.disk.write.bytes.rate_vfw: + properties: + name: disk.write.bytes.rate + abstract_vfw.scalable_vfw: + properties: + max_instances: 1 + min_instances: 1 + abstract_vpg.memory_vpg: + properties: + name: memory + abstract_vpg.disk.ephemeral.size_vpg: + properties: + name: disk.ephemeral.size + abstract_vfw.memory.usage_vfw: + properties: + name: memory.usage + abstract_vpg.disk.device.read.requests.rate_vpg: + properties: + name: disk.device.read.requests.rate + abstract_vpg.disk.device.write.requests_vpg: + properties: + name: disk.device.write.requests + abstract_vpg.disk.device.latency_vpg: + properties: + name: disk.device.latency + abstract_vfw.disk.device.usage_vfw: + properties: + name: disk.device.usage + abstract_vfw.network.incoming.packets_vfw_vfw_int_private2_port_0: + properties: + name: network.incoming.packets + abstract_vfw.disk.device.write.bytes.rate_vfw: + properties: + name: disk.device.write.bytes.rate + abstract_vpg.cpu.delta_vpg: + properties: + name: cpu.delta + abstract_vsn.network.outpoing.packets_vsn_vsn_onap_private_port_0: + properties: + name: network.outpoing.packets + abstract_vfw.instance_vfw: + properties: + name: instance + abstract_vsn.disk.latency_vsn: + properties: + name: disk.latency + abstract_vsn.network.incoming.bytes_vsn_vsn_onap_private_port_0: + properties: + name: network.incoming.bytes + abstract_vpg.disk.write.bytes.rate_vpg: + properties: + name: disk.write.bytes.rate + abstract_vfw.network.outgoing.bytes_vfw_vfw_int_private1_port_0: + properties: + name: network.outgoing.bytes + abstract_vpg.network.outgoing.bytes_vpg_vpg_onap_private_port_0: + properties: + name: network.outgoing.bytes + abstract_vsn.network.incoming.bytes_vsn_vsn_int_private2_port_0: + properties: + name: network.incoming.bytes + abstract_vfw.disk.device.write.requests.rate_vfw: + properties: + name: disk.device.write.requests.rate + abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_onap_private_port_0: + properties: + name: network.outgoing.bytes.rate + abstract_vpg.disk.write.requests_vpg: + properties: + name: disk.write.requests + abstract_vsn.disk.read.bytes.rate_vsn: + properties: + name: disk.read.bytes.rate + abstract_vsn.disk.device.usage_vsn: + properties: + name: disk.device.usage + abstract_vsn.network.outpoing.packets_vsn_vsn_int_private2_port_0: + properties: + name: network.outpoing.packets + groups: + vfwcds_vf0..VfwcdsVf..vsn..module-1: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: VfwcdsVf..vsn..module-1 + vfModuleModelInvariantUUID: f4b9d91b-75b7-4d14-98e5-907d8034fc4c + vfModuleModelUUID: fda666d1-d0d0-47c4-82cf-d02ee041a021 + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: 34040775-31da-4034-9387-e2bb3fab236c + properties: + min_vf_module_instances: 0 + vf_module_label: vsn + vf_module_type: Expansion + isBase: false + initial_count: 0 + volume_group: false + vfwcds_vf0..VfwcdsVf..vpg..module-2: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: VfwcdsVf..vpg..module-2 + vfModuleModelInvariantUUID: 048e1738-4cc7-49d4-99a4-fb2d75e7a8db + vfModuleModelUUID: cfd79d7d-e63a-46ab-a765-b6753c781f32 + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: d134bf7f-af50-4ea2-aa9c-1220497a6ec7 + properties: + min_vf_module_instances: 0 + vf_module_label: vpg + vf_module_type: Expansion + isBase: false + initial_count: 0 + volume_group: false + vfwcds_vf0..VfwcdsVf..vfw..module-3: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: VfwcdsVf..vfw..module-3 + vfModuleModelInvariantUUID: 09d24ca5-b3ef-4f82-a3ca-532e565929ed + vfModuleModelUUID: adf1eae4-0bb1-456e-8162-3cbc0554349f + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: 2d9a63ad-d364-471f-a780-29140f3a2d62 + properties: + min_vf_module_instances: 0 + vf_module_label: vfw + vf_module_type: Expansion + isBase: false + initial_count: 0 + volume_group: false + vfwcds_vf0..VfwcdsVf..base_template..module-0: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: VfwcdsVf..base_template..module-0 + vfModuleModelInvariantUUID: 1b1c6c52-b506-4a37-9b83-8fddab20a0e5 + vfModuleModelUUID: 49dc98c5-2e56-4d37-a8bb-5f814b772a42 + vfModuleModelVersion: '1' + vfModuleModelCustomizationUUID: 4533702f-7d3f-4205-a5d4-d1b213ab8f2e + properties: + min_vf_module_instances: 1 + vf_module_label: base_template + max_vf_module_instances: 1 + vf_module_type: Base + isBase: true + initial_count: 1 + volume_group: false + substitution_mappings: + node_type: org.openecomp.service.VfwcdsService + capabilities: + vfwcds_vf0.abstract_vsn.instance_vsn: + - vfwcds_VF 0 + - abstract_vsn.instance_vsn + vfwcds_vf0.abstract_vsn.disk.device.read.bytes_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.read.bytes_vsn + vfwcds_vf0.abstract_vpg.memory.usage_vpg: + - vfwcds_VF 0 + - abstract_vpg.memory.usage_vpg + vfwcds_vf0.abstract_vsn.network.outpoing.packets_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outpoing.packets_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vfw.attachment_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.attachment_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vsn.host_vsn: + - vfwcds_VF 0 + - abstract_vsn.host_vsn + vfwcds_vf0.abstract_vsn.network.outgoing.packets.rate_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outgoing.packets.rate_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vfw.cpu.delta_vfw: + - vfwcds_VF 0 + - abstract_vfw.cpu.delta_vfw + vfwcds_vf0.abstract_vfw.network.incoming.packets_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.packets_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vfw.forwarder_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.forwarder_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vsn.disk.device.usage_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.usage_vsn + vfwcds_vf0.abstract_vfw.feature_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.feature_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vfw.feature_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.feature_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vpg.port_mirroring_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.port_mirroring_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.device.read.bytes_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.read.bytes_vfw + vfwcds_vf0.abstract_vpg.network.incoming.packets_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.packets_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.forwarder_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.forwarder_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.disk.latency_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.latency_vfw + vfwcds_vf0.abstract_vpg.memory.resident_vpg: + - vfwcds_VF 0 + - abstract_vpg.memory.resident_vpg + vfwcds_vf0.abstract_vfw.os_vfw: + - vfwcds_VF 0 + - abstract_vfw.os_vfw + vfwcds_vf0.abstract_vpg.instance_vpg: + - vfwcds_VF 0 + - abstract_vpg.instance_vpg + vfwcds_vf0.abstract_vfw.disk.read.bytes_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.read.bytes_vfw + vfwcds_vf0.abstract_vfw.feature_vfw: + - vfwcds_VF 0 + - abstract_vfw.feature_vfw + vfwcds_vf0.abstract_vfw.disk.device.read.requests_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.read.requests_vfw + vfwcds_vf0.int_private2_network.link: + - vfwcds_VF 0 + - int_private2_network.link + vfwcds_vf0.abstract_vpg.disk.device.latency_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.latency_vpg + vfwcds_vf0.abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vsn.forwarder_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.forwarder_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vfw.binding_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.binding_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.network.incoming.packets.rate_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.packets.rate_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vpg.disk.root.size_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.root.size_vpg + vfwcds_vf0.abstract_vfw.memory.resident_vfw: + - vfwcds_VF 0 + - abstract_vfw.memory.resident_vfw + vfwcds_vf0.abstract_vpg.forwarder_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.forwarder_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vsn.vcpus_vsn: + - vfwcds_VF 0 + - abstract_vsn.vcpus_vsn + vfwcds_vf0.abstract_vpg.disk.device.read.bytes.rate_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.read.bytes.rate_vpg + vfwcds_vf0.abstract_vfw.disk.device.write.bytes.rate_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.write.bytes.rate_vfw + vfwcds_vf0.abstract_vpg.vcpus_vpg: + - vfwcds_VF 0 + - abstract_vpg.vcpus_vpg + vfwcds_vf0.abstract_vpg.disk.device.write.requests.rate_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.write.requests.rate_vpg + vfwcds_vf0.abstract_vsn.disk.device.latency_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.latency_vsn + vfwcds_vf0.abstract_vfw.disk.root.size_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.root.size_vfw + vfwcds_vf0.abstract_vfw.disk.device.capacity_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.capacity_vfw + vfwcds_vf0.abstract_vsn.disk.device.read.bytes.rate_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.read.bytes.rate_vsn + vfwcds_vf0.abstract_vsn.disk.write.requests.rate_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.write.requests.rate_vsn + vfwcds_vf0.abstract_vsn.cpu.delta_vsn: + - vfwcds_VF 0 + - abstract_vsn.cpu.delta_vsn + vfwcds_vf0.abstract_vpg.disk.capacity_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.capacity_vpg + vfwcds_vf0.abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outgoing.bytes.rate_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vsn.os_vsn: + - vfwcds_VF 0 + - abstract_vsn.os_vsn + vfwcds_vf0.abstract_vfw.binding_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.binding_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vsn.disk.root.size_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.root.size_vsn + vfwcds_vf0.abstract_vsn.network.outgoing.bytes_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outgoing.bytes_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vfw.network.incoming.packets.rate_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.packets.rate_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.network.outpoing.packets_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outpoing.packets_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vfw.scalable_vfw: + - vfwcds_VF 0 + - abstract_vfw.scalable_vfw + vfwcds_vf0.abstract_vpg.network.incoming.bytes_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.bytes_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vsn.feature_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.feature_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vsn.disk.device.capacity_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.capacity_vsn + vfwcds_vf0.abstract_vsn.binding_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.binding_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vfw.binding_vfw: + - vfwcds_VF 0 + - abstract_vfw.binding_vfw + vfwcds_vf0.abstract_vpg.os_vpg: + - vfwcds_VF 0 + - abstract_vpg.os_vpg + vfwcds_vf0.abstract_vpg.disk.device.write.bytes.rate_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.write.bytes.rate_vpg + vfwcds_vf0.abstract_vsn.cpu_util_vsn: + - vfwcds_VF 0 + - abstract_vsn.cpu_util_vsn + vfwcds_vf0.abstract_vpg.disk.write.bytes.rate_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.write.bytes.rate_vpg + vfwcds_vf0.abstract_vsn.disk.device.allocation_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.allocation_vsn + vfwcds_vf0.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.packets.rate_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vpg.network.outpoing.packets_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outpoing.packets_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vpg.disk.read.bytes.rate_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.read.bytes.rate_vpg + vfwcds_vf0.int_private1_network.link: + - vfwcds_VF 0 + - int_private1_network.link + vfwcds_vf0.abstract_vfw.disk.device.iops_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.iops_vfw + vfwcds_vf0.abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outgoing.bytes.rate_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vsn.disk.device.write.requests.rate_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.write.requests.rate_vsn + vfwcds_vf0.abstract_vpg.disk.allocation_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.allocation_vpg + vfwcds_vf0.abstract_vsn.binding_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.binding_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.cpu_util_vfw: + - vfwcds_VF 0 + - abstract_vfw.cpu_util_vfw + vfwcds_vf0.abstract_vfw.network.outpoing.packets_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outpoing.packets_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vsn.endpoint_vsn: + - vfwcds_VF 0 + - abstract_vsn.endpoint_vsn + vfwcds_vf0.abstract_vfw.network.outgoing.bytes_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.bytes_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vsn.disk.device.write.requests_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.write.requests_vsn + vfwcds_vf0.abstract_vpg.network.incoming.packets.rate_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.packets.rate_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vsn.network.incoming.packets.rate_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.packets.rate_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vpg.network.incoming.bytes_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.bytes_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.network.incoming.bytes_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.bytes_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vsn.forwarder_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.forwarder_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vsn.disk.device.iops_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.iops_vsn + vfwcds_vf0.abstract_vfw.disk.read.requests_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.read.requests_vfw + vfwcds_vf0.abstract_vpg.network.incoming.packets_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.packets_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vpg.feature_vpg: + - vfwcds_VF 0 + - abstract_vpg.feature_vpg + vfwcds_vf0.abstract_vsn.disk.capacity_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.capacity_vsn + vfwcds_vf0.abstract_vfw.disk.read.bytes.rate_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.read.bytes.rate_vfw + vfwcds_vf0.abstract_vsn.network.incoming.packets.rate_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.packets.rate_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vsn.scalable_vsn: + - vfwcds_VF 0 + - abstract_vsn.scalable_vsn + vfwcds_vf0.abstract_vpg.binding_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.binding_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vpg.disk.device.read.bytes_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.read.bytes_vpg + vfwcds_vf0.abstract_vpg.feature_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.feature_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vpg.disk.device.write.bytes_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.write.bytes_vpg + vfwcds_vf0.abstract_vpg.attachment_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.attachment_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vsn.disk.device.write.bytes_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.write.bytes_vsn + vfwcds_vf0.abstract_vpg.disk.device.read.requests_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.read.requests_vpg + vfwcds_vf0.abstract_vsn.feature_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.feature_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vsn.feature_vsn: + - vfwcds_VF 0 + - abstract_vsn.feature_vsn + vfwcds_vf0.abstract_vsn.disk.usage_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.usage_vsn + vfwcds_vf0.abstract_vfw.network.outgoing.bytes_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.bytes_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vpg.network.outgoing.packets.rate_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outgoing.packets.rate_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.device.usage_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.usage_vfw + vfwcds_vf0.int_private2_network.feature: + - vfwcds_VF 0 + - int_private2_network.feature + vfwcds_vf0.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.bytes.rate_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vfw.network.incoming.bytes_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.bytes_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vpg.host_vpg: + - vfwcds_VF 0 + - abstract_vpg.host_vpg + vfwcds_vf0.abstract_vfw.disk.device.read.requests.rate_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.read.requests.rate_vfw + vfwcds_vf0.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.bytes.rate_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vsn.disk.iops_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.iops_vsn + vfwcds_vf0.abstract_vfw.disk.write.bytes_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.write.bytes_vfw + vfwcds_vf0.abstract_vfw.attachment_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.attachment_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.network.incoming.packets_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.packets_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.cpu_vfw: + - vfwcds_VF 0 + - abstract_vfw.cpu_vfw + vfwcds_vf0.abstract_vpg.disk.device.read.requests.rate_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.read.requests.rate_vpg + vfwcds_vf0.int_private1_network.feature: + - vfwcds_VF 0 + - int_private1_network.feature + vfwcds_vf0.abstract_vpg.disk.iops_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.iops_vpg + vfwcds_vf0.abstract_vfw.disk.device.latency_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.latency_vfw + vfwcds_vf0.abstract_vpg.disk.latency_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.latency_vpg + vfwcds_vf0.abstract_vfw.feature_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.feature_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vfw.forwarder_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.forwarder_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vfw.instance_vfw: + - vfwcds_VF 0 + - abstract_vfw.instance_vfw + vfwcds_vf0.abstract_vfw.disk.capacity_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.capacity_vfw + vfwcds_vf0.abstract_vpg.network.incoming.bytes.rate_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.bytes.rate_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vpg.disk.device.write.requests_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.write.requests_vpg + vfwcds_vf0.abstract_vsn.network.outgoing.packets.rate_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outgoing.packets.rate_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.write.bytes.rate_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.write.bytes.rate_vfw + vfwcds_vf0.abstract_vfw.network.incoming.packets_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.packets_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vsn.disk.read.bytes.rate_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.read.bytes.rate_vsn + vfwcds_vf0.abstract_vsn.memory.resident_vsn: + - vfwcds_VF 0 + - abstract_vsn.memory.resident_vsn + vfwcds_vf0.abstract_vpg.disk.write.requests_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.write.requests_vpg + vfwcds_vf0.int_private1_network.end_point: + - vfwcds_VF 0 + - int_private1_network.end_point + vfwcds_vf0.abstract_vfw.memory_vfw: + - vfwcds_VF 0 + - abstract_vfw.memory_vfw + vfwcds_vf0.abstract_vfw.attachment_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.attachment_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vpg.disk.write.bytes_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.write.bytes_vpg + vfwcds_vf0.abstract_vpg.cpu_vpg: + - vfwcds_VF 0 + - abstract_vpg.cpu_vpg + vfwcds_vf0.abstract_vpg.network.incoming.bytes.rate_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.bytes.rate_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.network.outgoing.bytes_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.bytes_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.memory.usage_vfw: + - vfwcds_VF 0 + - abstract_vfw.memory.usage_vfw + vfwcds_vf0.abstract_vpg.attachment_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.attachment_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vsn.disk.read.bytes_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.read.bytes_vsn + vfwcds_vf0.abstract_vsn.disk.write.requests_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.write.requests_vsn + vfwcds_vf0.int_private2_network.end_point: + - vfwcds_VF 0 + - int_private2_network.end_point + vfwcds_vf0.abstract_vsn.disk.device.read.requests_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.read.requests_vsn + vfwcds_vf0.abstract_vfw.endpoint_vfw: + - vfwcds_VF 0 + - abstract_vfw.endpoint_vfw + vfwcds_vf0.abstract_vpg.network.outgoing.bytes_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outgoing.bytes_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vpg.network.incoming.packets.rate_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.incoming.packets.rate_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vpg.network.outgoing.bytes_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outgoing.bytes_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vsn.network.outpoing.packets_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outpoing.packets_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vpg.binding_vpg: + - vfwcds_VF 0 + - abstract_vpg.binding_vpg + vfwcds_vf0.abstract_vpg.disk.usage_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.usage_vpg + vfwcds_vf0.abstract_vfw.disk.write.requests.rate_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.write.requests.rate_vfw + vfwcds_vf0.abstract_vsn.binding_vsn: + - vfwcds_VF 0 + - abstract_vsn.binding_vsn + vfwcds_vf0.abstract_vpg.disk.write.requests.rate_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.write.requests.rate_vpg + vfwcds_vf0.abstract_vsn.disk.latency_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.latency_vsn + vfwcds_vf0.abstract_vpg.memory_vpg: + - vfwcds_VF 0 + - abstract_vpg.memory_vpg + vfwcds_vf0.abstract_vsn.network.outgoing.bytes_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.outgoing.bytes_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vfw.network.outpoing.packets_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outpoing.packets_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.device.read.bytes.rate_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.read.bytes.rate_vfw + vfwcds_vf0.abstract_vsn.disk.ephemeral.size_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.ephemeral.size_vsn + vfwcds_vf0.abstract_vfw.binding_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.binding_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vpg.feature_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.feature_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vpg.binding_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.binding_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.device.allocation_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.allocation_vfw + vfwcds_vf0.abstract_vpg.scalable_vpg: + - vfwcds_VF 0 + - abstract_vpg.scalable_vpg + vfwcds_vf0.abstract_vsn.attachment_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.attachment_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vpg.network.outpoing.packets_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outpoing.packets_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vsn.memory.usage_vsn: + - vfwcds_VF 0 + - abstract_vsn.memory.usage_vsn + vfwcds_vf0.abstract_vsn.network.incoming.bytes.rate_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.bytes.rate_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vsn.memory_vsn: + - vfwcds_VF 0 + - abstract_vsn.memory_vsn + vfwcds_vf0.abstract_vpg.disk.device.iops_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.iops_vpg + vfwcds_vf0.int_private1_network.attachment: + - vfwcds_VF 0 + - int_private1_network.attachment + vfwcds_vf0.abstract_vfw.disk.ephemeral.size_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.ephemeral.size_vfw + vfwcds_vf0.abstract_vsn.network.incoming.bytes_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.bytes_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vsn.attachment_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.attachment_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.device.write.requests.rate_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.write.requests.rate_vfw + vfwcds_vf0.abstract_vsn.disk.allocation_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.allocation_vsn + vfwcds_vf0.abstract_vfw.network.incoming.bytes_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.bytes_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.packets.rate_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vsn.network.incoming.bytes_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.bytes_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vpg.cpu_util_vpg: + - vfwcds_VF 0 + - abstract_vpg.cpu_util_vpg + vfwcds_vf0.abstract_vpg.disk.device.usage_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.usage_vpg + vfwcds_vf0.abstract_vfw.disk.usage_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.usage_vfw + vfwcds_vf0.abstract_vsn.disk.device.write.bytes.rate_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.write.bytes.rate_vsn + vfwcds_vf0.abstract_vpg.network.outgoing.packets.rate_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.network.outgoing.packets.rate_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vfw.disk.allocation_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.allocation_vfw + vfwcds_vf0.abstract_vfw.network.incoming.packets.rate_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.packets.rate_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vfw.network.incoming.bytes.rate_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.incoming.bytes.rate_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vsn.disk.read.requests_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.read.requests_vsn + vfwcds_vf0.abstract_vsn.network.incoming.bytes.rate_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.bytes.rate_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vfw.host_vfw: + - vfwcds_VF 0 + - abstract_vfw.host_vfw + vfwcds_vf0.abstract_vsn.network.incoming.packets_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.packets_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vpg.disk.read.requests_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.read.requests_vpg + vfwcds_vf0.abstract_vsn.disk.device.read.requests.rate_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.device.read.requests.rate_vsn + vfwcds_vf0.abstract_vfw.port_mirroring_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.port_mirroring_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.device.write.bytes_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.write.bytes_vfw + vfwcds_vf0.int_private2_network.attachment: + - vfwcds_VF 0 + - int_private2_network.attachment + vfwcds_vf0.abstract_vfw.network.outgoing.packets.rate_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.packets.rate_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vfw.vcpus_vfw: + - vfwcds_VF 0 + - abstract_vfw.vcpus_vfw + vfwcds_vf0.abstract_vpg.disk.read.bytes_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.read.bytes_vpg + vfwcds_vf0.abstract_vpg.disk.ephemeral.size_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.ephemeral.size_vpg + vfwcds_vf0.abstract_vsn.network.incoming.packets_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.network.incoming.packets_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vpg.endpoint_vpg: + - vfwcds_VF 0 + - abstract_vpg.endpoint_vpg + vfwcds_vf0.abstract_vpg.forwarder_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.forwarder_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.iops_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.iops_vfw + vfwcds_vf0.abstract_vpg.cpu.delta_vpg: + - vfwcds_VF 0 + - abstract_vpg.cpu.delta_vpg + vfwcds_vf0.abstract_vpg.disk.device.capacity_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.capacity_vpg + vfwcds_vf0.abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.network.outgoing.bytes.rate_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vsn.cpu_vsn: + - vfwcds_VF 0 + - abstract_vsn.cpu_vsn + vfwcds_vf0.abstract_vpg.disk.device.allocation_vpg: + - vfwcds_VF 0 + - abstract_vpg.disk.device.allocation_vpg + vfwcds_vf0.abstract_vsn.disk.write.bytes_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.write.bytes_vsn + vfwcds_vf0.abstract_vsn.disk.write.bytes.rate_vsn: + - vfwcds_VF 0 + - abstract_vsn.disk.write.bytes.rate_vsn + vfwcds_vf0.abstract_vfw.disk.device.write.requests_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.device.write.requests_vfw + vfwcds_vf0.abstract_vsn.port_mirroring_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.port_mirroring_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vfw.disk.write.requests_vfw: + - vfwcds_VF 0 + - abstract_vfw.disk.write.requests_vfw + requirements: + vfwcds_vf0.abstract_vpg.dependency_vpg: + - vfwcds_VF 0 + - abstract_vpg.dependency_vpg + vfwcds_vf0.abstract_vpg.link_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.link_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vsn.local_storage_vsn: + - vfwcds_VF 0 + - abstract_vsn.local_storage_vsn + vfwcds_vf0.abstract_vfw.dependency_vfw: + - vfwcds_VF 0 + - abstract_vfw.dependency_vfw + vfwcds_vf0.abstract_vfw.local_storage_vfw: + - vfwcds_VF 0 + - abstract_vfw.local_storage_vfw + vfwcds_vf0.int_private2_network.dependency: + - vfwcds_VF 0 + - int_private2_network.dependency + vfwcds_vf0.int_private1_network.dependency: + - vfwcds_VF 0 + - int_private1_network.dependency + vfwcds_vf0.abstract_vfw.dependency_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.dependency_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vpg.dependency_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.dependency_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vfw.dependency_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.dependency_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vpg.dependency_vpg_vpg_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vpg.dependency_vpg_vpg_onap_private_port_0 + vfwcds_vf0.abstract_vsn.link_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.link_vsn_vsn_onap_private_port_0 + vfwcds_vf0.abstract_vpg.link_vpg_vpg_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vpg.link_vpg_vpg_int_private1_port_0 + vfwcds_vf0.abstract_vfw.link_vfw_vfw_int_private1_port_0: + - vfwcds_VF 0 + - abstract_vfw.link_vfw_vfw_int_private1_port_0 + vfwcds_vf0.abstract_vpg.local_storage_vpg: + - vfwcds_VF 0 + - abstract_vpg.local_storage_vpg + vfwcds_vf0.abstract_vfw.link_vfw_vfw_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vfw.link_vfw_vfw_int_private2_port_0 + vfwcds_vf0.abstract_vsn.dependency_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.dependency_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vsn.link_vsn_vsn_int_private2_port_0: + - vfwcds_VF 0 + - abstract_vsn.link_vsn_vsn_int_private2_port_0 + vfwcds_vf0.abstract_vsn.dependency_vsn: + - vfwcds_VF 0 + - abstract_vsn.dependency_vsn + vfwcds_vf0.abstract_vfw.link_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.link_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vfw.dependency_vfw_vfw_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vfw.dependency_vfw_vfw_onap_private_port_0 + vfwcds_vf0.abstract_vsn.dependency_vsn_vsn_onap_private_port_0: + - vfwcds_VF 0 + - abstract_vsn.dependency_vsn_vsn_onap_private_port_0 diff --git a/tests/data/test.csar b/tests/data/test.csar Binary files differnew file mode 100644 index 0000000..adedc40 --- /dev/null +++ b/tests/data/test.csar diff --git a/tests/data/test_so_service_data.yaml b/tests/data/test_so_service_data.yaml new file mode 100644 index 0000000..594ff17 --- /dev/null +++ b/tests/data/test_so_service_data.yaml @@ -0,0 +1,35 @@ +myservice: + subscription_service_type: myservice + vnfs: + - model_name: myvfmodel + instance_name: myfirstvnf + parameters: + param1: value1 + processing_priority: 1 + vf_modules: + - instance_name: mysecondvfm + model_name: base + processing_priority: 2 + parameters: + param-vfm1: value-vfm1 + - instance_name: myfirstvfm + model_name: base + processing_priority: 1 + parameters: + param-vfm1: value-vfm1 + - model_name: myvfmodel + instance_name: mysecondvnf + parameters: + param1: value1 + processing_priority: 2 + vf_modules: + - instance_name: myfirstvfm + model_name: base + processing_priority: 1 + parameters: + param-vfm1: value-vfm1 + - instance_name: mysecondvfm + model_name: base + processing_priority: 2 + parameters: + param-vfm1: value-vfm1
\ No newline at end of file diff --git a/tests/data/tests_settings.py b/tests/data/tests_settings.py new file mode 100644 index 0000000..09437b6 --- /dev/null +++ b/tests/data/tests_settings.py @@ -0,0 +1,15 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +AAI_URL = "http://tests.settings.py:1234" +TEST_VALUE = "test" diff --git a/tests/data/utils_load_json_file_test.json b/tests/data/utils_load_json_file_test.json new file mode 100644 index 0000000..3b4000d --- /dev/null +++ b/tests/data/utils_load_json_file_test.json @@ -0,0 +1 @@ +{"event":{"test1":"val1"}} diff --git a/tests/data/vLB_CBA_Python.zip b/tests/data/vLB_CBA_Python.zip Binary files differnew file mode 100755 index 0000000..ddd41ac --- /dev/null +++ b/tests/data/vLB_CBA_Python.zip diff --git a/tests/test_aai_bulk.py b/tests/test_aai_bulk.py new file mode 100644 index 0000000..0567055 --- /dev/null +++ b/tests/test_aai_bulk.py @@ -0,0 +1,90 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.bulk import AaiBulk, AaiBulkRequest, AaiBulkResponse + + +BULK_RESPONSES = { + "operation-responses": [ + { + "action": "put", + "uri": "test-uri", + "response-status-code": 400, + "response-body": None + }, + { + "action": "post", + "uri": "test-uri", + "response-status-code": 201, + "response-body": "blabla" + } + ] +} + + +@mock.patch("onapsdk.aai.bulk.AaiBulk.send_message_json") +def test_aai_bulk(mock_send_message_json): + assert AaiBulk().url.endswith("bulk") + mock_send_message_json.return_value = BULK_RESPONSES + responses = list(AaiBulk.single_transaction( + [ + AaiBulkRequest( + action="post", + uri="test-uri", + body={"blabla: blabla"} + ), + AaiBulkRequest( + action="get", + uri="test-uri", + body={} + ) + ] + )) + assert len(responses) == 2 + resp_1, resp_2 = responses + assert resp_1.action == "put" + assert resp_1.uri == "test-uri" + assert resp_1.status_code == 400 + assert resp_1.body is None + assert resp_2.action == "post" + assert resp_2.uri == "test-uri" + assert resp_2.status_code == 201 + assert resp_2.body == "blabla" + + # Check if requests was splitted into chunks for generator + mock_send_message_json.reset_mock() + responses = list(AaiBulk.single_transaction( + ( + AaiBulkRequest( + action="post", + uri=f"test-uri-{i}", + body={"blabla: blabla"} + ) for i in range(31) + ) + )) + assert mock_send_message_json.call_count == 2 + + # Check if requests was splitted into chunks for list + mock_send_message_json.reset_mock() + responses = list(AaiBulk.single_transaction( + [ + AaiBulkRequest( + action="post", + uri=f"test-uri-{i}", + body={"blabla: blabla"} + ) for i in range(31) + ] + )) + assert mock_send_message_json.call_count == 2 diff --git a/tests/test_aai_cloud_region.py b/tests/test_aai_cloud_region.py new file mode 100644 index 0000000..a821090 --- /dev/null +++ b/tests/test_aai_cloud_region.py @@ -0,0 +1,71 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.cloud_infrastructure.cloud_region import CloudRegion, Tenant +from onapsdk.exceptions import ResourceNotFound + + +COUNT = { + "results":[ + { + "cloud-region":2 + } + ] +} + + +@mock.patch("onapsdk.aai.cloud_infrastructure.cloud_region.AaiResource.relationships", new_callable=mock.PropertyMock) +@mock.patch("onapsdk.aai.cloud_infrastructure.cloud_region.Complex.get_by_physical_location_id") +def test_cloud_region_complex_property(mock_complex_get, mock_relationships): + cr = CloudRegion("test_cloud_owner", "test_cloud_region_id", False, False) + + mock_relationships.return_value = [] + assert cr.complex is None + + mock_relationships.return_value = [mock.MagicMock()] + assert cr.complex is None + + relationship_mock = mock.MagicMock() + relationship_mock.related_to = "complex" + relationship_mock.get_relationship_data.return_value = None + mock_relationships.return_value = [relationship_mock] + assert cr.complex is None + + relationship_mock.get_relationship_data.return_value = "123" + mock_complex_get.side_effect = ResourceNotFound + assert cr.complex is None + + mock_complex_get.side_effect = None + mock_complex_get.return_value = mock.MagicMock() + assert cr.complex is not None + + mock_relationships.side_effect = ResourceNotFound + assert cr.complex is None + +@mock.patch("onapsdk.aai.cloud_infrastructure.cloud_region.CloudRegion.tenants", new_callable=mock.PropertyMock) +def test_cloud_region_get_tenants_by_name(mock_tenants): + cr = CloudRegion("test_cloud_owner", "test_cloud_region_id", False, False) + mock_tenants.return_value = iter([ + Tenant(cloud_region="test_cloud_region_id",tenant_id="test-tenant",tenant_name="test-tenant") + ]) + tenants = list(cr.get_tenants_by_name("test-tenant")) + assert len(tenants) == 1 + assert isinstance(tenants[0], Tenant) + assert tenants[0].name == "test-tenant" + +@mock.patch("onapsdk.aai.cloud_infrastructure.cloud_region.CloudRegion.send_message_json") +def test_cloud_region_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert CloudRegion.count() == 2 diff --git a/tests/test_aai_complex.py b/tests/test_aai_complex.py new file mode 100644 index 0000000..13d2cf5 --- /dev/null +++ b/tests/test_aai_complex.py @@ -0,0 +1,138 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.cloud_infrastructure import Complex +from onapsdk.aai.cloud_infrastructure import CloudRegion + + +COMPLEXES = { + "complex":[ + { + "physical-location-id":"integration_test_complex", + "data-center-code":"1234", + "complex-name":"integration_test_complex", + "identity-url":"", + "resource-version":"1588244056133", + "physical-location-type":"", + "street1":"", + "street2":"", + "city":"", + "state":"", + "postal-code":"", + "country":"", + "region":"", + "latitude":"", + "longitude":"", + "elevation":"", + "lata":"", + "time-zone":"", + "data-owner":"", + "data-source":"", + "data-source-version":"" + } + ] +} + + +COMPLEXES_COUNT = { + "results":[ + { + "complex":12 + } + ] +} + + +@mock.patch.object(Complex, "send_message") +def test_complex(mock_send_message): + cmplx = Complex(name="test_complex_name", + physical_location_id="test_location_id", + resource_version="1234") + assert cmplx.name == "test_complex_name" + assert cmplx.physical_location_id == "test_location_id" + assert cmplx.url == (f"{Complex.base_url}{Complex.api_version}/cloud-infrastructure/" + "complexes/complex/test_location_id") + + cmplx2 = Complex.create(name="test_complex_name", + physical_location_id="test_location_id") + mock_send_message.assert_called_once() + assert cmplx2.name == "test_complex_name" + assert cmplx2.physical_location_id == "test_location_id" + assert cmplx2.url == (f"{Complex.base_url}{Complex.api_version}/cloud-infrastructure/" + "complexes/complex/test_location_id") + method, _, url = mock_send_message.call_args[0] + assert method == "PUT" + assert url == (f"{Complex.base_url}{Complex.api_version}/cloud-infrastructure/" + "complexes/complex/test_location_id") + + +@mock.patch.object(Complex, "send_message_json") +def test_complex_get_all(mock_send_message_json): + mock_send_message_json.return_value = COMPLEXES + complexes = list(Complex.get_all()) + assert len(complexes) == 1 + cmplx = complexes[0] + assert cmplx.name == "integration_test_complex" + assert cmplx.physical_location_id == "integration_test_complex" + + +@mock.patch.object(CloudRegion, "add_relationship") +def test_cloud_region_link_to_complex(mock_add_rel): + """Test Cloud Region linking with Complex. + + Test Relationship object creation + """ + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + cmplx = Complex(name="test_complex_name", + physical_location_id="test_location_id", + resource_version="1234") + cloud_region.link_to_complex(cmplx) + mock_add_rel.assert_called_once() + relationship = mock_add_rel.call_args[0][0] + assert relationship.related_to == "complex" + assert relationship.related_link == (f"aai/v13/cloud-infrastructure/complexes/" + f"complex/test_location_id") + assert len(relationship.relationship_data) == 2 + + +@mock.patch.object(Complex, "send_message_json") +def test_complex_get_by_physical_location_id(mock_send_message_json): + """Test complex get_by_physical_location_id url creation.""" + Complex.get_by_physical_location_id("test") + assert mock_send_message_json.called_once_with( + "GET", + "Get complex with physical location id: test", + f"{Complex.base_url}{Complex.api_version}/cloud-infrastructure/" + f"complexes/complex/test" + ) + +@mock.patch.object(Complex, "send_message") +def test_complex_delete(mock_send_message): + cmplx = Complex(physical_location_id="test_location_id", + resource_version="1234") + cmplx.delete() + mock_send_message.assert_called_once_with( + "DELETE", + "Delete test_location_id complex", + f"{cmplx.url}?resource-version={cmplx.resource_version}" + ) + +@mock.patch.object(Complex, "send_message_json") +def test_complex_count(mock_send_message_json): + mock_send_message_json.return_value = COMPLEXES_COUNT + assert Complex.count() == 12 diff --git a/tests/test_aai_customer.py b/tests/test_aai_customer.py new file mode 100644 index 0000000..7e427bd --- /dev/null +++ b/tests/test_aai_customer.py @@ -0,0 +1,580 @@ +"""Test A&AI Customer module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from onapsdk.aai.business import Customer, ServiceSubscription +from onapsdk.aai.cloud_infrastructure import CloudRegion, Tenant +from onapsdk.msb.multicloud import Multicloud +from onapsdk.sdc.service import Service as SdcService +from onapsdk.exceptions import ParameterError, ResourceNotFound + + +SIMPLE_CUSTOMER = { + "customer": [ + { + "global-customer-id": "generic", + "subscriber-name": "generic", + "subscriber-type": "INFRA", + "resource-version": "1561218640404", + } + ] +} + + +SERVICE_SUBSCRIPTION = { + "service-subscription": [ + { + "service-type": "freeradius", + "resource-version": "1562591478146", + "relationship-list": { + "relationship": [ + { + "related-to": "tenant", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/cloud-infrastructure/cloud-regions/cloud-region/OPNFV/RegionOne/tenants/tenant/4bdc6f0f2539430f9428c852ba606808", + "relationship-data": [ + { + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "OPNFV", + }, + { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "RegionOne", + }, + { + "relationship-key": "tenant.tenant-id", + "relationship-value": "4bdc6f0f2539430f9428c852ba606808", + }, + ], + "related-to-property": [ + { + "property-key": "tenant.tenant-name", + "property-value": "onap-dublin-daily-vnfs", + } + ], + } + ] + }, + }, + {"service-type": "ims"}, + ] +} + + +CUSTOMERS = { + "customer": [ + { + "subscriber-name": "generic", + "subscriber-type": "INFRA", + "global-customer-id": "generic", + "resource-version": "1581510772967", + } + ] +} + + +SIMPLE_CUSTOMER_2 = { + "global-customer-id": "generic", + "subscriber-name": "generic", + "subscriber-type": "INFRA", + "resource-version": "1561218640404", +} + + +SERVICE_INSTANCES = { + "service-instance":[ + { + "service-instance-id":"5410bf79-2aa3-450e-a324-ec5630dc18cf", + "service-instance-name":"test", + "environment-context":"General_Revenue-Bearing", + "workload-context":"Production", + "model-invariant-id":"2a51a89b-6f94-4417-8831-c468fb30ed02", + "model-version-id":"92a82807-b483-4579-86b1-c79b1286aab4", + "resource-version":"1589457727708", + "orchestration-status":"Active", + "relationship-list":{ + "relationship":[ + { + "related-to":"owning-entity", + "relationship-label":"org.onap.relationships.inventory.BelongsTo", + "related-link":"/aai/v16/business/owning-entities/owning-entity/ff6c945f-89ab-4f14-bafd-0cdd6eac791a", + "relationship-data":[ + { + "relationship-key":"owning-entity.owning-entity-id", + "relationship-value":"ff6c945f-89ab-4f14-bafd-0cdd6eac791a" + } + ] + }, + { + "related-to":"project", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v16/business/projects/project/python_onap_sdk_project", + "relationship-data":[ + { + "relationship-key":"project.project-name", + "relationship-value":"python_onap_sdk_project" + } + ] + } + ] + } + } + ] +} + + +SERVICE_SUBSCRIPTION_RELATIONSHIPS = { + "relationship": [ + { + "related-to": "tenant", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/cloud-infrastructure/cloud-regions/cloud-region/OPNFV/RegionOne/tenants/tenant/4bdc6f0f2539430f9428c852ba606808", + "relationship-data": [ + { + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "OPNFV", + }, + { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "RegionOne", + }, + { + "relationship-key": "tenant.tenant-id", + "relationship-value": "4bdc6f0f2539430f9428c852ba606808", + }, + ], + "related-to-property": [ + { + "property-key": "tenant.tenant-name", + "property-value": "onap-dublin-daily-vnfs", + } + ], + } + ] +} + + +CLOUD_REGION = { + "cloud-region": [ + { + "cloud-owner": "OPNFV", + "cloud-region-id": "RegionOne", + "cloud-type": "openstack", + "owner-defined-type": "N/A", + "cloud-region-version": "pike", + "identity-url": "http://msb-iag.onap:80/api/multicloud-pike/v0/OPNFV_RegionOne/identity/v2.0", + "cloud-zone": "OPNFV LaaS", + "complex-name": "Cruguil", + "resource-version": "1561217827955", + "orchestration-disabled": True, + "in-maint": False, + "relationship-list": { + "relationship": [ + { + "related-to": "complex", + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "related-link": "/aai/v13/cloud-infrastructure/complexes/complex/cruguil", + "relationship-data": [ + { + "relationship-key": "complex.physical-location-id", + "relationship-value": "cruguil", + } + ], + } + ] + }, + } + ] +} + + +TENANT = { + "tenant-id": "4bdc6f0f2539430f9428c852ba606808", + "tenant-name": "onap-dublin-daily-vnfs", + "resource-version": "1562591004273", + "relationship-list": { + "relationship": [ + { + "related-to": "service-subscription", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/business/customers/customer/generic/service-subscriptions/service-subscription/freeradius", + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "generic", + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "freeradius", + }, + ], + }, + { + "related-to": "service-subscription", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/business/customers/customer/generic/service-subscriptions/service-subscription/ims", + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "generic", + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "ims", + }, + ], + }, + { + "related-to": "service-subscription", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/business/customers/customer/generic/service-subscriptions/service-subscription/ubuntu16", + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "generic", + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "ubuntu16", + }, + ], + }, + ] + }, +} + + +CUSTOMERS_COUNT = { + "results":[ + { + "customer":12 + } + ] +} + + +@mock.patch.object(Customer, 'send_message_json') +def test_customer_service_tenant_relations(mock_send): + """Test the retrieval of service/tenant relations in A&AI.""" + mock_send.return_value = SIMPLE_CUSTOMER + customer = next(Customer.get_all()) + mock_send.return_value = SERVICE_SUBSCRIPTION + res = list(customer.service_subscriptions) + assert len(res) == 2 + assert res[0].service_type == "freeradius" + + +@mock.patch.object(Customer, "send_message_json") +def test_customers_get_all(mock_send): + """Test get_all Customer class method.""" + mock_send.return_value = {} + customers = list(Customer.get_all()) + assert len(customers) == 0 + + mock_send.return_value = CUSTOMERS + customers = list(Customer.get_all()) + assert len(customers) == 1 + + +@mock.patch.object(Customer, "send_message_json") +def test_customer_get_service_subscription_by_service_type(mock_send): + """Test Customer's get_service_subscription_by_service_type method.""" + mock_send.return_value = CUSTOMERS + customer = next(Customer.get_all()) + + mock_send.return_value = SERVICE_SUBSCRIPTION + service_subscription = customer.get_service_subscription_by_service_type("freeradius") + assert service_subscription.service_type == "freeradius" + + +@mock.patch.object(Customer, "send_message_json") +@mock.patch.object(ServiceSubscription, "send_message_json") +def test_customer_service_subscription_service_instance(mock_send_serv_sub, mock_send): + """Test Customer's service subscription service instances.""" + mock_send.return_value = CUSTOMERS + customer = next(Customer.get_all()) + mock_send.return_value = SERVICE_SUBSCRIPTION + service_subscription = customer.get_service_subscription_by_service_type("freeradius") + + mock_send_serv_sub.return_value = SERVICE_INSTANCES + service_instances = list(service_subscription.service_instances) + assert len(service_instances) == 1 + service_instance = service_instances[0] + assert service_instance.instance_name == "test" + assert service_instance.instance_id == "5410bf79-2aa3-450e-a324-ec5630dc18cf" + assert service_instance.service_subscription == service_subscription + assert service_instance.url == (f"{service_subscription.url}/service-instances/" + f"service-instance/{service_instance.instance_id}") + + +@mock.patch.object(Customer, "send_message_json") +@mock.patch.object(ServiceSubscription, "send_message_json") +@mock.patch.object(CloudRegion, "send_message_json") +def test_customer_service_subscription_cloud_region(mock_cloud_region, mock_send_serv_sub, mock_send): + """Test Customer's service subscription cloud region object.""" + mock_send.return_value = CUSTOMERS + customer = next(Customer.get_all()) + mock_send.return_value = SERVICE_SUBSCRIPTION + service_subscription = customer.get_service_subscription_by_service_type("freeradius") + + mock_send_serv_sub.return_value = {} + relationships = list(service_subscription.relationships) + assert len(relationships) == 0 + with pytest.raises(ParameterError): + service_subscription.cloud_region + with pytest.raises(ParameterError): + service_subscription.tenant + with pytest.raises(StopIteration): + next(service_subscription.cloud_regions) + with pytest.raises(StopIteration): + next(service_subscription.tenants) + + mock_cloud_region.return_value = CLOUD_REGION + mock_send_serv_sub.return_value = SERVICE_SUBSCRIPTION_RELATIONSHIPS + relationships = list(service_subscription.relationships) + assert len(relationships) == 1 + cloud_region = next(service_subscription.cloud_regions) + assert cloud_region.cloud_owner == "OPNFV" + assert cloud_region.cloud_region_id == "RegionOne" + assert cloud_region.cloud_type == "openstack" + + mock_cloud_region.side_effect = ResourceNotFound + with pytest.raises(StopIteration): + next(service_subscription.tenants) + mock_cloud_region.side_effect = [CLOUD_REGION, TENANT] + tenant = next(service_subscription.tenants) + assert tenant.tenant_id == "4bdc6f0f2539430f9428c852ba606808" + assert tenant.name == "onap-dublin-daily-vnfs" + + +@mock.patch.object(Customer, "send_message_json") +def test_customer_get_by_global_customer_id(mock_send): + """Test Customer's get_by_global_customer_id method.""" + mock_send.return_value = SIMPLE_CUSTOMER_2 + customer = Customer.get_by_global_customer_id("generic") + assert customer.global_customer_id == "generic" + assert customer.subscriber_name == "generic" + assert customer.subscriber_type == "INFRA" + assert customer.resource_version is not None + + +@mock.patch.object(Customer, "send_message") +@mock.patch.object(Customer, "send_message_json") +def test_customer_create(mock_send_json, mock_send): + """Test Customer's create method.""" + mock_send_json.return_value = SIMPLE_CUSTOMER_2 + customer = Customer.create("generic", "generic", "INFRA") + assert customer.global_customer_id == "generic" + assert customer.subscriber_name == "generic" + assert customer.subscriber_type == "INFRA" + assert customer.resource_version is not None + + customer = Customer.create("generic", "generic", "INFRA", service_subscriptions=["test-service-type"]) + assert customer.global_customer_id == "generic" + assert customer.subscriber_name == "generic" + assert customer.subscriber_type == "INFRA" + assert customer.resource_version is not None + + +@mock.patch.object(Customer, "send_message") +def test_customer_delete(mock_send): + """Test Customer's delete method.""" + customer = Customer("test", "test", "test", "test") + customer.delete() + mock_send.assert_called_once_with( + "DELETE", + "Delete customer", + customer.url + ) + + +def test_customer_url(): + """Test Customer's url property.""" + customer = Customer("generic", "generic", "INFRA") + assert customer.url == (f"{customer.base_url}{customer.api_version}/business/customers/" + f"customer/{customer.global_customer_id}?" + f"resource-version={customer.resource_version}") + + +@mock.patch.object(ServiceSubscription, "add_relationship") +def test_service_subscription_link_cloud_region_and_tenant(mock_add_rel): + """Test service subscription linking with cloud region and tenant. + + Test Relationship object creation + """ + service_subscription = ServiceSubscription(customer=None, + service_type="test_service_type", + resource_version="test_resource_version") + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + tenant = Tenant(cloud_region=cloud_region, + tenant_id="test_tenant_id", + tenant_name="test_tenant_name") + service_subscription.link_to_cloud_region_and_tenant(cloud_region, tenant) + mock_add_rel.assert_called_once() + relationship = mock_add_rel.call_args[0][0] + assert relationship.related_to == "tenant" + assert relationship.related_link == tenant.url + assert len(relationship.relationship_data) == 3 + + +@mock.patch.object(Customer, "send_message_json") +@mock.patch.object(Customer, "send_message") +def test_customer_subscribe_service(mock_send_message, mock_send_message_json): + customer = Customer(global_customer_id="test_customer_id", + subscriber_name="test_subscriber_name", + subscriber_type="test_subscriber_type") + mock_send_message_json.side_effect = (ResourceNotFound, SERVICE_SUBSCRIPTION) + customer.subscribe_service("test_service") + + +#test the Cloud Region Class +AVAILABILITY_ZONE = { + "availability-zone-name":"OPNFV LaaS", + "hypervisor-type":"1234", + "operational-status":"working", + "resource-version":"version1.0" +} + +AVAILABILITY_ZONES = { + "availability-zone":[ + { + "availability-zone-name":"OPNFV LaaS", + "hypervisor-type":"1234", + "operational-status":"working", + "resource-version":"version1.0" + } + ] +} + + +@mock.patch.object(CloudRegion, "send_message_json") +def test_availability_zones(mock_send_message_json): + """Test Cloud Region property""" + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + mock_send_message_json.return_value = AVAILABILITY_ZONES + cloud_zones = cloud_region.availability_zones + zone1 = next(cloud_zones) + assert zone1.name == "OPNFV LaaS" + assert zone1.hypervisor_type == "1234" + +@mock.patch.object(CloudRegion, "send_message_json") +def test_get_availability_zone_from_name(mock_send_message_json): + """Test get Availability Zone by name""" + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + mock_send_message_json.return_value = AVAILABILITY_ZONE + availability_zone = cloud_region.get_availability_zone_by_name("OPNFV LaaS") + assert availability_zone.name == "OPNFV LaaS" + assert availability_zone.hypervisor_type == "1234" + assert availability_zone.resource_version == "version1.0" + +@mock.patch.object(CloudRegion, "send_message") +def test_add_availability_zone(mock_send_message): + """Test Cloud Region class method""" + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + cloud_region.add_availability_zone(availability_zone_name="test_zone", + availability_zone_hypervisor_type="1234") + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "PUT" + assert description == "Add availability zone to cloud region" + assert url == f"{cloud_region.url}/availability-zones/availability-zone/test_zone" + +@mock.patch.object(CloudRegion, "send_message") +def test_add_tenant_to_cloud(mock_send_message): + """Test Cloud Region class method""" + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + cloud_region.add_tenant(tenant_id="123456", tenant_name="test_tenant") + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "PUT" + assert description == "add tenant to cloud region" + assert url == f"{cloud_region.url}/tenants/tenant/123456" + + +@mock.patch.object(CloudRegion, "send_message") +def test_add_esr_system_info(mock_send_message): + """Test Cloud Region class method""" + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + cloud_region.add_esr_system_info(esr_system_info_id="123456", + user_name="test_user", + password="password", + system_type="test_type") + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "PUT" + assert description == "Add external system info to cloud region" + assert url == f"{cloud_region.url}/esr-system-info-list/esr-system-info/123456" + + +@mock.patch.object(Multicloud, "register_vim") +def test_register_to_multicloud(mock_register): + """Test register to multicloud""" + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + cloud_region.register_to_multicloud() + mock_register.assert_called_once() + + +@mock.patch.object(Multicloud, "unregister_vim") +def test_unregister_from_multicloud(mock_unregister): + """Test register to multicloud""" + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + cloud_region.unregister_from_multicloud() + mock_unregister.assert_called_once() + + +@mock.patch.object(CloudRegion, "send_message") +def test_delete_cloud_region(mock_send_message): + cloud_region = CloudRegion(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=True, + in_maint=False) + cloud_region.delete() + mock_send_message.assert_called_once() + method, descritption, url = mock_send_message.call_args[0] + assert method == "DELETE" + assert descritption == f"Delete cloud region test_cloud_region" + assert url == cloud_region.url + +@mock.patch.object(Customer, "send_message_json") +def test_customer_count(mock_send_message_json): + mock_send_message_json.return_value = CUSTOMERS_COUNT + assert Customer.count() == 12 + diff --git a/tests/test_aai_geo_region.py b/tests/test_aai_geo_region.py new file mode 100644 index 0000000..b33f77a --- /dev/null +++ b/tests/test_aai_geo_region.py @@ -0,0 +1,54 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest.mock import patch + +from onapsdk.aai.cloud_infrastructure.geo_region import GeoRegion + +GEO_REGIONS = { + "geo-region": [ + { + "geo-region-id": "123" + }, + { + "geo-region-id": "321" + } + ] +} + +GEO_REGION = { + "geo-region-id": "123", + "resource-version": "123" +} + +@patch("onapsdk.aai.cloud_infrastructure.geo_region.GeoRegion.send_message_json") +def test_geo_region_get_all(mock_send_message_json): + mock_send_message_json.return_value = {} + assert len(list(GeoRegion.get_all())) == 0 + + mock_send_message_json.return_value = GEO_REGIONS + assert len(list(GeoRegion.get_all())) == 2 + +@patch("onapsdk.aai.cloud_infrastructure.geo_region.GeoRegion.send_message_json") +def test_geo_region_get_by_region_id(mock_send_message_json): + mock_send_message_json.return_value = GEO_REGION + geo_region = GeoRegion.get_by_geo_region_id("123") + assert geo_region.geo_region_id == "123" + assert geo_region.resource_version == "123" + +@patch("onapsdk.aai.cloud_infrastructure.geo_region.GeoRegion.send_message") +@patch("onapsdk.aai.cloud_infrastructure.geo_region.GeoRegion.get_by_geo_region_id") +def test_geo_region_create(mock_get_geo_region_by_id, mock_send_message): + GeoRegion.create("123") + mock_send_message.assert_called_once() + assert mock_get_geo_region_by_id.called_once_with("123") diff --git a/tests/test_aai_line_of_business.py b/tests/test_aai_line_of_business.py new file mode 100644 index 0000000..1bf4672 --- /dev/null +++ b/tests/test_aai_line_of_business.py @@ -0,0 +1,82 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.business.line_of_business import LineOfBusiness + + +LINES_OF_BUSINESS = { + "line-of-business": [ + { + "line-of-business-name": "test-name", + "resource-version": "1234" + }, + { + "line-of-business-name": "test-name2", + "resource-version": "4321" + } + ] +} + + +COUNT = { + "results":[ + { + "line-of-business":1 + } + ] +} + + +@mock.patch("onapsdk.aai.business.line_of_business.LineOfBusiness.send_message_json") +def test_line_of_business_get_all(mock_send_message_json): + mock_send_message_json.return_value = {} + assert len(list(LineOfBusiness.get_all())) == 0 + + mock_send_message_json.return_value = LINES_OF_BUSINESS + lines_of_business = list(LineOfBusiness.get_all()) + assert len(lines_of_business) == 2 + lob1, lob2 = lines_of_business + assert lob1.name == "test-name" + assert lob1.resource_version == "1234" + assert lob2.name == "test-name2" + assert lob2.resource_version == "4321" + + +@mock.patch("onapsdk.aai.business.line_of_business.LineOfBusiness.send_message_json") +def test_line_of_business_get_by_name(mock_send): + LineOfBusiness.get_by_name(name="test-name") + mock_send.assert_called_once_with("GET", + "Get test-name line of business", + "https://aai.api.sparky.simpledemo.onap.org:30233/aai/v23/business/lines-of-business/line-of-business/test-name") + + +@mock.patch("onapsdk.aai.business.line_of_business.LineOfBusiness.send_message") +@mock.patch("onapsdk.aai.business.line_of_business.LineOfBusiness.get_by_name") +def test_line_of_business_create(_, mock_send): + LineOfBusiness.create(name="test-name") + mock_send.assert_called_once_with("PUT", + "Declare A&AI line of business", + "https://aai.api.sparky.simpledemo.onap.org:30233/aai/v23/business/lines-of-business/line-of-business/test-name", + data='{\n "line-of-business-name": "test-name"\n}') + + +@mock.patch("onapsdk.aai.business.line_of_business.LineOfBusiness.send_message_json") +def test_line_of_business_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert LineOfBusiness.count() == 1 + +def test_line_of_business_url(): + line_of_business = LineOfBusiness(name="test-lob", resource_version="123") + assert line_of_business.name in line_of_business.url diff --git a/tests/test_aai_network.py b/tests/test_aai_network.py new file mode 100644 index 0000000..7196d5a --- /dev/null +++ b/tests/test_aai_network.py @@ -0,0 +1,159 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.business import NetworkInstance +from onapsdk.so.deletion import NetworkDeletionRequest + + +NETWORK_INSTANCE = { + 'network-id': '49dab38b-3a5b-47e5-9cd6-b8d069d6109d', + 'network-name': 'Python_ONAP_SDK_network_instance_0b4308ca-3fe0-4af1-9c4e-ed2c816b9496', + 'is-bound-to-vpn': False, + 'resource-version': '1593162237842', + 'orchestration-status': 'Inventoried', + 'model-invariant-id': 'cdbb2169-e638-4aab-a4e9-b9d2d6d62b04', + 'model-version-id': '51789f7b-5ffc-4c12-ac87-02363fdb40b1', + 'model-customization-id': 'db9c9a6c-2a1c-4cdd-8fbc-e10448d0e4cc', + 'is-provider-network': False, + 'is-shared-network': False, + 'is-external-network': False, + 'relationship-list': { + 'relationship': [ + { + 'related-to': 'service-instance', + 'relationship-label': 'org.onap.relationships.inventory.ComposedOf', + 'related-link': '/aai/v19/business/customers/customer/TestCustomer/service-subscriptions/service-subscription/vFW_with_net/service-instances/service-instance/72fd9ee9-077f-4d3d-8e86-08ed24514802', + 'relationship-data': [ + { + 'relationship-key': 'customer.global-customer-id', + 'relationship-value': 'TestCustomer' + }, + { + 'relationship-key': 'service-subscription.service-type', + 'relationship-value': 'vFW_with_net' + }, + { + 'relationship-key': 'service-instance.service-instance-id', + 'relationship-value': '72fd9ee9-077f-4d3d-8e86-08ed24514802' + } + ], + 'related-to-property': [ + { + 'property-key': 'service-instance.service-instance-name', + 'property-value': 'Python_ONAP_SDK_service_instance_7be66d06-c466-46cf-b84a-cd7af2d633ed' + } + ] + }, + { + 'related-to': 'cloud-region', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/TestCloudOwner/RegionOne', + 'relationship-data': [ + { + 'relationship-key': 'cloud-region.cloud-owner', + 'relationship-value': 'TestCloudOwner' + }, + { + 'relationship-key': 'cloud-region.cloud-region-id', + 'relationship-value': 'RegionOne' + } + ], + 'related-to-property': [ + { + 'property-key': 'cloud-region.owner-defined-type', + 'property-value': '' + } + ] + }, + { + 'related-to': 'line-of-business', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/business/lines-of-business/line-of-business/Test-BusinessLine', + 'relationship-data': [ + { + 'relationship-key': 'line-of-business.line-of-business-name', + 'relationship-value': 'Test-BusinessLine' + } + ] + }, + { + 'related-to': 'tenant', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/TestCloudOwner/RegionOne/tenants/tenant/89788fdf49514f94963b12a6c0cfdc71', + 'relationship-data': [ + { + 'relationship-key': 'cloud-region.cloud-owner', + 'relationship-value': 'TestCloudOwner' + }, + { + 'relationship-key': 'cloud-region.cloud-region-id', + 'relationship-value': 'RegionOne' + }, + { + 'relationship-key': 'tenant.tenant-id', + 'relationship-value': '89788fdf49514f94963b12a6c0cfdc71' + } + ], + 'related-to-property': [ + { + 'property-key': 'tenant.tenant-name', + 'property-value': 'test-tenant' + } + ] + }, + { + 'related-to': 'platform', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/business/platforms/platform/Test-Platform', + 'relationship-data': [ + { + 'relationship-key': 'platform.platform-name', + 'relationship-value': 'Test-Platform' + } + ] + } + ] + } +} + + +def test_create_network_instance_from_api_response(): + service_instance = mock.MagicMock() + network_instance = NetworkInstance.create_from_api_response( + NETWORK_INSTANCE, + service_instance + ) + assert network_instance.network_name == "Python_ONAP_SDK_network_instance_0b4308ca-3fe0-4af1-9c4e-ed2c816b9496" + assert network_instance.network_id == "49dab38b-3a5b-47e5-9cd6-b8d069d6109d" + assert network_instance.is_bound_to_vpn is False + assert network_instance.is_provider_network is False + assert network_instance.is_shared_network is False + assert network_instance.is_external_network is False + assert network_instance.resource_version == "1593162237842" + assert network_instance.model_invariant_id == "cdbb2169-e638-4aab-a4e9-b9d2d6d62b04" + assert network_instance.model_version_id == "51789f7b-5ffc-4c12-ac87-02363fdb40b1" + assert network_instance.model_customization_id == "db9c9a6c-2a1c-4cdd-8fbc-e10448d0e4cc" + + +@mock.patch.object(NetworkDeletionRequest, "send_message_json") +def test_network_instance_delete(mock_send_message_json): + network_instance = NetworkInstance(mock.MagicMock(), + network_id="test_network_id", + is_bound_to_vpn=True, + is_provider_network=False, + is_shared_network=True, + is_external_network=False) + network_instance.delete() + mock_send_message_json.assert_called_once() diff --git a/tests/test_aai_owning_entity.py b/tests/test_aai_owning_entity.py new file mode 100644 index 0000000..0f16044 --- /dev/null +++ b/tests/test_aai_owning_entity.py @@ -0,0 +1,87 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from onapsdk.aai.business import OwningEntity +from onapsdk.exceptions import ResourceNotFound + + +OWNING_ENTITIES = { + "owning-entity":[ + { + "owning-entity-id":"ff6c945f-89ab-4f14-bafd-0cdd6eac791a", + "owning-entity-name":"OE-Generic", + "resource-version":"1588244348931", + }, + { + "owning-entity-id":"OE-generic", + "owning-entity-name":"OE-generic", + "resource-version":"1587388597761" + }, + { + "owning-entity-id":"b3dcdbb0-edae-4384-b91e-2f114472520c" + ,"owning-entity-name":"test", + "resource-version":"1588145971158" + } + ] +} + + +OWNING_ENTITY = { + "owning-entity-id":"OE-generic", + "owning-entity-name":"OE-generic", + "resource-version":"1587388597761" +} + + +@mock.patch.object(OwningEntity, "send_message_json") +def test_owning_entity_get_all(mock_send): + mock_send.return_value = OWNING_ENTITIES + owning_entities = list(OwningEntity.get_all()) + assert len(owning_entities) == 3 + owning_entity = owning_entities[0] + assert owning_entity.owning_entity_id == "ff6c945f-89ab-4f14-bafd-0cdd6eac791a" + assert owning_entity.name == "OE-Generic" + assert owning_entity.url == (f"{owning_entity.base_url}{owning_entity.api_version}/" + "business/owning-entities/owning-entity/" + f"{owning_entity.owning_entity_id}") + + +@mock.patch.object(OwningEntity, "send_message_json") +def test_owning_entity_get_by_name(mock_send): + mock_send.return_value = OWNING_ENTITIES + with pytest.raises(ResourceNotFound) as exc: + OwningEntity.get_by_owning_entity_name("invalid name") + assert exc.type == ResourceNotFound + owning_entity = OwningEntity.get_by_owning_entity_name("OE-Generic") + assert owning_entity.owning_entity_id == "ff6c945f-89ab-4f14-bafd-0cdd6eac791a" + assert owning_entity.name == "OE-Generic" + + +@mock.patch.object(OwningEntity, "send_message") +@mock.patch.object(OwningEntity, "send_message_json") +def test_owning_entity_create(mock_send_json, mock_send): + mock_send_json.return_value = OWNING_ENTITY + OwningEntity.create( + name="OE-generic", + ) + + owning_entity = OwningEntity.create( + name="OE-generic", + owning_entity_id="OE-generic" + ) + assert owning_entity.owning_entity_id == "OE-generic" + assert owning_entity.name == "OE-generic" diff --git a/tests/test_aai_platform.py b/tests/test_aai_platform.py new file mode 100644 index 0000000..ed20e50 --- /dev/null +++ b/tests/test_aai_platform.py @@ -0,0 +1,82 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.business.platform import Platform + + +PLATFORMS = { + "platform": [ + { + "platform-name": "test-name", + "resource-version": "1234" + }, + { + "platform-name": "test-name2", + "resource-version": "4321" + } + ] +} + + +COUNT = { + "results":[ + { + "platform":1 + } + ] +} + + +@mock.patch("onapsdk.aai.business.platform.Platform.send_message_json") +def test_platform_get_all(mock_send_message_json): + mock_send_message_json.return_value = {} + assert len(list(Platform.get_all())) == 0 + + mock_send_message_json.return_value = PLATFORMS + platforms = list(Platform.get_all()) + assert len(platforms) == 2 + lob1, lob2 = platforms + assert lob1.name == "test-name" + assert lob1.resource_version == "1234" + assert lob2.name == "test-name2" + assert lob2.resource_version == "4321" + + +@mock.patch("onapsdk.aai.business.platform.Platform.send_message_json") +def test_platform_get_by_name(mock_send): + Platform.get_by_name(name="test-name") + mock_send.assert_called_once_with("GET", + "Get test-name platform", + "https://aai.api.sparky.simpledemo.onap.org:30233/aai/v23/business/platforms/platform/test-name") + + +@mock.patch("onapsdk.aai.business.platform.Platform.send_message") +@mock.patch("onapsdk.aai.business.platform.Platform.get_by_name") +def test_platform_create(_, mock_send): + Platform.create(name="test-name") + mock_send.assert_called_once_with("PUT", + "Declare A&AI platform", + "https://aai.api.sparky.simpledemo.onap.org:30233/aai/v23/business/platforms/platform/test-name", + data='{\n "platform-name": "test-name"\n}') + + +@mock.patch("onapsdk.aai.business.platform.Platform.send_message_json") +def test_line_of_business_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert Platform.count() == 1 + +def test_platform_url(): + platform = Platform(name="test-platform", resource_version="123") + assert platform.name in platform.url diff --git a/tests/test_aai_pnf.py b/tests/test_aai_pnf.py new file mode 100644 index 0000000..32e9ea7 --- /dev/null +++ b/tests/test_aai_pnf.py @@ -0,0 +1,140 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from onapsdk.aai.business import PnfInstance, pnf +from onapsdk.exceptions import ResourceNotFound +# from onapsdk.so.deletion import NetworkDeletionRequest + + +PNF_INSTANCE = { + "pnf-name": "blablabla", + "pnf-id": "546b282b-2ff7-41a4-9329-55c9a2888477", + "equip-type": "pnf", + "equip-vendor": "PNF", + "equip-model": "Simulated Device", + "orchestration-status": "Active", + "ipaddress-v4-oam": "172.30.1.6", + "sw-version": "2.3.5", + "in-maint":False, + "serial-number": "123", + "ipaddress-v6-oam": "0:0:0:0:0:ffff:a0a:011", + "resource-version": "1610142659380", + "nf-role": "sdn controller", + "model-customization-id": "137ce8e8-bee9-465f-b7e1-0c006f10b443", + "model-invariant-id": "2ca7ea68-cf61-449c-a733-8122bcac1f9a", + "model-version-id": "da467f24-a26d-4620-b185-e1afa1d365ac", + "relationship-list": { + "relationship":[ + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/test/service-subscriptions/service-subscription/test/service-instances/service-instance/4c3ab996-afdb-4956-9c4d-038b4eed3db1", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"test" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"test" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"4c3ab996-afdb-4956-9c4d-038b4eed3db1" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"blablabla" + } + ] + } + ] + } +} + + +COUNT = { + "results":[ + { + "pnf":12 + } + ] +} + + +def test_create_pnf_instance_from_api_response(): + service_instance = mock.MagicMock() + pnf_instance = PnfInstance.create_from_api_response( + PNF_INSTANCE, + service_instance + ) + assert pnf_instance.pnf_name == "blablabla" + assert pnf_instance.pnf_id == "546b282b-2ff7-41a4-9329-55c9a2888477" + assert pnf_instance.equip_type == "pnf" + assert pnf_instance.equip_vendor == "PNF" + assert pnf_instance.equip_model == "Simulated Device" + assert pnf_instance.orchestration_status == "Active" + assert pnf_instance.ipaddress_v4_oam == "172.30.1.6" + assert pnf_instance.sw_version == "2.3.5" + assert pnf_instance.in_maint == False + assert pnf_instance.serial_number == "123" + assert pnf_instance.ipaddress_v6_oam == "0:0:0:0:0:ffff:a0a:011" + assert pnf_instance.resource_version == "1610142659380" + assert pnf_instance.nf_role == "sdn controller" + assert pnf_instance.model_customization_id == "137ce8e8-bee9-465f-b7e1-0c006f10b443" + assert pnf_instance.model_invariant_id == "2ca7ea68-cf61-449c-a733-8122bcac1f9a" + assert pnf_instance.model_version_id == "da467f24-a26d-4620-b185-e1afa1d365ac" + + assert pnf_instance.url.endswith(pnf_instance.pnf_name) + + +@mock.patch.object(PnfInstance, "send_message") +def test_delete_pnf_instance(mock_send_message): + pnf = PnfInstance(mock.MagicMock, "test_pnf", False) + pnf.delete() + method, _, address = mock_send_message.call_args[0] + assert method == "DELETE" + assert address == f"{pnf.url}?resource-version={pnf.resource_version}" + + +def test_pnf_instance_pnf(): + service_instance = mock.MagicMock() + pnf_instance = PnfInstance.create_from_api_response( + PNF_INSTANCE, + service_instance + ) + + assert pnf_instance._pnf is None + service_instance.sdc_service.pnfs = [] + with pytest.raises(ResourceNotFound) as exc: + pnf_instance.pnf + assert exc.type == ResourceNotFound + assert pnf_instance._pnf is None + + pnf = mock.MagicMock() + pnf.model_version_id = "da467f24-a26d-4620-b185-e1afa1d365ac" + service_instance.sdc_service.pnfs = [pnf] + assert pnf == pnf_instance.pnf + assert pnf_instance._pnf is not None + assert pnf_instance.pnf == pnf_instance._pnf + +@mock.patch.object(PnfInstance, "send_message_json") +def test_pnf_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert PnfInstance.count() == 12 diff --git a/tests/test_aai_project.py b/tests/test_aai_project.py new file mode 100644 index 0000000..4186772 --- /dev/null +++ b/tests/test_aai_project.py @@ -0,0 +1,82 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.business.project import Project + + +PROJECTS = { + "project": [ + { + "project-name": "test-name", + "resource-version": "1234" + }, + { + "project-name": "test-name2", + "resource-version": "4321" + } + ] +} + + +COUNT = { + "results":[ + { + "project":1 + } + ] +} + + +@mock.patch("onapsdk.aai.business.project.Project.send_message_json") +def test_project_get_all(mock_send_message_json): + mock_send_message_json.return_value = {} + assert len(list(Project.get_all())) == 0 + + mock_send_message_json.return_value = PROJECTS + projects = list(Project.get_all()) + assert len(projects) == 2 + lob1, lob2 = projects + assert lob1.name == "test-name" + assert lob1.resource_version == "1234" + assert lob2.name == "test-name2" + assert lob2.resource_version == "4321" + + +@mock.patch("onapsdk.aai.business.project.Project.send_message_json") +def test_project_get_by_name(mock_send): + Project.get_by_name(name="test-name") + mock_send.assert_called_once_with("GET", + "Get test-name project", + "https://aai.api.sparky.simpledemo.onap.org:30233/aai/v23/business/projects/project/test-name") + + +@mock.patch("onapsdk.aai.business.project.Project.send_message") +@mock.patch("onapsdk.aai.business.project.Project.get_by_name") +def test_project_create(_, mock_send): + Project.create(name="test-name") + mock_send.assert_called_once_with("PUT", + "Declare A&AI project", + "https://aai.api.sparky.simpledemo.onap.org:30233/aai/v23/business/projects/project/test-name", + data='{\n "project-name": "test-name"\n}') + + +@mock.patch("onapsdk.aai.business.project.Project.send_message_json") +def test_project_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert Project.count() == 1 + +def test_project_url(): + project = Project(name="test-project", resource_version="123") + assert project.name in project.url diff --git a/tests/test_aai_resource.py b/tests/test_aai_resource.py new file mode 100644 index 0000000..c1da0b7 --- /dev/null +++ b/tests/test_aai_resource.py @@ -0,0 +1,60 @@ +"""Test A&AI Element.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest +from unittest import mock + +from onapsdk.aai.aai_element import AaiResource, Relationship +from onapsdk.exceptions import RequestError, ResourceNotFound, RelationshipNotFound +from onapsdk.utils.gui import GuiList + +@mock.patch.object(AaiResource, "send_message_json") +@mock.patch.object(AaiResource, "url") +def test_relationship_not_found(mock_send, mock_url): + + aai_element = AaiResource() + mock_url.return_value = "http://my.url/" + + mock_send.side_effect = ResourceNotFound + + aai_element.send_message_json = mock_send + + with pytest.raises(ResourceNotFound) as exc: + list(aai_element.relationships) + assert exc.type == RelationshipNotFound + + mock_send.assert_called_once() + + +def test_relationship_get_relationship_data(): + r = Relationship( + related_to="test", + related_link="test", + relationship_data=[{ + "relationship-key": "test", + "relationship-value": "test" + }] + ) + assert r.get_relationship_data("invalid key") is None + assert r.get_relationship_data("test") == "test" + +@mock.patch.object(AaiResource, "send_message") +def test_get_guis(send_message_mock): + component = AaiResource() + send_message_mock.return_value.status_code = 200 + send_message_mock.return_value.url = "https://aai.api.sparky.simpledemo.onap.org:30220/services/aai/webapp/index.html#/browse" + gui_results = component.get_guis() + assert type(gui_results) == GuiList + assert gui_results.guilist[0].url == send_message_mock.return_value.url + assert gui_results.guilist[0].status == send_message_mock.return_value.status_code diff --git a/tests/test_aai_service.py b/tests/test_aai_service.py new file mode 100644 index 0000000..aac4c59 --- /dev/null +++ b/tests/test_aai_service.py @@ -0,0 +1,770 @@ +"""Test AaiElement module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from onapsdk.aai.aai_element import AaiElement, AaiResource, Relationship +from onapsdk.aai.cloud_infrastructure import ( + CloudRegion, + Complex, + EsrSystemInfo, + Tenant +) +from onapsdk.aai.business import Customer +from onapsdk.aai.service_design_and_creation import Service, Model +from onapsdk.onap_service import OnapService + + +# pylint: disable=C0301 +TENANT = { + "tenant": [ + { + "tenant-id": "4bdc6f0f2539430f9428c852ba606808", + "tenant-name": "onap-dublin-daily-vnfs", + "resource-version": "1562591004273", + "relationship-list": { + "relationship": [ + { + "related-to": "service-subscription", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/business/customers/customer/generic/service-subscriptions/service-subscription/freeradius", + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "generic", + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "freeradius", + }, + ], + }, + { + "related-to": "service-subscription", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/business/customers/customer/generic/service-subscriptions/service-subscription/ims", + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "generic", + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "ims", + }, + ], + }, + { + "related-to": "service-subscription", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/business/customers/customer/generic/service-subscriptions/service-subscription/ubuntu16", + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "generic", + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "ubuntu16", + }, + ], + }, + ] + }, + } + ] +} + + +CLOUD_REGIONS = { + "cloud-region": [ + { + "cloud-owner": "OPNFV", + "cloud-region-id": "RegionOne", + "cloud-type": "openstack", + "owner-defined-type": "N/A", + "cloud-region-version": "pike", + "identity-url": "http://msb-iag.onap:80/api/multicloud-pike/v0/OPNFV_RegionOne/identity/v2.0", + "cloud-zone": "OPNFV LaaS", + "complex-name": "Cruguil", + "resource-version": "1561217827955", + "orchestration-disabled": False, + "in-maint": False, + "relationship-list": { + "relationship": [ + { + "related-to": "complex", + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "related-link": "/aai/v13/cloud-infrastructure/complexes/complex/cruguil", + "relationship-data": [ + { + "relationship-key": "complex.physical-location-id", + "relationship-value": "cruguil", + } + ], + } + ] + }, + } + ] +} + + +CLOUD_REGION = { + "cloud-region": [ + { + "cloud-owner": "OPNFV", + "cloud-region-id": "RegionOne", + "cloud-type": "openstack", + "owner-defined-type": "N/A", + "cloud-region-version": "pike", + "identity-url": "http://msb-iag.onap:80/api/multicloud-pike/v0/OPNFV_RegionOne/identity/v2.0", + "cloud-zone": "OPNFV LaaS", + "complex-name": "Cruguil", + "resource-version": "1561217827955", + "orchestration-disabled": True, + "in-maint": False, + "relationship-list": { + "relationship": [ + { + "related-to": "complex", + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "related-link": "/aai/v13/cloud-infrastructure/complexes/complex/cruguil", + "relationship-data": [ + { + "relationship-key": "complex.physical-location-id", + "relationship-value": "cruguil", + } + ], + } + ] + }, + } + ] +} + + +COMPLEXES = { + "complex": [ + { + "city": "", + "data-center-code": "1234", + "street1": "", + "street2": "", + "physical-location-id": "integration_test_complex", + "identity-url": "", + "lata": "", + "elevation": "", + "state": "", + "physical-location-type": "", + "longitude": "", + "relationship-list": { + "relationship": [ + { + "related-to-property": [ + { + "property-value": "OwnerType", + "property-key": "cloud-region.owner-defined-type", + } + ], + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "related-link": "/aai/v16/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionOne", + "relationship-data": [ + { + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "CloudOwner", + }, + { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "RegionOne", + }, + ], + "related-to": "cloud-region", + } + ] + }, + "resource-version": "1581510773583", + "latitude": "", + "complex-name": "integration_test_complex", + "postal-code": "", + "country": "", + "region": "", + }, + { + "city": "Beijing", + "data-center-code": "example-data-center-code-val-5556", + "street1": "example-street1-val-34205", + "street2": "example-street2-val-99210", + "physical-location-id": "My_Complex", + "identity-url": "example-identity-url-val-56898", + "lata": "example-lata-val-46073", + "elevation": "example-elevation-val-30253", + "state": "example-state-val-59487", + "physical-location-type": "example-physical-location-type-val-7608", + "longitude": "106.4074", + "resource-version": "1581504768889", + "latitude": "39.9042", + "complex-name": "My_Complex", + "postal-code": "100000", + "country": "example-country-val-94173", + "region": "example-region-val-13893", + }, + ] +} + + +CLOUD_REGION_RELATIONSHIP = { + "relationship": [ + { + "relationship-label": "org.onap.relationships.inventory.LocatedIn", + "related-link": "/aai/v16/cloud-infrastructure/complexes/complex/integration_test_complex", + "relationship-data": [ + { + "relationship-key": "complex.physical-location-id", + "relationship-value": "integration_test_complex", + } + ], + "related-to": "complex", + } + ] +} + + +SERVICE_SUBSCRIPTION = { + "service-subscription": [ + { + "service-type": "freeradius", + "resource-version": "1562591478146", + "relationship-list": { + "relationship": [ + { + "related-to": "tenant", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v16/cloud-infrastructure/cloud-regions/cloud-region/OPNFV/RegionOne/tenants/tenant/4bdc6f0f2539430f9428c852ba606808", + "relationship-data": [ + { + "relationship-key": "cloud-region.cloud-owner", + "relationship-value": "OPNFV", + }, + { + "relationship-key": "cloud-region.cloud-region-id", + "relationship-value": "RegionOne", + }, + { + "relationship-key": "tenant.tenant-id", + "relationship-value": "4bdc6f0f2539430f9428c852ba606808", + }, + ], + "related-to-property": [ + { + "property-key": "tenant.tenant-name", + "property-value": "onap-dublin-daily-vnfs", + } + ], + } + ] + }, + }, + {"service-type": "ims"}, + ] +} + + +SUBSCRIPTION_TYPES_NO_RESOURCES = { + "requestError": { + "serviceException": { + "messageId": "SVC3001", + "text": ("Resource not found for %1 using id " + "%2 (msg=%3) +(ec=%4)"), + "variables": [ + "GET", + "service-design-and-creation/services", + ( + "Node Not Found:No Node of type service found at: " + + "/service-design-and-creation/services" + ), + "ERR.5.4.6114", + ], + } + } +} + + +SUBSCRIPTION_TYPES_LIST = { + "service": [ + { + "service-id": "f4bcf0b0-b44e-423a-8357-5758afc14e88", + "service-description": "ubuntu16", + "resource-version": "1561218639393", + }, + { + "service-id": "2e812e77-e437-46c4-8e8e-908fbc7e176c", + "service-description": "freeradius", + "resource-version": "1561219163076", + }, + { + "service-id": "f208de57-0e02-4505-a0fa-375b13ad24ac", + "service-description": "ims", + "resource-version": "1561219799684", + }, + ] +} + + +CUSTOMERS_NO_RESOURCES = { + "requestError": { + "serviceException": { + "messageId": "SVC3001", + "text": ("Resource not found for %1 using id " + "%2 (msg=%3) +(ec=%4)"), + "variables": [ + "GET", + "business/customers", + ( + "Node Not Found:No Node of type customer found at: " + + "business/customers" + ), + "ERR.5.4.6114", + ], + } + } +} + + +SIMPLE_CUSTOMER = { + "customer": [ + { + "global-customer-id": "generic", + "subscriber-name": "generic", + "subscriber-type": "INFRA", + "resource-version": "1561218640404", + } + ] +} + + +ESR_SYSTEM_INFO = { + 'esr-system-info': [ + { + 'esr-system-info-id': 'c2d5e75d-56fd-47bc-af31-95607b26fa93', + 'service-url': 'http://keystone:5000/v3', + 'user-name': 'test-devel', + 'password': 'test-devel', + 'system-type': 'openstack', + 'cloud-domain': 'Default', + 'resource-version': '1586436352654' + } + ] +} + + +CLOUD_REGIONS_ITERATOR = ( + cloud_region + for cloud_region in [ + CloudRegion( + cloud_owner="OPNFV", + cloud_region_id="RegionOne", + cloud_type="openstack", + owner_defined_type="N/A", + cloud_region_version="pike", + identity_url=None, + cloud_zone="OPNFV LaaS", + complex_name="Cruguil", + sriov_automation=None, + cloud_extra_info=None, + upgrade_cycle=None, + orchestration_disabled=False, + in_maint=False, + resource_version=None, + ) + ] +) +# pylint: enable=C0301 + + +def test_init(): + """Test the initialization.""" + element = AaiElement() + assert isinstance(element, OnapService) + + +def test_class_variables(): + """Test the class variables.""" + assert AaiElement.server == "AAI" + assert AaiElement.base_url == "https://aai.api.sparky.simpledemo.onap.org:30233" + assert AaiElement.headers == { + "Content-Type": "application/json", + "Accept": "application/json", + "x-fromappid": "AAI", + "x-transactionid": "0a3f6713-ba96-4971-a6f8-c2da85a3176e", + "authorization": "Basic QUFJOkFBSQ=="} + +@mock.patch.object(AaiElement, 'send_message_json') +def test_customers(mock_send): + """Test get_customer function of A&AI.""" + mock_send.return_value = SIMPLE_CUSTOMER + assert len(list(Customer.get_all())) == 1 + aai_customer_1 = next(Customer.get_all()) + assert aai_customer_1.global_customer_id == "generic" + assert aai_customer_1.subscriber_name == "generic" + assert aai_customer_1.subscriber_type == "INFRA" + assert aai_customer_1.resource_version == "1561218640404" + mock_send.assert_called_with("GET", 'get customers', mock.ANY) + +@mock.patch.object(AaiElement, 'send_message_json') +def test_customers_no_resources(mock_send): + """Test get_customer function with no customer declared in A&AI.""" + mock_send.return_value = CUSTOMERS_NO_RESOURCES + assert len(list(Customer.get_all())) == 0 + mock_send.assert_called_with("GET", 'get customers', mock.ANY) + +@mock.patch.object(AaiElement, 'send_message_json') +def test_subscription_type_list(mock_send): + """Test the getter of subscription types in A&AI.""" + mock_send.return_value = {} + assert len(list(Service.get_all())) == 0 + assert len(list(Service.get_all())) == 0 + + mock_send.return_value = SUBSCRIPTION_TYPES_LIST + assert len(list(Service.get_all())) == 3 + assert len(list(Service.get_all())) == 3 + subscriptions = Service.get_all() + aai_service_1 = next(subscriptions) + aai_service_2 = next(subscriptions) + aai_service_3 = next(subscriptions) + assert aai_service_1.service_id == "f4bcf0b0-b44e-423a-8357-5758afc14e88" + assert aai_service_1.service_description == "ubuntu16" + assert aai_service_1.resource_version == "1561218639393" + assert aai_service_2.service_id == "2e812e77-e437-46c4-8e8e-908fbc7e176c" + assert aai_service_2.service_description == "freeradius" + assert aai_service_2.resource_version == "1561219163076" + assert aai_service_3.service_id == "f208de57-0e02-4505-a0fa-375b13ad24ac" + assert aai_service_3.service_description == "ims" + assert aai_service_3.resource_version == "1561219799684" + mock_send.assert_called_with("GET", 'get subscriptions', mock.ANY) + +@mock.patch.object(AaiElement, 'send_message_json') +def test_subscription_types_no_resources(mock_send): + """Test get_customer function with no customer declared in A&AI.""" + mock_send.return_value = SUBSCRIPTION_TYPES_NO_RESOURCES + assert len(list(Service.get_all())) == 0 + mock_send.assert_called_with("GET", 'get subscriptions', mock.ANY) + +@mock.patch.object(AaiElement, 'send_message_json') +def test_cloud_regions(mock_send): + """Test get cloud regions from A&AI.""" + mock_send.return_value = CLOUD_REGION + assert len(list(CloudRegion.get_all())) == 1 + cloud_region = next(CloudRegion.get_all()) + assert cloud_region.cloud_owner == "OPNFV" + assert cloud_region.cloud_type == "openstack" + assert cloud_region.complex_name == "Cruguil" + + cloud_region = next(CloudRegion.get_all()) + assert cloud_region.cloud_owner == "OPNFV" + assert cloud_region.cloud_type == "openstack" + assert cloud_region.complex_name == "Cruguil" + + mock_send.return_value = {} + cloud_regions = list(CloudRegion.get_all()) + assert len(cloud_regions) == 0 + + with pytest.raises(StopIteration): + cloud_region = next(CloudRegion.get_all()) + + mock_send.return_value = CLOUD_REGIONS + cloud_regions = list(CloudRegion.get_all()) + assert len(cloud_regions) == 1 + +@mock.patch.object(CloudRegion, "send_message") +def test_cloud_region_creation(mock_send): + """Test cloud region creation""" + cloud_region = CloudRegion.create( + cloud_owner="test_owner", + cloud_region_id="test_cloud_region", + orchestration_disabled=False, + in_maint=True, + owner_defined_type="Test", + cloud_zone="Test zone", + sriov_automation="Test", + upgrade_cycle="Test" + ) + assert cloud_region.cloud_owner == "test_owner" + assert cloud_region.cloud_region_id == "test_cloud_region" + assert cloud_region.orchestration_disabled == False + assert cloud_region.in_maint == True + assert cloud_region.cloud_type == "" + assert cloud_region.owner_defined_type == "Test" + assert cloud_region.cloud_region_version == "" + assert cloud_region.identity_url == "" + assert cloud_region.cloud_zone == "Test zone" + assert cloud_region.complex_name == "" + assert cloud_region.sriov_automation == "Test" + assert cloud_region.cloud_extra_info == "" + assert cloud_region.upgrade_cycle == "Test" + +@mock.patch.object(CloudRegion, 'get_all') +@mock.patch.object(AaiElement, 'send_message_json') +def test_tenants_info(mock_send, mock_cloud_regions): + """Test get Tenant from A&AI.""" + mock_cloud_regions.return_value = CLOUD_REGIONS_ITERATOR + mock_send.return_value = TENANT + cloud_name = "RegionOne" + cloud_region = CloudRegion.get_by_id("DT", cloud_name) + res = list(cloud_region.tenants) + assert len(res) == 1 + assert isinstance(res[0], Tenant) + tenant = res[0] + assert tenant.tenant_id == "4bdc6f0f2539430f9428c852ba606808" + assert tenant.name == "onap-dublin-daily-vnfs" + assert tenant.context is None + assert tenant.resource_version == "1562591004273" + assert tenant.url == ( + f"{tenant.base_url}{tenant.api_version}/cloud-infrastructure/cloud-regions/cloud-region/" + f"OPNFV/RegionOne/tenants/tenant/4bdc6f0f2539430f9428c852ba606808?" + f"resource-version=1562591004273" + ) + +@mock.patch.object(CloudRegion, 'get_all') +@mock.patch.object(AaiElement, 'send_message_json') +def test_tenants_info_wrong_cloud_name(mock_send, mock_cloud_regions): + """Test get Tenant from A&AI.""" + mock_cloud_regions.return_value = CLOUD_REGIONS_ITERATOR + mock_send.return_value = TENANT + cloud_name = "Wrong_cloud_name" + with pytest.raises(Exception) as excinfo: + CloudRegion.get_by_id("DT", cloud_name) + assert "not found" in str(excinfo.value) + + +@mock.patch.object(CloudRegion, "send_message_json") +def test_cloud_regions_relationship(mock_send): + """Test cloud region relationship property.""" + mock_send.return_value = CLOUD_REGION_RELATIONSHIP + cloud_region = CloudRegion(cloud_owner="tester", cloud_region_id="test", + orchestration_disabled=True, in_maint=False) + relationship = next(cloud_region.relationships) + assert isinstance(relationship, Relationship) + assert relationship.relationship_label == "org.onap.relationships.inventory.LocatedIn" + assert relationship.related_link == \ + "/aai/v16/cloud-infrastructure/complexes/complex/integration_test_complex" + assert relationship.related_to == "complex" + assert relationship.relationship_data[0]["relationship-key"] == "complex.physical-location-id" + assert relationship.relationship_data[0]["relationship-value"] == "integration_test_complex" + + +@mock.patch.object(CloudRegion, "send_message_json") +def test_cloud_regions_esr_system_infos(mock_send): + """Test cloud region esr system info""" + mock_send.return_value = ESR_SYSTEM_INFO + cloud_region = CloudRegion(cloud_owner="tester", cloud_region_id="test", + orchestration_disabled=True, in_maint=False) + esr_system_info = next(cloud_region.esr_system_infos) + assert isinstance(esr_system_info, EsrSystemInfo) + assert esr_system_info.esr_system_info_id == "c2d5e75d-56fd-47bc-af31-95607b26fa93" + assert esr_system_info.user_name == "test-devel" + assert esr_system_info.password == "test-devel" + assert esr_system_info.system_type == "openstack" + assert esr_system_info.resource_version == "1586436352654" + assert esr_system_info.system_name is None + assert esr_system_info.esr_type is None + assert esr_system_info.vendor is None + assert esr_system_info.version is None + assert esr_system_info.service_url == "http://keystone:5000/v3" + assert esr_system_info.protocol is None + assert esr_system_info.ssl_cacert is None + assert esr_system_info.ssl_insecure is None + assert esr_system_info.ip_address is None + assert esr_system_info.port is None + assert esr_system_info.cloud_domain == "Default" + assert esr_system_info.default_tenant is None + assert esr_system_info.passive is None + assert esr_system_info.remote_path is None + assert esr_system_info.system_status is None + assert esr_system_info.openstack_region_id is None + +@mock.patch.object(Complex, "send_message") +def test_create_complex(mock_send): + """Test complex creation""" + cmplx = Complex.create( + name="test complex", + physical_location_id="somewhere", + data_center_code="5555", + physical_location_type="test", + city="Test City", + postal_code="55555", + region="Test region", + elevation="TestElevation", + ) + + assert cmplx.name == "test complex" + assert cmplx.physical_location_id == "somewhere" + assert cmplx.identity_url == "" + assert cmplx.physical_location_type == "test" + assert cmplx.street1 == "" + assert cmplx.street2 == "" + assert cmplx.city == "Test City" + assert cmplx.state == "" + assert cmplx.postal_code == "55555" + assert cmplx.country == "" + assert cmplx.region == "Test region" + assert cmplx.latitude == "" + assert cmplx.longitude == "" + assert cmplx.elevation == "TestElevation" + assert cmplx.lata == "" + + +@mock.patch.object(Complex, "send_message_json") +def text_get_all_complexes(mock_send): + """Test get_all Complex class method.""" + mock_send.return_value = {} + assert len(list(Complex.get_all())) == 0 + + mock_send.return_value = COMPLEXES + assert len(list(Complex.get_all())) == 2 + + +def test_filter_none_value(): + """Test method to filter out None value keys from dictionary.""" + ret: dict = AaiResource.filter_none_key_values({"a": None}) + assert not ret + + ret: dict = AaiResource.filter_none_key_values({"a": "b", "c": None}) + assert ret == {"a": "b"} + + ret: dict = AaiResource.filter_none_key_values({"a": "b", "c": "d"}) + assert ret == {"a": "b", "c": "d"} + + +@mock.patch.object(AaiResource, "send_message") +def test_add_relationship(mock_send): + """Test add_relationship method.""" + cloud_region = CloudRegion(cloud_owner="tester", cloud_region_id="test", + orchestration_disabled=True, in_maint=False) + cloud_region.add_relationship(Relationship(related_to="test", + related_link="test", + relationship_data={})) + + +# # ----------------------------------------------------------------------------- +# def test_check_aai_resource_service(): +# """Test that a given service instance is in A&AI.""" +# pass + +# def test_check_aai_resource_service_not_found(): +# """Test that a given service instance is not in A&AI (cleaned).""" +# pass + +# def test_check_aai_resource_vnf(): +# """Test that a given vnf is in A&AI.""" +# pass + +# def test_check_aai_resource_vnf_not_found(): +# """Test that a given vnf is not in A&AI (cleaned).""" +# pass + +# def test_check_aai_resource_module(): +# """Test that a given module is in A&AI.""" +# pass + +# def test_check_aai_resource_module_not_found(): +# """Test that a given module is not in A&AI (cleaned).""" +# pass + +# def test_check_aai_net_module(): +# """Test that a given net is in A&AI.""" +# pass + +# def test_check_aai_resource_net_not_found(): +# """Test that a given net is not in A&AI (cleaned).""" +# pass + + +# pylint: disable=C0301 +SIMPLE_MODEL = { + "model": [ + { + "model-invariant-id": "1234567890", + "model-type": "generic", + "resource-version": "1561218640404", + } + ] +} +# pylint: enable=C0301 + + +def test_service_url(): + """Test service property""" + service = Service("12345", "description", "version1.0") + assert service.url == (f"{service.base_url}{service.api_version}/service-design-and-creation/services/service/" + f"{service.service_id}?resource-version={service.resource_version}") + + +@mock.patch.object(Service, 'send_message') +def test_service_create(mock_send): + """Test service creation""" + Service.create("1234", "description") + mock_send.assert_called_once() + method, description, url = mock_send.call_args[0] + assert method == "PUT" + assert description == "Create A&AI service" + assert url == (f"{Service.base_url}{Service.api_version}/service-design-and-creation/" + f"services/service/1234") + + +def test_model_init(): + """Test model initailization""" + model = Model("12345", "ubuntu", "version16") + assert isinstance(model, Model) + + +def test_model_url(): + """Test Model's url property""" + model = Model("12345", "ubuntu", "version16") + assert model.url == (f"{model.base_url}{model.api_version}/service-design-and-creation/models/" + f"model/{model.invariant_id}?resource-version={model.resource_version}") + + +@mock.patch.object(Model, 'send_message_json') +def test_zero_model_get_all(mock_send_message_json): + """Test get_all Model class method""" + mock_send_message_json.return_value = {} + Model.get_all() + assert len(list(Model.get_all())) == 0 + + +@mock.patch.object(Model, 'send_message_json') +def test_model_get_all(mock_send_message_json): + """Test get_all Model class method""" + mock_send_message_json.return_value = SIMPLE_MODEL + Model.get_all() + assert len(list(Model.get_all())) == 1 + model_1 = next(Model.get_all()) + assert model_1.invariant_id == "1234567890" + assert model_1.model_type == "generic" + assert model_1.resource_version == "1561218640404" + mock_send_message_json.assert_called_with("GET", 'Get A&AI sdc models', mock.ANY) + + +@mock.patch.object(CloudRegion, "send_message_json") +@mock.patch.object(Complex, "get_by_physical_location_id") +def test_cloud_region_complex_property(mock_complex_get_by_physical_location_id, mock_send): + """Test cloud region complex property.""" + mock_send.return_value = {} + cloud_region = CloudRegion(cloud_owner="tester", cloud_region_id="test", + orchestration_disabled=True, in_maint=False) + assert cloud_region.complex is None + mock_send.return_value = CLOUD_REGION_RELATIONSHIP + assert cloud_region.complex is not None + assert mock_complex_get_by_physical_location_id.called_once_with("integration_test_complex") diff --git a/tests/test_aai_service_instance.py b/tests/test_aai_service_instance.py new file mode 100644 index 0000000..9f84dfd --- /dev/null +++ b/tests/test_aai_service_instance.py @@ -0,0 +1,275 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from onapsdk.aai.aai_element import AaiElement +from onapsdk.aai.business import ServiceInstance +from onapsdk.so.deletion import ServiceDeletionRequest +from onapsdk.so.instantiation import NetworkInstantiation, VnfInstantiation +from onapsdk.exceptions import StatusError + + +RELATIONSHIPS_VNF = { + "relationship": [ + { + "related-to": "generic-vnf", + "relationship_label": "anything", + "related_link": "test_relationship_related_link", + "relationship_data": [] + } + ] +} + + +RELATIONSHIPS_NETWORK = { + "relationship": [ + { + "related-to": "l3-network", + "relationship-label": "anything", + "related-link": "related_link", + "relationship-data": [] + } + ] +} + + +NETWORK_INSTANCE = { + 'network-id': '49dab38b-3a5b-47e5-9cd6-b8d069d6109d', + 'network-name': 'Python_ONAP_SDK_network_instance_0b4308ca-3fe0-4af1-9c4e-ed2c816b9496', + 'is-bound-to-vpn': False, + 'resource-version': '1593162237842', + 'orchestration-status': 'Inventoried', + 'model-invariant-id': 'cdbb2169-e638-4aab-a4e9-b9d2d6d62b04', + 'model-version-id': '51789f7b-5ffc-4c12-ac87-02363fdb40b1', + 'model-customization-id': 'db9c9a6c-2a1c-4cdd-8fbc-e10448d0e4cc', + 'is-provider-network': False, + 'is-shared-network': False, + 'is-external-network': False, + 'relationship-list': { + 'relationship': [ + { + 'related-to': 'service-instance', + 'relationship-label': 'org.onap.relationships.inventory.ComposedOf', + 'related-link': '/aai/v19/business/customers/customer/TestCustomer/service-subscriptions/service-subscription/vFW_with_net/service-instances/service-instance/72fd9ee9-077f-4d3d-8e86-08ed24514802', + 'relationship-data': [ + { + 'relationship-key': 'customer.global-customer-id', + 'relationship-value': 'TestCustomer' + }, + { + 'relationship-key': 'service-subscription.service-type', + 'relationship-value': 'vFW_with_net' + }, + { + 'relationship-key': 'service-instance.service-instance-id', + 'relationship-value': '72fd9ee9-077f-4d3d-8e86-08ed24514802' + } + ], + 'related-to-property': [ + { + 'property-key': 'service-instance.service-instance-name', + 'property-value': 'Python_ONAP_SDK_service_instance_7be66d06-c466-46cf-b84a-cd7af2d633ed' + } + ] + }, + { + 'related-to': 'cloud-region', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/TestCloudOwner/RegionOne', + 'relationship-data': [ + { + 'relationship-key': 'cloud-region.cloud-owner', + 'relationship-value': 'TestCloudOwner' + }, + { + 'relationship-key': 'cloud-region.cloud-region-id', + 'relationship-value': 'RegionOne' + } + ], + 'related-to-property': [ + { + 'property-key': 'cloud-region.owner-defined-type', + 'property-value': '' + } + ] + }, + { + 'related-to': 'line-of-business', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/business/lines-of-business/line-of-business/Test-BusinessLine', + 'relationship-data': [ + { + 'relationship-key': 'line-of-business.line-of-business-name', + 'relationship-value': 'Test-BusinessLine' + } + ] + }, + { + 'related-to': 'tenant', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/TestCloudOwner/RegionOne/tenants/tenant/89788fdf49514f94963b12a6c0cfdc71', + 'relationship-data': [ + { + 'relationship-key': 'cloud-region.cloud-owner', + 'relationship-value': 'TestCloudOwner' + }, + { + 'relationship-key': 'cloud-region.cloud-region-id', + 'relationship-value': 'RegionOne' + }, + { + 'relationship-key': 'tenant.tenant-id', + 'relationship-value': '89788fdf49514f94963b12a6c0cfdc71' + } + ], + 'related-to-property': [ + { + 'property-key': 'tenant.tenant-name', + 'property-value': 'test-tenant' + } + ] + }, + { + 'related-to': 'platform', + 'relationship-label': 'org.onap.relationships.inventory.Uses', + 'related-link': '/aai/v19/business/platforms/platform/Test-Platform', + 'relationship-data': [ + { + 'relationship-key': 'platform.platform-name', + 'relationship-value': 'Test-Platform' + } + ] + } + ] + } +} + + +COUNT = { + "results":[ + { + "service-instance":29 + } + ] +} + + +def test_service_instance(): + service_subscription = mock.MagicMock() + service_subscription.url = "test_url" + service_instance = ServiceInstance(service_subscription=service_subscription, + instance_id="test_service_instance_id") + assert service_instance.url == (f"{service_instance.service_subscription.url}/service-instances/" + f"service-instance/{service_instance.instance_id}") + + +@mock.patch.object(ServiceInstance, "send_message_json") +def test_service_instance_vnf_instances(mock_relationships_send_message_json): + service_instance = ServiceInstance(service_subscription=mock.MagicMock(), + instance_id="test_service_instance_id") + mock_relationships_send_message_json.return_value = {"relationship": []} + assert len(list(service_instance.vnf_instances)) == 0 + mock_relationships_send_message_json.return_value = RELATIONSHIPS_VNF + assert len(list(service_instance.vnf_instances)) == 1 + + +@mock.patch.object(AaiElement, "send_message_json") +def test_service_instance_network_instances(mock_aai_element_send_message_json): + service_instance = ServiceInstance(service_subscription=mock.MagicMock(), + instance_id="test_service_instance_id") + mock_aai_element_send_message_json.side_effect = [RELATIONSHIPS_NETWORK, NETWORK_INSTANCE] + assert len(list(service_instance.network_instances)) == 1 + + +@mock.patch.object(VnfInstantiation, "instantiate_ala_carte") +@mock.patch.object(ServiceInstance, "sdc_service", new_callable=mock.PropertyMock) +def test_service_instance_add_vnf(mock_sdc_service, mock_vnf_instantiation): + service_instance = ServiceInstance(service_subscription=mock.MagicMock(), + instance_id="test_service_instance_id") + service_instance.orchestration_status = "Inactive" + with pytest.raises(StatusError) as exc: + service_instance.add_vnf(mock.MagicMock(), + mock.MagicMock(), + mock.MagicMock()) + assert exc.type == StatusError + service_instance.orchestration_status = "Active" + service_instance.add_vnf(mock.MagicMock(), + mock.MagicMock(), + mock.MagicMock()) + mock_vnf_instantiation.assert_called_once() + + +@mock.patch.object(VnfInstantiation, "instantiate_macro") +@mock.patch.object(ServiceInstance, "sdc_service", new_callable=mock.PropertyMock) +def test_service_instance_add_vnf_macro(mock_sdc_service, mock_vnf_instantiation): + service_instance = ServiceInstance(service_subscription=mock.MagicMock(), + instance_id="test_service_instance_id") + service_instance.orchestration_status = "Inactive" + with pytest.raises(StatusError) as exc: + service_instance.add_vnf(mock.MagicMock(), + mock.MagicMock(), + mock.MagicMock(), + a_la_carte=False) + assert exc.type == StatusError + service_instance.orchestration_status = "Active" + service_instance.add_vnf(mock.MagicMock(), + mock.MagicMock(), + mock.MagicMock(), + a_la_carte=False) + mock_vnf_instantiation.assert_called_once() + + +@mock.patch.object(NetworkInstantiation, "instantiate_ala_carte") +@mock.patch.object(ServiceInstance, "sdc_service", new_callable=mock.PropertyMock) +def test_service_instance_add_network(mock_sdc_service, mock_network_instantiation): + service_instance = ServiceInstance(service_subscription=mock.MagicMock(), + instance_id="test_service_instance_id") + service_instance.orchestration_status = "Inactive" + with pytest.raises(StatusError) as exc: + service_instance.add_network(mock.MagicMock(), + mock.MagicMock(), + mock.MagicMock()) + assert exc.type == StatusError + service_instance.orchestration_status = "Active" + service_instance.add_network(mock.MagicMock(), + mock.MagicMock(), + mock.MagicMock()) + mock_network_instantiation.assert_called_once() + + +@mock.patch.object(ServiceDeletionRequest, "send_request") +@mock.patch.object(ServiceInstance, "sdc_service", new_callable=mock.PropertyMock) +def test_service_instance_deletion(mock_sdc_service, mock_service_deletion_request): + service_instance = ServiceInstance(service_subscription=mock.MagicMock(), + instance_id="test_service_instance_id") + service_instance.delete() + mock_service_deletion_request.assert_called_once_with(service_instance, True) + + +@mock.patch("onapsdk.aai.business.service.Service.get_by_unique_uuid") +def test_service_instance_sdc_service(mock_service_get_by_unique_uuid): + si = ServiceInstance(service_subscription=mock.MagicMock(), + instance_id="test_service_instance_id", + model_invariant_id="1234") + si.sdc_service + mock_service_get_by_unique_uuid.assert_called_once_with("1234") + si.sdc_service + mock_service_get_by_unique_uuid.assert_called_once_with("1234") + +@mock.patch.object(ServiceInstance, "send_message_json") +def test_service_instance_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert ServiceInstance.count(service_subscription=mock.MagicMock()) diff --git a/tests/test_aai_service_subscription.py b/tests/test_aai_service_subscription.py new file mode 100644 index 0000000..3c7eb91 --- /dev/null +++ b/tests/test_aai_service_subscription.py @@ -0,0 +1,191 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.business import Customer, ServiceSubscription, ServiceInstance +from onapsdk.aai.cloud_infrastructure import CloudRegion + + +SERVICE_INSTANCES = { + "service-instance":[ + { + "service-instance-id":"5410bf79-2aa3-450e-a324-ec5630dc18cf", + "service-instance-name":"test", + "environment-context":"General_Revenue-Bearing", + "workload-context":"Production", + "model-invariant-id":"2a51a89b-6f94-4417-8831-c468fb30ed02", + "model-version-id":"92a82807-b483-4579-86b1-c79b1286aab4", + "resource-version":"1589457727708", + "orchestration-status":"Active", + "relationship-list":{ + "relationship":[ + { + "related-to":"owning-entity", + "relationship-label":"org.onap.relationships.inventory.BelongsTo", + "related-link":"/aai/v16/business/owning-entities/owning-entity/ff6c945f-89ab-4f14-bafd-0cdd6eac791a", + "relationship-data":[ + { + "relationship-key":"owning-entity.owning-entity-id", + "relationship-value":"ff6c945f-89ab-4f14-bafd-0cdd6eac791a" + } + ] + }, + { + "related-to":"project", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v16/business/projects/project/python_onap_sdk_project", + "relationship-data":[ + { + "relationship-key":"project.project-name", + "relationship-value":"python_onap_sdk_project" + } + ] + } + ] + } + } + ] +} + + +MULTIPLE_CLOUD_REGIONS_AND_TENATS_RELATIONSHIP = { + "relationship":[ + { + "related-to":"tenant", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/DT/RegionOne/tenants/tenant/8fa33ca96caa4172aeeeefd1dbf5c715", + "relationship-data":[ + { + "relationship-key":"cloud-region.cloud-owner", + "relationship-value":"DT" + }, + { + "relationship-key":"cloud-region.cloud-region-id", + "relationship-value":"RegionOne" + }, + { + "relationship-key":"tenant.tenant-id", + "relationship-value":"8fa33ca96caa4172aeeeefd1dbf5c715" + } + ], + "related-to-property":[ + { + "property-key":"tenant.tenant-name", + "property-value":"ci-onap-master-vnfs" + } + ] + }, + { + "related-to":"tenant", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/test_cloud_owner/test_cloud_region_id/tenants/tenant/1234", + "relationship-data":[ + { + "relationship-key":"cloud-region.cloud-owner", + "relationship-value":"test_cloud_owner" + }, + { + "relationship-key":"cloud-region.cloud-region-id", + "relationship-value":"test_cloud_region_id" + }, + { + "relationship-key":"tenant.tenant-id", + "relationship-value":"1234" + } + ], + "related-to-property":[ + { + "property-key":"tenant.tenant-name", + "property-value":"test_tenant" + } + ] + } + ] +} + + +COUNT = { + "results":[ + { + "service-subscription":1 + } + ] +} + + +@mock.patch.object(ServiceSubscription, "send_message_json") +def test_get_service_instance_by_filter_parameter(mock_send_message_json): + """Test Service Subscription get_service_instance_by_filter_parameter method""" + customer = Customer("generic", "generic", "INFRA") + service_subscription = ServiceSubscription(customer=customer, + service_type="test_service_type", + resource_version="test_resource_version") + mock_send_message_json.return_value = SERVICE_INSTANCES + service_instance = service_subscription._get_service_instance_by_filter_parameter(filter_parameter_name="service-instance-id", filter_parameter_value="5410bf79-2aa3-450e-a324-ec5630dc18cf") + assert service_instance.instance_name == "test" + assert service_instance.instance_id == "5410bf79-2aa3-450e-a324-ec5630dc18cf" + + +@mock.patch.object(ServiceSubscription, "_get_service_instance_by_filter_parameter") +def test_get_service_instance_by_id(mock_get): + """Test Service Subscription get_service_instance_by_id method""" + service_subscription = ServiceSubscription(customer=None, + service_type="test_service_type", + resource_version="test_resource_version") + mock_get.return_value = ServiceInstance(service_subscription="ServiceSubscription", + instance_id="5410bf79-2aa3-450e-a324-ec5630dc18cf") + service_instance = service_subscription.get_service_instance_by_id(service_instance_id="5410bf79-2aa3-450e-a324-ec5630dc18cf") + assert service_instance.instance_id == "5410bf79-2aa3-450e-a324-ec5630dc18cf" + + +@mock.patch.object(ServiceSubscription, "_get_service_instance_by_filter_parameter") +def test_get_service_instance_by_name(mock_get): + """Test Service Subscription get_service_instance_by_name method""" + service_subscription = ServiceSubscription(customer=None, + service_type="test_service_type", + resource_version="test_resource_version") + mock_get.return_value = ServiceInstance(service_subscription="ServiceSubscription", + instance_id="5410bf79-2aa3-450e-a324-ec5630dc18cf", + instance_name="test") + service_instance = service_subscription.get_service_instance_by_name(service_instance_name="test") + assert service_instance.instance_name == "test" + + +@mock.patch.object(ServiceSubscription, "send_message_json") +@mock.patch.object(CloudRegion, "get_by_id") +def test_cloud_regions(mock_cloud_region_get_by_id, mock_send_message_json): + """Test service subscription `cloud_regions` property""" + service_subscription = ServiceSubscription(customer=mock.MagicMock(), + service_type="test_service_type", + resource_version="test_resource_version") + mock_send_message_json.return_value = MULTIPLE_CLOUD_REGIONS_AND_TENATS_RELATIONSHIP + assert len(list(service_subscription.cloud_regions)) == 2 + assert len(mock_cloud_region_get_by_id.mock_calls) == 2 + + +@mock.patch.object(ServiceSubscription, "send_message_json") +@mock.patch.object(CloudRegion, "get_by_id") +@mock.patch.object(CloudRegion, "get_tenant") +def test_tenants(mock_cloud_region_get_tenant, mock_cloud_region_get_by_id, mock_send_message_json): + """Test service subscription `tenants` property""" + service_subscription = ServiceSubscription(customer=mock.MagicMock(), + service_type="test_service_type", + resource_version="test_resource_version") + mock_send_message_json.return_value = MULTIPLE_CLOUD_REGIONS_AND_TENATS_RELATIONSHIP + assert len(list(service_subscription.tenants)) == 2 + +@mock.patch.object(ServiceSubscription, "send_message_json") +def test_service_subscription_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert ServiceSubscription.count(customer=mock.MagicMock()) == 1 diff --git a/tests/test_aai_site_resource.py b/tests/test_aai_site_resource.py new file mode 100644 index 0000000..68dd556 --- /dev/null +++ b/tests/test_aai_site_resource.py @@ -0,0 +1,57 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest.mock import patch + +from onapsdk.aai.network.site_resource import SiteResource + +SITE_RESOURCE = { + "site-resource-id":"123", + "resource-version":"213" +} + +SITE_RESOURCES = { + "site-resource":[ + SITE_RESOURCE, + { + "site-resource-id":"321", + "resource-version":"312" + } + ] +} + +@patch("onapsdk.aai.network.site_resource.SiteResource.send_message_json") +def test_site_resource_get_all(mock_send_message_json): + assert len(list(SiteResource.get_all())) == 0 + mock_send_message_json.return_value = SITE_RESOURCES + site_resources = list(SiteResource.get_all()) + assert len(site_resources) == 2 + sr1, sr2 = site_resources + assert sr1.site_resource_id == "123" + assert sr1.resource_version == "213" + assert sr2.site_resource_id == "321" + assert sr2.resource_version == "312" + +@patch("onapsdk.aai.network.site_resource.SiteResource.send_message_json") +def test_site_resource_get_by_id(mock_send_message_json): + mock_send_message_json.return_value = SITE_RESOURCE + sr = SiteResource.get_by_site_resource_id("123") + assert sr.site_resource_id == "123" + assert sr.resource_version == "213" + +@patch("onapsdk.aai.network.site_resource.SiteResource.send_message") +@patch("onapsdk.aai.network.site_resource.SiteResource.get_by_site_resource_id") +def test_site_resource_create(mock_get_by_site_resource_id, mock_send_message): + SiteResource.create("123") + mock_send_message.assert_called_once() + assert mock_get_by_site_resource_id.called_once_with("123") diff --git a/tests/test_aai_vf_module.py b/tests/test_aai_vf_module.py new file mode 100644 index 0000000..7f3b8a6 --- /dev/null +++ b/tests/test_aai_vf_module.py @@ -0,0 +1,83 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from onapsdk.aai.business import VfModuleInstance +from onapsdk.so.deletion import VfModuleDeletionRequest +from onapsdk.exceptions import ResourceNotFound + + +COUNT = { + "results":[ + { + "vf-module":1 + } + ] +} + + +def test_vf_module(): + vnf_instance = mock.MagicMock() + vnf_instance.url = "test_url" + vf_module_instance = VfModuleInstance(vnf_instance=vnf_instance, + vf_module_id="test_vf_module_id", + is_base_vf_module=True, + automated_assignment=False) + + assert vf_module_instance.url == (f"{vf_module_instance.vnf_instance.url}/vf-modules/" + f"vf-module/{vf_module_instance.vf_module_id}") + + +@mock.patch.object(VfModuleDeletionRequest, "send_request") +def test_vf_module_deletion(mock_deletion_request): + vf_module_instance = VfModuleInstance(vnf_instance=mock.MagicMock(), + vf_module_id="test_vf_module_id", + is_base_vf_module=True, + automated_assignment=False) + vf_module_instance.delete() + mock_deletion_request.assert_called_once_with(vf_module_instance, True) + + +def test_vnf_vf_module(): + """Test VfModudleInstance's vf_module property""" + vnf_instance = mock.MagicMock() + vnf_instance.vnf = mock.MagicMock() + + vf_module = mock.MagicMock() + vf_module.model_version_id = "test_model_version_id" + + vf_module_instance = VfModuleInstance(vnf_instance=vnf_instance, + model_version_id="test_model_version_id", + vf_module_id="test_vf_module_id", + is_base_vf_module=True, + automated_assignment=False) + + vnf_instance.vnf.vf_modules = [] + with pytest.raises(ResourceNotFound) as exc: + vf_module_instance.vf_module + assert exc.type == ResourceNotFound + assert vf_module_instance._vf_module is None + + vnf_instance.vnf.vf_modules = [vf_module] + + assert vf_module == vf_module_instance.vf_module + assert vf_module_instance._vf_module is not None + assert vf_module_instance.vf_module == vf_module_instance._vf_module + +@mock.patch.object(VfModuleInstance, "send_message_json") +def test_vf_module_instance_count(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert VfModuleInstance.count(vnf_instance=mock.MagicMock()) == 1 diff --git a/tests/test_aai_vnf.py b/tests/test_aai_vnf.py new file mode 100644 index 0000000..4dea6a8 --- /dev/null +++ b/tests/test_aai_vnf.py @@ -0,0 +1,449 @@ +"""Test A&AI VNF module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest import mock + +import pytest + +from onapsdk.aai.business import ServiceInstance, VnfInstance, PnfInstance, VfModuleInstance +from onapsdk.so.deletion import VnfDeletionRequest +from onapsdk.so.instantiation import VfModuleInstantiation, VnfInstantiation, SoService +from onapsdk.exceptions import ResourceNotFound, StatusError + + +VNF_INSTANCE = { + "vnf-id":"6d644ab5-254d-4a49-98fe-0f481c099f1a", + "vnf-name":"Python_ONAP_SDK_vnf_instance_14856120-e946-46ce-bf5f-384b20209f9c", + "vnf-type":"testService11/testVF11 0", + "service-id":"1234", + "prov-status":"PREPROV", + "orchestration-status":"Inventoried", + "in-maint":True, + "is-closed-loop-disabled":False, + "resource-version":"1590395148980", + "model-invariant-id":"a3285832-77d5-4ab2-95c5-217070de77c9", + "model-version-id":"0da841b9-f787-4ce0-9227-a23092a4a035", + "model-customization-id":"9426293e-bc5d-4fd3-8236-85190f1142aa", + "selflink":"restconf/config/GENERIC-RESOURCE-API:services/service/5410bf79-2aa3-450e-a324-ec5630dc18cf/service-data/vnfs/vnf/6d644ab5-254d-4a49-98fe-0f481c099f1a/vnf-data/vnf-topology/", + "relationship-list":{ + "relationship":[ + { + "related-to":"tenant", + "relationship-label":"org.onap.relationships.inventory.BelongsTo", + "related-link":"/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/DT/RegionOne/tenants/tenant/89788fdf49514f94963b12a6c0cfdc71", + "relationship-data":[ + { + "relationship-key":"cloud-region.cloud-owner", + "relationship-value":"DT" + }, + { + "relationship-key":"cloud-region.cloud-region-id", + "relationship-value":"RegionOne" + }, + { + "relationship-key":"tenant.tenant-id", + "relationship-value":"89788fdf49514f94963b12a6c0cfdc71" + } + ], + "related-to-property":[ + { + "property-key":"tenant.tenant-name", + "property-value":"onap-devel" + } + ] + }, + { + "related-to":"cloud-region", + "relationship-label":"org.onap.relationships.inventory.LocatedIn", + "related-link":"/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/DT/RegionOne", + "relationship-data":[ + { + "relationship-key":"cloud-region.cloud-owner", + "relationship-value":"DT" + },{ + "relationship-key":"cloud-region.cloud-region-id", + "relationship-value":"RegionOne" + } + ], + "related-to-property":[ + { + "property-key":"cloud-region.owner-defined-type", + "property-value":"" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v19/business/customers/customer/generic/service-subscriptions/service-subscription/testService11/service-instances/service-instance/5410bf79-2aa3-450e-a324-ec5630dc18cf", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"generic" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"testService11" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"5410bf79-2aa3-450e-a324-ec5630dc18cf" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"test22" + } + ] + }, + { + "related-to":"availability-zone", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/DT/RegionOne/availability-zones/availability-zone/nova", + "relationship-data":[ + { + "relationship-key":"cloud-region.cloud-owner", + "relationship-value":"DT" + }, + { + "relationship-key":"cloud-region.cloud-region-id", + "relationship-value":"RegionOne" + }, + { + "relationship-key":"availability-zone.availability-zone-name", + "relationship-value":"nova" + } + ] + }, + { + "related-to":"availability-zone", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/DT/RegionOne/availability-zones/availability-zone/brittany", + "relationship-data":[ + { + "relationship-key":"cloud-region.cloud-owner", + "relationship-value":"DT" + }, + { + "relationship-key":"cloud-region.cloud-region-id", + "relationship-value":"RegionOne" + }, + { + "relationship-key":"availability-zone.availability-zone-name", + "relationship-value":"brittany" + } + ] + }, + { + "related-to":"platform", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v19/business/platforms/platform/Python_ONAPSDK_Platform", + "relationship-data":[ + { + "relationship-key":"platform.platform-name", + "relationship-value":"Python_ONAPSDK_Platform" + } + ] + }, + { + "related-to":"line-of-business", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v19/business/lines-of-business/line-of-business/Python_ONAPSDK_LineOfBusiness", + "relationship-data":[ + { + "relationship-key":"line-of-business.line-of-business-name", + "relationship-value":"Python_ONAPSDK_LineOfBusiness" + } + ] + } + ] + } +} + + +VF_MODULE = { + "vf-module": [ + { + "vf-module-id": "test-module-id", + "is-base-vf-module": True, + "automated-assignment": False, + "vf-module-name": "test_vf_module", + "heat-stack-id": "test_heat_stack_id", + "orchestration-status": "test_orchestration_status", + "resource-version": "1590395148980", + "model-invariant-id": "test_model_invariant_id", + "model-version-id": "test_model_version_id" + } + ] +} + + +COUNT = { + "results":[ + { + "generic-vnf":17 + } + ] +} + + +@mock.patch.object(VnfDeletionRequest, "send_request") +def test_vnf_instance(mock_vnf_deletion_request): + service_instance = ServiceInstance(None, + instance_id="test_service_instance_id") + vnf_instance = VnfInstance(service_instance, + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True) + assert vnf_instance.service_instance == service_instance + assert vnf_instance.vnf_id == "test_vnf_id" + assert vnf_instance.vnf_type == "test_vnf_type" + assert vnf_instance.in_maint is False + assert vnf_instance.is_closed_loop_disabled is True + assert vnf_instance._vnf is None + assert vnf_instance.url == (f"{vnf_instance.base_url}{vnf_instance.api_version}/network/" + f"generic-vnfs/generic-vnf/{vnf_instance.vnf_id}") + vnf_instance.delete() + mock_vnf_deletion_request.assert_called_once_with(vnf_instance, True) + + +@mock.patch.object(VnfInstance, "send_message_json") +def test_vnf_instance_vf_modules(mock_vnf_instance_send_message_json): + service_instance = mock.MagicMock() + vnf_instance = VnfInstance(service_instance, + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True) + mock_vnf_instance_send_message_json.return_value = {"vf-module": []} + vf_modules = list(vnf_instance.vf_modules) + assert len(vf_modules) == 0 + + mock_vnf_instance_send_message_json.return_value = VF_MODULE + vf_modules = list(vnf_instance.vf_modules) + assert len(vf_modules) == 1 + + +def test_vnf_instance_vnf(): + service_instance = mock.MagicMock() + vnf_instance = VnfInstance(service_instance, + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True, + model_version_id="test_model_version_id") + assert vnf_instance._vnf is None + service_instance.sdc_service.vnfs = [] + with pytest.raises(ResourceNotFound) as exc: + vnf_instance.vnf + assert exc.type == ResourceNotFound + assert vnf_instance._vnf is None + + vnf = mock.MagicMock() + vnf.model_version_id = "test_model_version_id" + service_instance.sdc_service.vnfs = [vnf] + assert vnf == vnf_instance.vnf + assert vnf_instance._vnf is not None + assert vnf_instance.vnf == vnf_instance._vnf + + +@mock.patch.object(VfModuleInstantiation, "instantiate_ala_carte") +def test_vnf_add_vf_module(mock_vf_module_instantiation): + vnf_instance = VnfInstance(mock.MagicMock(), + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True, + model_version_id="test_model_version_id") + vnf_instance.add_vf_module(mock.MagicMock()) + mock_vf_module_instantiation.assert_called_once() + + +@mock.patch.object(VnfInstance, "_execute_so_action") +@mock.patch.object(VnfInstance, "vnf") +def test_vnf_update(mock_vnf, mock_vnf_instantiation): + + property_skip_true = mock.MagicMock() + property_skip_true.name = "skip_post_instantiation_configuration" + property_skip_true.value = "false" + + vnf_instance = mock.MagicMock() + vnf_instance.vnf = mock_vnf + vnf_instance.vnf.properties = (item for item in [property_skip_true]) + + vnf_instance = VnfInstance(vnf_instance, + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True) + + vnf_instance.update([mock.MagicMock()]) + mock_vnf_instantiation.assert_called_once() + + property_skip_false = mock.MagicMock() + property_skip_false.name = "skip_post_instantiation_configuration" + property_skip_false.value = "true" + + vnf_instance2 = mock.MagicMock() + vnf_instance2.vnf = mock_vnf + vnf_instance2.vnf.properties = (item for item in [property_skip_false]) + + vnf_instance2 = VnfInstance(vnf_instance2, + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True) + + with pytest.raises(StatusError): + vnf_instance2.update([mock.MagicMock()]) + + +@mock.patch.object(VnfInstance, "_execute_so_action") +def test_vnf_healthcheck(mock_vnf_instantiation): + + instance = mock.MagicMock() + vnf_instance = VnfInstance(instance, + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True) + + vnf_instance.healthcheck() + mock_vnf_instantiation.assert_called_once() + + +@mock.patch.object(VnfInstance, "_build_so_input") +@mock.patch.object(VnfInstantiation, "so_action") +def test_vnf_execute_so_action(mock_build_so_input, mock_so_action): + + instance = mock.MagicMock() + + relation_1 = mock.MagicMock() + relation_1.related_to = "line-of-business" + relation_1.relationship_data = [{"relationship-value": "test"}] + relation_2 = mock.MagicMock() + relation_2.related_to = "platform" + relation_2.relationship_data = [{"relationship-value": "test"}] + + vnf_instance = VnfInstance(instance, + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True) + + vnf_instance.service_instance = mock.MagicMock() + vnf_instance.service_instance.active = True + + type(vnf_instance).relationships = mock.PropertyMock(return_value=[relation_1, relation_2]) + + vnf_instance._execute_so_action(operation_type="test", + vnf_parameters=[mock.MagicMock()]) + mock_so_action.assert_called_once() + + vnf_instance.service_instance.active = False + with pytest.raises(StatusError): + vnf_instance._execute_so_action(operation_type="test", + vnf_parameters=[mock.MagicMock()]) + + +@mock.patch.object(VnfInstance, "send_message") +def test_build_so_input(mock_send_message): + + pnf = mock.MagicMock() + pnf.model_version_id = "test_pnf_model_version_id" + pnf.model_name = "test_model" + + vnf = mock.MagicMock() + vnf.model_version_id = "test_vnf_model_version_id" + vnf.model_name = "vnf_test_model" + + vf_module = mock.MagicMock() + vf_module.model_version_id = "test_vfm_model_version_id" + vf_module.model_name = "test..vfm_model..name" + + vnf.vf_modules = [vf_module] + + instance = mock.MagicMock() + instance.service_subscription = mock.MagicMock() + instance.service_subscription.service_type = "1234" + + instance.sdc_service.pnfs = [pnf] + instance.sdc_service.vnfs = [vnf] + + pnf_instance = PnfInstance(instance, + pnf_name="test_pnf", + in_maint=False, + model_version_id="test_pnf_model_version_id") + + vnf_instance = VnfInstance(instance, + vnf_name="test_name", + vnf_id="test_vnf_id", + vnf_type="test_vnf_type", + in_maint=False, + is_closed_loop_disabled=True, + model_version_id="test_vnf_model_version_id") + + vf_module_instance = VfModuleInstance(vnf_instance=vnf_instance, + vf_module_name="test_vfm_name", + model_version_id="test_vfm_model_version_id", + vf_module_id="test_vf_module_id", + is_base_vf_module=True, + automated_assignment=False) + + vnf_instance.vnf.vf_modules = [vf_module] + type(vnf_instance).vf_modules = mock.PropertyMock(return_value=[vf_module_instance]) + instance.pnfs = [pnf_instance] + instance.vnf_instances = [vnf_instance] + + test_so_input_no_params = vnf_instance._build_so_input() + + assert isinstance(test_so_input_no_params, SoService) + assert len(test_so_input_no_params.vnfs[0].parameters) == 0 + + vnf_param1 = mock.MagicMock() + vnf_param1.name = "test_name" + vnf_param1.value = "test_value" + + test_so_input = vnf_instance._build_so_input([vnf_param1]) + + assert isinstance(test_so_input, SoService) + assert test_so_input.subscription_service_type == "1234" + assert not test_so_input.instance_name + assert len(test_so_input.vnfs) == 1 + + test_so_input_vnf = test_so_input.vnfs[0] + + assert test_so_input_vnf.model_name == "vnf_test_model" + assert test_so_input_vnf.instance_name == "test_name" + assert len(test_so_input_vnf.parameters) == 1 + assert test_so_input_vnf.parameters["test_name"] == "test_value" + assert len(test_so_input_vnf.vf_modules) == 1 + + test_so_input_vnf_vf_module = test_so_input_vnf.vf_modules[0] + + assert test_so_input_vnf_vf_module.model_name == "vfm_model" + assert test_so_input_vnf_vf_module.instance_name == "test_vfm_name" + assert len(test_so_input_vnf_vf_module.parameters) == 0 + + assert len(test_so_input.pnfs) == 1 + assert test_so_input.pnfs[0].model_name == "test_model" + assert test_so_input.pnfs[0].instance_name == "test_pnf" + +@mock.patch.object(VnfInstance, "send_message_json") +def test_vnf_instance_mock(mock_send_message_json): + mock_send_message_json.return_value = COUNT + assert VnfInstance.count() == 17 diff --git a/tests/test_cds.py b/tests/test_cds.py new file mode 100644 index 0000000..b7859f3 --- /dev/null +++ b/tests/test_cds.py @@ -0,0 +1,435 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import json +import os.path +from pathlib import Path +from tempfile import TemporaryDirectory +from unittest.mock import MagicMock, patch, PropertyMock, mock_open + +from pytest import raises + +from onapsdk.cds.blueprint import Blueprint, Mapping, MappingSet, ResolvedTemplate, Workflow +from onapsdk.cds.blueprint_processor import Blueprintprocessor +from onapsdk.cds.cds_element import CdsElement +from onapsdk.cds.data_dictionary import DataDictionary, DataDictionarySet +from onapsdk.exceptions import FileError, ParameterError, RequestError, ValidationError +from onapsdk.utils.gui import GuiItem, GuiList + +DD_1 = { + "name": "vf-module-name", + "tags": "vf-module-name", + "data_type": "string", + "description": "vf-module-name", + "entry_schema": "string", + "updatedBy": "Singal, Kapil <ks220y@att.com>", + "definition": { + "tags": "vf-module-name", + "name": "vf-module-name", + "property": { + "description": "vf-module-name", + "type": "string" + }, + "updated-by": "Singal, Kapil <ks220y@att.com>", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + } +} + + +RAW_DD = { + "tags": "vf-module-name", + "name": "vf-module-name", + "property": { + "description": "vf-module-name", + "type": "string" + }, + "updated-by": "Singal, Kapil <ks220y@att.com>", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } +} + + +vLB_CBA_Python_meta_bytes = b'TOSCA-Meta-File-Version: 1.0.0\nCSAR-Version: 1.0\nCreated-By: PLATANIA, MARCO <platania@research.att.com>\nEntry-Definitions: Definitions/vLB_CDS.json\nTemplate-Tags: vDNS-CDS-test1\nContent-Type: application/vnd.oasis.bpmn\nTemplate-Name: vDNS-CDS-test1\nTemplate-Version: 1.0' + +vLB_CBA_Python_base_template_mapping_bytes = b'[\n {\n "name": "service-instance-id",\n "property": {\n "description": "",\n "required": false,\n "type": "string",\n "status": "",\n "constraints": [\n {}\n ],\n "entry_schema": {\n "type": ""\n }\n },\n "input-param": false,\n "dictionary-name": "service-instance-id",\n "dictionary-source": "input",\n "dependencies": [],\n "version": 0\n },\n {\n "name": "vnf-id",\n "property": {\n "description": "",\n "required": false,\n "type": "string",\n "status": "",\n "constraints": [\n {}\n ],\n "entry_schema": {\n "type": ""\n }\n },\n "input-param": false,\n "dictionary-name": "vnf-id",\n "dictionary-source": "input",\n "dependencies": [],\n "version": 0\n },\n {\n "name": "vdns_vf_module_id",\n "property": {\n "description": "",\n "required": false,\n "type": "string",\n "status": "",\n "constraints": [\n {}\n ],\n "entry_schema": {\n "type": ""\n }\n },\n "input-param": false,\n "dictionary-name": "vdns_vf_module_id",\n "dictionary-source": "sdnc",\n "dependencies": [\n\t "service-instance-id",\n "vnf-id"\n ],\n "version": 0\n },\n {\n "name": "vdns_int_private_ip_0",\n "property": {\n "description": "",\n "required": false,\n "type": "string",\n "status": "",\n "constraints": [\n {}\n ],\n "entry_schema": {\n "type": ""\n }\n },\n "input-param": false,\n "dictionary-name": "vdns_int_private_ip_0",\n "dictionary-source": "sdnc",\n "dependencies": [\n "service-instance-id",\n "vnf-id",\n "vdns_vf_module_id"\n ],\n "version": 0\n },\n {\n "name": "vdns_onap_private_ip_0",\n "property": {\n "description": "",\n "required": false,\n "type": "string",\n "status": "",\n "constraints": [\n {}\n ],\n "entry_schema": {\n "type": ""\n }\n },\n "input-param": false,\n "dictionary-name": "vdns_onap_private_ip_0",\n "dictionary-source": "sdnc",\n "dependencies": [\n "service-instance-id",\n "vnf-id",\n "vdns_vf_module_id"\n ],\n "version": 0\n }\n]' + + +@patch.object(Blueprint, "send_message") +def test_blueprint_enrichment(send_message_mock): + blueprint = Blueprint(b"test cba - it will never work") + blueprint.enrich() + send_message_mock.assert_called_once() + send_message_mock.reset_mock() + send_message_mock.side_effect = RequestError + with raises(RequestError): + blueprint.enrich() + + +@patch.object(Blueprint, "send_message") +def test_blueprint_publish(send_message_mock): + blueprint = Blueprint(b"test cba - it will never work") + blueprint.publish() + send_message_mock.assert_called_once() + + +@patch.object(Blueprint, "send_message") +def test_blueprint_deploy(send_message_mock): + blueprint = Blueprint(b"test cba - it will never work") + blueprint.deploy() + send_message_mock.assert_called_once() + + +def test_blueprint_load_from_file(): + with TemporaryDirectory() as tmpdirname: + path = os.path.join(tmpdirname, "test.zip") + with open(path, "wb") as f: + f.write(b"test cba - it will never work") + blueprint = Blueprint.load_from_file(path) + assert blueprint.cba_file_bytes == b"test cba - it will never work" + +def test_blueprint_load_from_file_file_error(): + + with TemporaryDirectory() as tmpdirname, \ + patch("__main__.open", new_callable=mock_open) as mo, \ + raises(FileError) as exc: + + path = os.path.join(tmpdirname, "nonexistent_file.zip") + mo.side_effect = FileNotFoundError + + Blueprint.load_from_file(path) + + assert exc.type == FileError + + +def test_blueprint_save(): + blueprint = Blueprint(b"test cba - it will never work") + with TemporaryDirectory() as tmpdirname: + path = os.path.join(tmpdirname, "test.zip") + blueprint.save(path) + with open(path, "rb") as f: + assert f.read() == b"test cba - it will never work" + + +def test_blueprint_read_cba_metadata(): + b = Blueprint(b"test cba - it will never work") + with raises(ValidationError) as exc: + b.get_cba_metadata(b"Invalid") + b.get_cba_metadata(b"123: 456") + assert exc.type is ValidationError + + cba_metadata = b.get_cba_metadata(vLB_CBA_Python_meta_bytes) + assert cba_metadata.tosca_meta_file_version == "1.0.0" + assert cba_metadata.csar_version == 1.0 + assert cba_metadata.created_by == "PLATANIA, MARCO <platania@research.att.com>" + assert cba_metadata.entry_definitions == "Definitions/vLB_CDS.json" + assert cba_metadata.template_name == "vDNS-CDS-test1" + assert cba_metadata.template_version == 1.0 + assert cba_metadata.template_tags == "vDNS-CDS-test1" + + with open(Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip"), "rb") as cba_file: + b = Blueprint(cba_file.read()) + assert b.metadata.tosca_meta_file_version == "1.0.0" + assert b.metadata.csar_version == 1.0 + assert b.metadata.created_by == "PLATANIA, MARCO <platania@research.att.com>" + assert b.metadata.entry_definitions == "Definitions/vLB_CDS.json" + assert b.metadata.template_name == "vDNS-CDS-test1" + assert b.metadata.template_version == 1.0 + assert b.metadata.template_tags == "vDNS-CDS-test1" + + +def test_blueprint_get_mappings_from_mapping_file(): + b = Blueprint(b"test cba - it will never work") + mappings = list(b.get_mappings_from_mapping_file(vLB_CBA_Python_base_template_mapping_bytes)) + assert len(mappings) == 5 + mapping = mappings[0] + assert mapping.name == "service-instance-id" + assert mapping.mapping_type == "string" + assert mapping.dictionary_name == "service-instance-id" + assert mapping.dictionary_sources == ["input"] + + +def test_blueprint_generate_data_dictionary_set(): + with open(Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip"), "rb") as cba_file: + b = Blueprint(cba_file.read()) + dd_set = b.get_data_dictionaries() + print(dd_set) + + +@patch.object(CdsElement, "_url", new_callable=PropertyMock) +def test_data_dictionary(cds_element_url_property_mock): + cds_element_url_property_mock.return_value = "http://127.0.0.1" + + with raises(ValidationError) as exc: + DataDictionary({}) + assert exc.type is ValidationError + + dd = DataDictionary({}, fix_schema=False) + assert dd.url == "http://127.0.0.1/api/v1/dictionary" + assert dd.data_dictionary_json == {} + + dd = DataDictionary(DD_1) + dd.name == DD_1["name"] + + +@patch.object(DataDictionary, "send_message") +def test_data_dictionary_upload(send_message_mock): + dd = DataDictionary(DD_1) + dd.upload() + send_message_mock.assert_called_once() + + +@patch.object(DataDictionary, "send_message") +def test_data_dictionary_set(send_message_mock): + dd_set = DataDictionarySet() + + dd_set.add(DataDictionary(DD_1)) + assert dd_set.length == 1 + + dd_set.add(DataDictionary(DD_1)) + assert dd_set.length == 1 + + dd_set.add(DataDictionary({"name": "test"}, fix_schema=False)) + assert dd_set.length == 2 + + dd_set.upload() + assert send_message_mock.call_count == 2 + + +def test_data_dictionary_set_save_to_file_load_from_file(): + dd = DataDictionarySet() + dd.add(DataDictionary(DD_1)) + with TemporaryDirectory() as tmpdirname: + path = os.path.join(tmpdirname, "dd.json") + dd.save_to_file(path) + with open(path, "r") as f: + assert f.read() == json.dumps([dd.data_dictionary_json for dd in dd.dd_set], indent=4) + dd_2 = DataDictionarySet.load_from_file(path) + assert dd.dd_set == dd_2.dd_set + +def test_data_dictionary_load_from_file_file_error(): + + with TemporaryDirectory() as tmpdirname, \ + patch("__main__.open", new_callable=mock_open) as mo, \ + raises(FileError) as exc: + + path = os.path.join(tmpdirname, "nonexistent_file.zip") + mo.side_effect = FileNotFoundError + + DataDictionarySet.load_from_file(path) + + assert exc.type == FileError + + +def test_mapping(): + m1 = Mapping(name="test", + mapping_type="string", + dictionary_name="test_dictionary_name", + dictionary_sources=["dictionary_source_1"]) + + m2 = Mapping(name="test", mapping_type="string", dictionary_name="test_dictionary_name", dictionary_sources=["dictionary_source_2"]) + + assert m1 == m2 + m1.merge(m2) + assert sorted(m1.dictionary_sources) == ["dictionary_source_1", "dictionary_source_2"] + m1.merge(m2) + assert sorted(m1.dictionary_sources) == ["dictionary_source_1", "dictionary_source_2"] + + +def test_mapping_set(): + ms = MappingSet() + assert len(ms) == 0 + m1 = Mapping(name="test", + mapping_type="string", + dictionary_name="test_dictionary_name", + dictionary_sources=["dictionary_source_1"]) + + m2 = Mapping(name="test", mapping_type="string", dictionary_name="test_dictionary_name", dictionary_sources=["dictionary_source_2"]) + + ms.add(m1) + assert len(ms) == 1 + ms.add(m2) + assert len(ms) == 1 + assert sorted(ms[0].dictionary_sources) == ["dictionary_source_1", "dictionary_source_2"] + + +def test_blueprint_get_workflows_from_entry_definitions_file(): + with open(Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip"), "rb") as cba_file: + b = Blueprint(cba_file.read()) + assert len(b.workflows) == 3 + workflow = b.workflows[0] + assert len(workflow.steps) == 1 + assert workflow.steps[0].name == "resource-assignment" + assert workflow.steps[0].description == "Resource Assign Workflow" + assert workflow.steps[0].target == "resource-assignment" + assert len(workflow.inputs) == 2 + assert len(workflow.outputs) == 1 + + +def test_blueprint_get_workflow_by_name(): + with open(Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip"), "rb") as cba_file: + b = Blueprint(cba_file.read()) + workflow = b.get_workflow_by_name("resource-assignment") + assert workflow.name == "resource-assignment" + workflow = b.get_workflow_by_name("config-assign") + assert workflow.name == "config-assign" + workflow = b.get_workflow_by_name("config-deploy") + assert workflow.name == "config-deploy" + with raises(ParameterError): + b.get_workflow_by_name("non-existing-workflow") + + +@patch.object(Workflow, "send_message") +def test_workflow_execute(send_message_mock): + metadata = MagicMock(template_name="test", template_version="test") + blueprint = MagicMock(metadata=metadata) + workflow = Workflow("test_workflow", {}, blueprint) + assert len(workflow.steps) == 0 + assert len(workflow.inputs) == 0 + assert len(workflow.outputs) == 0 + workflow.execute({}) + send_message_mock.assert_called_once() + + +def test_data_dictionary_validation(): + assert DataDictionary(DD_1).has_valid_schema() + raw_dd = DataDictionary(RAW_DD, fix_schema=False) + assert not raw_dd.has_valid_schema() + raw_dd = DataDictionary(RAW_DD, fix_schema=True) + assert raw_dd.has_valid_schema() + + +@patch.object(Blueprintprocessor, "send_message") +def test_blueprintprocessor_bootstrap(mock_send_message): + + Blueprintprocessor.bootstrap() + assert mock_send_message.called_once() + assert mock_send_message.call_args[1]["data"] == '{\n "loadModelType" : true,\n "loadResourceDictionary" : true,\n "loadCBA" : true\n}' + mock_send_message.reset_mock() + + Blueprintprocessor.bootstrap(load_cba=False, load_model_type=False, load_resource_dictionary=False) + assert mock_send_message.called_once() + assert mock_send_message.call_args[1]["data"] == '{\n "loadModelType" : false,\n "loadResourceDictionary" : false,\n "loadCBA" : false\n}' + + +@patch.object(DataDictionary, "send_message_json") +def test_data_dictionary_get_by_name(mock_send_message_json): + + DataDictionary.get_by_name("test_name") + mock_send_message_json.assert_called_once() + assert "test_name" in mock_send_message_json.call_args[0][2] + + +@patch.object(CdsElement, "send_message") +def test_get_guis(send_message_mock): + component = CdsElement() + send_message_mock.return_value.status_code = 200 + send_message_mock.return_value.url = "http://portal.api.simpledemo.onap.org:30449/" + gui_results = component.get_guis() + assert type(gui_results) == GuiList + assert gui_results.guilist[0].url == send_message_mock.return_value.url + assert gui_results.guilist[0].status == send_message_mock.return_value.status_code + + +@patch.object(ResolvedTemplate, "send_message_json") +@patch.object(CdsElement, "_url", new_callable=PropertyMock) +def test_blueprint_get_resolved_template(cds_element_url_property_mock, mock_send_message_json): + cds_element_url_property_mock.return_value = "http://127.0.0.1" + + with open(Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip"), "rb") as cba_file: + b = Blueprint(cba_file.read()) + b.get_resolved_template("test_artifact") + assert mock_send_message_json.called_once() + assert mock_send_message_json.call_args[0][2] == 'http://127.0.0.1/api/v1/template?bpName=vDNS-CDS-test1&bpVersion=1.0&artifactName=test_artifact&format=application%2Fjson' + + +@patch.object(ResolvedTemplate, "send_message") +@patch.object(CdsElement, "_url", new_callable=PropertyMock) +def test_blueprint_store_resolved_template(cds_element_url_property_mock, mock_send_message): + cds_element_url_property_mock.return_value = "http://127.0.0.1" + + with open(Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip"), "rb") as cba_file: + b = Blueprint(cba_file.read()) + b.store_resolved_template("test_artifact", resolution_key="resolution_key", data={"a": "b"}) + assert mock_send_message.called_once() + assert mock_send_message.call_args[0][2] == 'http://127.0.0.1/api/v1/template/vDNS-CDS-test1/1.0/test_artifact/resolution_key' + + +@patch.object(ResolvedTemplate, "send_message_json") +@patch.object(CdsElement, "_url", new_callable=PropertyMock) +def test_resolved_template_get_template_url(cds_element_url_property_mock, mock_send_message_json): + cds_element_url_property_mock.return_value = "http://127.0.0.1" + blueprint = MagicMock() + blueprint.metadata.template_name = "test_blueprint" + blueprint.metadata.template_version = "v1.0.0" + rt = ResolvedTemplate(blueprint, "test_artifact") + rt.get_resolved_template() + assert mock_send_message_json.called_once() + assert mock_send_message_json.call_args[0][2] == 'http://127.0.0.1/api/v1/template?bpName=test_blueprint&bpVersion=v1.0.0&artifactName=test_artifact&format=application%2Fjson' + + mock_send_message_json.reset_mock() + blueprint = MagicMock() + blueprint.metadata.template_name = "test_blueprint" + blueprint.metadata.template_version = "v1.0.0" + rt = ResolvedTemplate(blueprint, resolution_key="test_rk") + rt.get_resolved_template() + assert mock_send_message_json.called_once() + assert mock_send_message_json.call_args[0][2] == 'http://127.0.0.1/api/v1/template?bpName=test_blueprint&bpVersion=v1.0.0&resolutionKey=test_rk&format=application%2Fjson' + + mock_send_message_json.reset_mock() + blueprint = MagicMock() + blueprint.metadata.template_name = "test_blueprint" + blueprint.metadata.template_version = "v1.0.0" + rt = ResolvedTemplate(blueprint, resource_id="r_id", resource_type="r_type") + rt.get_resolved_template() + assert mock_send_message_json.called_once() + assert mock_send_message_json.call_args[0][2] == 'http://127.0.0.1/api/v1/template?bpName=test_blueprint&bpVersion=v1.0.0&resourceType=r_type&resourceId=r_id&format=application%2Fjson' + + +@patch.object(ResolvedTemplate, "send_message") +@patch.object(CdsElement, "_url", new_callable=PropertyMock) +def test_resolved_template_store_template_url(cds_element_url_property_mock, mock_send_message): + cds_element_url_property_mock.return_value = "http://127.0.0.1" + + blueprint = MagicMock() + blueprint.metadata.template_name = "test_blueprint" + blueprint.metadata.template_version = "v1.0.0" + rt = ResolvedTemplate(blueprint, "test_artifact", resolution_key="resolution_key") + rt.store_resolved_template({"a": "b"}) + assert mock_send_message.called_once() + assert mock_send_message.call_args[0][2] == 'http://127.0.0.1/api/v1/template/test_blueprint/v1.0.0/test_artifact/resolution_key' + + mock_send_message.reset_mock() + rt = ResolvedTemplate(blueprint, "test_artifact", resource_id="resource_id", resource_type="resource_type") + rt.store_resolved_template({"a": "b"}) + assert mock_send_message.called_once() + assert mock_send_message.call_args[0][2] == 'http://127.0.0.1/api/v1/template/test_blueprint/v1.0.0/test_artifact/resource_type/resource_id' + + mock_send_message.reset_mock() + rt = ResolvedTemplate(blueprint, "test_artifact") + with raises(ParameterError): + rt.store_resolved_template({"a": "b"}) diff --git a/tests/test_cds_blueprint_models.py b/tests/test_cds_blueprint_models.py new file mode 100644 index 0000000..4b1744d --- /dev/null +++ b/tests/test_cds_blueprint_models.py @@ -0,0 +1,201 @@ +"""Test CdsBlueprintModel module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os.path + +from unittest import mock +from tempfile import TemporaryDirectory + +import pytest +import requests +import io + +from onapsdk.exceptions import ResourceNotFound +from onapsdk.cds.blueprint_model import BlueprintModel +from onapsdk.cds.cds_element import CdsElement +from onapsdk.cds.blueprint import Blueprint +from onapsdk.onap_service import OnapService + + +# pylint: disable=C0301 +BLUEPRINT_MODEL = { + "blueprintModel": { + "id": "11111111-2222-3333-4444-555555555555", + "artifactUUId": None, + "artifactType": "SDNC_MODEL", + "artifactVersion": "1.0.0", + "artifactDescription": "", + "internalVersion": None, + "createdDate": "2020-12-14T19:33:57.000Z", + "artifactName": "test_blueprint", + "published": "Y", + "updatedBy": "Carlos Santana <carlos.santana@onap.com>", + "tags": "Carlos Santana, test, blueprint" + } +} + +BLUEPRINT_MODEL_LIST = [ + BLUEPRINT_MODEL +] +# pylint: enable=C0301 + + +def test_init(): + """Test the initialization.""" + element = CdsElement() + assert isinstance(element, OnapService) + + +def test_class_variables(): + """Test the class variables.""" + assert CdsElement._url == "http://portal.api.simpledemo.onap.org:30449" + assert CdsElement.auth == ("ccsdkapps", "ccsdkapps") + assert CdsElement.headers == { + "Content-Type": "application/json", + "Accept": "application/json"} + + +@mock.patch.object(CdsElement, 'send_message_json') +def test_blueprint_model_all(mock_send): + """Test get_all function of BlueprintModel.""" + mock_send.return_value = BLUEPRINT_MODEL_LIST + assert len(list(BlueprintModel.get_all())) == 1 + + blueprint_model_1 = next(BlueprintModel.get_all()) + assert blueprint_model_1.blueprint_model_id == "11111111-2222-3333-4444-555555555555" + assert blueprint_model_1.artifact_uuid is None + assert blueprint_model_1.artifact_type == "SDNC_MODEL" + assert blueprint_model_1.artifact_version == "1.0.0" + assert blueprint_model_1.internal_version is None + assert blueprint_model_1.created_date == "2020-12-14T19:33:57.000Z" + assert blueprint_model_1.artifact_name == "test_blueprint" + assert blueprint_model_1.published == "Y" + assert blueprint_model_1.updated_by == "Carlos Santana <carlos.santana@onap.com>" + assert blueprint_model_1.tags == "Carlos Santana, test, blueprint" + + +@mock.patch.object(CdsElement, 'send_message_json') +def test_blueprint_model_all_empty(mock_send): + """Test get_all function of BlueprintModel with no BlueprintModels.""" + mock_send.return_value = "" + assert len(list(BlueprintModel.get_all())) == 0 + + +@mock.patch.object(CdsElement, 'send_message_json') +def test_blueprint_model_by_id(mock_send): + """Test get_by_id function of BlueprintModel.""" + mock_send.return_value = BLUEPRINT_MODEL + + blueprint_model_2 = BlueprintModel.get_by_id( + blueprint_model_id="11111111-2222-3333-4444-555555555555") + assert blueprint_model_2.blueprint_model_id == "11111111-2222-3333-4444-555555555555" + assert blueprint_model_2.artifact_uuid is None + assert blueprint_model_2.artifact_type == "SDNC_MODEL" + assert blueprint_model_2.artifact_version == "1.0.0" + assert blueprint_model_2.internal_version is None + assert blueprint_model_2.created_date == "2020-12-14T19:33:57.000Z" + assert blueprint_model_2.artifact_name == "test_blueprint" + assert blueprint_model_2.published == "Y" + assert blueprint_model_2.updated_by == "Carlos Santana <carlos.santana@onap.com>" + assert blueprint_model_2.tags == "Carlos Santana, test, blueprint" + + +@mock.patch.object(CdsElement, 'send_message_json') +def test_blueprint_model_by_id_non_existing(mock_send): + """Test get_by_id exception for non existing BlueprintModel.""" + + mock_send.side_effect = ResourceNotFound + with pytest.raises(ResourceNotFound) as exc: + BlueprintModel.get_by_id( + blueprint_model_id="11111111-2222-3333-4444-555555555555") + + assert exc.type == ResourceNotFound + + +@mock.patch.object(CdsElement, 'send_message_json') +def test_blueprint_model_by_name_and_version(mock_send): + """Test get_by_name_and_version function of BlueprintModel.""" + mock_send.return_value = BLUEPRINT_MODEL + + blueprint_model_3 = BlueprintModel.get_by_name_and_version( + blueprint_name="test_blueprint", + blueprint_version="1.0.0") + assert blueprint_model_3.blueprint_model_id == "11111111-2222-3333-4444-555555555555" + assert blueprint_model_3.artifact_uuid is None + assert blueprint_model_3.artifact_type == "SDNC_MODEL" + assert blueprint_model_3.artifact_version == "1.0.0" + assert blueprint_model_3.internal_version is None + assert blueprint_model_3.created_date == "2020-12-14T19:33:57.000Z" + assert blueprint_model_3.artifact_name == "test_blueprint" + assert blueprint_model_3.published == "Y" + assert blueprint_model_3.updated_by == "Carlos Santana <carlos.santana@onap.com>" + assert blueprint_model_3.tags == "Carlos Santana, test, blueprint" + + +@mock.patch.object(CdsElement, 'send_message_json') +def test_blueprint_model_by_name_and_version_non_existing(mock_send): + """Test get_by_name_and_version exception for non existing BlueprintModel.""" + + mock_send.side_effect = ResourceNotFound + with pytest.raises(ResourceNotFound) as exc: + BlueprintModel.get_by_name_and_version( + blueprint_name="test_blueprint_wrong", + blueprint_version="1.0.0") + + assert exc.type == ResourceNotFound + + +@mock.patch.object(CdsElement, 'send_message') +def test_get_blueprint_object(mock_send): + """Test retrieve Blueprint object for selected BlueprintModel.""" + mock_send.return_value.content = b"test cba - it will never work" + + blueprint_model_4 = BlueprintModel( + blueprint_model_id="11111111-2222-3333-4444-555555555555") + + blueprint4_object = blueprint_model_4.get_blueprint() + assert isinstance(blueprint4_object, Blueprint) + + +@mock.patch.object(CdsElement, 'send_message') +def test_save_blueprint(mock_send): + """Test download BlueprintModel from onap cds.""" + r = requests.Response() + r.raw = io.BytesIO(b'test cba - it will never work') + mock_send.return_value = r + + blueprint_model_5 = BlueprintModel( + blueprint_model_id="11111111-2222-3333-4444-555555555555") + + with TemporaryDirectory() as tmpdirname: + path = os.path.join(tmpdirname, "test.zip") + blueprint_model_5.save(dst_file_path=path) + + with open(path, "rb") as f: + assert f.read() == b"test cba - it will never work" + + +@mock.patch.object(CdsElement, 'send_message') +def test_delete_blueprint(mock_send): + """Test delete BlueprintModel in onap cds. """ + + blueprint_model_6 = BlueprintModel( + blueprint_model_id="11111111-2222-3333-4444-555555555555") + blueprint_model_6.delete() + mock_send.assert_called_once() + + method, description, url = mock_send.call_args[0] + assert method == "DELETE" + assert description == f"Delete blueprint" + assert url == f"{CdsElement._url}/api/v1/blueprint-model/{blueprint_model_6.blueprint_model_id}" diff --git a/tests/test_clamp.py b/tests/test_clamp.py new file mode 100644 index 0000000..5768341 --- /dev/null +++ b/tests/test_clamp.py @@ -0,0 +1,532 @@ +"""Test clamp module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest import mock +import pytest + +from onapsdk.clamp.clamp_element import Clamp +from onapsdk.clamp.loop_instance import LoopInstance +from onapsdk.exceptions import ParameterError, ResourceNotFound +from onapsdk.sdc.service import Service + +#examples +TEMPLATES = [ + { + "name" : "test_template", + "modelService" : { + "serviceDetails" : { + "name" : "test" + } + } + } +] + +POLICIES = [ + { + "policyModelType" : "onap.policies.controlloop.Test", + "version" : "1.0.0", + "policyAcronym" : "Test", + "createdDate" : "2020-04-30T09:03:30.362897Z", + "updatedDate" : "2020-04-30T09:03:30.362897Z", + "updatedBy" : "Not found", + "createdBy" : "Not found" + } +] + +LOOP_DETAILS = { + "name" : "LOOP_test", + "globalPropertiesJson": { + "dcaeDeployParameters" : { + "uniqueBlueprintParameters" : { + "policy_id" : "Microservice12345" + } + } + }, + "components" : { + "POLICY" : { + "componentState" : { + "stateName" : "UNKNOWN" + } + }, + "DCAE" : { + "componentState" : { + "stateName" : "BLUEPRINT_DEPLOYED" + } + } + }, + "modelService" : { + "resourceDetails": { + "VFModule" : { + "resourceID" : { + "vfModuleModelName" : "resourceID", + "vfModuleModelInvariantUUID" : "InvariantUUID", + "vfModuleModelUUID" : "UUID", + "vfModuleModelVersion" : "1.0", + "vfModuleModelCustomizationUUID" : "CustomizationUUID" + } + } + } + }, + "operationalPolicies" : [ + { + "name" : "MICROSERVICE_test" + } + ], + "microServicePolicies" : [ + { + "name" : "MICROSERVICE_test" + } + ] +} + +#for policy deploy to policy engine +SUBMITED_POLICY = { + "components" : { + "POLICY" : { + "componentState" : { + "stateName" : "SENT_AND_DEPLOYED" + } + } + } +} + +NOT_SUBMITED_POLICY = { + "components" : { + "POLICY" : { + "componentState" : { + "stateName" : "SENT" + } + } + } +} + +#for the deploy to DCAE +SUBMITED = { + "components" : { + "DCAE" : { + "componentState" : { + "stateName" : "MICROSERVICE_INSTALLED_SUCCESSFULLY" + } + } + } +} + +NOT_SUBMITED = { + "components" : { + "DCAE" : { + "componentState" : { + "stateName" : "MICROSERVICE_INSTALLATION_FAILED" + } + } + } +} +#end of examples + + +def test_initialization(): + """Class initialization test.""" + clamp = Clamp() + assert isinstance(clamp, Clamp) + + +@mock.patch.object(Clamp, 'send_message_json') +def test_check_loop_template(mock_send_message_json): + """Test Clamp's class method.""" + svc = Service(name='test') + mock_send_message_json.return_value = TEMPLATES + template = Clamp.check_loop_template(service=svc) + mock_send_message_json.assert_called_once_with('GET', + 'Get Loop Templates', + (f"{Clamp.base_url()}/templates/")) + assert template == "test_template" + + +@mock.patch.object(Clamp, 'send_message_json') +def test_check_loop_template_none(mock_send_message_json): + """Test Clamp's class method.""" + svc = Service(name='test') + mock_send_message_json.return_value = {} + with pytest.raises(ResourceNotFound) as exc: + template = Clamp.check_loop_template(service=svc) + assert template is None + assert exc.type is ResourceNotFound + + +@mock.patch.object(Clamp, 'send_message_json') +def test_check_policies(mock_send_message_json): + mock_send_message_json.return_value = POLICIES + exists = Clamp.check_policies(policy_name="Test", req_policies=1) + mock_send_message_json.\ + assert_called_once_with('GET', + 'Get stocked policies', + (f"{Clamp.base_url()}/policyToscaModels/")) + assert exists + + +@mock.patch.object(Clamp, 'send_message_json') +def test_check_policies_none(mock_send_message_json): + mock_send_message_json.return_value = POLICIES + exists = Clamp.check_policies(policy_name="Test") + mock_send_message_json.\ + assert_called_once_with('GET', + 'Get stocked policies', + (f"{Clamp.base_url()}/policyToscaModels/")) + assert not exists + + +def test_cl_initialization(): + """Class initialization test.""" + loop = LoopInstance(template="template", name="LOOP_name", details={}) + assert isinstance(loop, LoopInstance) + + +@mock.patch.object(LoopInstance, '_update_loop_details') +def test_details(mock_update): + """Test loop instace details gette.""" + loop = LoopInstance(template="template", name="LOOP_name", details={}) + mock_update.return_value = {"name" : "test"} + details = loop.details + assert details == {} + + +@mock.patch.object(LoopInstance, 'send_message_json') +def test_update_loop_details(mock_send_message_json): + """Test Loop instance methode.""" + loop = LoopInstance(template="template", name="test", details={}) + mock_send_message_json.return_value = LOOP_DETAILS + loop.details = loop._update_loop_details() + mock_send_message_json.assert_called_once_with('GET', 'Get loop details', + (f"{loop.base_url()}/loop/LOOP_test")) + assert loop.details == LOOP_DETAILS + + +@mock.patch('time.sleep', return_value=False) +@mock.patch.object(LoopInstance, 'send_message_json') +def test_refresh_status(mock_send_message_json,mock_timer): + """Test Loop instance methode.""" + loop = LoopInstance(template="template", name="test", details={}) + mock_send_message_json.return_value = LOOP_DETAILS + loop.refresh_status() + mock_send_message_json.assert_called_once_with('GET', 'Get loop status', + (f"{loop.base_url()}/loop/getstatus/LOOP_test")) + assert loop.details == LOOP_DETAILS + + +def test_validate(): + """Test Loop instance details validation.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + valid = loop.validate_details() + assert valid + + +def test_validate_details(): + """Test Loop instance details validation.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + loop.details = {"test":"test"} + valid = loop.validate_details() + assert not valid + + +@mock.patch.object(LoopInstance, 'send_message_json') +def test_create(mock_send_message_json): + """Test Loop instance creation.""" + instance = LoopInstance(template="template", name="test", details={}) + mock_send_message_json.return_value = LOOP_DETAILS + instance.create() + mock_send_message_json.assert_called_once_with('POST', 'Create Loop Instance', + (f"{instance.base_url()}/loop/create/LOOP_test?templateName=template")) + assert instance.name == "LOOP_test" + assert len(instance.details["microServicePolicies"]) > 0 + + +@mock.patch.object(LoopInstance, 'send_message_json') +def test_add_operational_policy(mock_send_message_json): + """Test adding an op policy.""" + loop = LoopInstance(template="template", name="test", details={}) + loop.details = { + "name" : "LOOP_test", + "operationalPolicies" : None, + "microServicePolicies" : [ + { + "name" : "MICROSERVICE_test" + } + ] + } + mock_send_message_json.return_value = LOOP_DETAILS + loop.add_operational_policy(policy_type="FrequencyLimiter", policy_version="1.0.0") + mock_send_message_json.assert_called_once_with('PUT', 'Create Operational Policy', + (f"{loop.base_url()}/loop/addOperationaPolicy/{loop.name}/policyModel/FrequencyLimiter/1.0.0")) + assert loop.name == "LOOP_test" + assert len(loop.details["operationalPolicies"]) > 0 + + +@mock.patch.object(LoopInstance, 'send_message_json') +def test_not_add_operational_policy_parameter_error(mock_send_message_json): + """Test adding an op policy - mistaken policy version.""" + loop = LoopInstance(template="template", name="test", details={}) + loop.details = { + "name" : "LOOP_test", + "operationalPolicies" : [], + "microServicePolicies" : [ + { + "name" : "MICROSERVICE_test" + } + ] + } + with pytest.raises(ParameterError) as exc: + mock_send_message_json.return_value = loop.details + loop.add_operational_policy(policy_type="FrequencyLimiter", policy_version="not_correct") + mock_send_message_json.assert_called_once_with('PUT', 'Create Operational Policy', + (f"{loop.base_url()}/loop/addOperationaPolicy/{loop.name}/policyModel/FrequencyLimiter/not_correct")) + assert len(loop.details["operationalPolicies"]) == 0 + assert exc.type is ParameterError + +@mock.patch.object(LoopInstance, 'send_message_json') +def test_add_operational_policy_key_parameter_error(mock_send_message_json): + """Test adding an op policy - key doesn't exist.""" + loop = LoopInstance(template="template", name="test", details={}) + loop.details = {} + with pytest.raises(ParameterError) as exc: + mock_send_message_json.return_value = loop.details + loop.add_operational_policy(policy_type="FrequencyLimiter", policy_version="not_correct") + mock_send_message_json.assert_called_once_with('PUT', 'Create Operational Policy', + (f"{loop.base_url()}/loop/addOperationaPolicy/{loop.name}/policyModel/FrequencyLimiter/not_correct")) + assert exc.type is ParameterError + +@mock.patch.object(LoopInstance, 'send_message_json') +def test_add_operational_policy_condition_parameter_error(mock_send_message_json): + """Test adding an op policy - response cintains more policies.""" + + key = "operationalPolicies" + + response_policies = ["one"] # N policies + current_policies = ["one", "two"] # N+1 policies + + details = {key: current_policies} + response = {key: response_policies} + + loop = LoopInstance(template="template", name="test", details=details) + + assert len(response_policies) < len(current_policies) # raising condition + with pytest.raises(ParameterError) as exc: + mock_send_message_json.return_value = response + loop.add_operational_policy(policy_type="FrequencyLimiter", policy_version="not_correct") + assert exc.type is ParameterError + + +@mock.patch.object(LoopInstance, 'send_message_json') +def test_remove_operational_policy(mock_send_message_json): + """Test remove an op policy.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_send_message_json.return_value = { + "name" : "LOOP_test", + "operationalPolicies" : [], + "microServicePolicies" : [ + { + "name" : "MICROSERVICE_test" + } + ] + } + loop.remove_operational_policy(policy_type="FrequencyLimiter", policy_version="1.0.0") + mock_send_message_json.assert_called_once_with('PUT', 'Remove Operational Policy', + (f"{loop.base_url()}/loop/removeOperationaPolicy/{loop.name}/policyModel/FrequencyLimiter/1.0.0")) + assert len(loop.details["operationalPolicies"]) == 0 + + +@mock.patch.object(LoopInstance, 'send_message') +def test_update_microservice_policy(mock_send_message): + """Test Loop Instance add TCA configuration.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_send_message.return_value = True + loop.update_microservice_policy() + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "ADD TCA config" + assert url == (f"{loop.base_url()}/loop/updateMicroservicePolicy/{loop.name}") + + +@mock.patch.object(LoopInstance, 'send_message') +def test_update_microservice_policy_none(mock_send_message): + """Test Loop Instance add TCA configuration.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_send_message.return_value = False + loop.update_microservice_policy() + mock_send_message.assert_called_once() + + +def test_extract_operational_policy_name(): + """Test Loop Instance extract operational policy name.""" + loop = LoopInstance(template="template", name="test", details={}) + loop.details = {"operationalPolicies":[{"name":"test","policyModel":{"policyAcronym":"Drools"}}]} + policy_name = loop.extract_operational_policy_name(policy_type="Drools") + assert policy_name=='test' + + +def test_extract_none(): + """Test Loop Instance extract operational policy name.""" + loop = LoopInstance(template="template", name="test", details={}) + loop.details = {"operationalPolicies":[]} + with pytest.raises(ParameterError) as exc: + policy_name = loop.extract_operational_policy_name(policy_type="Drools") + assert policy_name == None + assert exc.type is ParameterError + + +@mock.patch.object(LoopInstance, 'extract_operational_policy_name') +@mock.patch.object(LoopInstance, 'send_message') +def test_add_drools_policy_config(mock_send_message, mock_extract): + """Test Loop Instance add op policy configuration.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_send_message.return_value = True + loop.add_op_policy_config(loop.add_drools_conf) + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "ADD operational policy config" + assert url == (f"{loop.base_url()}/loop/updateOperationalPolicies/{loop.name}") + + +@mock.patch.object(LoopInstance, 'extract_operational_policy_name') +@mock.patch.object(LoopInstance, 'send_message') +def test_add_minmax_config(mock_send_message, mock_extract): + """Test Loop Instance add op policy configuration.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_send_message.return_value = True + loop.add_op_policy_config(loop.add_minmax_config) + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "ADD operational policy config" + assert url == (f"{loop.base_url()}/loop/updateOperationalPolicies/{loop.name}") + + +@mock.patch.object(LoopInstance, 'extract_operational_policy_name') +@mock.patch.object(LoopInstance, 'send_message') +def test_add_frequency_policy_config(mock_send_message, mock_extract): + """Test Loop Instance add op policy configuration.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_send_message.return_value = True + loop.add_op_policy_config(loop.add_frequency_limiter) + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "ADD operational policy config" + assert url == (f"{loop.base_url()}/loop/updateOperationalPolicies/{loop.name}") + +@mock.patch.object(LoopInstance, 'send_message') +@mock.patch.object(LoopInstance, 'add_minmax_config') +@mock.patch.object(LoopInstance, 'add_frequency_limiter') +def test_add_two_policies_config(mock_freq, mock_min, mock_send_message): + """Test Loop Instance add op policy configuration.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_min.return_value = '[{"test1":"test1"}]' + mock_freq.return_value = '[{"test2":"test2"}]' + loop.add_op_policy_config(loop.add_minmax_config) + mock_min.assert_called_once() + mock_send_message.assert_called_once() + loop.add_op_policy_config(loop.add_frequency_limiter) + mock_freq.assert_called_once() + assert loop.operational_policies == '[{"test1":"test1"},{"test2":"test2"}]' + + +@mock.patch.object(LoopInstance, 'refresh_status') +@mock.patch.object(LoopInstance, 'send_message') +def test_submit_policy(mock_send_message, mock_refresh): + """Test submit policies to policy engine.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + action = loop.act_on_loop_policy(loop.submit) + mock_send_message.assert_called_once_with('PUT', + 'submit policy', + (f"{loop.base_url()}/loop/submit/LOOP_test")) + mock_refresh.assert_called_once() + loop.details = SUBMITED_POLICY + assert loop.details["components"]["POLICY"]["componentState"]["stateName"] == "SENT_AND_DEPLOYED" + + +@mock.patch.object(LoopInstance, 'refresh_status') +@mock.patch.object(LoopInstance, 'send_message') +def test_stop_policy(mock_send_message, mock_refresh): + """Test submit policies to policy engine.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + action = loop.act_on_loop_policy(loop.stop) + mock_send_message.assert_called_once_with('PUT', + 'stop policy', + (f"{loop.base_url()}/loop/stop/LOOP_test")) + mock_refresh.assert_called_once() + loop.details = {"components":{"POLICY":{"componentState":{"stateName":"SENT"}}}} + assert loop.details["components"]["POLICY"]["componentState"]["stateName"] == "SENT" + + +@mock.patch.object(LoopInstance, 'refresh_status') +@mock.patch.object(LoopInstance, 'send_message') +def test_restart_policy(mock_send_message, mock_refresh): + """Test submit policies to policy engine.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + action = loop.act_on_loop_policy(loop.restart) + mock_send_message.assert_called_once_with('PUT', + 'restart policy', + (f"{loop.base_url()}/loop/restart/LOOP_test")) + mock_refresh.assert_called_once() + loop.details = SUBMITED_POLICY + assert loop.details["components"]["POLICY"]["componentState"]["stateName"] == "SENT_AND_DEPLOYED" + + +@mock.patch.object(LoopInstance, 'refresh_status') +@mock.patch.object(LoopInstance, 'send_message') +def test_not_submited_policy(mock_send_message, mock_refresh): + """Test submit policies to policy engine.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_refresh.return_value = NOT_SUBMITED_POLICY + action = loop.act_on_loop_policy(loop.submit) + mock_send_message.assert_called_once_with('PUT', + 'submit policy', + (f"{loop.base_url()}/loop/submit/LOOP_test")) + mock_refresh.assert_called_once() + loop.details = NOT_SUBMITED_POLICY + assert loop.details["components"]["POLICY"]["componentState"]["stateName"] == "SENT" + + +@mock.patch('time.sleep', return_value=False) +@mock.patch.object(LoopInstance, 'send_message_json') +@mock.patch.object(LoopInstance, 'send_message') +def test_deploy_microservice_to_dcae(mock_send_message, mock_send_message_json, mock_timer): + """Test stop microservice.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + mock_send_message_json.return_value = SUBMITED + state = loop.deploy_microservice_to_dcae() + mock_send_message.assert_called_once_with('PUT', + 'Deploy microservice to DCAE', + (f"{loop.base_url()}/loop/deploy/LOOP_test")) + assert state + + +@mock.patch.object(LoopInstance, 'send_message') +def test_undeploy_microservice_from_dcae(mock_send_message): + """Test stop microservice.""" + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + request = loop.undeploy_microservice_from_dcae() + mock_send_message.assert_called_once_with('PUT', + 'Undeploy microservice from DCAE', + (f"{loop.base_url()}/loop/undeploy/LOOP_test")) + + +@mock.patch.object(LoopInstance, 'send_message') +def test_delete(mock_send_message): + loop = LoopInstance(template="template", name="test", details=LOOP_DETAILS) + request = loop.delete() + mock_send_message.assert_called_once_with('PUT', + 'Delete loop instance', + (f"{loop.base_url()}/loop/delete/{loop.name}")) diff --git a/tests/test_configuration.py b/tests/test_configuration.py new file mode 100644 index 0000000..70ae14a --- /dev/null +++ b/tests/test_configuration.py @@ -0,0 +1,24 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from onapsdk.utils.configuration import tosca_path +from onapsdk.utils.configuration import components_needing_distribution + +def test_tosca_path(): + assert tosca_path() == "/tmp/tosca_files/" + +def test_components_needing_distribution(): + assert "SO" in components_needing_distribution() + assert "sdnc" in components_needing_distribution() + assert "aai" in components_needing_distribution() diff --git a/tests/test_cps.py b/tests/test_cps.py new file mode 100644 index 0000000..8f7bdc4 --- /dev/null +++ b/tests/test_cps.py @@ -0,0 +1,240 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest import mock +from typing import List + +from onapsdk.cps import Anchor, Dataspace, SchemaSet, SchemaSetModuleReference, anchor + +DATASPACE_ANCHOR = { + "name": "anchor1", + "schemaSetName": "schemaSet1" +} + +DATASPACE_ANCHORS = [ + DATASPACE_ANCHOR, + { + "name": "anchor2", + "schemaSetName": "schemaSet2" + } +] + +DATASPACE_SCHEMA_SET = { + "name": "schemaSet1", + "moduleReferences": [ + { + "name": "mr1", + "namespace": "mr1_namespace", + "revision": "mr1_revision", + }, + { + "name": "mr2", + "namespace": "mr2_namespace", + "revision": "mr2_revision", + } + ] +} + +# Dataspace tests +def test_dataspace(): + ds = Dataspace(name="test_ds") + assert ds.name == "test_ds" + assert f"cps/api/v1/dataspaces/{ds.name}" in ds.url + +@mock.patch("onapsdk.cps.Dataspace.send_message") +def test_dataspace_create_anchor(mock_send_message): + ds = Dataspace(name="test_ds") + anchor = ds.create_anchor(mock.MagicMock(), "test_anchor") + mock_send_message.assert_called_once() + assert anchor.name == "test_anchor" + +@mock.patch("onapsdk.cps.Dataspace.send_message_json") +def test_dataspace_get_anchors(mock_send_message_json): + mock_send_message_json.return_value = DATASPACE_ANCHORS + ds = Dataspace(name="test_ds") + anchors = list(ds.get_anchors()) + assert len(anchors) == 2 + anchor_1, anchor_2 = anchors + assert isinstance(anchor_1, Anchor) + assert isinstance(anchor_2, Anchor) + assert anchor_1.name == "anchor1" + assert isinstance(anchor_1.schema_set, SchemaSet) + assert anchor_1.schema_set.name == "schemaSet1" + assert anchor_1.schema_set.dataspace == ds + assert anchor_2.name == "anchor2" + assert isinstance(anchor_2.schema_set, SchemaSet) + assert anchor_2.schema_set.name == "schemaSet2" + assert anchor_2.schema_set.dataspace == ds + +@mock.patch("onapsdk.cps.Dataspace.send_message_json") +def test_dataspace_get_anchor(mock_send_message_json): + mock_send_message_json.return_value = DATASPACE_ANCHOR + ds = Dataspace(name="test_ds") + anchor = ds.get_anchor("anything") + assert anchor.name == "anchor1" + assert anchor.schema_set.name == "schemaSet1" + assert anchor.schema_set.dataspace == ds + +@mock.patch("onapsdk.cps.Dataspace.send_message_json") +def test_dataspace_get_schema_set(mock_send_message_json): + mock_send_message_json.return_value = DATASPACE_SCHEMA_SET + ds = Dataspace(name="test_ds") + schema_set = ds.get_schema_set("anything") + assert isinstance(schema_set, SchemaSet) + assert schema_set.dataspace == ds + assert schema_set.name == "schemaSet1" + assert len(schema_set.module_refences) == 2 + mr_1, mr_2 = schema_set.module_refences + assert mr_1.name == "mr1" + assert mr_1.namespace == "mr1_namespace" + assert mr_1.revision == "mr1_revision" + assert mr_2.name == "mr2" + assert mr_2.namespace == "mr2_namespace" + assert mr_2.revision == "mr2_revision" + +@mock.patch("onapsdk.cps.Dataspace.send_message") +@mock.patch("onapsdk.cps.Dataspace.get_schema_set") +def test_dataspace_create_schema_set(mock_get_chema_set, mock_send_message): + ds = Dataspace(name="test_ds") + _ = ds.create_schema_set("test_schema_set_name", b"fake_file") + mock_send_message.assert_called_once() + mock_get_chema_set.assert_called_once_with("test_schema_set_name") + +@mock.patch("onapsdk.cps.Dataspace.send_message") +def test_dataspace_delete(mock_send_message): + ds = Dataspace(name="test_ds") + ds.delete() + mock_send_message.assert_called_once() + +# Schemaset tests +def test_schema_set(): + schema_set = SchemaSet(name="test", dataspace=mock.MagicMock()) + assert schema_set.name == "test" + assert isinstance(schema_set.module_refences, List) + assert not len(schema_set.module_refences) + + schema_set = SchemaSet(name="test_with_mr", dataspace=mock.MagicMock(), + module_references=[SchemaSetModuleReference(name="mr1", namespace="mr1_n", revision="mr1_rev"), + SchemaSetModuleReference(name="mr2", namespace="mr2_n", revision="mr2_rev")]) + assert schema_set.name == "test_with_mr" + assert isinstance(schema_set.module_refences, List) + assert len(schema_set.module_refences) == 2 + mr_1, mr_2 = schema_set.module_refences + assert isinstance(mr_1, SchemaSetModuleReference) + assert isinstance(mr_2, SchemaSetModuleReference) + assert mr_1.name == "mr1" + assert mr_1.namespace == "mr1_n" + assert mr_1.revision == "mr1_rev" + assert mr_2.name == "mr2" + assert mr_2.namespace == "mr2_n" + assert mr_2.revision == "mr2_rev" + +@mock.patch("onapsdk.cps.SchemaSet.send_message") +def test_schemaset_delete(mock_send_message): + schema_set = SchemaSet(name="test", dataspace=mock.MagicMock()) + schema_set.delete() + mock_send_message.assert_called_once() + +# Anchor tests +def test_anchor(): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + assert anchor.name == "test_anchor" + assert "test_anchor" in anchor.url + +@mock.patch("onapsdk.cps.Anchor.send_message") +def test_anchor_delete(mock_send_message): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.delete() + mock_send_message.assert_called_once() + url = mock_send_message.call_args[0][2] + assert anchor.url in url + +@mock.patch("onapsdk.cps.Anchor.send_message") +def test_anchor_create_node(mock_send_message): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.create_node('{"test": "data"}') + mock_send_message.assert_called_once() + data = mock_send_message.call_args[1]["data"] + assert data == '{"test": "data"}' + +@mock.patch("onapsdk.cps.Anchor.send_message_json") +def test_anchor_get_node(mock_send_message_json): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.get_node("test-xpath") + mock_send_message_json.assert_called_once() + url = mock_send_message_json.call_args[0][2] + assert "xpath=test-xpath" in url + assert "include-descendants=False" in url + + mock_send_message_json.reset_mock() + anchor.get_node("test-xpath-2", include_descendants=True) + mock_send_message_json.assert_called_once() + url = mock_send_message_json.call_args[0][2] + assert "xpath=test-xpath-2" in url + assert "include-descendants=True" in url + + mock_send_message_json.reset_mock() + anchor.get_node("test-xpath-3", include_descendants=False) + mock_send_message_json.assert_called_once() + url = mock_send_message_json.call_args[0][2] + assert "xpath=test-xpath-3" in url + assert "include-descendants=False" in url + +@mock.patch("onapsdk.cps.Anchor.send_message") +def test_anchor_update_node(mock_send_message): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.update_node("test-xpath", '{"test": "data"}') + mock_send_message.assert_called_once() + url = mock_send_message.call_args[0][2] + assert "xpath=test-xpath" in url + +@mock.patch("onapsdk.cps.Anchor.send_message") +def test_anchor_replace_node(mock_send_message): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.replace_node("test-xpath", '{"test": "data"}') + mock_send_message.assert_called_once() + url = mock_send_message.call_args[0][2] + assert "xpath=test-xpath" in url + +@mock.patch("onapsdk.cps.Anchor.send_message") +def test_anchor_add_list_node(mock_send_message): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.add_list_node("test-xpath", '{"test": "data"}') + mock_send_message.assert_called_once() + url = mock_send_message.call_args[0][2] + assert "xpath=test-xpath" in url + +@mock.patch("onapsdk.cps.Anchor.send_message_json") +def test_anchor_query_node(mock_send_message_json): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.query_node("/test-query") + mock_send_message_json.assert_called_once() + url = mock_send_message_json.call_args[0][2] + assert "cps-path=/test-query" in url + assert "include-descendants=False" in url + + mock_send_message_json.reset_mock() + anchor.query_node("/test-query1", include_descendants=True) + mock_send_message_json.assert_called_once() + url = mock_send_message_json.call_args[0][2] + assert "cps-path=/test-query1" in url + assert "include-descendants=True" in url + +@mock.patch("onapsdk.cps.Anchor.send_message") +def test_anchor_delete_nodes(mock_send_message): + anchor = Anchor(name="test_anchor", schema_set=mock.MagicMock()) + anchor.delete_nodes("test-xpath") + mock_send_message.assert_called_once() + url = mock_send_message.call_args[0][2] + assert "xpath=test-xpath" in url diff --git a/tests/test_dmaap.py b/tests/test_dmaap.py new file mode 100644 index 0000000..28165bc --- /dev/null +++ b/tests/test_dmaap.py @@ -0,0 +1,47 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest.mock import patch + +from onapsdk.dmaap.dmaap import Dmaap, ACTION, GET_HTTP_METHOD + +TOPIC = "fault" + +DMAAP_EVENTS_URL = "http://dmaap.api.simpledemo.onap.org:3904/events" +DMAAP_EVENTS_FROM_TOPIC_URL = f"http://dmaap.api.simpledemo.onap.org:3904/events/{TOPIC}/CG1/C1" +DMAAP_RESET_EVENTS = "http://dmaap.api.simpledemo.onap.org:3904/reset" +DMAAP_GET_ALL_TOPICS = "http://dmaap.api.simpledemo.onap.org:3904/topics" +BASIC_AUTH = {'username': 'dcae@dcae.onap.org', 'password': 'demo123456!'} + + +@patch.object(Dmaap, "send_message_json") +def test_should_get_all_events(send_message_mock): + Dmaap.get_all_events(BASIC_AUTH) + verify_send_event_to_ves_called(send_message_mock, DMAAP_EVENTS_URL) + +@patch.object(Dmaap, "send_message_json") +def test_should_get_events_from_topic(send_message_mock): + Dmaap.get_events_for_topic(TOPIC, BASIC_AUTH) + verify_send_event_to_ves_called(send_message_mock, DMAAP_EVENTS_FROM_TOPIC_URL) + +@patch.object(Dmaap, "send_message_json") +def test_should_get_all_topics(send_message_mock): + Dmaap.get_all_topics(BASIC_AUTH) + verify_send_event_to_ves_called(send_message_mock, DMAAP_GET_ALL_TOPICS) + +def verify_send_event_to_ves_called(send_message_mock, dmaap_url): + send_message_mock.assert_called_once_with( + GET_HTTP_METHOD, ACTION, dmaap_url, + basic_auth=BASIC_AUTH + ) + diff --git a/tests/test_esr.py b/tests/test_esr.py new file mode 100644 index 0000000..9f3c234 --- /dev/null +++ b/tests/test_esr.py @@ -0,0 +1,39 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.msb.esr import ESR, MSB + + +def test_esr(): + esr = ESR() + assert esr.base_url == f"{MSB.base_url}/api/aai-esr-server/v1/vims" + + +@mock.patch.object(ESR, "send_message") +def test_est_register_vim(mock_esr_send_message): + ESR.register_vim( + "test_cloud_owner", + "test_cloud_region_id", + "test_cloud_type", + "test_cloud_region_version", + "test_auth_info_cloud_domain", + "test_auth_info_username", + "test_auth_info_password", + "test_auth_info_url" + ) + mock_esr_send_message.assert_called_once() + method, _, url = mock_esr_send_message.call_args[0] + assert method == "POST" + assert url == ESR.base_url diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py new file mode 100644 index 0000000..6c564b6 --- /dev/null +++ b/tests/test_exceptions.py @@ -0,0 +1,23 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from onapsdk.exceptions import APIError + + +def test_api_error_response_status_code(): + err = APIError() + assert err.response_status_code == 0 + err.response_status_code = 404 + assert err.response_status_code == 404 + err = APIError(response_status_code=404) + assert err.response_status_code == 404 diff --git a/tests/test_generic_instance.txt b/tests/test_generic_instance.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/test_generic_instance.txt diff --git a/tests/test_gui.py b/tests/test_gui.py new file mode 100644 index 0000000..06b2a28 --- /dev/null +++ b/tests/test_gui.py @@ -0,0 +1,55 @@ +"""Test A&AI Element.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import logging +import unittest + +from onapsdk.nbi.nbi import Nbi +from onapsdk.utils.gui import GuiItem, GuiList +from onapsdk.exceptions import NoGuiError + +class GuiTestingBase(unittest.TestCase): + + """The super class which testing classes could inherit.""" + logging.disable(logging.CRITICAL) + + def test_get_guis_request_error(self): + nbi_element = Nbi() + with self.assertRaises(NoGuiError): + nbi_element.get_guis() + + def test_create_bad_gui_item(self): + with self.assertRaises(TypeError): + gui1 = GuiItem(184) + + def test_create_bad_gui_list(self): + with self.assertRaises(TypeError): + list = GuiList(1, 2, 3) + + def test_add_gui_item(self): + gui1 = GuiItem('url1', 184) + gui2 = GuiItem('url2', 200) + test = GuiList([]) + test.add(gui1) + test.add(gui2) + assert len(test.guilist) == 2 + assert test.guilist[0].status == 184 + assert test.guilist[1].url == 'url2' + + def test_add_bad_gui_item(self): + with self.assertRaises(AttributeError): + test = GuiList([]) + test.add('not a gui item object') + + diff --git a/tests/test_headers_creator.py b/tests/test_headers_creator.py new file mode 100644 index 0000000..98efd8d --- /dev/null +++ b/tests/test_headers_creator.py @@ -0,0 +1,84 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from onapsdk.utils.headers_creator import ( + headers_aai_creator, + headers_sdc_creator, + headers_sdc_tester, + headers_sdc_governor, + headers_sdc_operator, + headers_sdnc_creator, + headers_so_creator, + headers_so_catelog_db_creator, +) + +def test_headers_sdc_creator(): + base_header = {} + sdc_headers_creator = headers_sdc_creator(base_header) + assert base_header != sdc_headers_creator + assert sdc_headers_creator["USER_ID"] == "cs0008" + assert sdc_headers_creator["Authorization"] + +def test_headers_sdc_tester(): + base_header = {} + sdc_headers_tester = headers_sdc_tester(base_header) + assert base_header != sdc_headers_tester + assert sdc_headers_tester["USER_ID"] == "jm0007" + assert sdc_headers_tester["Authorization"] + +def test_headers_sdc_governor(): + base_header = {} + sdc_headers_governor = headers_sdc_governor(base_header) + assert base_header != sdc_headers_governor + assert sdc_headers_governor["USER_ID"] == "gv0001" + assert sdc_headers_governor["Authorization"] + +def test_headers_sdc_operator(): + base_header = {} + sdc_headers_operator = headers_sdc_operator(base_header) + assert base_header != sdc_headers_operator + assert sdc_headers_operator["USER_ID"] == "op0001" + assert sdc_headers_operator["Authorization"] + +def test_headers_aai_creator(): + base_header = {} + aai_headers_creator = headers_aai_creator(base_header) + assert base_header != aai_headers_creator + assert aai_headers_creator["x-fromappid"] == "AAI" + assert aai_headers_creator["authorization"] + assert aai_headers_creator["x-transactionid"] + +def test_headers_so_creator(): + base_header = {} + so_headers_creator = headers_so_creator(base_header) + assert base_header != so_headers_creator + assert so_headers_creator["x-fromappid"] == "AAI" + assert so_headers_creator["authorization"] + assert so_headers_creator["x-transactionid"] + +def test_headers_so_catelog_db_creator(): + base_header = {} + so_headers_creator = headers_so_catelog_db_creator(base_header) + assert base_header != so_headers_creator + assert so_headers_creator["x-fromappid"] == "AAI" + assert so_headers_creator["authorization"] + assert so_headers_creator["x-transactionid"] + +def test_headers_sdnc_creator(): + base_header = {} + so_headers_creator = headers_sdnc_creator(base_header) + assert base_header != so_headers_creator + assert so_headers_creator["x-fromappid"] == "API client" + assert so_headers_creator["authorization"] + assert so_headers_creator["x-transactionid"] diff --git a/tests/test_jinja.py b/tests/test_jinja.py new file mode 100644 index 0000000..8ba6d34 --- /dev/null +++ b/tests/test_jinja.py @@ -0,0 +1,26 @@ +"""Test Jinja module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from jinja2 import Environment + +from onapsdk.utils.jinja import jinja_env + +def test_jinja_env(): + """test jinja_env function.""" + test_jinja_env = jinja_env() + assert isinstance(test_jinja_env, Environment) + assert 'sdc_element_action.json.j2' in test_jinja_env.list_templates() + assert 'vendor_create.json.j2' in test_jinja_env.list_templates() + assert 'vsp_create.json.j2' in test_jinja_env.list_templates() + assert test_jinja_env.autoescape != None diff --git a/tests/test_msb_k8s.py b/tests/test_msb_k8s.py new file mode 100644 index 0000000..37be189 --- /dev/null +++ b/tests/test_msb_k8s.py @@ -0,0 +1,378 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.msb.k8s import Definition, ConnectivityInfo, Instance + + +CONNECTIVITY_INFO = { + "cloud-region": "test_cloud_region", + "cloud-owner": "test_cloud_owner", + "other-connectivity-list": {}, + "kubeconfig": "test_kubeconfig" +} + + +DEFINITION = { + "rb-name": "test_rb_name_0", + "rb-version": "test_rb_version_0" +} + + +DEFINITIONS = [ + DEFINITION, + { + "rb-name": "test_rb_name_1", + "rb-version": "test_rb_version_1", + "chart-name": "test_chart_name_1", + "description": "test_description_1", + "labels": {} + } +] + + +PROFILE = { + "rb-name": "test_rb_name", + "rb-version": "test_rb_version", + "profile-name": "test_profile_name", + "namespace": "test_namespace" +} + + +PROFILES = [ + PROFILE, + { + "rb-name": "test_rb_name_1", + "rb-version": "test_rb_version_1", + "profile-name": "test_profile_name_1", + "namespace": "test_namespace_1" + } +] + + +CONFIGURATION_TEMPLATE = { + "template-name": "test_configuration_template_name", + "description": "test_configuration_template_description" +} + + +CONFIGURATION_TEMPLATES = [ + CONFIGURATION_TEMPLATE, + { + "template-name": "test_configuration_template_name_0" + } +] + + +INSTANCE = { + "id": "ID_GENERATED_BY_K8SPLUGIN", + "namespace": "NAMESPACE_WHERE_INSTANCE_HAS_BEEN_DEPLOYED_AS_DERIVED_FROM_PROFILE", + "release-name": "RELEASE_NAME_AS_COMPUTED_BASED_ON_INSTANTIATION_REQUEST_AND_PROFILE_DEFAULT", + "request": { + "rb-name": "test-rbdef", + "rb-version": "v1", + "profile-name": "p1", + "release-name": "release-x", + "cloud-region": "krd", + "override-values": { + "optionalDictOfParameters": "andTheirValues, like", + "global.name": "dummy-name" + }, + "labels": { + "optionalLabelForInternalK8spluginInstancesMetadata": "dummy-value" + }, + }, + "resources": [ + { + "GVK": { + "Group": "", + "Kind": "ConfigMap", + "Version": "v1" + }, + "Name": "test-cm" + }, + { + "GVK": { + "Group": "", + "Kind": "Service", + "Version": "v1" + }, + "Name": "test-svc" + }, + { + "GVK": { + "Group": "apps", + "Kind": "Deployment", + "Version": "v1" + }, + "Name": "test-dep" + } + ] +} + + +INSTANCES = [ + INSTANCE +] + + +@mock.patch.object(ConnectivityInfo, "send_message_json") +def test_get_connectivity_info_by_region_id(mock_send_message_json): + mock_send_message_json.return_value = CONNECTIVITY_INFO + conn_info: ConnectivityInfo = ConnectivityInfo.get_connectivity_info_by_region_id("test_cloud_region_id") + assert conn_info.cloud_region_id == "test_cloud_region" + assert conn_info.cloud_owner == "test_cloud_owner" + assert conn_info.other_connectivity_list == {} + assert conn_info.kubeconfig == "test_kubeconfig" + + +@mock.patch.object(ConnectivityInfo, "send_message") +@mock.patch.object(ConnectivityInfo, "send_message_json") +def test_connectivity_info_create_delete(mock_send_message_json, mock_send_message): + mock_send_message_json.return_value = CONNECTIVITY_INFO + conn_info: ConnectivityInfo = ConnectivityInfo.create("test_cloud_region", "test_cloud_owner", b"kubeconfig") + assert conn_info.cloud_region_id == "test_cloud_region" + assert conn_info.cloud_owner == "test_cloud_owner" + assert conn_info.other_connectivity_list == {} + assert conn_info.kubeconfig == "test_kubeconfig" + conn_info.delete() + + +@mock.patch.object(Definition, "send_message_json") +def test_definition_get_all(mock_send_message_json): + mock_send_message_json.return_value = [] + assert len(list(Definition.get_all())) == 0 + + mock_send_message_json.return_value = DEFINITIONS + definitions = list(Definition.get_all()) + assert len(definitions) == 2 + + def_0, def_1 = definitions + assert def_0.rb_name == "test_rb_name_0" + assert def_0.rb_version == "test_rb_version_0" + assert def_0.chart_name is None + assert def_0.description is None + assert def_0.labels is None + + assert def_1.rb_name == "test_rb_name_1" + assert def_1.rb_version == "test_rb_version_1" + assert def_1.chart_name == "test_chart_name_1" + assert def_1.description == "test_description_1" + assert def_1.labels == {} + + +@mock.patch.object(Definition, "send_message_json") +def test_get_definition_by_name_version(mock_send_message_json): + mock_send_message_json.return_value = DEFINITION + def_0 = Definition.get_definition_by_name_version("rb_name", "rb_version") + assert def_0.rb_name == "test_rb_name_0" + assert def_0.rb_version == "test_rb_version_0" + assert def_0.chart_name is None + assert def_0.description is None + assert def_0.labels is None + + +@mock.patch.object(Definition, "send_message_json") +@mock.patch.object(Definition, "send_message") +def test_create_definition(mock_send_message, mock_send_message_json): + mock_send_message_json.return_value = DEFINITION + def_0 = Definition.create( + rb_name="test_rb_name_0", + rb_version="test_rb_version_0" + ) + assert def_0.rb_name == "test_rb_name_0" + assert def_0.rb_version == "test_rb_version_0" + assert def_0.chart_name is None + assert def_0.description is None + assert def_0.labels is None + + +@mock.patch.object(Definition, "send_message_json") +@mock.patch.object(Definition, "send_message") +def test_definition_create_profile(mock_send_message, mock_send_message_json): + mock_send_message_json.return_value = PROFILE + deff = Definition( + rb_name="test_rb_name", + rb_version="test_rb_version", + chart_name="test_chart_name", + description="test_description", + labels={} + ) + profile = deff.create_profile( + profile_name="test_profile_name", + namespace="test_namespace", + kubernetes_version="test_k8s_version" + ) + assert profile.rb_name == "test_rb_name" + assert profile.rb_version == "test_rb_version" + assert profile.profile_name == "test_profile_name" + assert profile.namespace == "test_namespace" + assert profile.kubernetes_version is None + assert profile.labels == {} + assert profile.release_name == "test_profile_name" + + +@mock.patch.object(Definition, "send_message_json") +def test_definition_get_profile_by_name(mock_send_message_json): + mock_send_message_json.return_value = PROFILE + deff = Definition( + rb_name="test_rb_name", + rb_version="test_rb_version", + chart_name="test_chart_name", + description="test_description", + labels={} + ) + profile = deff.get_profile_by_name("test_profile_name") + assert profile.rb_name == "test_rb_name" + assert profile.rb_version == "test_rb_version" + assert profile.profile_name == "test_profile_name" + assert profile.namespace == "test_namespace" + assert profile.kubernetes_version is None + assert profile.labels == {} + assert profile.release_name == "test_profile_name" + + +@mock.patch.object(Definition, "send_message_json") +def test_definition_get_all_profiles(mock_send_message_json): + mock_send_message_json.return_value = [] + deff = Definition( + rb_name="test_rb_name", + rb_version="test_rb_version", + chart_name="test_chart_name", + description="test_description", + labels={} + ) + assert len(list(deff.get_all_profiles())) == 0 + + mock_send_message_json.return_value = PROFILES + profiles = list(deff.get_all_profiles()) + assert len(profiles) == 2 + prof_0, prof_1 = profiles + + assert prof_0.rb_name == "test_rb_name" + assert prof_0.rb_version == "test_rb_version" + assert prof_0.profile_name == "test_profile_name" + assert prof_0.namespace == "test_namespace" + assert prof_0.kubernetes_version is None + assert prof_0.labels == {} + assert prof_0.release_name == "test_profile_name" + + assert prof_1.rb_name == "test_rb_name_1" + assert prof_1.rb_version == "test_rb_version_1" + assert prof_1.profile_name == "test_profile_name_1" + assert prof_1.namespace == "test_namespace_1" + assert prof_1.kubernetes_version is None + assert prof_1.labels == {} + assert prof_1.release_name == "test_profile_name_1" + + +@mock.patch.object(Definition, "send_message_json") +def test_definition_get_configuration_template_by_name(mock_send_message_json): + mock_send_message_json.return_value = CONFIGURATION_TEMPLATE + deff = Definition( + rb_name="test_rb_name", + rb_version="test_rb_version", + chart_name="test_chart_name", + description="test_description", + labels={} + ) + configuration_tmpl = deff.get_configuration_template_by_name( + template_name="test_configuration_template_name" + ) + assert configuration_tmpl.rb_name == deff.rb_name + assert configuration_tmpl.rb_version == deff.rb_version + assert configuration_tmpl.template_name == "test_configuration_template_name" + assert configuration_tmpl.description == "test_configuration_template_description" + + +@mock.patch.object(Definition, "send_message_json") +@mock.patch.object(Definition, "send_message") +def test_definition_create_configuration_template(mock_send_message, mock_send_message_json): + mock_send_message_json.return_value = CONFIGURATION_TEMPLATE + deff = Definition( + rb_name="test_rb_name", + rb_version="test_rb_version", + chart_name="test_chart_name", + description="test_description", + labels={} + ) + configuration_tmpl = deff.create_configuration_template( + template_name="test_configuration_template_name", + description="test_configuration_template_description" + ) + assert configuration_tmpl.rb_name == deff.rb_name + assert configuration_tmpl.rb_version == deff.rb_version + assert configuration_tmpl.template_name == "test_configuration_template_name" + assert configuration_tmpl.description == "test_configuration_template_description" + assert configuration_tmpl.url == f"{deff.base_url}/{deff.rb_name}/{deff.rb_version}/config-template/test_configuration_template_name" + + +@mock.patch.object(Definition, "send_message_json") +def test_definition_get_all_configuration_templates(mock_send_message_json): + mock_send_message_json.return_value = [] + deff = Definition( + rb_name="test_rb_name", + rb_version="test_rb_version", + chart_name="test_chart_name", + description="test_description", + labels={} + ) + assert len(list(deff.get_all_configuration_templates())) == 0 + + mock_send_message_json.return_value = CONFIGURATION_TEMPLATES + configuration_tmplts = list(deff.get_all_configuration_templates()) + assert len(configuration_tmplts) == 2 + + tmpl_0, tmpl_1 = configuration_tmplts + assert tmpl_0.rb_name == deff.rb_name + assert tmpl_0.rb_version == deff.rb_version + assert tmpl_0.template_name == "test_configuration_template_name" + assert tmpl_0.description == "test_configuration_template_description" + + assert tmpl_1.rb_name == deff.rb_name + assert tmpl_1.rb_version == deff.rb_version + assert tmpl_1.template_name == "test_configuration_template_name_0" + assert tmpl_1.description is None + + +@mock.patch.object(Instance, "send_message_json") +def test_instance_get_all(mock_send_message_json): + mock_send_message_json.return_value = [] + assert len(list(Instance.get_all())) == 0 + + mock_send_message_json.return_value = INSTANCES + assert len(list(Instance.get_all())) == 1 + + +@mock.patch.object(Instance, "send_message_json") +def test_instance_create(mock_send_message_json): + mock_send_message_json.return_value = INSTANCE + instance = Instance.create( + "test_cloud_region_id", + "test_profile_name", + "test_rb_name", + "test_rb_version" + ) + assert instance.instance_id == "ID_GENERATED_BY_K8SPLUGIN" + assert instance.namespace == "NAMESPACE_WHERE_INSTANCE_HAS_BEEN_DEPLOYED_AS_DERIVED_FROM_PROFILE" + + +@mock.patch.object(Instance, "send_message_json") +@mock.patch.object(Instance, "send_message") +def test_instance_get_by_id(mock_send_message, mock_send_message_json): + mock_send_message_json.return_value = INSTANCE + instance = Instance.get_by_id("ID_GENERATED_BY_K8SPLUGIN") + assert instance.instance_id == "ID_GENERATED_BY_K8SPLUGIN" + assert instance.namespace == "NAMESPACE_WHERE_INSTANCE_HAS_BEEN_DEPLOYED_AS_DERIVED_FROM_PROFILE" + instance.delete() diff --git a/tests/test_multicloud.py b/tests/test_multicloud.py new file mode 100644 index 0000000..8c05b93 --- /dev/null +++ b/tests/test_multicloud.py @@ -0,0 +1,38 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.msb.multicloud import Multicloud + + +@mock.patch.object(Multicloud, "send_message") +def test_multicloud_register(mock_send_message): + Multicloud.register_vim(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region") + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "Register VIM instance to ONAP" + assert url == f"{Multicloud.base_url}/test_cloud_owner/test_cloud_region/registry" + + +@mock.patch.object(Multicloud, "send_message") +def test_multicloud_unregister(mock_send_message): + Multicloud.unregister_vim(cloud_owner="test_cloud_owner", + cloud_region_id="test_cloud_region") + mock_send_message.assert_called_once() + method, description, url = mock_send_message.call_args[0] + assert method == "DELETE" + assert description == "Unregister VIM instance from ONAP" + assert url == f"{Multicloud.base_url}/test_cloud_owner/test_cloud_region" diff --git a/tests/test_nbi.py b/tests/test_nbi.py new file mode 100644 index 0000000..725baf2 --- /dev/null +++ b/tests/test_nbi.py @@ -0,0 +1,563 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from collections import namedtuple +from unittest import mock + +from onapsdk.aai.business import Customer +from onapsdk.exceptions import RequestError +from onapsdk.nbi import Nbi, Service, ServiceOrder, ServiceSpecification + + +SERVICE_SPECIFICATION = { + "id":"a80c901c-6593-491f-9465-877e5acffb46", + "name":"testService1", + "invariantUUID":"217deaa7-dfc3-41d8-aa53-bb009029c09f", + "category":"Network Service", + "distributionStatus":"DISTRIBUTED", + "version":"1.0", + "lifecycleStatus":"CERTIFIED", + "relatedParty":{ + "id":"cs0008", + "role":"lastUpdater" + } +} + + +SERVICE_SPECIFICATIONS = [ + { + "id":"a80c901c-6593-491f-9465-877e5acffb46", + "name":"testService1", + "invariantUUID":"217deaa7-dfc3-41d8-aa53-bb009029c09f", + "category":"Network Service", + "distributionStatus":"DISTRIBUTED", + "version":"1.0", + "lifecycleStatus":"CERTIFIED", + "relatedParty":{ + "id":"cs0008", + "role":"lastUpdater" + } + }, + { + "id":"b1cda0ab-d968-41ef-9051-d26b33b120be", + "name":"testService2", + "invariantUUID":"906c3185-9656-4639-8f4d-d51d9ee0695d", + "category":"Network Service", + "distributionStatus":"DISTRIBUTED", + "version":"1.0", + "lifecycleStatus":"CERTIFIED", + "relatedParty":{ + "id":"cs0008" + ,"role":"lastUpdater" + } + } +] + + +SERVICES = [ + { + "id":"5c855390-7c39-4fe4-b164-2029b09de57c", + "name":"test6", + "serviceSpecification":{ + "name":"testService9", + "id":"125727ad-8660-423e-b4a1-99cd4a749f45" + }, + "relatedParty":{ + "role":"ONAPcustomer", + "id":"generic" + }, + "href":"service/5c855390-7c39-4fe4-b164-2029b09de57c" + }, + { + "id":"f948be83-c3e8-4515-a27d-2983eba63911", + "name":"test4", + "serviceSpecification":{ + "name":"testService8", + "id":"0960aedb-3ad8-49e1-ade5-a59414f6fda4" + }, + "relatedParty":{ + "role":"ONAPcustomer", + "id":"generic" + }, + "href":"service/f948be83-c3e8-4515-a27d-2983eba63911" + }, + { + "id":"5066eabd-846c-4ed9-886b-69892a12968d", + "name":"test5", + "serviceSpecification":{ + "name":"testService8", + "id":"0960aedb-3ad8-49e1-ade5-a59414f6fda4" + }, + "relatedParty":{ + "role":"ONAPcustomer", + "id":"generic" + }, + "href":"service/5066eabd-846c-4ed9-886b-69892a12968d" + } +] + + +SERVICES_CUSTOMER = [ + { + "id":"6a855390-7c39-4fe4-b164-2029b09de57d", + "name":"test7", + "serviceSpecification":{ + "name":"testService9", + "id":"125727ad-8660-423e-b4a1-99cd4a749f45" + }, + "relatedParty":{ + "role":"ONAPcustomer", + "id":"test_customer" + }, + "href":"service/6a855390-7c39-4fe4-b164-2029b09de57d" + } +] + + + +SERVICE_ORDERS = [ + { + "id":"5e9d6d98ae76af6b04e4df9a", + "href":"serviceOrder/5e9d6d98ae76af6b04e4df9a", + "externalId":"", + "priority":"1", + "description":"testService order for generic customer via Python ONAP SDK", + "category":"Consumer", + "state":"rejected", + "orderDate":"2020-04-20T09:38:32.286Z", + "completionDateTime":"2020-04-20T09:38:47.866Z", + "expectedCompletionDate":None, + "requestedStartDate":"2020-04-20T09:47:49.919Z", + "requestedCompletionDate":"2020-04-20T09:47:49.919Z", + "startDate":None, + "@baseType":None, + "@type":None, + "@schemaLocation":None, + "relatedParty":[ + { + "id":"generic", + "href":None, + "role":"ONAPcustomer", + "name":"generic", + "@referredType":None + } + ], + "orderRelationship":None, + "orderItem":[ + { + "orderMessage":[], + "id":"1", + "action":"add", + "state":"rejected", + "percentProgress":"0", + "@type":None, + "@schemaLocation":None, + "@baseType":None, + "orderItemRelationship":[], + "service":{ + "id":None, + "serviceType":None, + "href":None, + "name":"08d960ae-c2e1-4d5c-baf0-6420659ea68a", + "serviceState":"active", + "@type":None, + "@schemaLocation":None, + "serviceCharacteristic":None, + "serviceRelationship":None, + "relatedParty":None, + "serviceSpecification":{ + "id":"a80c901c-6593-491f-9465-877e5acffb46", + "href":None, + "name":None, + "version":None, + "targetServiceSchema":None, + "@type":None, + "@schemaLocation":None, + "@baseType":None + } + }, + "orderItemMessage":[] + } + ], + "orderMessage":[ + { + "code":"501", + "field":None, + "messageInformation":"Problem with AAI API", + "severity":"error", + "correctionRequired":True + }, + { + "code":"503", + "field":None, + "messageInformation":"tenantId not found in AAI", + "severity":"error", + "correctionRequired":True + } + ] + } +] + +SERVICE_ORDERS_NO_RELATED_PARTY = [ + { + "id":"5e9d6d98ae76af6b04e4df9a", + "href":"serviceOrder/5e9d6d98ae76af6b04e4df9a", + "externalId":"", + "priority":"1", + "description":"testService order for generic customer via Python ONAP SDK", + "category":"Consumer", + "state":"rejected", + "orderDate":"2020-04-20T09:38:32.286Z", + "completionDateTime":"2020-04-20T09:38:47.866Z", + "expectedCompletionDate":None, + "requestedStartDate":"2020-04-20T09:47:49.919Z", + "requestedCompletionDate":"2020-04-20T09:47:49.919Z", + "startDate":None, + "@baseType":None, + "@type":None, + "@schemaLocation":None, + "relatedParty": None, + "orderRelationship":None, + "orderItem":[ + { + "orderMessage":[], + "id":"1", + "action":"add", + "state":"rejected", + "percentProgress":"0", + "@type":None, + "@schemaLocation":None, + "@baseType":None, + "orderItemRelationship":[], + "service":{ + "id":None, + "serviceType":None, + "href":None, + "name":"08d960ae-c2e1-4d5c-baf0-6420659ea68a", + "serviceState":"active", + "@type":None, + "@schemaLocation":None, + "serviceCharacteristic":None, + "serviceRelationship":None, + "relatedParty":None, + "serviceSpecification":{ + "id":"a80c901c-6593-491f-9465-877e5acffb46", + "href":None, + "name":None, + "version":None, + "targetServiceSchema":None, + "@type":None, + "@schemaLocation":None, + "@baseType":None + } + }, + "orderItemMessage":[] + } + ], + "orderMessage":[ + { + "code":"501", + "field":None, + "messageInformation":"Problem with AAI API", + "severity":"error", + "correctionRequired":True + }, + { + "code":"503", + "field":None, + "messageInformation":"tenantId not found in AAI", + "severity":"error", + "correctionRequired":True + } + ] + } +] + +SERVICE_ORDER_STATE_COMPLETED = { + 'state': 'completed' +} + +SERVICE_ORDER_STATE_FAILED = { + 'state': 'failed' +} + +SERVICE_ORDER_STATE_IN_PROGRESS = { + 'state': 'inProgress' +} + +SERVICE_ORDER_STATE_REJECTED = { + 'state': 'rejected' +} + +SERVICE_ORDER_STATE_UNKNOWN = { + 'state': 'lalala' +} + +@mock.patch.object(Nbi, "send_message") +def test_nbi(mock_send_message): + + assert Nbi.base_url == "https://nbi.api.simpledemo.onap.org:30274" + assert Nbi.api_version == "/nbi/api/v4" + + mock_send_message.side_effect = RequestError + assert Nbi.is_status_ok() == False + mock_send_message.side_effect = None + assert Nbi.is_status_ok() == True + + +@mock.patch.object(ServiceSpecification, "send_message_json") +def test_service_specification_get_all(mock_service_specification_send_message): + mock_service_specification_send_message.return_value = [] + assert len(list(ServiceSpecification.get_all())) == 0 + + mock_service_specification_send_message.return_value = SERVICE_SPECIFICATIONS + service_specifications = list(ServiceSpecification.get_all()) + assert len(service_specifications) == 2 + + assert service_specifications[0].unique_id == "a80c901c-6593-491f-9465-877e5acffb46" + assert service_specifications[0].name == "testService1" + assert service_specifications[0].invariant_uuid == "217deaa7-dfc3-41d8-aa53-bb009029c09f" + assert service_specifications[0].category == "Network Service" + assert service_specifications[0].distribution_status == "DISTRIBUTED" + assert service_specifications[0].version == "1.0" + assert service_specifications[0].lifecycle_status == "CERTIFIED" + + assert service_specifications[1].unique_id == "b1cda0ab-d968-41ef-9051-d26b33b120be" + assert service_specifications[1].name == "testService2" + assert service_specifications[1].invariant_uuid == "906c3185-9656-4639-8f4d-d51d9ee0695d" + assert service_specifications[1].category == "Network Service" + assert service_specifications[1].distribution_status == "DISTRIBUTED" + assert service_specifications[1].version == "1.0" + assert service_specifications[1].lifecycle_status == "CERTIFIED" + + +@mock.patch.object(ServiceSpecification, "send_message_json") +def test_service_specification_get_by_id(mock_service_specification_send_message): + + mock_service_specification_send_message.return_value = SERVICE_SPECIFICATION + service_specification = ServiceSpecification.get_by_id("test") + assert service_specification.unique_id == "a80c901c-6593-491f-9465-877e5acffb46" + assert service_specification.name == "testService1" + assert service_specification.invariant_uuid == "217deaa7-dfc3-41d8-aa53-bb009029c09f" + assert service_specification.category == "Network Service" + assert service_specification.distribution_status == "DISTRIBUTED" + assert service_specification.version == "1.0" + assert service_specification.lifecycle_status == "CERTIFIED" + + +@mock.patch.object(Service, "send_message_json") +@mock.patch.object(Customer, "get_by_global_customer_id") +@mock.patch.object(ServiceSpecification, "get_by_id") +def test_service_get_all(mock_service_specification_get_by_id, + mock_customer_get_by_id, + mock_service_send_message): + mock_service_send_message.return_value = [] + assert len(list(Service.get_all())) == 0 + mock_service_send_message.return_value = SERVICES + services_list = list(Service.get_all()) + assert len(services_list) == 3 + + service = services_list[0] + + assert service.name == "test6" + assert service.service_id == "5c855390-7c39-4fe4-b164-2029b09de57c" + assert service._service_specification_name == "testService9" + assert service._service_specification_id == "125727ad-8660-423e-b4a1-99cd4a749f45" + assert service._customer_id == "generic" + assert service.customer_role == "ONAPcustomer" + assert service.href == "service/5c855390-7c39-4fe4-b164-2029b09de57c" + + assert service.customer is not None + mock_customer_get_by_id.assert_called_once_with(service._customer_id) + + service._customer_id = None + assert service.customer is None + + assert service.service_specification is not None + mock_service_specification_get_by_id.assert_called_once_with(service._service_specification_id) + + service._service_specification_id = None + assert service.service_specification is None + + mock_service_send_message.return_value = SERVICES_CUSTOMER + services_list = list(Service.get_all(customer_id="test_customer")) + assert len(services_list) == 1 + + service = services_list[0] + + assert service.name == "test7" + assert service.service_id == "6a855390-7c39-4fe4-b164-2029b09de57d" + assert service._service_specification_name == "testService9" + assert service._service_specification_id == "125727ad-8660-423e-b4a1-99cd4a749f45" + assert service._customer_id == "test_customer" + assert service.customer_role == "ONAPcustomer" + assert service.href == "service/6a855390-7c39-4fe4-b164-2029b09de57d" + + + +@mock.patch.object(ServiceOrder, "send_message_json") +def test_service_order(mock_service_order_send_message): + mock_service_order_send_message.return_value = [] + assert len(list(ServiceOrder.get_all())) == 0 + + mock_service_order_send_message.return_value = SERVICE_ORDERS + service_orders = list(ServiceOrder.get_all()) + assert len(service_orders) == 1 + service_order = service_orders[0] + assert service_order.unique_id == "5e9d6d98ae76af6b04e4df9a" + assert service_order.href =="serviceOrder/5e9d6d98ae76af6b04e4df9a" + assert service_order.priority == "1" + assert service_order.category == "Consumer" + assert service_order.description == "testService order for generic customer via Python ONAP SDK" + assert service_order.external_id == "" + assert service_order._customer == None + assert service_order._customer_id == "generic" + assert service_order._service_specification == None + assert service_order._service_specification_id == "a80c901c-6593-491f-9465-877e5acffb46" + assert service_order.service_instance_name == "08d960ae-c2e1-4d5c-baf0-6420659ea68a" + assert service_order.state == "rejected" + + +@mock.patch.object(ServiceOrder, "send_message_json") +def test_service_order_status(mock_service_order_send_message): + mock_service_order_send_message.return_value = SERVICE_ORDERS + service_order = next(ServiceOrder.get_all()) + + mock_service_order_send_message.return_value = SERVICE_ORDER_STATE_COMPLETED + assert service_order.status == service_order.StatusEnum.COMPLETED + assert service_order.completed + assert service_order.finished + assert not service_order.rejected + assert not service_order.failed + + mock_service_order_send_message.return_value = SERVICE_ORDER_STATE_FAILED + assert service_order.status == service_order.StatusEnum.FAILED + assert not service_order.completed + assert service_order.finished + assert not service_order.rejected + assert service_order.failed + + mock_service_order_send_message.return_value = SERVICE_ORDER_STATE_IN_PROGRESS + assert service_order.status == service_order.StatusEnum.IN_PROGRESS + assert not service_order.completed + assert not service_order.finished + assert not service_order.rejected + assert not service_order.failed + + mock_service_order_send_message.return_value = SERVICE_ORDER_STATE_REJECTED + assert service_order.status == service_order.StatusEnum.REJECTED + assert not service_order.completed + assert service_order.finished + assert service_order.rejected + assert not service_order.failed + + mock_service_order_send_message.return_value = SERVICE_ORDER_STATE_UNKNOWN + assert service_order.status == service_order.StatusEnum.UNKNOWN + assert not service_order.completed + assert service_order.finished + assert not service_order.rejected + assert not service_order.failed + + mock_service_order_send_message.return_value = {} + assert service_order.status == service_order.StatusEnum.UNKNOWN + assert not service_order.completed + assert service_order.finished + assert not service_order.rejected + assert not service_order.failed + + +@mock.patch.object(ServiceOrder, "send_message_json") +def test_service_order_no_related_party(mock_service_order_send_message): + mock_service_order_send_message.return_value = [] + assert len(list(ServiceOrder.get_all())) == 0 + + mock_service_order_send_message.return_value = SERVICE_ORDERS_NO_RELATED_PARTY + service_orders = list(ServiceOrder.get_all()) + assert len(service_orders) == 1 + service_order = service_orders[0] + assert service_order.unique_id == "5e9d6d98ae76af6b04e4df9a" + assert service_order.href =="serviceOrder/5e9d6d98ae76af6b04e4df9a" + assert service_order.priority == "1" + assert service_order.category == "Consumer" + assert service_order.description == "testService order for generic customer via Python ONAP SDK" + assert service_order.external_id == "" + assert service_order._customer == None + assert service_order._customer_id == None + assert service_order._service_specification == None + assert service_order._service_specification_id == "a80c901c-6593-491f-9465-877e5acffb46" + assert service_order.service_instance_name == "08d960ae-c2e1-4d5c-baf0-6420659ea68a" + assert service_order.state == "rejected" + + +@mock.patch.object(Customer, "get_by_global_customer_id") +def test_service_order_customer(mock_customer_get_by_id): + service_order = ServiceOrder("test_unique_id", + "test_href", + "test_priority", + "test_description", + "test_category", + "test_external_id", + "test_service_instance_name") + assert service_order.customer is None + assert service_order._customer is None + service_order._customer_id = "test_customer_id" + assert service_order.customer is not None + mock_customer_get_by_id.assert_called_once_with("test_customer_id") + assert service_order._customer is not None + + +@mock.patch.object(ServiceSpecification, "get_by_id") +def test_service_order_service_specification(mock_service_spec_get_by_id): + service_order = ServiceOrder("test_unique_id", + "test_href", + "test_priority", + "test_description", + "test_category", + "test_external_id", + "test_service_instance_name") + assert service_order.service_specification is None + assert service_order._service_specification_id is None + service_order._service_specification_id = "test_service_spec_id" + assert service_order.service_specification is not None + mock_service_spec_get_by_id.assert_called_once_with("test_service_spec_id") + assert service_order._service_specification is not None + + +@mock.patch.object(ServiceOrder, "send_message_json") +def test_service_order_create(mock_service_order_send_message): + ServiceOrder.create(customer=mock.MagicMock(), + service_specification=mock.MagicMock()) + mock_service_order_send_message.assert_called_once() + method, _, url = mock_service_order_send_message.call_args[0] + assert method == "POST" + assert url == f"{ServiceOrder.base_url}{ServiceOrder.api_version}/serviceOrder" + + +def test_service_order_wait_for_finish(): + with mock.patch.object(ServiceOrder, "finished", new_callable=mock.PropertyMock) as mock_finished: + with mock.patch.object(ServiceOrder, "completed", new_callable=mock.PropertyMock) as mock_completed: + service_order = ServiceOrder( + unique_id="test", + href="test", + priority="test", + description="test", + category="test", + external_id="test", + service_instance_name="test", + ) + service_order.WAIT_FOR_SLEEP_TIME = 0 + mock_finished.side_effect = [False, False, True] + mock_completed.return_value = True + rv = namedtuple("Value", ["return_value"]) + service_order._wait_for_finish(rv) + assert rv.return_value diff --git a/tests/test_onap_service.py b/tests/test_onap_service.py new file mode 100644 index 0000000..62a9880 --- /dev/null +++ b/tests/test_onap_service.py @@ -0,0 +1,380 @@ +"""Test OnapService module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock +from unittest.mock import ANY + +import pytest +from requests import Response, Session + +from requests import ConnectionError, RequestException + +from onapsdk.exceptions import ( + RequestError, APIError, ResourceNotFound, InvalidResponse, ConnectionFailed +) + +from onapsdk.onap_service import OnapService +from onapsdk.sdc.vendor import Vendor + +def http_codes(): + return [ + 400, # Bad Request + 401, # Unauthorized + 403, # Forbidden + 405, # Method Not Allowed + 408, # Request Timeout + 415, # Unsupported Media Type + 429, # Too Many Requests + 500, # Internal Server Error + 501, # Not Implemented + 502, # Bad Gateway + 503, # Service Unavailable + 504 # Gateway Timeout + ] + +class TestException(Exception): + """Test exception.""" + +def test_init(): + """Test initialization.""" + svc = OnapService() + +def test_class_variables(): + """Test class variables.""" + assert OnapService.server == None + assert OnapService.headers == { + "Content-Type": "application/json", + "Accept": "application/json", + } + assert OnapService.proxy == None + +def test_set_proxy(): + """Test set_proxy().""" + assert OnapService.proxy == None + Vendor.set_proxy({'the', 'proxy'}) + assert OnapService.proxy == {'the', 'proxy'} + Vendor.set_proxy(None) + assert OnapService.proxy == None + +# ------------------ + +@mock.patch.object(Session, 'request') +def test_send_message_OK(mock_request): + """Returns response if OK.""" + svc = OnapService() + mocked_response = Response() + mocked_response.status_code = 200 + mock_request.return_value = mocked_response + expect_headers = { + "Content-Type": "application/json", + "Accept": "application/json", + } + response = svc.send_message("GET", 'test get', 'http://my.url/') + mock_request.assert_called_once_with('GET', 'http://my.url/', + headers=expect_headers, verify=False, + proxies=None) + assert response == mocked_response + +@mock.patch.object(Session, 'request') +def test_send_message_custom_header_OK(mock_request): + """Returns response if returns OK with a custom header.""" + svc = OnapService() + mocked_response = Response() + mocked_response.status_code = 200 + mock_request.return_value = mocked_response + expect_headers = { + "Content-Type": "application/json", + "Accept": "application/json", + "Custom": "Header" + } + response = svc.send_message("GET", 'test get', 'http://my.url/', + headers=expect_headers) + mock_request.assert_called_once_with('GET', 'http://my.url/', + headers=expect_headers, verify=False, + proxies=None) + assert response == mocked_response + +@mock.patch.object(OnapService, '_set_basic_auth_if_needed') +@mock.patch.object(Session, 'request') +def test_send_message_with_basic_auth(mock_request, mock_set_basic_auth_if_needed): + """Should give response of request if OK.""" + svc = OnapService() + mocked_response = Response() + mocked_response.status_code = 200 + basic_auth = {'username': 'user1', "password": "password1"} + mock_request.return_value = mocked_response + expect_headers = { + "Content-Type": "application/json", + "Accept": "application/json", + "Once": "Upon a time" + } + response = svc.send_message("GET", 'test get', 'http://my.url/', + headers=expect_headers, basic_auth=basic_auth) + mock_set_basic_auth_if_needed.assert_called_once_with(basic_auth, ANY) + mock_request.assert_called_once_with('GET', 'http://my.url/', + headers=expect_headers, verify=False, + proxies=None) + assert response == mocked_response + +@mock.patch.object(Session, 'request') +def test_send_message_resource_not_found(mock_request): + """Should raise ResourceNotFound if status code 404.""" + svc = OnapService() + + mocked_response = Response() + mocked_response.status_code = 404 + + mock_request.return_value = mocked_response + + with pytest.raises(ResourceNotFound) as exc: + svc.send_message("GET", 'test get', 'http://my.url/') + assert exc.type is ResourceNotFound + + mock_request.assert_called_once() + +@mock.patch.object(Session, 'request') +@pytest.mark.parametrize("code", http_codes()) +def test_send_message_api_error(mock_request, code): + """Raise APIError if status code is between 400 and 599, and not 404.""" + svc = OnapService() + mocked_response = Response() + mocked_response.status_code = code + mock_request.return_value = mocked_response + + with pytest.raises(APIError) as exc: + svc.send_message("GET", 'test get', 'http://my.url/') + assert exc.type is APIError + + mock_request.assert_called_once() + +@mock.patch.object(Session, 'request') +def test_send_message_connection_failed(mock_request): + """Should raise ResourceNotFound if status code 404.""" + svc = OnapService() + + mock_request.side_effect = ConnectionError + + with pytest.raises(ConnectionFailed) as exc: + svc.send_message("GET", 'test get', 'http://my.url/') + assert exc.type is ConnectionFailed + + mock_request.assert_called_once() + +@mock.patch.object(Session, 'request') +def test_send_message_request_error(mock_request): + """Should raise RequestError for an amiguous request exception.""" + svc = OnapService() + + mock_request.side_effect = RequestException + + with pytest.raises(RequestError) as exc: + svc.send_message("GET", 'test get', 'http://my.url/') + assert exc.type is RequestError + + mock_request.assert_called_once() + + +@mock.patch.object(Session, 'request') +def test_send_message_custom_error(mock_request): + """Should raise RequestError for an amiguous request exception.""" + svc = OnapService() + + mock_request.side_effect = RequestException + + with pytest.raises(TestException) as exc: + svc.send_message("GET", 'test get', 'http://my.url/', + exception=TestException) + assert exc.type is TestException + + mock_request.assert_called_once() + +@mock.patch.object(OnapService, 'send_message') +def test_send_message_json_OK(mock_send): + """JSON is received and successfully decoded.""" + svc = OnapService() + + mocked_response = Response() + mocked_response._content = b'{"yolo": "yala"}' + mocked_response.encoding = "UTF-8" + mocked_response.status_code = 200 + + mock_send.return_value = mocked_response + + response = svc.send_message_json("GET", 'test get', 'http://my.url/') + + mock_send.assert_called_once_with("GET", 'test get', 'http://my.url/') + assert response['yolo'] == 'yala' + +@mock.patch.object(OnapService, 'send_message') +def test_send_message_json_invalid_response(mock_send): + """Raises InvalidResponse if response is not JSON.""" + svc = OnapService() + + mocked_response = Response() + mocked_response._content = b'{yolo}' + mocked_response.encoding = "UTF-8" + mocked_response.status_code = 200 + + mock_send.return_value = mocked_response + + with pytest.raises(InvalidResponse) as exc: + svc.send_message_json("GET", 'test get', 'http://my.url/') + assert exc.type is InvalidResponse + + mock_send.assert_called_once() + +@mock.patch.object(OnapService, 'send_message') +def test_send_message_json_connection_failed(mock_send): + """ConnectionFailed from send_message is handled.""" + svc = OnapService() + + mock_send.side_effect = ConnectionFailed + + with pytest.raises(ConnectionFailed) as exc: + svc.send_message_json("GET", 'test get', 'http://my.url/') + assert exc.type is ConnectionFailed + + mock_send.assert_called_once() + +@mock.patch.object(OnapService, 'send_message') +def test_send_message_json_api_error(mock_send): + """APIError (error codes) from send_message is handled.""" + svc = OnapService() + + mock_send.side_effect = APIError + + with pytest.raises(APIError) as exc: + svc.send_message_json("GET", 'test get', 'http://my.url/') + assert exc.type is APIError + + mock_send.assert_called_once() + +@mock.patch.object(OnapService, 'send_message') +def test_send_message_json_resource_not_found(mock_send): + """ResourceNotFound exception from send_message is handled.""" + svc = OnapService() + + mock_send.side_effect = ResourceNotFound + + with pytest.raises(ResourceNotFound) as exc: + svc.send_message_json("GET", 'test get', 'http://my.url/') + assert exc.type is ResourceNotFound + + mock_send.assert_called_once() + +@mock.patch.object(OnapService, 'send_message') +def test_send_message_json_request_error(mock_send): + """RequestError exception from send_message is handled.""" + svc = OnapService() + + mock_send.side_effect = RequestError + + with pytest.raises(RequestError) as exc: + svc.send_message_json("GET", 'test get', 'http://my.url/') + assert exc.type is RequestError + + mock_send.assert_called_once() + + +@mock.patch.object(OnapService, 'send_message') +def test_send_message_json_custom_error(mock_send): + """RequestError exception from send_message is handled.""" + svc = OnapService() + + mock_send.side_effect = RequestError + + with pytest.raises(TestException) as exc: + svc.send_message_json("GET", 'test get', 'http://my.url/', + exception=TestException) + assert exc.type is TestException + + mock_send.assert_called_once() + +@mock.patch("onapsdk.onap_service.requests.Session") +def test_set_header(mock_session): + + OnapService.send_message("GET", 'test get', 'http://my.url/') + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-key" not in headers + + mock_session.reset_mock() + OnapService.set_header({"test-header-key": "test-header-value"}) + OnapService.send_message("GET", 'test get', 'http://my.url/') + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-key" in headers + assert headers["test-header-key"] == "test-header-value" + + mock_session.reset_mock() + OnapService.send_message("GET", 'test get', 'http://my.url/', headers={}) + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-key" in headers + assert headers["test-header-key"] == "test-header-value" + + mock_session.reset_mock() + OnapService.send_message("GET", 'test get', 'http://my.url/', headers={"test-header-key": "test-header-another-value"}) + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-key" in headers + assert headers["test-header-key"] == "test-header-value" + + mock_session.reset_mock() + OnapService.set_header(None) + OnapService.send_message("GET", 'test get', 'http://my.url/') + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-key" not in headers + + def test_header_method(): + return {"test-header-callable-key": "test-header-callable-value"} + + mock_session.reset_mock() + OnapService.set_header(test_header_method) + OnapService.send_message("GET", 'test get', 'http://my.url/', headers={}) + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-callable-key" in headers + assert headers["test-header-callable-key"] == "test-header-callable-value" + + mock_session.reset_mock() + OnapService.send_message("GET", 'test get', 'http://my.url/', headers={"test-header-key": "test-header-value"}) + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-callable-key" in headers + assert headers["test-header-callable-key"] == "test-header-callable-value" + assert "test-header-key" in headers + assert headers["test-header-key"] == "test-header-value" + + mock_session.reset_mock() + OnapService.set_header({"test-header-dict-key": "test-header-dict-value"}) + OnapService.send_message("GET", 'test get', 'http://my.url/', headers={}) + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-callable-key" in headers + assert headers["test-header-callable-key"] == "test-header-callable-value" + assert "test-header-dict-key" in headers + assert headers["test-header-dict-key"] == "test-header-dict-value" + + mock_session.reset_mock() + OnapService.send_message("GET", 'test get', 'http://my.url/', headers={"test-header-common-key": "test-header-common-value"}) + _, _, kwargs = mock_session.return_value.request.mock_calls[0] + headers = kwargs["headers"] + assert "test-header-callable-key" in headers + assert headers["test-header-callable-key"] == "test-header-callable-value" + assert "test-header-dict-key" in headers + assert headers["test-header-dict-key"] == "test-header-dict-value" + assert "test-header-common-key" in headers + assert headers["test-header-common-key"] == "test-header-common-value" diff --git a/tests/test_pnf.py b/tests/test_pnf.py new file mode 100644 index 0000000..0f606a0 --- /dev/null +++ b/tests/test_pnf.py @@ -0,0 +1,485 @@ +"""Test pnf module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest import mock +from unittest.mock import MagicMock +from pathlib import Path + +import pytest + +import onapsdk.constants as const +from onapsdk.exceptions import ParameterError, RequestError, StatusError +from onapsdk.sdc.category_management import ResourceCategory +from onapsdk.sdc.properties import Property +from onapsdk.sdc.sdc_resource import SdcResource +from onapsdk.sdc.pnf import Pnf +from onapsdk.sdc.vsp import Vsp +from onapsdk.sdc.vsp import Vendor + + +@mock.patch.object(Pnf, 'send_message_json') +def test_get_all_no_pnf(mock_send): + """Returns empty array if no pnfs.""" + mock_send.return_value = {} + assert Pnf.get_all() == [] + mock_send.assert_called_once_with("GET", 'get Pnfs', 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/resources?resourceType=PNF') + + +@mock.patch.object(Pnf, 'send_message_json') +def test_get_all_some_pnfs(mock_send): + """Returns a list of pnfs.""" + mock_send.return_value = [ + {'resourceType': 'PNF', 'name': 'one', 'uuid': '1234', 'invariantUUID': '5678', 'version': '1.0', 'lifecycleState': 'CERTIFIED', 'category': 'Generic', "subCategory": "Abstract"}, + {'resourceType': 'PNF', 'name': 'two', 'uuid': '1235', 'invariantUUID': '5679', 'version': '1.0', 'lifecycleState': 'NOT_CERTIFIED_CHECKOUT', 'category': 'Generic', "subCategory": "Abstract"}] + all_pnfs = Pnf.get_all() + assert len(all_pnfs) == 2 + pnf_1 = all_pnfs[0] + assert pnf_1.name == "one" + assert pnf_1.identifier == "1234" + assert pnf_1.unique_uuid == "5678" + assert pnf_1.version == "1.0" + assert pnf_1.status == const.CERTIFIED + assert pnf_1.created() + pnf_2 = all_pnfs[1] + assert pnf_2.name == "two" + assert pnf_2.identifier == "1235" + assert pnf_2.unique_uuid == "5679" + assert pnf_2.status == const.DRAFT + assert pnf_2.version == "1.0" + assert pnf_2.created() + mock_send.assert_called_once_with("GET", 'get Pnfs', 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/resources?resourceType=PNF') + + +def test_init_no_name(): + """Check init with no names.""" + pnf = Pnf() + assert isinstance(pnf, SdcResource) + assert pnf._identifier is None + assert pnf._version is None + assert pnf.name == "ONAP-test-PNF" + assert pnf.headers["USER_ID"] == "cs0008" + assert pnf.vsp is None + assert pnf.vendor is None + assert isinstance(pnf._base_url(), str) + +@mock.patch.object(Pnf, 'exists') +def test_init_with_name(mock_exists): + """Check init with names.""" + mock_exists.return_value = False + pnf = Pnf(name="YOLO") + assert pnf._identifier == None + assert pnf._version == None + assert pnf.name == "YOLO" + assert pnf.created() == False + assert pnf.headers["USER_ID"] == "cs0008" + assert pnf.vsp == None + assert isinstance(pnf._base_url(), str) + + +def test_equality_really_equals(): + """Check two pnfs are equals if name is the same.""" + pnf_1 = Pnf(name="equal") + pnf_1.identifier = "1234" + pnf_2 = Pnf(name="equal") + pnf_2.identifier = "1235" + assert pnf_1 == pnf_2 + + +def test_equality_not_equals(): + """Check two pnfs are not equals if name is not the same.""" + pnf_1 = Pnf(name="equal") + pnf_1.identifier = "1234" + pnf_2 = Pnf(name="not_equal") + pnf_2.identifier = "1234" + assert pnf_1 != pnf_2 + + +def test_equality_not_equals_not_same_object(): + """Check a pnf and something different are not equals.""" + pnf_1 = Pnf(name="equal") + pnf_1.identifier = "1234" + pnf_2 = SdcResource() + pnf_2.name = "equal" + assert pnf_1 != pnf_2 + + +@mock.patch.object(Pnf, 'get_all') +def test_exists_not_exists(mock_get_all): + """Return False if pnf doesn't exist in SDC.""" + pnf_1 = Pnf(name="one") + pnf_1.identifier = "1234" + mock_get_all.return_value = [pnf_1] + pnf = Pnf(name="two") + assert not pnf.exists() + + +@mock.patch.object(Pnf, 'get_all') +def test_exists(mock_get_all): + """Return True if pnf exists in SDC.""" + pnf_1 = Pnf(name="one") + pnf_1.identifier = "1234" + pnf_1.unique_uuid = "5689" + pnf_1.unique_identifier = "71011" + pnf_1.status = const.DRAFT + pnf_1.version = "1.1" + mock_get_all.return_value = [pnf_1] + pnf = Pnf(name="one") + assert pnf.exists() + assert pnf.identifier == "1234" + assert pnf.unique_uuid == "5689" + assert pnf.unique_identifier == "71011" + assert pnf.status == const.DRAFT + assert pnf.version == "1.1" + + +@mock.patch.object(Pnf, 'exists') +def test_load_created(mock_exists): + """Load is a wrapper around exists().""" + pnf = Pnf(name="one") + pnf.load() + mock_exists.assert_called_once() + + +@mock.patch.object(Pnf, 'exists') +def test_create_no_vsp_no_vendor(mock_exists): + """Do nothing if no vsp and no vendor""" + pnf = Pnf() + mock_exists.return_value = False + with pytest.raises(ParameterError) as err: + pnf.create() + assert err.type == ParameterError + assert str(err.value) == "Neither Vsp nor Vendor provided." + + +@mock.patch.object(Pnf, 'exists') +@mock.patch.object(Pnf, 'send_message_json') +@mock.patch.object(Pnf, "category") +def test_create_already_exists(mock_category, mock_send, mock_exists): + """Do nothing if already created in SDC.""" + pnf = Pnf() + vsp = Vsp() + vsp._identifier = "1232" + pnf.vsp = vsp + mock_exists.return_value = True + pnf.create() + mock_send.assert_not_called() + + +@mock.patch.object(Pnf, 'exists') +@mock.patch.object(Pnf, 'send_message_json') +@mock.patch.object(Pnf, "category", new_callable=mock.PropertyMock) +def test_create_issue_in_creation(mock_category, mock_send, mock_exists): +# def test_create_issue_in_creation(mock_send, mock_exists): + """Do nothing if not created but issue during creation.""" + pnf = Pnf() + vsp = Vsp() + vendor = Vendor() + vsp._identifier = "1232" + vsp.create_csar = MagicMock(return_value=True) + vsp.vendor = vendor + pnf.vsp = vsp + expected_data = '{\n "artifacts": {},\n "attributes": [],\n "capabilities": {},\n "categories": [\n {\n "normalizedName": "generic",\n "name": "Generic",\n "uniqueId": "resourceNewCategory.generic",\n "subcategories": [{"empty": false, "groupings": null, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": null, "type": null, "uniqueId": "resourceNewCategory.generic.abstract", "version": null}],\n "version": null,\n "ownerId": null,\n "empty": false,\n "type": null,\n "icons": null\n }\n ],\n "componentInstances": [],\n "componentInstancesAttributes": {},\n "componentInstancesProperties": {},\n "componentType": "RESOURCE",\n "contactId": "cs0008",\n \n "csarUUID": "None",\n "csarVersion": "1.0",\n "vendorName": "Generic-Vendor",\n \n "deploymentArtifacts": {},\n "description": "PNF",\n "icon": "defaulticon",\n "name": "ONAP-test-PNF",\n "properties": [],\n "groups": [],\n "requirements": {},\n "resourceType": "PNF",\n "tags": ["ONAP-test-PNF"],\n "toscaArtifacts": {},\n "vendorRelease": "1.0"\n}' + mock_exists.return_value = False + mock_send.side_effect = RequestError + rc = ResourceCategory( + name="Generic" + ) + rc.normalized_name="generic" + rc.unique_id="resourceNewCategory.generic" + rc.subcategories=[{"empty": False, "groupings": None, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": None, "type": None, "uniqueId": "resourceNewCategory.generic.abstract", "version": None}] + rc.version=None + rc.owner_id=None + rc.empty=False + rc.type=None + rc.icons=None + mock_category.return_value = rc + with pytest.raises(RequestError) as exc: + pnf.create() + mock_send.assert_called_once_with("POST", "create Pnf", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources', data=expected_data) + assert not pnf.created() + + +@mock.patch.object(Pnf, 'exists') +@mock.patch.object(Pnf, 'send_message_json') +@mock.patch.object(Pnf, "category", new_callable=mock.PropertyMock) +def test_create_OK(mock_category, mock_send, mock_exists): + """Create and update object.""" + pnf = Pnf() + vsp = Vsp() + vendor = Vendor() + vsp._identifier = "1232" + pnf.vsp = vsp + vsp.vendor = vendor + vsp._csar_uuid = "1234" + expected_data = '{\n "artifacts": {},\n "attributes": [],\n "capabilities": {},\n "categories": [\n {\n "normalizedName": "generic",\n "name": "Generic",\n "uniqueId": "resourceNewCategory.generic",\n "subcategories": [{"empty": false, "groupings": null, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": null, "type": null, "uniqueId": "resourceNewCategory.generic.abstract", "version": null}],\n "version": null,\n "ownerId": null,\n "empty": false,\n "type": null,\n "icons": null\n }\n ],\n "componentInstances": [],\n "componentInstancesAttributes": {},\n "componentInstancesProperties": {},\n "componentType": "RESOURCE",\n "contactId": "cs0008",\n \n "csarUUID": "1234",\n "csarVersion": "1.0",\n "vendorName": "Generic-Vendor",\n \n "deploymentArtifacts": {},\n "description": "PNF",\n "icon": "defaulticon",\n "name": "ONAP-test-PNF",\n "properties": [],\n "groups": [],\n "requirements": {},\n "resourceType": "PNF",\n "tags": ["ONAP-test-PNF"],\n "toscaArtifacts": {},\n "vendorRelease": "1.0"\n}' + mock_exists.return_value = False + mock_send.return_value = {'resourceType': 'PNF', 'name': 'one', 'uuid': '1234', 'invariantUUID': '5678', 'version': '1.0', 'uniqueId': '91011', 'lifecycleState': 'NOT_CERTIFIED_CHECKOUT'} + rc = ResourceCategory( + name="Generic" + ) + rc.normalized_name="generic" + rc.unique_id="resourceNewCategory.generic" + rc.subcategories=[{"empty": False, "groupings": None, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": None, "type": None, "uniqueId": "resourceNewCategory.generic.abstract", "version": None}] + rc.version=None + rc.owner_id=None + rc.empty=False + rc.type=None + rc.icons=None + mock_category.return_value = rc + pnf.create() + mock_send.assert_called_once_with("POST", "create Pnf", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources', data=expected_data) + assert pnf.created() + assert pnf._status == const.DRAFT + assert pnf.identifier == "1234" + assert pnf.unique_uuid == "5678" + assert pnf.version == "1.0" + +@mock.patch.object(Pnf, 'exists') +@mock.patch.object(Pnf, 'load') +def test_version_no_load_no_created(mock_load, mock_exists): + """Test versions when not created.""" + mock_exists.return_value = False + pnf = Pnf() + assert pnf.version is None + mock_load.assert_not_called() + +@mock.patch.object(Pnf, 'load') +def test_version_no_load_created(mock_load): + """Test versions when created.""" + pnf = Pnf() + pnf.identifier = "1234" + pnf._version = "64" + assert pnf.version == "64" + mock_load.assert_not_called() + + +@mock.patch.object(Pnf, 'load') +def test_version_with_load(mock_load): + """Test versions when not created but with identifier.""" + pnf = Pnf() + pnf.identifier = "1234" + assert pnf.version is None + mock_load.assert_called_once() + +@mock.patch.object(Pnf, 'exists') +@mock.patch.object(Pnf, 'load') +def test_status_no_load_no_created(mock_load, mock_exists): + """Test status when not created.""" + mock_exists.return_value = False + pnf = Pnf() + assert pnf.status is None + + +@pytest.mark.parametrize("status", [const.COMMITED, const.CERTIFIED, const.UPLOADED, const.VALIDATED]) +@mock.patch.object(Pnf, 'exists') +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'send_message') +def test_submit_not_Commited(mock_send, mock_load, mock_exists, status): + """Do nothing if not created.""" + mock_exists.return_value = False + pnf = Pnf() + pnf._status = status + pnf.submit() + mock_send.assert_not_called() + +@mock.patch.object(Pnf, 'exists') +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'send_message') +def test_submit_OK(mock_send, mock_load, mock_exists): + """Don't update status if submission NOK.""" + mock_exists.return_value = True + pnf = Pnf() + pnf._status = const.COMMITED + expected_data = '{\n "userRemarks": "certify"\n}' + pnf._version = "1234" + pnf._unique_identifier = "12345" + pnf.submit() + mock_send.assert_called_once_with( + "POST", "Certify Pnf", + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources/12345/lifecycleState/Certify', + data=expected_data) + + +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'certify') +@mock.patch.object(Pnf, 'submit') +@mock.patch.object(Pnf, 'create') +def test_onboard_new_pnf(mock_create, mock_submit, mock_certify, mock_load): + getter_mock = mock.Mock(wraps=Pnf.status.fget) + mock_status = Pnf.status.getter(getter_mock) + with mock.patch.object(Pnf, 'status', mock_status): + getter_mock.side_effect = [None, const.APPROVED, const.APPROVED, + const.APPROVED, const.APPROVED] + vsp = Vsp() + pnf = Pnf(vsp=vsp) + pnf._time_wait = 0 + pnf.onboard() + mock_create.assert_called_once() + mock_submit.assert_not_called() + mock_certify.assert_not_called() + mock_load.assert_not_called() + +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'certify') +@mock.patch.object(Pnf, 'submit') +@mock.patch.object(Pnf, 'create') +def test_onboard_pnf_submit(mock_create, mock_submit, mock_certify, mock_load): + getter_mock = mock.Mock(wraps=Pnf.status.fget) + mock_status = Pnf.status.getter(getter_mock) + with mock.patch.object(Pnf, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.DRAFT, const.APPROVED, + const.APPROVED, const.APPROVED, const.APPROVED] + pnf = Pnf() + pnf._time_wait = 0 + pnf.onboard() + mock_create.assert_not_called() + mock_submit.assert_called_once() + mock_certify.assert_not_called() + mock_load.assert_not_called() + +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'certify') +@mock.patch.object(Pnf, 'submit') +@mock.patch.object(Pnf, 'create') +def test_onboard_pnf_certify(mock_create, mock_submit, mock_certify, mock_load): + getter_mock = mock.Mock(wraps=Pnf.status.fget) + mock_status = Pnf.status.getter(getter_mock) + with mock.patch.object(Pnf, 'status', mock_status): + getter_mock.side_effect = [const.CHECKED_IN, const.CHECKED_IN, const.CHECKED_IN, + const.APPROVED, const.APPROVED, const.APPROVED, + const.APPROVED] + pnf = Pnf() + pnf._time_wait = 0 + pnf.onboard() + mock_create.assert_not_called() + mock_submit.assert_not_called() + mock_certify.assert_called_once() + mock_load.assert_not_called() + +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'certify') +@mock.patch.object(Pnf, 'submit') +@mock.patch.object(Pnf, 'create') +def test_onboard_pnf_load(mock_create, mock_submit, mock_certify, mock_load): + getter_mock = mock.Mock(wraps=Pnf.status.fget) + mock_status = Pnf.status.getter(getter_mock) + with mock.patch.object(Pnf, 'status', mock_status): + getter_mock.side_effect = [const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.CERTIFIED, + const.APPROVED, const.APPROVED, + const.APPROVED] + pnf = Pnf() + pnf._time_wait = 0 + pnf.onboard() + mock_create.assert_not_called() + mock_submit.assert_not_called() + mock_certify.assert_not_called() + mock_load.assert_called_once() + +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'submit') +@mock.patch.object(Pnf, 'create') +@mock.patch.object(Pnf, 'certify') +def test_onboard_whole_pnf_vsp(mock_certify, mock_create, mock_submit, mock_load): + """Test onboarding with vsp""" + getter_mock = mock.Mock(wraps=Pnf.status.fget) + mock_status = Pnf.status.getter(getter_mock) + with mock.patch.object(Pnf, 'status', mock_status): + getter_mock.side_effect = [None, const.DRAFT, const.DRAFT, + const.CHECKED_IN, const.CHECKED_IN, const.CHECKED_IN, + const.CERTIFIED, const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.APPROVED, const.APPROVED, + const.APPROVED, const.APPROVED] + vsp = Vsp() + pnf = Pnf(vsp=vsp) + pnf._time_wait = 0 + pnf.onboard() + mock_create.assert_called_once() + mock_submit.assert_called_once() + mock_load.assert_called_once() + mock_certify.assert_called_once() + +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'submit') +@mock.patch.object(Pnf, 'create') +@mock.patch.object(Pnf, 'certify') +def test_onboard_whole_pnf_vendor(mock_certify, mock_create, mock_submit, mock_load): + """Test onboarding with vendor""" + getter_mock = mock.Mock(wraps=Pnf.status.fget) + mock_status = Pnf.status.getter(getter_mock) + with mock.patch.object(Pnf, 'status', mock_status): + getter_mock.side_effect = [None, const.DRAFT, const.DRAFT, + const.CHECKED_IN, const.CHECKED_IN, const.CHECKED_IN, + const.CERTIFIED, const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.APPROVED, const.APPROVED, + const.APPROVED, const.APPROVED] + vendor = Vendor() + pnf = Pnf(vendor=vendor) + pnf._time_wait = 0 + pnf.onboard() + mock_create.assert_called_once() + mock_submit.assert_called_once() + mock_load.assert_called_once() + mock_certify.assert_called_once() + +@mock.patch.object(Pnf, "send_message_json") +def test_add_properties(mock_send_message_json): + pnf = Pnf(name="test") + pnf._identifier = "toto" + pnf._unique_identifier = "toto" + pnf._status = const.CERTIFIED + with pytest.raises(StatusError) as err: + pnf.add_property(Property(name="test", property_type="string")) + pnf._status = const.DRAFT + pnf.add_property(Property(name="test", property_type="string")) + mock_send_message_json.assert_called_once() + +@mock.patch.object(Pnf, 'load') +@mock.patch.object(Pnf, 'send_message') +def test_add_artifact_to_pnf(mock_send_message, mock_load): + """Test Pnf add artifact""" + pnf = Pnf(name="test") + pnf.status = const.DRAFT + mycbapath = Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip") + + result = pnf.add_deployment_artifact(artifact_label="cba", + artifact_type="CONTROLLER_BLUEPRINT_ARCHIVE", + artifact_name="vLB_CBA_Python.zip", + artifact=mycbapath) + mock_send_message.assert_called() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "Add deployment artifact for test sdc resource" + assert url == ("https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources/" + f"{pnf.unique_identifier}/artifacts") + + +@mock.patch.object(Pnf, "created") +@mock.patch.object(ResourceCategory, "get") +def test_pnf_category(mock_resource_category, mock_created): + mock_created.return_value = False + pnf = Pnf(name="test") + _ = pnf.category + mock_resource_category.assert_called_once_with(name="Generic", subcategory="Abstract") + mock_resource_category.reset_mock() + + pnf = Pnf(name="test", category="test", subcategory="test") + _ = pnf.category + mock_resource_category.assert_called_once_with(name="test", subcategory="test") + mock_resource_category.reset_mock() + + mock_created.return_value = True + _ = pnf.category + mock_resource_category.assert_called_once_with(name="test", subcategory="test") diff --git a/tests/test_preload.py b/tests/test_preload.py new file mode 100644 index 0000000..0a97043 --- /dev/null +++ b/tests/test_preload.py @@ -0,0 +1,150 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import json +from collections.abc import Iterable +from unittest import mock + +from onapsdk.sdnc.preload import NetworkPreload, PreloadInformation, VfModulePreload +from onapsdk.so.instantiation import Subnet + + +PRELOAD_INFORMATIONS = { + 'preload-information': { + 'preload-list': [ + { + 'preload-id': 'Python_ONAP_SDK_network_instance_338d5238-22fe-44d1-857a-223e2f6edd9b', + 'preload-type': 'network', + 'preload-data': { + 'preload-network-topology-information': { + 'physical-network-name': 'Not Aplicable', + 'is-provider-network': False, + 'is-external-network': False, + 'network-topology-identifier-structure': { + 'network-technology': 'neutron', + 'network-type': 'Generic NeutronNet', + 'network-name': 'Python_ONAP_SDK_network_instance_338d5238-22fe-44d1-857a-223e2f6edd9b', + 'network-role': 'integration_test_net' + }, + 'is-shared-network': False + }, + 'preload-oper-status': { + 'create-timestamp': '2020-06-26T09:12:03.708Z', + 'order-status': 'PendingAssignment' + } + } + }, + { + 'preload-id': 'Python_ONAP_SDK_network_instance_5d61bcf6-ec37-4cea-9d1b-744d0c2b75b9', + 'preload-type': 'network', + 'preload-data': { + 'preload-network-topology-information': { + 'is-provider-network': False, + 'is-external-network': False, + 'network-topology-identifier-structure': { + 'network-technology': 'neutron', + 'network-type': 'Generic NeutronNet', + 'network-name': 'Python_ONAP_SDK_network_instance_5d61bcf6-ec37-4cea-9d1b-744d0c2b75b9', + 'network-id': '1234', + 'network-role': 'integration_test_net' + }, + 'is-shared-network': False + }, + 'preload-oper-status': { + 'create-timestamp': '2020-06-25T12:22:35.939Z', + 'order-status': 'PendingAssignment' + } + } + } + ] + } +} + + +@mock.patch.object(VfModulePreload, "send_message_json") +def test_vf_module_preload_gr_api(mock_send_message_json): + VfModulePreload.upload_vf_module_preload(vnf_instance=mock.MagicMock(), + vf_module_instance_name="test", + vf_module=mock.MagicMock()) + mock_send_message_json.assert_called_once() + method, description, url = mock_send_message_json.call_args[0] + assert method == "POST" + assert description == "Upload VF module preload using GENERIC-RESOURCE-API" + assert url == (f"{VfModulePreload.base_url}/restconf/operations/" + "GENERIC-RESOURCE-API:preload-vf-module-topology-operation") + + +@mock.patch.object(PreloadInformation, "send_message_json") +def test_preload_information(mock_send_message_json): + mock_send_message_json.return_value = PRELOAD_INFORMATIONS + preload_informations = PreloadInformation.get_all() + assert isinstance(preload_informations, Iterable) + preload_informations_list = list(preload_informations) + assert len(preload_informations_list) == 2 + preload_information = preload_informations_list[0] + assert isinstance(preload_information, PreloadInformation) + assert preload_information.preload_id == "Python_ONAP_SDK_network_instance_338d5238-22fe-44d1-857a-223e2f6edd9b" + assert preload_information.preload_type == "network" + + +@mock.patch.object(NetworkPreload, "send_message_json") +def test_network_preload(mock_send_message_json): + NetworkPreload.upload_network_preload( + mock.MagicMock(), + network_instance_name="test_instance", + ) + mock_send_message_json.assert_called_once() + _, _, kwargs = mock_send_message_json.mock_calls[0] + assert "data" in kwargs + data = json.loads(kwargs["data"]) + assert not len(data["input"]["preload-network-topology-information"]["subnets"]) + + mock_send_message_json.reset_mock() + NetworkPreload.upload_network_preload( + mock.MagicMock(), + network_instance_name="test_instance", + subnets=[Subnet( + name="test_subnet", + start_address="127.0.0.0", + gateway_address="127.0.0.1" + )] + ) + mock_send_message_json.assert_called_once() + _, _, kwargs = mock_send_message_json.mock_calls[0] + assert "data" in kwargs + data = json.loads(kwargs["data"]) + assert len(data["input"]["preload-network-topology-information"]["subnets"]) + assert data["input"]["preload-network-topology-information"]["subnets"][0]["subnet-name"] == "test_subnet" + assert data["input"]["preload-network-topology-information"]["subnets"][0]["dhcp-enabled"] == "N" + + mock_send_message_json.reset_mock() + NetworkPreload.upload_network_preload( + mock.MagicMock(), + network_instance_name="test_instance", + subnets=[Subnet( + name="test_subnet", + start_address="127.0.0.0", + gateway_address="127.0.0.1", + dhcp_enabled=True, + dhcp_start_address="192.168.0.0", + dhcp_end_address="192.168.0.1" + )] + ) + mock_send_message_json.assert_called_once() + _, _, kwargs = mock_send_message_json.mock_calls[0] + assert "data" in kwargs + data = json.loads(kwargs["data"]) + assert len(data["input"]["preload-network-topology-information"]["subnets"]) + assert data["input"]["preload-network-topology-information"]["subnets"][0]["subnet-name"] == "test_subnet" + assert data["input"]["preload-network-topology-information"]["subnets"][0]["dhcp-start-address"] == "192.168.0.0" + assert data["input"]["preload-network-topology-information"]["subnets"][0]["dhcp-end-address"] == "192.168.0.1" diff --git a/tests/test_sdc_category_management.py b/tests/test_sdc_category_management.py new file mode 100644 index 0000000..59ca5f5 --- /dev/null +++ b/tests/test_sdc_category_management.py @@ -0,0 +1,349 @@ +"""Test SdcElement module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest +from onapsdk.exceptions import APIError, ResourceNotFound + +from onapsdk.sdc.category_management import ResourceCategory, ServiceCategory + + +CATEGORIES = { + "categories": { + 'resourceCategories': [ + { + 'name': 'Network L4+', + 'normalizedName': 'network l4+', + 'uniqueId': 'resourceNewCategory.network l4+', + 'icons': None, + 'subcategories': [ + { + 'name': 'Common Network Resources', + 'normalizedName': 'common network resources', + 'uniqueId': 'resourceNewCategory.network l4+.common network resources', + 'icons': ['network'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + } + ], + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Network L2-3', + 'normalizedName': 'network l2-3', + 'uniqueId': 'resourceNewCategory.network l2-3', + 'icons': None, + 'subcategories': [ + { + 'name': 'Router', + 'normalizedName': 'router', + 'uniqueId': 'resourceNewCategory.network l2-3.router', + 'icons': ['router', 'vRouter'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'LAN Connectors', + 'normalizedName': 'lan connectors', + 'uniqueId': 'resourceNewCategory.network l2-3.lan connectors', + 'icons': ['network', 'connector', 'port'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Infrastructure', + 'normalizedName': 'infrastructure', + 'uniqueId': 'resourceNewCategory.network l2-3.infrastructure', + 'icons': ['ucpe'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Gateway', + 'normalizedName': 'gateway', + 'uniqueId': 'resourceNewCategory.network l2-3.gateway', + 'icons': ['gateway'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'WAN Connectors', + 'normalizedName': 'wan connectors', + 'uniqueId': 'resourceNewCategory.network l2-3.wan connectors', + 'icons': ['network', 'connector', 'port'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + } + ], + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Network Connectivity', + 'normalizedName': 'network connectivity', + 'uniqueId': 'resourceNewCategory.network connectivity', + 'icons': None, + 'subcategories': [ + { + 'name': 'Connection Points', + 'normalizedName': 'connection points', + 'uniqueId': 'resourceNewCategory.network connectivity.connection points', + 'icons': ['cp'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Virtual Links', + 'normalizedName': 'virtual links', + 'uniqueId': 'resourceNewCategory.network connectivity.virtual links', + 'icons': ['vl'], + 'groupings': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + } + ], + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Configuration', + 'normalizedName': 'configuration', + 'uniqueId': 'resourceNewCategory.configuration', + 'icons': None, + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + ], + 'serviceCategories': [ + { + 'name': 'Partner Domain Service', + 'normalizedName': 'partner domain service', + 'uniqueId': 'serviceNewCategory.partner domain service', + 'icons': ['partner_domain_service'], + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Mobility', + 'normalizedName': 'mobility', + 'uniqueId': 'serviceNewCategory.mobility', + 'icons': ['mobility'], + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'VoIP Call Control', + 'normalizedName': 'voip call control', + 'uniqueId': 'serviceNewCategory.voip call control', + 'icons': ['call_controll'], + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'E2E Service', + 'normalizedName': 'e2e service', + 'uniqueId': 'serviceNewCategory.e2e service', + 'icons': ['network_l_1-3'], + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Network L4+', + 'normalizedName': 'network l4+', + 'uniqueId': 'serviceNewCategory.network l4+', + 'icons': ['network_l_4'], + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Network L1-3', + 'normalizedName': 'network l1-3', + 'uniqueId': 'serviceNewCategory.network l1-3', + 'icons': ['network_l_1-3'], + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + { + 'name': 'Network Service', + 'normalizedName': 'network service', + 'uniqueId': 'serviceNewCategory.network service', + 'icons': ['network_l_1-3'], + 'subcategories': None, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + ], + 'productCategories': [] + } +} + + +@mock.patch.object(ResourceCategory, "send_message_json") +def test_resource_category_exists(mock_send_message_json): + + rc = ResourceCategory(name="test_name") + mock_send_message_json.return_value = {} + assert not rc.exists() + mock_send_message_json.return_value = CATEGORIES + assert not rc.exists() + rc = ResourceCategory(name="Network Connectivity") + assert rc.exists() + +@mock.patch.object(ResourceCategory, "send_message_json") +def test_resource_category_get(mock_send_message_json): + + mock_send_message_json.return_value = CATEGORIES + rc = ResourceCategory.get(name="Network Connectivity") + assert rc.name == "Network Connectivity" + assert rc.normalized_name == "network connectivity" + assert rc.unique_id == "resourceNewCategory.network connectivity" + assert not rc.icons + assert not rc.version + assert not rc.owner_id + assert not rc.empty + assert not rc.type + assert len(rc.subcategories) == 2 + + with pytest.raises(ResourceNotFound): + ResourceCategory.get(name="Network Connectivity", subcategory="Toto") + rc = ResourceCategory.get(name="Network Connectivity", subcategory="Connection Points") + assert rc.name == "Network Connectivity" + assert rc.normalized_name == "network connectivity" + assert rc.unique_id == "resourceNewCategory.network connectivity" + assert not rc.icons + assert not rc.version + assert not rc.owner_id + assert not rc.empty + assert not rc.type + assert len(rc.subcategories) == 1 + + mock_send_message_json.side_effect = APIError + with pytest.raises(ResourceNotFound): + ResourceCategory.get(name="Network Connectivity") + + mock_send_message_json.side_effect = KeyError + with pytest.raises(ResourceNotFound): + ResourceCategory.get(name="Network Connectivity") + +@mock.patch.object(ResourceCategory, "send_message_json") +def test_resource_category_create(mock_send_message_json): + + mock_send_message_json.return_value = CATEGORIES + rc = ResourceCategory.create(name="Network Connectivity") + assert rc.name == "Network Connectivity" + assert rc.normalized_name == "network connectivity" + assert rc.unique_id == "resourceNewCategory.network connectivity" + assert not rc.icons + assert not rc.version + assert not rc.owner_id + assert not rc.empty + assert not rc.type + ResourceCategory.create(name="New category") + +@mock.patch.object(ServiceCategory, "send_message_json") +def test_service_category_exists(mock_send_message_json): + + sc = ServiceCategory(name="test_name") + mock_send_message_json.return_value = CATEGORIES + assert not sc.exists() + sc = ServiceCategory(name="Partner Domain Service") + assert sc.exists() + mock_send_message_json.side_effect = APIError + assert not sc.exists() + mock_send_message_json.side_effect = KeyError + assert not sc.exists() + +@mock.patch.object(ServiceCategory, "send_message_json") +def test_service_category_get(mock_send_message_json): + + mock_send_message_json.return_value = {} + with pytest.raises(ResourceNotFound): + ServiceCategory.get(name="Partner Domain Service") + mock_send_message_json.return_value = CATEGORIES + sc = ServiceCategory.get(name="Partner Domain Service") + assert sc.name == "Partner Domain Service" + assert sc.normalized_name == "partner domain service" + assert sc.unique_id == "serviceNewCategory.partner domain service" + assert not sc.version + assert not sc.owner_id + assert not sc.empty + assert not sc.type + +@mock.patch.object(ServiceCategory, "send_message_json") +def test_service_category_create(mock_send_message_json): + + mock_send_message_json.return_value = CATEGORIES + sc = ServiceCategory.create(name="Partner Domain Service") + assert sc.name == "Partner Domain Service" + assert sc.normalized_name == "partner domain service" + assert sc.unique_id == "serviceNewCategory.partner domain service" + assert not sc.version + assert not sc.owner_id + assert not sc.empty + assert not sc.type + ServiceCategory.create(name="New category")
\ No newline at end of file diff --git a/tests/test_sdc_component.py b/tests/test_sdc_component.py new file mode 100644 index 0000000..ee77de7 --- /dev/null +++ b/tests/test_sdc_component.py @@ -0,0 +1,44 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.sdc.component import Component + + +def test_sdc_component_delete(): + mock_sdc_resource = mock.MagicMock() + mock_parent_sdc_resource = mock.MagicMock() + mock_parent_sdc_resource.resource_inputs_url = "http://test.onap.org" + component = Component( + created_from_csar=False, + actual_component_uid="123", + unique_id="456", + normalized_name="789", + name="test_component", + origin_type="test-origin-type", + customization_uuid="098", + component_uid="765", + component_version="432", + tosca_component_name="test-tosca-component-name", + component_name="test-component-name", + sdc_resource=mock_sdc_resource, + parent_sdc_resource=mock_parent_sdc_resource, + group_instances=None + ) + component.delete() + mock_sdc_resource.send_message_json.assert_called_once_with( + "DELETE", + "Delete test_component component", + f"http://test.onap.org/resourceInstance/{component.unique_id}" + ) diff --git a/tests/test_sdc_element.py b/tests/test_sdc_element.py new file mode 100644 index 0000000..88bcd8f --- /dev/null +++ b/tests/test_sdc_element.py @@ -0,0 +1,109 @@ +"""Test SdcElement module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.onap_service import OnapService +from onapsdk.sdc.sdc_element import SdcElement +from onapsdk.sdc.vendor import Vendor +from onapsdk.sdc.vsp import Vsp +from onapsdk.sdc import SDC +from onapsdk.utils.gui import GuiList + +def test_init(): + """Test the initialization.""" + element = Vendor() + assert isinstance(element, OnapService) + +def test_class_variables(): + """Test the class variables.""" + assert SdcElement.server == "SDC" + assert SdcElement.base_front_url == "https://sdc.api.fe.simpledemo.onap.org:30207" + assert SdcElement.base_back_url == "https://sdc.api.be.simpledemo.onap.org:30204" + assert SdcElement.headers == { + "Content-Type": "application/json", + "Accept": "application/json" + } + +@mock.patch.object(Vendor, 'created') +@mock.patch.object(Vendor, 'send_message_json') +def test__get_item_details_not_created(mock_send, mock_created): + vendor = Vendor() + mock_created.return_value = False + assert vendor._get_item_details() == {} + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'send_message_json') +def test__get_item_details_created(mock_send): + vsp = Vsp() + vsp.identifier = "1234" + mock_send.return_value = {'results': [{"creationTime": "2"}, {"creationTime": "3"}], "listCount": 2} + assert vsp._get_item_details() == {"creationTime": "3"} + mock_send.assert_called_once_with('GET', 'get item', "{}/items/1234/versions".format(vsp._base_url())) + +@mock.patch.object(Vsp, 'created') +@mock.patch.object(Vsp, 'send_message_json') +def test__get_items_version_details_not_created(mock_send, mock_created): + vsp = Vsp() + mock_created.return_value = False + assert vsp._get_item_version_details() == {} + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'load') +@mock.patch.object(Vsp, 'send_message_json') +def test__get_items_version_details_no_version(mock_send, mock_load): + vsp = Vsp() + vsp.identifier = "1234" + assert vsp._get_item_version_details() == {} + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'send_message_json') +def test__get_items_version_details(mock_send): + vsp = Vsp() + vsp.identifier = "1234" + vsp._version = "4567" + mock_send.return_value = {'return': 'value'} + assert vsp._get_item_version_details() == {'return': 'value'} + mock_send.assert_called_once_with('GET', 'get item version', "{}/items/1234/versions/4567".format(vsp._base_url())) + +@mock.patch.object(SDC, "send_message") +def test_get_guis(send_message_mock): + send_message_mock.return_value.status_code = 200 + send_message_mock.return_value.url = "https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/portal" + gui_results = SDC.get_guis() + assert type(gui_results) == GuiList + assert gui_results.guilist[0].url == send_message_mock.return_value.url + assert gui_results.guilist[0].status == send_message_mock.return_value.status_code + +@mock.patch.object(SDC, "get_all") +@mock.patch.object(Vsp, "created") +def test_exists_versions(mock_vsp_created, mock_get_all): + mock_vsp_created.return_value = True + sdc_el1 = Vsp(name="test1") + sdc_el1._version = "1.0" + sdc_el1._identifier = "123" + sdc_el2 = Vsp(name="test2") + sdc_el2._version = "2.0" + sdc_el2._identifier = "123" + mock_get_all.return_value = [sdc_el1, sdc_el2] + assert sdc_el1.exists() + + sdc_el1 = Vsp(name="test1") + sdc_el1._version = "anything" + sdc_el1._identifier = "123" + sdc_el2 = Vsp(name="test2") + sdc_el2._version = "what_is_not_a_float" + sdc_el2._identifier = "123" + mock_get_all.return_value = [sdc_el1, sdc_el2] + assert sdc_el1.exists() diff --git a/tests/test_sdc_resource.py b/tests/test_sdc_resource.py new file mode 100644 index 0000000..1bf562a --- /dev/null +++ b/tests/test_sdc_resource.py @@ -0,0 +1,487 @@ +"""Test SdcResource module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock +import logging + +import pytest + +import onapsdk.constants as const +from onapsdk.exceptions import ParameterError, RequestError, ResourceNotFound +from onapsdk.onap_service import OnapService +from onapsdk.sdc.component import Component +from onapsdk.sdc.properties import ComponentProperty, Input, NestedInput, Property +from onapsdk.sdc.sdc_resource import SdcResource +from onapsdk.sdc.service import Service +from onapsdk.sdc.vf import Vf +from onapsdk.utils.headers_creator import headers_sdc_tester +from onapsdk.utils.headers_creator import headers_sdc_creator + + +COMPONENT_PROPERTIES = [ + { + "uniqueId":"3d9a184f-4268-4a0e-9ddd-252e49670013.vf_module_id", + "type":"string", + "required":False, + "definition":False, + "description":"The vFirewall Module ID is provided by ECOMP", + "password":False, + "name":"vf_module_id", + "label":"vFirewall module ID", + "hidden":False, + "immutable":False, + "isDeclaredListInput":False, + "getInputProperty":False, + "empty":False + },{ + "uniqueId":"74f79006-ae56-4d58-947e-6a5089000774.skip_post_instantiation_configuration", + "type":"boolean", + "required":False, + "definition":False, + "password":False, + "name":"skip_post_instantiation_configuration", + "value":"true", + "hidden":False, + "immutable":False, + "parentUniqueId":"74f79006-ae56-4d58-947e-6a5089000774", + "isDeclaredListInput":False, + "getInputProperty":False, + "ownerId":"74f79006-ae56-4d58-947e-6a5089000774", + "empty":False + } +] + + + +def test_init(): + """Test the initialization.""" + element = SdcResource() + assert isinstance(element, OnapService) + +def test_class_variables(): + """Test the class variables.""" + assert SdcResource.server == "SDC" + assert SdcResource.base_front_url == "https://sdc.api.fe.simpledemo.onap.org:30207" + assert SdcResource.base_back_url == "https://sdc.api.be.simpledemo.onap.org:30204" + assert SdcResource.headers == { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": "Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=", + "USER_ID": "cs0008", + "X-ECOMP-InstanceID": "onapsdk" + } + +@mock.patch.object(Vf, 'load') +def test__unique_uuid_no_load(mock_load): + vf = Vf() + vf.identifier = "1234" + vf._unique_uuid = "4567" + assert vf.unique_uuid == "4567" + mock_load.assert_not_called() + +@mock.patch.object(Vf, 'load') +def test__unique_uuid_load(mock_load): + vf = Vf() + vf.identifier = "1234" + assert vf.unique_uuid == None + mock_load.assert_called_once() + +def test__unique_uuid_setter(): + vf = Vf() + vf.identifier = "1234" + vf.unique_uuid = "4567" + assert vf._unique_uuid == "4567" + +@mock.patch.object(Vf, 'deep_load') +def test__unique_identifier_load(mock_load): + vf = Vf() + vf.identifier = "1234" + assert vf.unique_identifier == None + mock_load.assert_called_once() + +@mock.patch.object(Vf, 'deep_load') +def test__unique_identifier_no_load(mock_load): + vf = Vf() + vf.identifier = "1234" + vf._unique_identifier= "toto" + assert vf.unique_identifier == "toto" + mock_load.assert_not_called() + +def test__status_setter(): + vf = Vf() + vf.identifier = "1234" + vf.status = "4567" + assert vf._status == "4567" + +@mock.patch.object(Vf, 'created') +@mock.patch.object(Vf, 'send_message_json') +def test__deep_load_request_error(mock_send, mock_created): + mock_created.return_value = True + vf = Vf() + vf.identifier = "1234" + vf._version = "4567" + vf._status = const.CHECKED_IN + mock_send.side_effect = RequestError + with pytest.raises(RequestError) as err: + vf.deep_load() + assert err.type == RequestError + assert vf._unique_identifier is None + mock_send.assert_called_once_with('GET', 'Deep Load Vf', + "{}/sdc1/feProxy/rest/v1/screen?excludeTypes=VFCMT&excludeTypes=Configuration".format(vf.base_front_url), + headers=headers_sdc_creator(vf.headers)) + +@mock.patch.object(Vf, 'created') +@mock.patch.object(Vf, 'send_message_json') +def test__deep_load_response_OK(mock_send, mock_created): + mock_created.return_value = True + vf = Vf() + vf.identifier = "5689" + vf.unique_uuid = "1234" + vf._version = "4567" + vf._status = const.CHECKED_IN + mock_send.return_value = {'resources': [{'uuid': '5689', 'name': 'test', 'uniqueId': '71011', 'invariantUUID': '1234', 'categories': [{'name': 'test', 'subcategories': [{'name': 'test_subcategory'}]}]}]} + vf.deep_load() + assert vf.unique_identifier == "71011" + assert vf._category_name == "test" + assert vf._subcategory_name == "test_subcategory" + mock_send.assert_called_once_with('GET', 'Deep Load Vf', + "{}/sdc1/feProxy/rest/v1/screen?excludeTypes=VFCMT&excludeTypes=Configuration".format(vf.base_front_url), + headers=headers_sdc_creator(vf.headers)) + +@mock.patch.object(Service, 'created') +@mock.patch.object(Service, 'send_message_json') +def test__deep_load_response_OK_dependency(mock_send, mock_created): + mock_created.return_value = True + vf = Service() + vf.identifier = "4321" + vf.unique_uuid = "1234" + vf._version = "4567" + vf._status = const.CHECKED_IN + mock_send.side_effect = [{'services': [{'uuid': '5689', 'name': 'test', 'uniqueId': '71011', 'invariantUUID': '1234', 'categories': [{'name': 'test', 'subcategories': [{'name': 'test_subcategory'}]}]}]}, [{'version': '4567', 'uniqueId': '71011'}]] + vf.deep_load() + assert vf.unique_identifier == "71011" + +@mock.patch.object(Vf, 'created') +@mock.patch.object(Vf, 'send_message_json') +def test__deep_load_response_NOK(mock_send, mock_created): + mock_created.return_value = True + vf = Vf() + vf.identifier = "5678" + vf.unique_uuid = "1234" + vf._version = "4567" + vf._status = const.CHECKED_IN + mock_send.return_value = {'resources': [{'uuid': '5689', 'name': 'test', 'uniqueId': '71011', 'invariantUUID': '1234', }]} + vf.deep_load() + assert vf._unique_identifier is None + mock_send.assert_called_once_with('GET', 'Deep Load Vf', + "{}/sdc1/feProxy/rest/v1/screen?excludeTypes=VFCMT&excludeTypes=Configuration".format(vf.base_front_url), + headers=headers_sdc_creator(vf.headers)) + +@mock.patch.object(Vf, 'created') +@mock.patch.object(Vf, 'send_message_json') +def test__deep_load_response_OK_under_cert(mock_send, mock_created): + mock_created.return_value = True + vf = Vf() + vf.identifier = "5689" + vf.unique_uuid = "1234" + vf._version = "4567" + vf._status = const.UNDER_CERTIFICATION + mock_send.return_value = {'resources': [{'uuid': '5689', 'name': 'test', 'uniqueId': '71011', 'invariantUUID': '1234', 'categories': [{'name': 'test', 'subcategories': [{'name': 'test_subcategory'}]}]}]} + vf.deep_load() + assert vf.unique_identifier == "71011" + assert vf._category_name == "test" + assert vf._subcategory_name == "test_subcategory" + mock_send.assert_called_once_with('GET', 'Deep Load Vf', + "{}/sdc1/feProxy/rest/v1/screen?excludeTypes=VFCMT&excludeTypes=Configuration".format(vf.base_front_url), + headers=headers_sdc_tester(vf.headers)) + +@mock.patch.object(Vf, 'created') +@mock.patch.object(Vf, 'send_message_json') +def test__deep_load_response_NOK_under_cert(mock_send, mock_created): + mock_created.return_value = True + vf = Vf() + vf.identifier = "5678" + vf.unique_uuid = "1234" + vf._version = "4567" + vf._status = const.UNDER_CERTIFICATION + mock_send.return_value = {'resources': [{'uuid': '5689', 'name': 'test', 'invariantUUID': '1234', 'uniqueId': '71011'}]} + vf.deep_load() + assert vf._unique_identifier is None + mock_send.assert_called_once_with('GET', 'Deep Load Vf', + "{}/sdc1/feProxy/rest/v1/screen?excludeTypes=VFCMT&excludeTypes=Configuration".format(vf.base_front_url), + headers=headers_sdc_tester(vf.headers)) + +def test__parse_sdc_status_certified(): + assert SdcResource._parse_sdc_status("CERTIFIED", None, logging.getLogger()) == const.CERTIFIED + +def test__parse_sdc_status_certified_not_approved(): + assert SdcResource._parse_sdc_status("CERTIFIED", + const.DISTRIBUTION_NOT_APPROVED, + logging.getLogger()) == const.CERTIFIED + +def test__parse_sdc_status_certified_approved(): + assert SdcResource._parse_sdc_status("CERTIFIED", + const.DISTRIBUTION_APPROVED, + logging.getLogger()) == const.CERTIFIED + +def test__parse_sdc_status_distributed(): + assert SdcResource._parse_sdc_status("CERTIFIED", const.SDC_DISTRIBUTED, + logging.getLogger()) == const.DISTRIBUTED + +def test__parse_sdc_status_draft(): + assert SdcResource._parse_sdc_status(const.NOT_CERTIFIED_CHECKOUT, None, + logging.getLogger() ) == const.DRAFT + +def test__parse_sdc_status_draft(): + assert SdcResource._parse_sdc_status(const.NOT_CERTIFIED_CHECKIN, None, + logging.getLogger() ) == const.CHECKED_IN + +def test__parse_sdc_status_submitted(): + assert SdcResource._parse_sdc_status(const.READY_FOR_CERTIFICATION, None, + logging.getLogger() ) == const.SUBMITTED + +def test__parse_sdc_status_under_certification(): + assert SdcResource._parse_sdc_status(const.CERTIFICATION_IN_PROGRESS, None, + logging.getLogger() ) == const.UNDER_CERTIFICATION + +def test__parse_sdc_status_unknown(): + assert SdcResource._parse_sdc_status("UNKNOWN", None, logging.getLogger() ) == 'UNKNOWN' + +def test__parse_sdc_status_empty(): + assert SdcResource._parse_sdc_status("", None, logging.getLogger() ) is None + +def test__really_submit(): + sdcResource = SdcResource() + with pytest.raises(NotImplementedError): + sdcResource._really_submit() + +def test__action_url_no_action_type(): + sdcResource = SdcResource() + url = sdcResource._action_url("base", "subpath", "version_path") + assert url == "base/resources/version_path/lifecycleState/subpath" + +def test__action_url_action_type(): + sdcResource = SdcResource() + url = sdcResource._action_url("base", "subpath", "version_path", + action_type="distribution") + assert url == "base/resources/version_path/distribution/subpath" + +@mock.patch.object(SdcResource, '_parse_sdc_status') +def test_update_informations_from_sdc_creation_no_distribitution_state(mock_parse): + mock_parse.return_value = "12" + sdcResource = SdcResource() + details = {'invariantUUID': '1234', + 'lifecycleState': 'state', + 'version': 'v12', + 'uniqueId': '5678'} + + sdcResource.update_informations_from_sdc_creation(details) + assert sdcResource.unique_uuid == "1234" + assert sdcResource.status == "12" + assert sdcResource.version == "v12" + assert sdcResource.unique_identifier == "5678" + mock_parse.assert_called_once_with("state", None, mock.ANY) + +@mock.patch.object(SdcResource, '_parse_sdc_status') +def test_update_informations_from_sdc_creation_distribitution_state(mock_parse): + mock_parse.return_value = "bgt" + sdcResource = SdcResource() + details = {'invariantUUID': '1234', + 'lifecycleState': 'state', + 'distributionStatus': 'trez', + 'version': 'v12', + 'uniqueId': '5678'} + + sdcResource.update_informations_from_sdc_creation(details) + assert sdcResource.unique_uuid == "1234" + assert sdcResource.status == "bgt" + assert sdcResource.version == "v12" + assert sdcResource.unique_identifier == "5678" + mock_parse.assert_called_once_with("state", 'trez', mock.ANY) + +@mock.patch.object(SdcResource, "is_own_property") +@mock.patch.object(SdcResource, "declare_input_for_own_property") +@mock.patch.object(SdcResource, "declare_nested_input") +def test_declare_input(mock_nested, mock_own, mock_is_own): + sdc_resource = SdcResource() + prop = Property(name="test", property_type="test") + mock_is_own.return_value = False + with pytest.raises(ParameterError): + sdc_resource.declare_input(prop) + mock_is_own.return_value = True + sdc_resource.declare_input(prop) + mock_own.assert_called_once() + mock_nested.assert_not_called() + + mock_nested.reset_mock() + mock_own.reset_mock() + sdc_resource.declare_input(NestedInput(sdc_resource=mock.MagicMock(), input_obj=mock.MagicMock())) + mock_own.assert_not_called() + mock_nested.assert_called_once() + +@mock.patch.object(SdcResource, "send_message_json") +@mock.patch.object(SdcResource, "get_component") +@mock.patch.object(SdcResource, "resource_inputs_url", new_callable=mock.PropertyMock) +def test_declare_nested_input(mock_resource_inputs, mock_get_component, mock_send_json): + sdc_resource = SdcResource() + sdc_resource.unique_identifier = "toto" + mock_resource_inputs.return_value = "test" + sdc_resource.declare_input(NestedInput(sdc_resource=mock.MagicMock(), input_obj=mock.MagicMock())) + mock_get_component.assert_called_once() + mock_send_json.assert_called_once() + +@mock.patch.object(SdcResource, "inputs", new_callable=mock.PropertyMock) +def test_get_input(mock_inputs): + sdc_resource = SdcResource() + + mock_inputs.return_value = [ + Input(unique_id="123", + input_type="integer", + name="test", + sdc_resource=sdc_resource), + Input(unique_id="321", + input_type="string", + name="test2", + sdc_resource=sdc_resource) + ] + assert sdc_resource.get_input("test") + assert sdc_resource.get_input("test2") + with pytest.raises(ResourceNotFound): + sdc_resource.get_input("test3") + +@mock.patch.object(SdcResource, "components", new_callable=mock.PropertyMock) +def test_get_component(mock_components): + sdc_resource = SdcResource() + + mock_components.return_value = [ + Component( + created_from_csar=False, + actual_component_uid="123", + unique_id="123", + normalized_name="123", + name="123", + origin_type="123", + customization_uuid="123", + tosca_component_name="123", + component_name="123", + component_uid="123", + component_version="123", + group_instances=None, + sdc_resource=SdcResource(name="test"), + parent_sdc_resource=sdc_resource + ) + ] + assert sdc_resource.get_component(SdcResource(name="test")) + with pytest.raises(ResourceNotFound): + sdc_resource.get_component(SdcResource(name="test2")) + assert sdc_resource.get_component_by_name("test") + with pytest.raises(ResourceNotFound): + sdc_resource.get_component_by_name("invalid_name") + +def test_component_properties(): + sdc_resource = mock.MagicMock() + parent_sdc_resource = SdcResource() + + component = Component( + created_from_csar=False, + actual_component_uid="123", + unique_id="123", + normalized_name="123", + name="123", + origin_type="123", + customization_uuid="123", + tosca_component_name="123", + component_name="123", + component_uid="123", + component_version="123", + group_instances=None, + sdc_resource=sdc_resource, + parent_sdc_resource=mock.MagicMock() + ) + sdc_resource.send_message_json.return_value = {} + assert not len(list(component.properties)) + + sdc_resource.send_message_json.return_value = COMPONENT_PROPERTIES + properties = list(component.properties) + assert len(properties) == 2 + prop1, prop2 = properties + + assert prop1.unique_id == "3d9a184f-4268-4a0e-9ddd-252e49670013.vf_module_id" + assert prop1.property_type == "string" + assert prop1.name == "vf_module_id" + assert prop1.value is None + + assert prop2.unique_id == "74f79006-ae56-4d58-947e-6a5089000774.skip_post_instantiation_configuration" + assert prop2.property_type == "boolean" + assert prop2.name == "skip_post_instantiation_configuration" + assert prop2.value == "true" + +@mock.patch.object(Component, "properties", new_callable=mock.PropertyMock) +def test_component_property_set_value(mock_component_properties): + mock_sdc_resource = mock.MagicMock() + component = Component( + created_from_csar=False, + actual_component_uid="123", + unique_id="123", + normalized_name="123", + name="123", + origin_type="123", + customization_uuid="123", + tosca_component_name="123", + component_name="123", + component_uid="123", + component_version="123", + group_instances=None, + sdc_resource=mock_sdc_resource, + parent_sdc_resource=mock.MagicMock() + ) + mock_component_properties.return_value = [ + ComponentProperty( + unique_id="123", + property_type="string", + name="test_property", + component=component + ) + ] + with pytest.raises(ParameterError): + component.get_property(property_name="non_exists") + prop1 = component.get_property(property_name="test_property") + assert prop1.name == "test_property" + assert prop1.unique_id == "123" + assert prop1.property_type == "string" + assert not prop1.value + + prop1.value = "123" + mock_sdc_resource.send_message_json.assert_called_once() + +@mock.patch.object(SdcResource, "_action_to_sdc") +def test_sdc_resource_checkout(mock_action_to_sdc): + mock_action_to_sdc.return_value = None + sdc_resource = SdcResource() + sdc_resource.checkout() + mock_action_to_sdc.assert_called_once_with(const.CHECKOUT, "lifecycleState") + +@mock.patch.object(SdcResource, "_action_to_sdc") +def test_sdc_resource_undo_checkout(mock_action_to_sdc): + mock_action_to_sdc.return_value = None + sdc_resource = SdcResource() + sdc_resource.undo_checkout() + mock_action_to_sdc.assert_called_once_with(const.UNDOCHECKOUT, "lifecycleState") + +@mock.patch.object(SdcResource, "_action_to_sdc") +def test_sdc_resource_certify(mock_action_to_sdc): + mock_action_to_sdc.return_value = None + sdc_resource = SdcResource() + sdc_resource.certify() + mock_action_to_sdc.assert_called_once_with(const.CERTIFY, "lifecycleState") diff --git a/tests/test_sdc_resource_properties.py b/tests/test_sdc_resource_properties.py new file mode 100644 index 0000000..4502868 --- /dev/null +++ b/tests/test_sdc_resource_properties.py @@ -0,0 +1,1080 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from onapsdk.exceptions import ParameterError +from onapsdk.sdc.properties import Input, Property +from onapsdk.sdc.sdc_resource import SdcResource +from onapsdk.sdc.service import Service +from onapsdk.sdc.vf import Vf +from onapsdk.sdc.vl import Vl + +INPUTS = { + 'inputs': [ + { + 'uniqueId': '9ee5fb23-4c4a-46bd-8682-68698559ee9c.skip_post_instantiation_configuration', + 'type': 'boolean', + 'required': False, + 'definition': False, + 'defaultValue': 'true', + 'description': None, + 'schema': None, + 'password': False, + 'name': 'skip_post_instantiation_configuration', + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': '9ee5fb23-4c4a-46bd-8682-68698559ee9c', + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'inputs': None, + 'properties': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': '9ee5fb23-4c4a-46bd-8682-68698559ee9c', + 'empty': False + }, + { + 'uniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079.test', + 'type': 'string', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': { + 'derivedFrom': None, + 'constraints': None, + 'properties': None, + 'property': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + 'password': False, + 'name': 'test', + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'propertyId': '4a84415b-4580-4a78-aa33-501f0cd3d079.sraka', + 'parentPropertyType': 'string', + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': 'cs0008', + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'inputs': None, + 'properties': None, + 'schemaType': '', + 'schemaProperty': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'getInputProperty': False, + 'version': None, + 'ownerId': 'cs0008', + 'empty': False + }, + { + 'uniqueId': '9ee5fb23-4c4a-46bd-8682-68698559ee9c.controller_actor', + 'type': 'string', + 'required': False, + 'definition': False, + 'defaultValue': 'SO-REF-DATA', + 'description': None, + 'schema': None, + 'password': False, + 'name': 'controller_actor', + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': '9ee5fb23-4c4a-46bd-8682-68698559ee9c', + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'inputs': None, + 'properties': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': '9ee5fb23-4c4a-46bd-8682-68698559ee9c', + 'empty': False + }, + { + 'uniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079.lililili', + 'type': 'list', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': { + 'derivedFrom': None, + 'constraints': None, + 'properties': None, + 'property': { + 'uniqueId': None, + 'type': 'abc', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + 'password': False, + 'name': 'lililili', + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': True, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'inputs': None, + 'properties': None, + 'schemaType': 'abc', + 'schemaProperty': { + 'uniqueId': None, + 'type': 'abc', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + } + ] +} + + +PROPERTIES = { + "properties": [{ + 'uniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079.llllll', + 'type': 'integer', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': { + 'derivedFrom': None, + 'constraints': None, + 'properties': None, + 'property': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + 'password': False, + 'name': 'llllll', + 'value': '{"get_input":["lililili","INDEX","llllll"]}', + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'getInputValues': [ + { + 'propName': None, + 'inputName': 'lililili', + 'inputId': '4a84415b-4580-4a78-aa33-501f0cd3d079.lililili', + 'indexValue': None, + 'getInputIndex': None, + 'list': False, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + } + ], + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'schemaType': '', + 'schemaProperty': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'getInputProperty': True, + 'version': None, + 'ownerId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'empty': False + }, + { + 'uniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079.test', + 'type': 'string', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': { + 'derivedFrom': None, + 'constraints': None, + 'properties': None, + 'property': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + 'password': False, + 'name': 'test', + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'getInputValues': [], + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'schemaType': '', + 'schemaProperty': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'getInputProperty': True, + 'version': None, + 'ownerId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'empty': False + }, + { + 'uniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079.yyy', + 'type': 'string', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': { + 'derivedFrom': None, + 'constraints': None, + 'properties': None, + 'property': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + 'password': False, + 'name': 'yyy', + 'value': 'lalala', + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'schemaType': '', + 'schemaProperty': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'getInputProperty': False, + 'version': None, + 'ownerId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'empty': False + }, + { + 'uniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079.test2', + 'type': 'boolean', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': 'test2', + 'schema': { + 'derivedFrom': None, + 'constraints': None, + 'properties': None, + 'property': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + }, + 'password': False, + 'name': 'test2', + 'value': '{"get_input":"test2"}', + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'getInputValues': [ + { + 'propName': None, + 'inputName': 'test2', + 'inputId': '4a84415b-4580-4a78-aa33-501f0cd3d079.test2', + 'indexValue': None, + 'getInputIndex': None, + 'list': False, + 'version': None, + 'ownerId': None, + 'empty': False, + 'type': None + } + ], + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'schemaType': '', + 'schemaProperty': { + 'uniqueId': None, + 'type': '', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': None, + 'schema': None, + 'password': False, + 'name': None, + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': None, + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': None, + 'empty': False + }, + 'getInputProperty': True, + 'version': None, + 'ownerId': '4a84415b-4580-4a78-aa33-501f0cd3d079', + 'empty': False + }] +} + + +VL_PROPERTIES = { + "properties": [{ + 'uniqueId': 'd37cd65e-9842-4490-9343-a1a874e6b52a.network_role', + 'type': 'string', + 'required': False, + 'definition': False, + 'defaultValue': None, + 'description': 'Unique label that defines the role that this network performs. example: vce oam network, vnat sr-iov1 network\n', + 'schema': None, + 'password': False, + 'name': 'network_role', + 'value': None, + 'label': None, + 'hidden': False, + 'immutable': False, + 'inputPath': None, + 'status': None, + 'inputId': None, + 'instanceUniqueId': None, + 'propertyId': None, + 'parentPropertyType': None, + 'subPropertyInputPath': None, + 'annotations': None, + 'parentUniqueId': '1af9771b-0f79-4e98-8747-30fd06da85cb', + 'getInputValues': None, + 'isDeclaredListInput': False, + 'getPolicyValues': None, + 'propertyConstraints': None, + 'constraints': None, + 'schemaType': None, + 'schemaProperty': None, + 'getInputProperty': False, + 'version': None, + 'ownerId': '1af9771b-0f79-4e98-8747-30fd06da85cb', + 'empty': False + }] +} + + +@mock.patch.object(Service, "send_message_json") +@mock.patch.object(Service, "send_message") +def test_service_properties(mock_send, mock_send_json): + + service = Service(name="test") + service.unique_identifier = "toto" + + mock_send_json.return_value = {} + assert len(list(service.properties)) == 0 + + mock_send_json.return_value = PROPERTIES + properties_list = list(service.properties) + assert len(properties_list) == 4 + prop1, prop2, prop3, prop4 = properties_list + + mock_send_json.return_value = INPUTS + + assert prop1.sdc_resource == service + assert prop1.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.llllll" + assert prop1.name == "llllll" + assert prop1.property_type == "integer" + assert prop1.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop1.value == '{"get_input":["lililili","INDEX","llllll"]}' + assert prop1.description is None + assert prop1.get_input_values + prop1_input = prop1.input + assert prop1_input.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.lililili" + assert prop1_input.input_type == "list" + assert prop1_input.name == "lililili" + assert prop1_input.default_value is None + + assert prop2.sdc_resource == service + assert prop2.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.test" + assert prop2.name == "test" + assert prop2.property_type == "string" + assert prop2.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop2.value is None + assert prop2.description is None + assert prop2.get_input_values == [] + assert prop2.input is None + + assert prop3.sdc_resource == service + assert prop3.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.yyy" + assert prop3.name == "yyy" + assert prop3.property_type == "string" + assert prop3.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop3.value == "lalala" + assert prop3.description is None + assert prop3.get_input_values is None + assert prop3.input is None + + assert prop4.sdc_resource == service + assert prop4.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.test2" + assert prop4.name == "test2" + assert prop4.property_type == "boolean" + assert prop4.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop4.value == '{"get_input":"test2"}' + assert prop4.description == "test2" + assert prop4.get_input_values + with pytest.raises(ParameterError): + prop4.input + + +@mock.patch.object(Service, "send_message_json") +def test_service_inputs(mock_send_json): + service = Service(name="test") + service.unique_identifier = "toto" + + mock_send_json.return_value = {} + assert len(list(service.inputs)) == 0 + + mock_send_json.return_value = INPUTS + inputs_list = list(service.inputs) + assert len(inputs_list) == 4 + + input1, input2, input3, input4 = inputs_list + assert input1.unique_id == "9ee5fb23-4c4a-46bd-8682-68698559ee9c.skip_post_instantiation_configuration" + assert input1.input_type == "boolean" + assert input1.name == "skip_post_instantiation_configuration" + assert input1.default_value == "true" + + assert input2.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.test" + assert input2.input_type == "string" + assert input2.name == "test" + assert input2.default_value is None + + assert input3.unique_id == "9ee5fb23-4c4a-46bd-8682-68698559ee9c.controller_actor" + assert input3.input_type == "string" + assert input3.name == "controller_actor" + assert input3.default_value == "SO-REF-DATA" + + assert input4.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.lililili" + assert input4.input_type == "list" + assert input4.name == "lililili" + assert input4.default_value is None + + +@mock.patch.object(Vf, "send_message_json") +def test_vf_properties(mock_send_json): + vf = Vf(name="test") + vf.unique_identifier = "toto" + + mock_send_json.return_value = {} + assert len(list(vf.properties)) == 0 + + mock_send_json.return_value = PROPERTIES + properties_list = list(vf.properties) + assert len(properties_list) == 4 + prop1, prop2, prop3, prop4 = properties_list + + mock_send_json.return_value = INPUTS + + assert prop1.sdc_resource == vf + assert prop1.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.llllll" + assert prop1.name == "llllll" + assert prop1.property_type == "integer" + assert prop1.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop1.value == '{"get_input":["lililili","INDEX","llllll"]}' + assert prop1.description is None + assert prop1.get_input_values + prop1_input = prop1.input + assert prop1_input.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.lililili" + assert prop1_input.input_type == "list" + assert prop1_input.name == "lililili" + assert prop1_input.default_value is None + + assert prop2.sdc_resource == vf + assert prop2.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.test" + assert prop2.name == "test" + assert prop2.property_type == "string" + assert prop2.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop2.value is None + assert prop2.description is None + assert prop2.get_input_values == [] + assert prop2.input is None + + assert prop3.sdc_resource == vf + assert prop3.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.yyy" + assert prop3.name == "yyy" + assert prop3.property_type == "string" + assert prop3.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop3.value == "lalala" + assert prop3.description is None + assert prop3.get_input_values is None + assert prop3.input is None + + assert prop4.sdc_resource == vf + assert prop4.unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079.test2" + assert prop4.name == "test2" + assert prop4.property_type == "boolean" + assert prop4.parent_unique_id == "4a84415b-4580-4a78-aa33-501f0cd3d079" + assert prop4.value == '{"get_input":"test2"}' + assert prop4.description == "test2" + assert prop4.get_input_values + with pytest.raises(ParameterError): + prop4.input + + +@mock.patch.object(Vl, "send_message_json") +@mock.patch.object(Vl, "exists") +def test_vl_properties(mock_exists, mock_send_json): + mock_exists.return_value = True + vl = Vl(name="test") + vl.unique_identifier = "toto" + + mock_send_json.return_value = {} + assert len(list(vl.properties)) == 0 + + mock_send_json.return_value = VL_PROPERTIES + properties_list = list(vl.properties) + assert len(properties_list) == 1 + prop = properties_list[0] + + assert prop.sdc_resource == vl + assert prop.unique_id == "d37cd65e-9842-4490-9343-a1a874e6b52a.network_role" + assert prop.name == "network_role" + assert prop.property_type == "string" + assert prop.parent_unique_id == "1af9771b-0f79-4e98-8747-30fd06da85cb" + assert prop.value is None + assert prop.description == "Unique label that defines the role that this network performs. example: vce oam network, vnat sr-iov1 network\n" + assert prop.get_input_values is None + assert prop.input is None + + +@mock.patch.object(SdcResource, "send_message_json") +def test_sdc_resource_is_own_property(mock_send_json): + sdc_resource = SdcResource(name="test") + sdc_resource.unique_identifier = "toto" + mock_send_json.return_value = PROPERTIES + prop1 = Property( + name="llllll", + property_type="integer" + ) + prop2 = Property( + name="test2", + property_type="string" + ) + assert sdc_resource.is_own_property(prop1) + assert not sdc_resource.is_own_property(prop2) + +@mock.patch.object(SdcResource, "properties", new_callable=mock.PropertyMock) +@mock.patch.object(SdcResource, "send_message_json") +def test_sdc_resource_set_property_value(mock_send_message_json, mock_sdc_resource_properties): + sdc_resource = SdcResource(name="test") + sdc_resource.unique_identifier = "toto" + + mock_sdc_resource_properties.return_value = [ + Property(name="test", + property_type="string", + sdc_resource=sdc_resource) + ] + with pytest.raises(ParameterError): + sdc_resource.set_property_value(Property(name="test2", + property_type="integer", + sdc_resource=sdc_resource), + value="lalala") + prop = sdc_resource.get_property(property_name="test") + assert prop.name == "test" + assert prop.property_type == "string" + assert not prop.value + + prop.value = "test" + mock_send_message_json.assert_called_once() + assert prop.value == "test" + +@mock.patch.object(SdcResource, "inputs", new_callable=mock.PropertyMock) +@mock.patch.object(SdcResource, "send_message_json") +def test_sdc_resource_input_default_value(mock_send_message_json, mock_inputs): + sdc_resource = SdcResource(name="test") + sdc_resource.unique_identifier = "toto" + + mock_inputs.return_value = [ + Input(unique_id="123", + input_type="integer", + name="test", + sdc_resource=sdc_resource) + ] + assert sdc_resource.get_input("test") + input_obj = sdc_resource.get_input("test") + assert not input_obj.default_value + input_obj.default_value = "123" + mock_send_message_json.assert_called_once() + assert input_obj.default_value == "123" diff --git a/tests/test_sdc_vfc.py b/tests/test_sdc_vfc.py new file mode 100644 index 0000000..7322e0a --- /dev/null +++ b/tests/test_sdc_vfc.py @@ -0,0 +1,82 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +import onapsdk.constants as const +from onapsdk.exceptions import ResourceNotFound +from onapsdk.sdc.vfc import Vfc + + +VFCS = [ + { + "uuid":"18167a36-5f7d-4e10-809f-b73ce7268b00", + "invariantUUID":"a5852d77-c364-4eec-97c6-8630b8f138ac", + "name":"Allotted Resource", + "version":"1.0", + "toscaModelURL":"/sdc/v1/catalog/resources/18167a36-5f7d-4e10-809f-b73ce7268b00/toscaModel", + "category":"Allotted Resource", + "subCategory":"Allotted Resource", + "resourceType":"VFC", + "lifecycleState":"CERTIFIED", + "lastUpdaterUserId":"jh0003" + }, + { + "uuid":"3b9f3a0d-f9d1-4d95-80ce-7f7812a2b7b5", + "invariantUUID":"c4aa9ad7-1c68-4fde-884e-b9d693b5f725", + "name":"Controller", + "version":"1.0", + "toscaModelURL":"/sdc/v1/catalog/resources/3b9f3a0d-f9d1-4d95-80ce-7f7812a2b7b5/toscaModel", + "category":"Generic", + "subCategory":"Infrastructure", + "resourceType":"VFC", + "lifecycleState":"CERTIFIED", + "lastUpdaterUserId":"jh0003" + } +] + + +@mock.patch.object(Vfc, 'send_message_json') +def test_get_all_no_vfc(mock_send): + """Returns empty array if no vfcs.""" + mock_send.return_value = {} + assert Vfc.get_all() == [] + mock_send.assert_called_once_with("GET", 'get Vfcs', 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/resources?resourceType=VFC') + + +@mock.patch.object(Vfc, 'send_message_json') +def test_get_all_vfc(mock_send): + mock_send.return_value = VFCS + vfcs = Vfc.get_all() + assert len(vfcs) == 2 + vfc = vfcs[0] + assert vfc.name == "Allotted Resource" + assert vfc.identifier == "18167a36-5f7d-4e10-809f-b73ce7268b00" + assert vfc.unique_uuid == "a5852d77-c364-4eec-97c6-8630b8f138ac" + assert vfc.version == "1.0" + assert vfc.status == const.CERTIFIED + vfc = vfcs[1] + assert vfc.name == "Controller" + assert vfc.identifier == "3b9f3a0d-f9d1-4d95-80ce-7f7812a2b7b5" + assert vfc.unique_uuid == "c4aa9ad7-1c68-4fde-884e-b9d693b5f725" + assert vfc.version == "1.0" + assert vfc.status == const.CERTIFIED + + +@mock.patch.object(Vfc, 'send_message_json') +def test_create_vfc_not_exists(mock_send): + mock_send.return_value = VFCS + with pytest.raises(ResourceNotFound): + Vfc("not_exists") diff --git a/tests/test_sdc_vl.py b/tests/test_sdc_vl.py new file mode 100644 index 0000000..8eb2a20 --- /dev/null +++ b/tests/test_sdc_vl.py @@ -0,0 +1,82 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +import onapsdk.constants as const +from onapsdk.exceptions import ResourceNotFound +from onapsdk.sdc.vl import Vl + + +VLS = [ + { + "uuid":"e12cedf4-fd3f-4d76-ae2a-0368eaee40dc", + "invariantUUID":"4084c513-5149-456d-9be0-efc503058799", + "name":"NeutronNet", + "version":"1.0", + "toscaModelURL":"/sdc/v1/catalog/resources/e12cedf4-fd3f-4d76-ae2a-0368eaee40dc/toscaModel", + "category":"Generic", + "subCategory":"Network Elements", + "resourceType":"VL", + "lifecycleState":"CERTIFIED", + "lastUpdaterUserId":"jh0003" + }, + { + "uuid":"3b9f3a0d-f9d1-4d95-80ce-7f7812a2b7b5", + "invariantUUID":"c4aa9ad7-1c68-4fde-884e-b9d693b5f725", + "name":"Network", + "version":"1.0", + "toscaModelURL":"/sdc/v1/catalog/resources/3b9f3a0d-f9d1-4d95-80ce-7f7812a2b7b5/toscaModel", + "category":"Generic", + "subCategory":"Infrastructure", + "resourceType":"VL", + "lifecycleState":"CERTIFIED", + "lastUpdaterUserId":"jh0003" + } +] + + +@mock.patch.object(Vl, 'send_message_json') +def test_get_all_no_vl(mock_send): + """Returns empty array if no vls.""" + mock_send.return_value = {} + assert Vl.get_all() == [] + mock_send.assert_called_once_with("GET", 'get Vls', 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/resources?resourceType=VL') + + +@mock.patch.object(Vl, 'send_message_json') +def test_get_all_vl(mock_send): + mock_send.return_value = VLS + vls = Vl.get_all() + assert len(vls) == 2 + vl = vls[0] + assert vl.name == "NeutronNet" + assert vl.identifier == "e12cedf4-fd3f-4d76-ae2a-0368eaee40dc" + assert vl.unique_uuid == "4084c513-5149-456d-9be0-efc503058799" + assert vl.version == "1.0" + assert vl.status == const.CERTIFIED + vl = vls[1] + assert vl.name == "Network" + assert vl.identifier == "3b9f3a0d-f9d1-4d95-80ce-7f7812a2b7b5" + assert vl.unique_uuid == "c4aa9ad7-1c68-4fde-884e-b9d693b5f725" + assert vl.version == "1.0" + assert vl.status == const.CERTIFIED + + +@mock.patch.object(Vl, 'send_message_json') +def test_create_vl_not_exists(mock_send): + mock_send.return_value = VLS + with pytest.raises(ResourceNotFound): + Vl("not_exists") diff --git a/tests/test_sdnc_element.py b/tests/test_sdnc_element.py new file mode 100644 index 0000000..6c8fe2d --- /dev/null +++ b/tests/test_sdnc_element.py @@ -0,0 +1,26 @@ +"""Test A&AI Element.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.sdnc.sdnc_element import SdncElement +from onapsdk.utils.gui import GuiList + +@mock.patch.object(SdncElement, "send_message") +def test_get_guis(send_message_mock): + component = SdncElement() + gui_results = component.get_guis() + assert type(gui_results) == GuiList + assert len(gui_results.guilist) == 2 + # assert gui_results.guilist[0].status == send_message_mock.return_value.status_code diff --git a/tests/test_service.py b/tests/test_service.py new file mode 100755 index 0000000..e486833 --- /dev/null +++ b/tests/test_service.py @@ -0,0 +1,1498 @@ +"""Test Service module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import path +from pathlib import Path +from unittest import mock +from unittest.mock import MagicMock, PropertyMock +import shutil + +import oyaml as yaml +import pytest + +import onapsdk.constants as const +from onapsdk.exceptions import ParameterError, RequestError, ResourceNotFound, StatusError, ValidationError +from onapsdk.sdc.category_management import ServiceCategory +from onapsdk.sdc.component import Component +from onapsdk.sdc.properties import ComponentProperty, Property +from onapsdk.sdc.service import Service, ServiceInstantiationType +from onapsdk.sdc.sdc_resource import SdcResource +from onapsdk.utils.headers_creator import headers_sdc_operator +from onapsdk.utils.headers_creator import headers_sdc_creator + + +ARTIFACTS = { + "componentInstances" : [ + { + "uniqueId" : "test_unique_id", + "componentName" : "ubuntu16test_VF 0" + } + ] +} + + +COMPONENTS = { + "componentInstances":[ + { + "actualComponentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "createdFromCsar":True, + "uniqueId":"bcfa7544-6e3d-4666-93b1-c5973356d069.374f0a98-a280-43f1-9e6c-00b436782ce7.abstract_vsn", + "normalizedName":"abstract_vsn", + "name":"abstract_vsn", + "originType":"CVFC", + "customizationUUID":"971043e1-495b-4b75-901e-3d09baed7521", + "componentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "componentVersion":"1.0", + "toscaComponentName":"org.openecomp.resource.vfc.11111cvfc.abstract.abstract.nodes.vsn", + "componentName":"11111-nodes.vsnCvfc", + "groupInstances":None + } + ] +} + + +COMPONENT = { + "metadata":{ + "uniqueId":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "name":"11111-nodes.vsnCvfc", + "version":"1.0", + "isHighestVersion":True, + "creationDate":1594898496259, + "lastUpdateDate":1594898496325, + "description":"Complex node type that is used as nested type in VF", + "lifecycleState":"CERTIFIED", + "tags":[ + "11111-nodes.vsnCvfc" + ], + "icon":"defaulticon", + "normalizedName":"11111nodesvsncvfc", + "systemName":"11111NodesVsncvfc", + "contactId":"cs0008", + "allVersions":{ + "1.0":"374f0a98-a280-43f1-9e6c-00b436782ce7" + }, + "isDeleted":None, + "projectCode":None, + "csarUUID":None, + "csarVersion":None, + "importedToscaChecksum":None, + "invariantUUID":"3c027ba1-8d3a-4b59-9394-d748fec5e42c", + "componentType":"RESOURCE", + "name":"Generic", + "normalizedName":"generic", + "uniqueId":"resourceNewCategory.generic", + "icons":None, + "creatorUserId":"cs0008", + "creatorFullName":"Carlos Santana", + "lastUpdaterUserId":"cs0008", + "lastUpdaterFullName":"Carlos Santana", + "archiveTime":0, + "vendorName":"mj", + "vendorRelease":"1.0", + "resourceVendorModelNumber":"", + "resourceType":"CVFC", + "isAbstract":None, + "cost":None, + "licenseType":None, + "toscaResourceName":"org.openecomp.resource.vfc.11111cvfc.abstract.abstract.nodes.vsn", + "derivedFrom":None, + "uuid":"59f05bfb-ccea-4857-8799-6acff59e6344", + "archived":False, + "vspArchived":False, + "groupInstances":None + } +} + + +COMPONENT_PROPERTIES = [ + { + "uniqueId":"3d9a184f-4268-4a0e-9ddd-252e49670013.vf_module_id", + "type":"string", + "required":False, + "definition":False, + "description":"The vFirewall Module ID is provided by ECOMP", + "password":False, + "name":"vf_module_id", + "label":"vFirewall module ID", + "hidden":False, + "immutable":False, + "isDeclaredListInput":False, + "getInputProperty":False, + "empty":False + },{ + "uniqueId":"74f79006-ae56-4d58-947e-6a5089000774.skip_post_instantiation_configuration", + "type":"boolean", + "required":False, + "definition":False, + "password":False, + "name":"skip_post_instantiation_configuration", + "value":"true", + "hidden":False, + "immutable":False, + "parentUniqueId":"74f79006-ae56-4d58-947e-6a5089000774", + "isDeclaredListInput":False, + "getInputProperty":False, + "ownerId":"74f79006-ae56-4d58-947e-6a5089000774", + "empty":False + } +] + + +COMPONENTS_WITH_ALL_ORIGIN_TYPES = { + "componentInstances":[ + { + "actualComponentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "createdFromCsar":True, + "uniqueId":"bcfa7544-6e3d-4666-93b1-c5973356d069.374f0a98-a280-43f1-9e6c-00b436782ce7.abstract_vsn", + "normalizedName":"abstract_vsn", + "name":"abstract_vsn", + "originType":"VF", + "customizationUUID":"971043e1-495b-4b75-901e-3d09baed7521", + "componentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "componentVersion":"1.0", + "toscaComponentName":"org.openecomp.resource.vfc.11111cvfc.abstract.abstract.nodes.vsn", + "componentName":"11111-nodes.vsnCvfc", + "groupInstances":None + }, + { + "actualComponentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "createdFromCsar":True, + "uniqueId":"bcfa7544-6e3d-4666-93b1-c5973356d069.374f0a98-a280-43f1-9e6c-00b436782ce7.abstract_vsn", + "normalizedName":"abstract_vsn", + "name":"abstract_vsn", + "originType":"PNF", + "customizationUUID":"971043e1-495b-4b75-901e-3d09baed7521", + "componentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "componentVersion":"1.0", + "toscaComponentName":"org.openecomp.resource.vfc.11111cvfc.abstract.abstract.nodes.vsn", + "componentName":"11111-nodes.vsnCvfc", + "groupInstances":None + }, + { + "actualComponentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "createdFromCsar":True, + "uniqueId":"bcfa7544-6e3d-4666-93b1-c5973356d069.374f0a98-a280-43f1-9e6c-00b436782ce7.abstract_vsn", + "normalizedName":"abstract_vsn", + "name":"abstract_vsn", + "originType":"VL", + "customizationUUID":"971043e1-495b-4b75-901e-3d09baed7521", + "componentUid":"374f0a98-a280-43f1-9e6c-00b436782ce7", + "componentVersion":"1.0", + "toscaComponentName":"org.openecomp.resource.vfc.11111cvfc.abstract.abstract.nodes.vsn", + "componentName":"11111-nodes.vsnCvfc", + "groupInstances":None + } + ] +} + + +def test_init_no_name(): + """Check init with no names.""" + svc = Service() + assert isinstance(svc, SdcResource) + assert svc._identifier is None + assert svc._version is None + assert svc.name == "ONAP-test-Service" + assert svc.headers["USER_ID"] == "cs0008" + assert svc.distribution_status is None + assert svc._distribution_id is None + assert isinstance(svc._base_url(), str) + +@mock.patch.object(Service, 'exists') +def test_init_with_name(mock_exists): + """Check init with no names.""" + mock_exists.return_value = False + svc = Service(name="YOLO") + assert svc._identifier == None + assert svc._version == None + assert svc.name == "YOLO" + assert svc.created() == False + assert svc.headers["USER_ID"] == "cs0008" + assert svc.distribution_status is None + assert svc._distribution_id is None + assert isinstance(svc._base_url(), str) + +@mock.patch.object(Service, 'exists') +def test_init_with_sdc_values(mock_exists): + """Check init with no names.""" + sdc_values = {'uuid': '12', 'version': '14', 'invariantUUID': '56', + 'distributionStatus': 'yes', 'lifecycleState': 'state', + 'category': 'Network Service'} + svc = Service(sdc_values=sdc_values) + mock_exists.return_value = True + assert svc._identifier == "12" + assert svc._version == "14" + assert svc.name == "ONAP-test-Service" + assert svc.created() + assert svc.headers["USER_ID"] == "cs0008" + assert svc.distribution_status == "yes" + assert svc._distribution_id is None + assert svc.category_name == "Network Service" + assert isinstance(svc._base_url(), str) + +@mock.patch.object(Service, 'get_all') +def test_version_filter(mock_get_all): + """Check version filter""" + svc_1 = Service(name="test_version_filter") + svc_1.identifier = "1111" + svc_1.unique_uuid = "2222" + svc_1.unique_identifier = "3333" + svc_1.status = const.CERTIFIED + svc_1.version = "1.0" + + svc_2 = Service(name="test_version_filter") + svc_2.identifier = "1111" + svc_2.unique_uuid = "2222" + svc_2.unique_identifier = "3333" + svc_2.status = const.DRAFT + svc_2.version = "1.1" + + mock_get_all.return_value = [svc_1, svc_2] + + svc = Service(name='test_version_filter') + assert svc.exists() + assert svc.version == "1.1" + + svc = Service(name='test_version_filter', version='1.0') + assert svc.exists() + assert svc.version == "1.0" + + svc = Service(name='test_version_filter', version='-111') + assert not svc.exists() + assert not svc.version + +@mock.patch.object(Service, 'get_all') +def test_get_the_latest_version(mock_get_all): + svc_1 = Service(name="test_get_max_version") + svc_1.identifier = "1111" + svc_1.unique_uuid = "2222" + svc_1.unique_identifier = "3333" + svc_1.status = const.CERTIFIED + svc_1.version = "9.0" + + svc_2 = Service(name="test_get_max_version") + svc_2.identifier = "1111" + svc_2.unique_uuid = "2222" + svc_2.unique_identifier = "3333" + svc_2.status = const.DRAFT + svc_2.version = "10.0" + + mock_get_all.return_value = [svc_1, svc_2] + svc = Service(name='test_get_max_version') + assert svc.version == "10.0" + + svc_3 = Service(name="test_get_max_version") + svc_3.identifier = "1111" + svc_3.unique_uuid = "2222" + svc_3.unique_identifier = "3333" + svc_3.status = const.DRAFT + svc_3.version = "10.1" + mock_get_all.return_value = [svc_1, svc_2, svc_3] + svc = Service(name='test_get_max_version') + assert svc.version == "10.1" + + svc_4 = Service(name="test_get_max_version") + svc_4.identifier = "1111" + svc_4.unique_uuid = "2222" + svc_4.unique_identifier = "3333" + svc_4.status = const.DRAFT + svc_4.version = "20.0" + mock_get_all.return_value = [svc_1, svc_2, svc_3, svc_4] + svc = Service(name='test_get_max_version') + assert svc.version == "20.0" + + svc_5 = Service(name="test_get_max_version") + svc_5.identifier = "1111" + svc_5.unique_uuid = "2222" + svc_5.unique_identifier = "3333" + svc_5.status = const.DRAFT + svc_5.version = "99.0" + + svc_6 = Service(name="test_get_max_version") + svc_6.identifier = "1111" + svc_6.unique_uuid = "2222" + svc_6.unique_identifier = "3333" + svc_6.status = const.DRAFT + svc_6.version = "100.0" + mock_get_all.return_value = [svc_1, svc_2, svc_3, svc_4, svc_5, svc_6] + svc = Service(name='test_get_max_version') + assert svc.version == "100.0" + + +def test_equality_really_equals(): + """Check two vfs are equals if name is the same.""" + svc_1 = Service(name="equal") + svc_1.identifier = "1234" + svc_2 = Service(name="equal") + svc_2.identifier = "1235" + assert svc_1 == svc_2 + + +def test_equality_not_equals(): + """Check two vfs are not equals if name is not the same.""" + svc_1 = Service(name="equal") + svc_1.identifier = "1234" + svc_2 = Service(name="not_equal") + svc_2.identifier = "1234" + assert svc_1 != svc_2 + + +def test_equality_not_equals_not_same_object(): + """Check a vf and something different are not equals.""" + svc_1 = Service(name="equal") + svc_1.identifier = "1234" + svc_2 = SdcResource() + svc_2.name = "equal" + assert svc_1 != svc_2 + +@mock.patch.object(Service, 'load_metadata') +def test_distribution_id_no_load(mock_load): + svc = Service() + svc.identifier = "1234" + svc._distribution_id = "4567" + assert svc.distribution_id == "4567" + mock_load.assert_not_called() + +@mock.patch.object(Service, 'load_metadata') +def test_distribution_id_load(mock_load): + svc = Service() + svc.identifier = "1234" + assert svc.distribution_id is None + mock_load.assert_called_once() + +@mock.patch.object(Service, '_check_distributed') +def test_distributed_no_load(mock_check_distributed): + svc = Service() + svc.identifier = "1234" + svc._distributed = True + assert svc.distributed + mock_check_distributed.assert_not_called() + +@mock.patch.object(Service, '_check_distributed') +def test_distributed_load(mock_check_distributed): + svc = Service() + svc.identifier = "1234" + assert not svc.distributed + mock_check_distributed.assert_called_once() + +def test_distribution_id_setter(): + svc = Service() + svc.identifier = "1234" + svc.distribution_id = "4567" + assert svc._distribution_id == "4567" + +@mock.patch.object(Service, '_create') +@mock.patch.object(Service, "category", new_callable=mock.PropertyMock) +@mock.patch.object(Service, "exists") +def test_create(mock_exists, mock_category, mock_create): + mock_exists.return_value = False + + svc = Service() + svc.create() + mock_create.assert_called_once_with("service_create.json.j2", + name="ONAP-test-Service", + instantiation_type="A-la-carte", + category=svc.category, + role="", + function="", + service_type="" + ) + mock_create.reset_mock() + svc = Service(instantiation_type=ServiceInstantiationType.MACRO) + svc.create() + mock_create.assert_called_once_with("service_create.json.j2", + name="ONAP-test-Service", + instantiation_type="Macro", + category=svc.category, + role="", + function="", + service_type="" + ) + +@mock.patch.object(Service, 'exists') +@mock.patch.object(Service, 'send_message') +def test_add_resource_not_draft(mock_send, mock_exists): + mock_exists.return_value = False + svc = Service() + resource = SdcResource() + with pytest.raises(StatusError): + svc.add_resource(resource) + mock_send.assert_not_called() + +@mock.patch.object(Service, 'load') +@mock.patch.object(Service, 'send_message') +def test_add_resource_bad_result(mock_send, mock_load): + svc = Service() + svc.unique_identifier = "45" + svc.identifier = "93" + svc.status = const.DRAFT + mock_send.return_value = {} + resource = SdcResource() + resource.unique_identifier = "12" + resource.created = MagicMock(return_value=True) + resource.version = "40" + resource.name = "test" + assert svc.add_resource(resource) is None + mock_send.assert_called_once_with( + 'POST', 'Add SDCRESOURCE to ServiceProxy', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/45/resourceInstance', + data='{\n "name": "test",\n "componentVersion": "40",\n "posY": 100,\n "posX": 200,\n "uniqueId": "12",\n "originType": "SDCRESOURCE",\n "componentUid": "12",\n "icon": "defaulticon"\n}') + +@mock.patch.object(Service, 'load') +@mock.patch.object(Service, 'send_message') +def test_add_resource_OK(mock_send, mock_load): + svc = Service() + svc.unique_identifier = "45" + svc.identifier = "93" + svc.status = const.DRAFT + mock_send.return_value = {'yes': 'indeed'} + resource = SdcResource() + resource.unique_identifier = "12" + resource.created = MagicMock(return_value=True) + resource.version = "40" + resource.name = "test" + result = svc.add_resource(resource) + assert result['yes'] == "indeed" + mock_send.assert_called_once_with( + 'POST', 'Add SDCRESOURCE to ServiceProxy', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/45/resourceInstance', + data='{\n "name": "test",\n "componentVersion": "40",\n "posY": 100,\n "posX": 200,\n "uniqueId": "12",\n "originType": "SDCRESOURCE",\n "componentUid": "12",\n "icon": "defaulticon"\n}') + +@mock.patch.object(Service, '_verify_action_to_sdc') +def test_checkin(mock_verify): + svc = Service() + svc.checkin() + mock_verify.assert_called_once_with(const.DRAFT, const.CHECKIN, 'lifecycleState') + +@mock.patch.object(Service, '_verify_action_to_sdc') +def test_submit(mock_verify): + svc = Service() + svc.submit() + mock_verify.assert_called_once_with(const.CHECKED_IN, const.SUBMIT_FOR_TESTING, 'lifecycleState') + +@mock.patch.object(Service, '_verify_action_to_sdc') +def test_certify(mock_verify): + svc = Service() + svc.certify() + mock_verify.assert_called_once_with( + const.CHECKED_IN, const.CERTIFY, 'lifecycleState', + headers=headers_sdc_creator(svc.headers)) + +@mock.patch.object(Service, '_verify_action_to_sdc') +def test_distribute(mock_verify): + svc = Service() + svc.distribute() + mock_verify.assert_called_once_with( + const.CERTIFIED, const.DISTRIBUTE, 'distribution', + headers=headers_sdc_creator(svc.headers)) + +@mock.patch.object(Service, '_verify_action_to_sdc') +def test_redistribute(mock_verify): + svc = Service() + svc.redistribute() + mock_verify.assert_called_once_with( + const.DISTRIBUTED, const.DISTRIBUTE, 'distribution', + headers=headers_sdc_creator(svc.headers)) + +@mock.patch.object(Service, 'send_message') +def test_get_tosca_no_result(mock_send): + if path.exists('/tmp/tosca_files'): + shutil.rmtree('/tmp/tosca_files') + mock_send.return_value = {} + svc = Service() + svc.identifier = "12" + svc.get_tosca() + headers = headers_sdc_creator(svc.headers) + headers['Accept'] = 'application/octet-stream' + mock_send.assert_called_once_with( + 'GET', 'Download Tosca Model for ONAP-test-Service', + 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/services/12/toscaModel', + headers=headers) + assert not path.exists('/tmp/tosca_files') + + +def test_get_tosca_bad_csart(requests_mock): + if path.exists('/tmp/tosca_files'): + shutil.rmtree('/tmp/tosca_files') + svc = Service() + svc.identifier = "12" + with open('tests/data/bad.csar', mode='rb') as file: + file_content = file.read() + requests_mock.get( + 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/services/12/toscaModel', + content=file_content) + svc.get_tosca() + + +def test_get_tosca_result(requests_mock): + if path.exists('/tmp/tosca_files'): + shutil.rmtree('/tmp/tosca_files') + with open('tests/data/test.csar', mode='rb') as file: + file_content = file.read() + requests_mock.get( + 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/services/12/toscaModel', + content=file_content) + svc = Service() + svc.identifier = "12" + svc.get_tosca() + +def test_get_tosca_result_no_service_in_csar(requests_mock): + if path.exists('/tmp/tosca_files'): + shutil.rmtree('/tmp/tosca_files') + with open('tests/data/bad_no_service.csar', mode='rb') as file: + file_content = file.read() + requests_mock.get( + 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/services/12/toscaModel', + content=file_content) + svc = Service() + svc.identifier = "12" + with pytest.raises(ValidationError): + svc.get_tosca() + +@mock.patch.object(Service, 'send_message_json') +def test_distributed_api_error(mock_send): + mock_send.side_effect = ResourceNotFound + svc = Service() + svc.distribution_id = "12" + assert not svc.distributed + +@mock.patch.object(Service, 'send_message_json') +def test_distributed_not_distributed(mock_send): + mock_send.return_value = { + 'distributionStatusList':[ + {'omfComponentID': "SO", 'status': "DOWNLOAD_OK"}, + {'omfComponentID': "sdnc", 'status': "DOWNLOAD_NOK"}, + {'omfComponentID': "aai", 'status': "DOWNLOAD_OK"}]} + svc = Service() + svc.distribution_id = "12" + assert not svc.distributed + mock_send.assert_called_once_with( + 'GET', 'Check distribution for ONAP-test-Service', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/distribution/12', + headers=headers_sdc_operator(svc.headers)) + +@mock.patch.object(Service, 'send_message_json') +def test_distributed_not_distributed(mock_send): + mock_send.return_value = { + 'distributionStatusList':[ + {'omfComponentID': "SO", 'status': "DOWNLOAD_OK"}, + {'omfComponentID': "aai", 'status': "DOWNLOAD_OK"}]} + svc = Service() + svc.distribution_id = "12" + assert not svc.distributed + mock_send.assert_called_once_with( + 'GET', 'Check distribution for ONAP-test-Service', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/distribution/12', + headers=headers_sdc_creator(svc.headers)) + +@mock.patch.object(Service, 'send_message_json') +def test_distributed_distributed(mock_send): + mock_send.return_value = { + 'distributionStatusList':[ + {'omfComponentID': "SO", 'status': "DOWNLOAD_OK"}, + {'omfComponentID': "sdnc", 'status': "DOWNLOAD_OK"}, + {'omfComponentID': "aai", 'status': "DOWNLOAD_OK"}]} + svc = Service() + svc.distribution_id = "12" + assert svc.distributed + mock_send.assert_called_once_with( + 'GET', 'Check distribution for ONAP-test-Service', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/distribution/12', + headers=headers_sdc_creator(svc.headers)) + +@mock.patch.object(Service, 'send_message_json') +def test_load_metadata_no_result(mock_send): + mock_send.return_value = {} + svc = Service() + svc.identifier = "1" + svc.load_metadata() + assert svc._distribution_id is None + mock_send.assert_called_once_with( + 'GET', 'Get Metadata for ONAP-test-Service', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/1/distribution', + headers=headers_sdc_creator(svc.headers)) + +@mock.patch.object(Service, 'send_message_json') +def test_load_metadata_bad_json(mock_send): + mock_send.return_value = {'yolo': 'in the wood'} + svc = Service() + svc.identifier = "1" + svc.load_metadata() + assert svc._distribution_id is None + mock_send.assert_called_once_with( + 'GET', 'Get Metadata for ONAP-test-Service', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/1/distribution', + headers=headers_sdc_creator(svc.headers)) + +@mock.patch.object(Service, 'send_message_json') +def test_load_metadata_OK(mock_send): + mock_send.return_value = {'distributionStatusOfServiceList': [ + {'distributionID': "11"}, {'distributionID': "12"}]} + svc = Service() + svc.identifier = "1" + svc.load_metadata() + assert svc._distribution_id == "11" + mock_send.assert_called_once_with( + 'GET', 'Get Metadata for ONAP-test-Service', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/1/distribution', + headers=headers_sdc_creator(svc.headers)) + +def test_get_all_url(): + assert Service._get_all_url() == "https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/services" + +@mock.patch.object(Service, '_action_to_sdc') +@mock.patch.object(Service, 'load') +def test_really_submit_request_failed(mock_load, mock_action): + mock_action.side_effect = RequestError + svc = Service() + with pytest.raises(RequestError) as err: + svc._really_submit() + assert err.type == RequestError + mock_load.assert_not_called() + mock_action.assert_called_once_with('Certify', action_type='lifecycleState') + +@mock.patch.object(Service, '_action_to_sdc') +@mock.patch.object(Service, 'load') +def test_really_submit_OK(mock_load, mock_action): + mock_action.return_value = "yes" + svc = Service() + svc._really_submit() + mock_load.assert_called_once() + mock_action.assert_called_once_with('Certify', action_type='lifecycleState') + +@mock.patch.object(Service, 'load') +@mock.patch.object(Service, '_action_to_sdc') +@mock.patch.object(Service, 'created') +def test_verify_action_to_sdc_not_created(mock_created, mock_action, mock_load): + mock_created.return_value = False + svc = Service() + svc._status = "no_yes" + svc._verify_action_to_sdc("yes", "action", action_type='lifecycleState') + mock_created.assert_called() + mock_action.assert_not_called() + mock_load.assert_not_called() + +@mock.patch.object(Service, 'load') +@mock.patch.object(Service, '_action_to_sdc') +@mock.patch.object(Service, 'created') +def test_verify_action_to_sdc_bad_status(mock_created, mock_action, mock_load): + mock_created.return_value = True + svc = Service() + svc._status = "no_yes" + with pytest.raises(StatusError) as err: + svc._verify_action_to_sdc("yes", "action", action_type='lifecycleState') + assert err.type == StatusError + mock_created.assert_called() + mock_action.assert_not_called() + mock_load.assert_not_called() + +@mock.patch.object(Service, 'load') +@mock.patch.object(Service, '_action_to_sdc') +@mock.patch.object(Service, 'created') +def test_verify_action_to_sdc_OK(mock_created, mock_action, mock_load): + mock_created.return_value = True + mock_action.return_value = "good" + svc = Service() + svc._status = "yes" + svc._verify_action_to_sdc("yes", "action", action_type='lifecycleState') + mock_created.assert_called() + mock_action.assert_called_once() + mock_load.assert_called_once() + +@mock.patch.object(Service, 'distribute') +@mock.patch.object(Service, 'approve') +@mock.patch.object(Service, 'certify') +@mock.patch.object(Service, 'start_certification') +@mock.patch.object(Service, 'submit') +@mock.patch.object(Service, 'checkin') +@mock.patch.object(Service, 'add_resource') +@mock.patch.object(Service, 'create') +def test_onboard_new_service(mock_create, mock_add_resource, + mock_checkin, mock_submit, + mock_start_certification, mock_certify, + mock_approve, mock_distribute): + getter_mock = mock.Mock(wraps=Service.status.fget) + mock_status = Service.status.getter(getter_mock) + with mock.patch.object(Service, 'status', mock_status): + getter_mock.side_effect = [None, const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, None] + service = Service() + service._time_wait = 0 + service.onboard() + mock_create.assert_called_once() + mock_add_resource.assert_not_called() + mock_checkin.assert_not_called() + mock_submit.assert_not_called() + mock_start_certification.assert_not_called() + mock_certify.assert_not_called() + mock_approve.assert_not_called() + mock_distribute.assert_not_called() + +@mock.patch.object(Service, 'status') +def test_onboard_invalid_status(mock_status): + mock_status.return_value = False + service = Service() + service._time_wait = 0 + with pytest.raises(StatusError) as err: + service.onboard() + assert err.type == StatusError + +@mock.patch.object(Service, 'distribute') +@mock.patch.object(Service, 'approve') +@mock.patch.object(Service, 'certify') +@mock.patch.object(Service, 'start_certification') +@mock.patch.object(Service, 'submit') +@mock.patch.object(Service, 'checkin') +@mock.patch.object(Service, 'add_resource') +@mock.patch.object(Service, 'create') +def test_onboard_service_no_resources(mock_create, + mock_add_resource, mock_checkin, + mock_submit, mock_start_certification, + mock_certify, mock_approve, + mock_distribute): + getter_mock = mock.Mock(wraps=Service.status.fget) + mock_status = Service.status.getter(getter_mock) + with mock.patch.object(Service, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.DRAFT, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, None] + service = Service() + service._time_wait = 0 + with pytest.raises(ParameterError): + service.onboard() + mock_create.assert_not_called() + mock_add_resource.assert_not_called() + mock_checkin.assert_not_called() + mock_submit.assert_not_called() + mock_start_certification.assert_not_called() + mock_certify.assert_not_called() + mock_approve.assert_not_called() + mock_distribute.assert_not_called() + +@mock.patch.object(Service, 'distribute') +@mock.patch.object(Service, 'approve') +@mock.patch.object(Service, 'certify') +@mock.patch.object(Service, 'start_certification') +@mock.patch.object(Service, 'submit') +@mock.patch.object(Service, 'checkin') +@mock.patch.object(Service, 'add_resource') +@mock.patch.object(Service, 'create') +def test_onboard_service_resources(mock_create, mock_add_resource, + mock_checkin, mock_submit, + mock_start_certification, mock_certify, + mock_approve, mock_distribute): + getter_mock = mock.Mock(wraps=Service.status.fget) + mock_status = Service.status.getter(getter_mock) + with mock.patch.object(Service, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.DRAFT, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, None] + resource = SdcResource() + service = Service(resources=[resource]) + service._time_wait = 0 + service.onboard() + mock_create.assert_not_called() + mock_add_resource.assert_called_once_with(resource) + mock_checkin.assert_called_once() + mock_submit.assert_not_called() + mock_start_certification.assert_not_called() + mock_certify.assert_not_called() + mock_approve.assert_not_called() + mock_distribute.assert_not_called() + +@mock.patch.object(Service, 'distribute') +@mock.patch.object(Service, 'approve') +@mock.patch.object(Service, 'certify') +@mock.patch.object(Service, 'start_certification') +@mock.patch.object(Service, 'submit') +@mock.patch.object(Service, 'checkin') +@mock.patch.object(Service, 'add_resource') +@mock.patch.object(Service, 'create') +def test_onboard_service_several_resources(mock_create, + mock_add_resource, mock_checkin, + mock_submit, + mock_start_certification, + mock_certify, mock_approve, + mock_distribute): + getter_mock = mock.Mock(wraps=Service.status.fget) + mock_status = Service.status.getter(getter_mock) + with mock.patch.object(Service, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.DRAFT, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, None] + resource1 = SdcResource() + resource2 = SdcResource() + service = Service(resources=[resource1, resource2]) + service._time_wait = 0 + service.onboard() + mock_create.assert_not_called() + calls = [mock.call(resource1), mock.call(resource2)] + mock_add_resource.assert_has_calls(calls, any_order=True) + assert mock_add_resource.call_count == 2 + mock_checkin.assert_called_once() + mock_submit.assert_not_called() + mock_start_certification.assert_not_called() + mock_certify.assert_not_called() + mock_approve.assert_not_called() + mock_distribute.assert_not_called() + +@mock.patch.object(Service, 'distribute') +@mock.patch.object(Service, 'approve') +@mock.patch.object(Service, 'certify') +@mock.patch.object(Service, 'start_certification') +@mock.patch.object(Service, 'submit') +@mock.patch.object(Service, 'checkin') +@mock.patch.object(Service, 'add_resource') +@mock.patch.object(Service, 'create') +def test_onboard_service_certifi(mock_create, + mock_add_resource, mock_checkin, + mock_submit, mock_start_certification, + mock_certify, mock_approve, + mock_distribute): + getter_mock = mock.Mock(wraps=Service.status.fget) + mock_status = Service.status.getter(getter_mock) + with mock.patch.object(Service, 'status', mock_status): + getter_mock.side_effect = [const.CHECKED_IN, + const.CHECKED_IN, + const.CHECKED_IN, + const.CHECKED_IN, + const.CHECKED_IN, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, None] + service = Service() + service._time_wait = 0 + service.onboard() + mock_create.assert_not_called() + mock_add_resource.assert_not_called() + mock_checkin.assert_not_called() + mock_submit.assert_not_called() + mock_start_certification.assert_not_called() + mock_certify.assert_called_once() + mock_approve.assert_not_called() + mock_distribute.assert_not_called() + +@mock.patch.object(Service, 'distribute') +@mock.patch.object(Service, 'certify') +@mock.patch.object(Service, 'checkin') +@mock.patch.object(Service, 'add_resource') +@mock.patch.object(Service, 'create') +def test_onboard_service_distribute(mock_create, + mock_add_resource, + mock_checkin, + mock_certify, + mock_distribute): + getter_mock = mock.Mock(wraps=Service.status.fget) + mock_status = Service.status.getter(getter_mock) + with mock.patch.object(Service, 'status', mock_status): + getter_mock.side_effect = [const.CERTIFIED, const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, None] + service = Service() + service._time_wait = 0 + service.onboard() + mock_create.assert_not_called() + mock_add_resource.assert_not_called() + mock_checkin.assert_not_called() + mock_certify.assert_not_called() + mock_distribute.assert_called_once() + +@mock.patch.object(Service, 'distribute') +@mock.patch.object(Service, 'certify') +@mock.patch.object(Service, 'checkin') +@mock.patch.object(Service, 'add_resource') +@mock.patch.object(Service, 'create') +def test_onboard_whole_service(mock_create, + mock_add_resource, + mock_checkin, + mock_certify, + mock_distribute): + getter_mock = mock.Mock(wraps=Service.status.fget) + mock_status = Service.status.getter(getter_mock) + with mock.patch.object(Service, 'status', mock_status): + getter_mock.side_effect = [None, const.DRAFT, const.DRAFT,const.CHECKED_IN, + const.CHECKED_IN, const.CHECKED_IN, + const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.CERTIFIED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, const.DISTRIBUTED, + const.DISTRIBUTED, None] + resource = SdcResource() + service = Service(resources=[resource]) + service._time_wait = 0 + service.onboard() + mock_create.assert_called_once() + mock_add_resource.assert_called_once_with(resource) + mock_checkin.assert_called_once() + mock_certify.assert_called_once() + mock_distribute.assert_called_once() + +@mock.patch("onapsdk.sdc.service.Service.send_message_json") +@mock.patch("onapsdk.sdc.service.SdcResource.import_from_sdc") +@mock.patch("onapsdk.sdc.service.Service.resource_inputs_url", new_callable=mock.PropertyMock) +def test_vnf_vf_modules_one(mock_service_resource_inputs_url, mock_import_from_sdc, mock_send_message_json): + """Test parsing TOSCA file with one VNF which has associated one VFmodule""" + service = Service(name="test") + mock_send_message_json.side_effect = [{ + "componentInstances": [{ + "actualComponentUid": "123", + "originType": "VF", + "name": "ubuntu16_VF 0", + "toscaComponentName": "org.openecomp.resource.vf.Ubuntu16Vf", + "createdFromCsar": False, + "uniqueId": "123", + "normalizedName": "123", + "customizationUUID": "123", + "componentUid": "123", + "componentVersion": "123", + "componentName": "123", + "groupInstances": [ + { + "name": "ubuntu16_vf0..Ubuntu16Vf..base_ubuntu16..module-0", + "type": "org.openecomp.groups.VfModule", + "groupName": "Ubuntu16Vf..base_ubuntu16..module-0", + "groupUUID": "ed041b38-63fc-486d-9d4d-4e2531bc7e54", + "invariantUUID": "f47c3a9b-6a5f-4d1a-8a0b-b7f56ebb9a90", + "version": "1", + "customizationUUID": "d946ea06-ec4b-4ed2-921a-117e1379b913", + "properties": [ + { + "name": "123", + "type": "test type", + "value": "val", + "description": "12234", + }, + { + "name": "123", + "type": "test type", + "value": None, + "description": "12234", + } + ] + } + ] + }] + }, MagicMock() + ] + vnfs = list(service.vnfs) + assert len(vnfs) == 1 + vnf = vnfs[0] + assert vnf.name == "ubuntu16_VF 0" + assert vnf.node_template_type == "org.openecomp.resource.vf.Ubuntu16Vf" + assert vnf.vf_modules + assert vnf.vf_modules[0].name == "ubuntu16_vf0..Ubuntu16Vf..base_ubuntu16..module-0" + assert len(list(vnf.vf_modules[0].properties)) == 1 + +@mock.patch("onapsdk.sdc.service.Service.send_message_json") +@mock.patch("onapsdk.sdc.service.SdcResource.import_from_sdc") +@mock.patch("onapsdk.sdc.service.Service.resource_inputs_url", new_callable=mock.PropertyMock) +def test_pnf_modules_one(mock_service_resource_inputs_url, mock_import_from_sdc, mock_send_message_json): + """Test parsing TOSCA file with one PNF which has associated one PNFmodule""" + service = Service(name="test") + mock_send_message_json.side_effect = [{ + "componentInstances": [{ + "actualComponentUid": "123", + "originType": "PNF", + "name": "test_pnf_vsp 0", + "toscaComponentName": "org.openecomp.resource.pnf.TestPnfVsp", + "createdFromCsar": False, + "uniqueId": "123", + "normalizedName": "123", + "customizationUUID": "123", + "componentUid": "123", + "componentVersion": "123", + "componentName": "123", + "groupInstances": None + }] + }, MagicMock() + ] + pnfs = list(service.pnfs) + assert len(pnfs) == 1 + pnf = pnfs[0] + assert pnf.name == "test_pnf_vsp 0" + assert pnf.node_template_type == "org.openecomp.resource.pnf.TestPnfVsp" + +@mock.patch("onapsdk.sdc.service.Service.send_message_json") +@mock.patch("onapsdk.sdc.service.SdcResource.import_from_sdc") +@mock.patch("onapsdk.sdc.service.Service.resource_inputs_url", new_callable=mock.PropertyMock) +def test_vnf_vf_modules_two(mock_service_resource_inputs_url, mock_import_from_sdc, mock_send_message_json): + """Test parsing TOSCA file with two VNF which has associated one VFmodule""" + service = Service(name="test") + mock_send_message_json.side_effect = [{ + "componentInstances": [{ + "actualComponentUid": "123", + "originType": "VF", + "name": "vFWCL_vPKG-vf 0", + "toscaComponentName": "org.openecomp.resource.vf.VfwclVpkgVf", + "createdFromCsar": False, + "uniqueId": "123", + "normalizedName": "123", + "customizationUUID": "123", + "componentUid": "123", + "componentVersion": "123", + "componentName": "123", + "groupInstances": [ + { + "name": "vfwcl_vpkgvf0..VfwclVpkgVf..base_vpkg..module-0", + "type": "org.openecomp.groups.VfModule", + "groupName": "Ubuntu16Vf..base_ubuntu16..module-0", + "groupUUID": "ed041b38-63fc-486d-9d4d-4e2531bc7e54", + "invariantUUID": "f47c3a9b-6a5f-4d1a-8a0b-b7f56ebb9a90", + "version": "1", + "customizationUUID": "d946ea06-ec4b-4ed2-921a-117e1379b913", + "properties": [ + { + "name": "123", + "type": "test type", + "value": "val", + "description": "12234", + }, + { + "name": "333", + "type": "test type", + "value": "val", + "description": "12234", + }, + { + "name": "123", + "type": "test type", + "value": None, + "description": "12234", + } + ] + }, + { + "name": "vfwcl_vpkgvf0..base_template_dummy_ignore..base_vpkg..module-0", + "type": "org.openecomp.groups.VfModule", + "groupName": "Ubuntu16Vf..base_ubuntu16..module-0", + "groupUUID": "ed041b38-63fc-486d-9d4d-4e2531bc7e54", + "invariantUUID": "f47c3a9b-6a5f-4d1a-8a0b-b7f56ebb9a90", + "version": "1", + "customizationUUID": "d946ea06-ec4b-4ed2-921a-117e1379b913", + "properties": [ + { + "name": "123", + "type": "test type", + "value": "val", + "description": "12234", + }, + { + "name": "333", + "type": "test type", + "value": "val", + "description": "12234", + }, + { + "name": "vf_module_label", + "type": "test type", + "value": "base_template_dummy_ignore", + "description": "12234", + } + ] + } + ] + }, + { + "actualComponentUid": "123", + "originType": "VF", + "name": "vFWCL_vFWSNK-vf 0", + "toscaComponentName": "org.openecomp.resource.vf.VfwclVfwsnkVf", + "createdFromCsar": False, + "uniqueId": "123", + "normalizedName": "123", + "customizationUUID": "123", + "componentUid": "123", + "componentVersion": "123", + "componentName": "123", + "groupInstances": [ + { + "name": "vfwcl_vfwsnkvf0..VfwclVfwsnkVf..base_vfw..module-0", + "type": "org.openecomp.groups.VfModule", + "groupName": "Ubuntu16Vf..base_ubuntu16..module-0", + "groupUUID": "ed041b38-63fc-486d-9d4d-4e2531bc7e54", + "invariantUUID": "f47c3a9b-6a5f-4d1a-8a0b-b7f56ebb9a90", + "version": "1", + "customizationUUID": "d946ea06-ec4b-4ed2-921a-117e1379b913", + "properties": [ + { + "name": "123", + "type": "test type", + "value": "val", + "description": "12234", + }, + { + "name": "123", + "type": "test type", + "value": None, + "description": "12234", + } + ] + } + ] + }] + }, MagicMock(), MagicMock() + ] + vnfs = list(service.vnfs) + assert len(vnfs) == 2 + vnf = vnfs[0] + assert vnf.name == "vFWCL_vPKG-vf 0" + assert vnf.node_template_type == "org.openecomp.resource.vf.VfwclVpkgVf" + assert vnf.vf_modules + assert len(vnf.vf_modules) == 1 + assert vnf.vf_modules[0].name == "vfwcl_vpkgvf0..VfwclVpkgVf..base_vpkg..module-0" + assert len(list(vnf.vf_modules[0].properties)) == 2 + + vnf = vnfs[1] + assert vnf.name == "vFWCL_vFWSNK-vf 0" + assert vnf.node_template_type == "org.openecomp.resource.vf.VfwclVfwsnkVf" + assert vnf.vf_modules + assert vnf.vf_modules[0].name == "vfwcl_vfwsnkvf0..VfwclVfwsnkVf..base_vfw..module-0" + assert len(list(vnf.vf_modules[0].properties)) == 1 + + +@mock.patch.object(Service, 'send_message_json') +def test_get_vnf_unique_id(mock_send): + """Test Service get nf uid with One Vf""" + svc = Service() + svc.unique_identifier = "service_unique_identifier" + mock_send.return_value = ARTIFACTS + unique_id = svc.get_nf_unique_id(nf_name="ubuntu16test_VF 0") + mock_send.assert_called_once_with( + 'GET', 'Get nf unique ID', + f"https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/{svc.unique_identifier}") + assert unique_id == 'test_unique_id' + +@mock.patch.object(Service, 'send_message_json') +def test_get_vnf_unique_id_not_found(mock_send): + """Test Service get nf uid with One Vf""" + svc = Service() + svc.unique_identifier = "service_unique_identifier" + artifacts = {"componentInstances": []} + mock_send.return_value = artifacts + with pytest.raises(ResourceNotFound) as err: + svc.get_nf_unique_id(nf_name="ubuntu16test_VF 0") + assert err.type == ResourceNotFound + mock_send.assert_called_once_with( + 'GET', 'Get nf unique ID', + f"https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/{svc.unique_identifier}") + +@mock.patch.object(Service, 'get_nf_unique_id') +@mock.patch.object(Service, 'load') +@mock.patch.object(Service, 'send_message') +def test_add_artifact_to_vf(mock_send_message, mock_load, mock_add): + """Test Service add artifact""" + svc = Service() + mock_add.return_value = "54321" + result = svc.add_artifact_to_vf(vnf_name="ubuntu16test_VF 0", + artifact_type="DCAE_INVENTORY_BLUEPRINT", + artifact_name="clampnode.yaml", + artifact="data".encode('utf-8')) + mock_send_message.assert_called() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "Add artifact to vf" + assert url == ("https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/" + f"{svc.unique_identifier}/resourceInstance/54321/artifacts") + +@mock.patch.object(Service, 'load') +@mock.patch.object(Service, 'send_message') +def test_add_artifact_to_service(mock_send_message, mock_load): + """Test Service add artifact""" + svc = Service() + svc.status = const.DRAFT + mycbapath = Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip") + + result = svc.add_deployment_artifact(artifact_label="cba", + artifact_type="CONTROLLER_BLUEPRINT_ARCHIVE", + artifact_name="vLB_CBA_Python.zip", + artifact=mycbapath) + mock_send_message.assert_called() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "Add deployment artifact for ONAP-test-Service sdc resource" + assert url == ("https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/services/" + f"{svc.unique_identifier}/artifacts") + +@mock.patch("onapsdk.sdc.service.Service.send_message_json") +@mock.patch("onapsdk.sdc.service.SdcResource.import_from_sdc") +@mock.patch("onapsdk.sdc.service.Service.resource_inputs_url", new_callable=mock.PropertyMock) +def test_service_networks(mock_service_resource_inputs_url, mock_import_from_sdc, mock_send_message_json): + mock_send_message_json.side_effect = [{ + "componentInstances": [{ + "actualComponentUid": "123", + "originType": "VL", + "name": "NeutronNet 0", + "toscaComponentName": "org.openecomp.resource.vl.nodes.heat.network.neutron.Net", + "createdFromCsar": False, + "uniqueId": "123", + "normalizedName": "123", + "customizationUUID": "123", + "componentUid": "123", + "componentVersion": "123", + "componentName": "123", + "groupInstances": None + }] + }, MagicMock() + ] + + service = Service(name="test") + networks = list(service.networks) + assert len(networks) == 1 + network = networks[0] + assert network.name == "NeutronNet 0" + assert network.node_template_type == "org.openecomp.resource.vl.nodes.heat.network.neutron.Net" + +@mock.patch.object(Service, '_unzip_csar_file') +def test_tosca_template_no_tosca_model(mock_unzip): + service = Service(name="test") + getter_mock = mock.Mock(wraps=Service.tosca_model.fget) + getter_mock.return_value = False + mock_tosca_model = Service.tosca_model.getter(getter_mock) + with mock.patch.object(Service, 'tosca_model', mock_tosca_model): + service.tosca_template + mock_unzip.assert_not_called() + +@mock.patch.object(Service, '_unzip_csar_file') +def test_tosca_template_tosca_model(mock_unzip): + service = Service(name="test") + service._tosca_model = str.encode("test") + service.tosca_template + mock_unzip.assert_called_once_with(mock.ANY, mock.ANY) + +@mock.patch.object(Service, '_unzip_csar_file') +def test_tosca_template_present(mock_unzip): + service = Service(name="test") + service._tosca_template = "test" + assert service.tosca_template == "test" + mock_unzip.assert_not_called() + +@mock.patch.object(Service, 'send_message') +def test_tosca_model(mock_send): + service = Service(name="test") + service.identifier = "toto" + service.tosca_model + mock_send.assert_called_once_with("GET", "Download Tosca Model for test", + "https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/services/toto/toscaModel", + headers={'Content-Type': 'application/json', 'Accept': 'application/octet-stream', 'USER_ID': 'cs0008', 'Authorization': 'Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=', 'X-ECOMP-InstanceID': 'onapsdk'}) + +@mock.patch.object(Service, "send_message_json") +def test_add_properties(mock_send_message_json): + service = Service(name="test") + service._identifier = "toto" + service._unique_identifier = "toto" + service._status = const.CERTIFIED + with pytest.raises(StatusError): + service.add_property(Property(name="test", property_type="string")) + service._status = const.DRAFT + service.add_property(Property(name="test", property_type="string")) + mock_send_message_json.assert_called_once() + +@mock.patch.object(Service, "send_message_json") +def test_service_components(mock_send_message_json): + service = Service(name="test") + service.unique_identifier = "toto" + + mock_send_message_json.return_value = {} + assert len(list(service.components)) == 0 + + mock_send_message_json.reset_mock() + mock_send_message_json.side_effect = [COMPONENTS, COMPONENT] + components = list(service.components) + assert len(components) == 1 + assert mock_send_message_json.call_count == 2 + component = components[0] + assert component.actual_component_uid == "374f0a98-a280-43f1-9e6c-00b436782ce7" + assert component.sdc_resource.unique_uuid == "3c027ba1-8d3a-4b59-9394-d748fec5e42c" + +def test_component_properties(): + sdc_resource = mock.MagicMock() + service = Service(name="test") + service.unique_identifier = "toto" + + component = Component( + created_from_csar=False, + actual_component_uid="123", + unique_id="123", + normalized_name="123", + name="123", + origin_type="123", + customization_uuid="123", + tosca_component_name="123", + component_name="123", + component_uid="123", + component_version="123", + sdc_resource=sdc_resource, + parent_sdc_resource=service, + group_instances=None + ) + sdc_resource.send_message_json.return_value = {} + assert not len(list(component.properties)) + + sdc_resource.send_message_json.return_value = COMPONENT_PROPERTIES + properties = list(component.properties) + assert len(properties) == 2 + prop1, prop2 = properties + + assert prop1.unique_id == "3d9a184f-4268-4a0e-9ddd-252e49670013.vf_module_id" + assert prop1.property_type == "string" + assert prop1.name == "vf_module_id" + assert prop1.value is None + + assert prop2.unique_id == "74f79006-ae56-4d58-947e-6a5089000774.skip_post_instantiation_configuration" + assert prop2.property_type == "boolean" + assert prop2.name == "skip_post_instantiation_configuration" + assert prop2.value == "true" + +@mock.patch.object(Component, "properties", new_callable=mock.PropertyMock) +def test_component_property_set_value(mock_component_properties): + mock_sdc_resource = mock.MagicMock() + service = Service(name="test") + service.unique_identifier = "toto" + component = Component( + created_from_csar=False, + actual_component_uid="123", + unique_id="123", + normalized_name="123", + name="123", + origin_type="123", + customization_uuid="123", + tosca_component_name="123", + component_name="123", + component_uid="123", + component_version="123", + sdc_resource=mock_sdc_resource, + parent_sdc_resource=service, + group_instances=None + ) + mock_component_properties.return_value = [ + ComponentProperty( + unique_id="123", + property_type="string", + name="test_property", + component=component + ) + ] + with pytest.raises(ParameterError): + component.get_property(property_name="non_exists") + prop1 = component.get_property(property_name="test_property") + assert prop1.name == "test_property" + assert prop1.unique_id == "123" + assert prop1.property_type == "string" + assert not prop1.value + + prop1.value = "123" + mock_sdc_resource.send_message_json.assert_called_once() + +@mock.patch.object(Service, "add_resource") +@mock.patch.object(Service, "add_property") +@mock.patch.object(Service, "declare_input") +def test_declare_resources_and_properties(mock_declare_input, mock_add_property, mock_add_resource): + + service = Service(name="test", + resources=[SdcResource()], + properties=[Property(name="test", property_type="string")], + inputs=[Property(name="test", property_type="string")]) + service.declare_resources_and_properties() + mock_add_resource.assert_called_once() + mock_add_property.assert_called_once() + mock_declare_input.assert_called_once() + +@mock.patch.object(Service, "created") +@mock.patch.object(ServiceCategory, "get") +def test_service_category(mock_resource_category, mock_created): + mock_created.return_value = False + service = Service(name="test") + _ = service.category + mock_resource_category.assert_called_once_with(name="Network Service") + mock_resource_category.reset_mock() + + service = Service(name="test", category="test") + _ = service.category + mock_resource_category.assert_called_once_with(name="test") + mock_resource_category.reset_mock() + + mock_created.return_value = True + _ = service.category + mock_resource_category.assert_called_once_with(name="test") + +def test_service_origin_type(): + service = Service(name="test") + assert service.origin_type == "ServiceProxy" + +@mock.patch.object(Service, "unique_identifier", new_callable=PropertyMock) +def test_service_metadata_url(mock_uniquie_identifier): + mock_uniquie_identifier.return_value = "1233" + service = Service(name="test") + assert service.metadata_url == f"{service._base_create_url()}/services/1233/filteredDataByParams?include=metadata" + + +@mock.patch.object(Service, "created") +@mock.patch.object(Service, "send_message_json") +@mock.patch.object(Service, "metadata_url", new_callable=PropertyMock) +def test_service_instantiation_type(mock_metadata_url, mock_send_message_json, mock_created): + mock_created.return_value = False + service = Service(name="test") + assert service.instantiation_type == ServiceInstantiationType.A_LA_CARTE + + service = Service(name="test", instantiation_type=ServiceInstantiationType.MACRO) + assert service.instantiation_type == ServiceInstantiationType.MACRO + + mock_created.return_value = True + mock_send_message_json.return_value = {"metadata": {"instantiationType": "A-la-carte"}} + service = Service(name="test") + assert service.instantiation_type == ServiceInstantiationType.A_LA_CARTE + + mock_send_message_json.return_value = {"metadata": {"instantiationType": "Macro"}} + service = Service(name="test") + assert service.instantiation_type == ServiceInstantiationType.MACRO + + +@mock.patch.object(Service, "get_all") +def test_service_get_by_unique_uuid(mock_get_all): + mock_get_all.return_value = [] + with pytest.raises(ResourceNotFound): + Service.get_by_unique_uuid("test") + mock_service = MagicMock() + mock_service.unique_uuid = "test" + mock_get_all.return_value = [mock_service] + Service.get_by_unique_uuid("test") + +@mock.patch.object(Service, "send_message_json") +def test_service_components(mock_send_message_json): + service = Service(name="test") + service.unique_identifier = "toto" + + mock_send_message_json.side_effect = [COMPONENTS, COMPONENT, COMPONENTS, COMPONENT, COMPONENTS, COMPONENT] + assert not service.has_vnfs + assert not service.has_pnfs + assert not service.has_vls + + mock_send_message_json.side_effect = [COMPONENTS_WITH_ALL_ORIGIN_TYPES, COMPONENT, + COMPONENTS_WITH_ALL_ORIGIN_TYPES, COMPONENT, COMPONENT, + COMPONENTS_WITH_ALL_ORIGIN_TYPES, COMPONENT, COMPONENT, COMPONENT] + assert service.has_vnfs + assert service.has_pnfs + assert service.has_vls diff --git a/tests/test_settings.py b/tests/test_settings.py new file mode 100644 index 0000000..7e62da6 --- /dev/null +++ b/tests/test_settings.py @@ -0,0 +1,79 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import sys +from pathlib import PurePath + +import pytest + +from onapsdk.configuration import settings, SETTINGS_ENV +from onapsdk.configuration.loader import SettingsLoader +from onapsdk.exceptions import ModuleError + + +def test_global_settings(): + """Test global settings.""" + assert len(settings._settings) == 43 + assert settings.AAI_URL == "https://aai.api.sparky.simpledemo.onap.org:30233" + assert settings.CDS_URL == "http://portal.api.simpledemo.onap.org:30449" + assert settings.SDNC_URL == "https://sdnc.api.simpledemo.onap.org:30267" + assert settings.SO_URL == "http://so.api.simpledemo.onap.org:30277" + assert settings.MSB_URL == "https://msb.api.simpledemo.onap.org:30283" + assert settings.SDC_FE_URL == "https://sdc.api.fe.simpledemo.onap.org:30207" + assert settings.SDC_BE_URL == "https://sdc.api.be.simpledemo.onap.org:30204" + assert settings.VID_URL == "https://vid.api.simpledemo.onap.org:30200" + assert settings.CLAMP_URL == "https://clamp.api.simpledemo.onap.org:30258" + assert settings.VES_URL == "http://ves.api.simpledemo.onap.org:30417" + assert settings.DMAAP_URL == "http://dmaap.api.simpledemo.onap.org:3904" + assert settings.NBI_URL == "https://nbi.api.simpledemo.onap.org:30274" + assert settings.DCAEMOD_URL == "" + assert settings.HOLMES_URL == "https://aai.api.sparky.simpledemo.onap.org:30293" + assert settings.POLICY_URL == "" + assert settings.AAI_GUI_URL == "https://aai.api.sparky.simpledemo.onap.org:30220" + assert settings.AAI_GUI_SERVICE == "https://aai.api.sparky.simpledemo.onap.org:30220/services/aai/webapp/index.html#/browse" + assert settings.CDS_GUI_SERVICE == "http://portal.api.simpledemo.onap.org:30449/" + assert settings.SO_MONITOR_GUI_SERVICE == "http://so.api.simpledemo.onap.org:30277/" + assert settings.SDC_GUI_SERVICE == "https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/portal" + assert settings.SDNC_DG_GUI_SERVICE == "https://sdnc.api.simpledemo.onap.org:30267/nifi/" + assert settings.SDNC_ODL_GUI_SERVICE == "https://sdnc.api.simpledemo.onap.org:30267/odlux/index.html" + assert settings.DCAEMOD_GUI_SERVICE == "/" + assert settings.HOLMES_GUI_SERVICE == "https://aai.api.sparky.simpledemo.onap.org:30293/iui/holmes/default.html" + assert settings.POLICY_GUI_SERVICE == "/onap/login.html" + assert settings.POLICY_CLAMP_GUI_SERVICE == "https://clamp.api.simpledemo.onap.org:30258/" + assert settings.PROJECT == "Onapsdk_project" + assert settings.LOB == "Onapsdk_lob" + assert settings.PLATFORM == "Onapsdk_platform" + assert hasattr(settings, "AAI_AUTH") + assert hasattr(settings, "CDS_AUTH") + assert hasattr(settings, "SDC_AUTH") + assert hasattr(settings, "SDNC_AUTH") + assert hasattr(settings, "CLAMP_AUTH") + assert hasattr(settings, "SO_AUTH") + assert hasattr(settings, "SO_CAT_DB_AUTH") + + +def test_settings_load_custom(): + """Test if custom settings is loaded correctly.""" + sys.path.append(str(PurePath(__file__).parent)) + os.environ[SETTINGS_ENV] = "data.tests_settings" + custom_settings = SettingsLoader() + assert custom_settings.AAI_URL == "http://tests.settings.py:1234" + assert custom_settings.TEST_VALUE == "test" + + +def test_invalid_custom_settings(): + """Test if loading invalid custom settings raises ModuleError.""" + os.environ[SETTINGS_ENV] = "non.existings.package" + with pytest.raises(ModuleError): + SettingsLoader() diff --git a/tests/test_so_db_adapter.py b/tests/test_so_db_adapter.py new file mode 100644 index 0000000..50f26d6 --- /dev/null +++ b/tests/test_so_db_adapter.py @@ -0,0 +1,136 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.so.so_db_adapter import SoDbAdapter, IdentityService + +ADD_CLOUD_SITE_RESPONSE = { + '_links': { + 'cloudSite': { + 'href': 'http://so.api.simpledemo.onap.org:30277/cloudSite/mc_test_cloud_site_3' + }, + 'self': { + 'href': 'http://so.api.simpledemo.onap.org:30277/cloudSite/mc_test_cloud_site_3' + } + }, + 'aic_version': '2.5', + 'clli': 'test_clli_0', + 'cloud_owner': None, + 'cloudify_id': None, + 'creation_timestamp': '2021-05-12T08:52:48.134+0000', + 'identityService': { + 'admin_tenant': 'service', + 'creation_timestamp': '2021-05-12T08:52:48.134+0000', + 'identityServerTypeAsString': 'KEYSTONE', + 'identity_authentication_type': 'USERNAME_PASSWORD', + 'identity_server_type': 'KEYSTONE', + 'identity_url': 'http://1.2.3.4:5000/v2.0', + 'last_updated_by': None, + 'member_role': 'admin', + 'mso_id': 'onapsdk_user', + 'mso_pass': 'mso_pass_onapsdk', + 'project_domain_name': 'NULL', + 'tenant_metadata': True, + 'update_timestamp': '2021-05-12T08:52:48.134+0000', + 'user_domain_name': 'NULL' + }, + 'identity_service_id': 'test_identity_0', + 'last_updated_by': None, + 'orchestrator': 'multicloud', + 'platform': None, + 'region_id': 'test_region_0', + 'support_fabric': True, + 'update_timestamp': '2021-05-12T08:52:48.134+0000', + 'uri': None +} + +SERVICE_VNF_RESPONSE = { + 'serviceVnfs': [ + { + 'modelInfo': { + 'modelName': 'test_vnf_01', + 'modelUuid': 'd2779cc5-fb01-449f-a355-7e5d911dca93', + 'modelInvariantUuid': '027cb696-f68f-47db-9b0e-585ea3eaa512', + 'modelVersion': '1.0', + 'modelCustomizationUuid': 'b8740912-e0fc-426f-af97-7657caf57847', + 'modelInstanceName': 'test_vnf_01 0' + }, + 'toscaNodeType': 'org.openecomp.resource.vf.Mvnr5gCucpVfT003', + 'nfFunction': None, + 'nfType': None, + 'nfRole': None, + 'nfNamingCode': None, + 'multiStageDesign': 'false', + 'vnfcInstGroupOrder': None, + 'resourceInput': None, + 'vfModules': [{'modelInfo': + { + 'modelName': 'test_vf_01', + 'modelUuid': '153464b8-4f47-4140-8b92-9614c4578d91', + 'modelInvariantUuid': '753deff5-99a2-4154-8c1d-3e956cb96f32', + 'modelVersion': '1', + 'modelCustomizationUuid': '7ca564f3-b908-499c-b086-ae77ad270d8c' + }, + 'isBase': False, + 'vfModuleLabel': 'vf_mod_label', + 'initialCount': 0, + 'hasVolumeGroup': False + } + ], + 'groups': [] + } + ] +} + + +def test_identity_service(): + identity_service = IdentityService(identity_id="identity_123") + assert identity_service.identity_id == "identity_123" + assert identity_service.url == "http://1.2.3.4:5000/v2.0" + assert identity_service.mso_id == "onapsdk_user" + assert identity_service.mso_pass == "mso_pass_onapsdk" + assert identity_service.project_domain_name == "NULL" + assert identity_service.user_domain_name == "NULL" + assert identity_service.admin_tenant == "service" + assert identity_service.member_role == "admin" + assert identity_service.identity_server_type == "KEYSTONE" + assert identity_service.identity_authentication_type == "USERNAME_PASSWORD" + assert identity_service.hibernate_lazy_initializer == {} + assert identity_service.server_type_as_string == "KEYSTONE" + assert identity_service.tenant_metadata is True + +@mock.patch.object(SoDbAdapter, "send_message_json") +def test_add_cloud_site(mock_send_message_json): + identity_service = IdentityService(identity_id="test_identity_0") + mock_send_message_json.return_value = ADD_CLOUD_SITE_RESPONSE + + response = SoDbAdapter.add_cloud_site(cloud_region_id="test_region_0", + complex_id="test_clli_0", + identity_service=identity_service) + assert response['region_id'] == "test_region_0" + assert response['aic_version'] == "2.5" + assert response['clli'] == "test_clli_0" + assert response['orchestrator'] == "multicloud" + assert response['identity_service_id'] == "test_identity_0" + +@mock.patch.object(SoDbAdapter, "send_message_json") +def test_get_service_vnf_info(mock_send_message_json): + mock_send_message_json.return_value = ADD_CLOUD_SITE_RESPONSE + + response = SoDbAdapter.get_service_vnf_info(identifier="test_id_0") + assert response['region_id'] == "test_region_0" + assert response['aic_version'] == "2.5" + assert response['clli'] == "test_clli_0" + assert response['orchestrator'] == "multicloud" + assert response['identity_service_id'] == "test_identity_0" diff --git a/tests/test_so_deletion.py b/tests/test_so_deletion.py new file mode 100644 index 0000000..ff10474 --- /dev/null +++ b/tests/test_so_deletion.py @@ -0,0 +1,74 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.so.deletion import ( + ServiceDeletionRequest, + VfModuleDeletionRequest, + VnfDeletionRequest +) + + +@mock.patch.object(ServiceDeletionRequest, "send_message") +def test_service_deletion_request(mock_send_message): + mock_instance = mock.MagicMock() + mock_instance.instance_id = "test_instance_id" + ServiceDeletionRequest.send_request(instance=mock_instance) + mock_send_message.assert_called_once() + method, _, url = mock_send_message.call_args[0] + assert method == "DELETE" + assert url == (f"{ServiceDeletionRequest.base_url}/onap/so/infra/" + f"serviceInstantiation/{ServiceDeletionRequest.api_version}/" + "serviceInstances/test_instance_id") + + +@mock.patch.object(VfModuleDeletionRequest, "send_message") +def test_vf_module_deletion_request(mock_send_message): + mock_vf_module_instance = mock.MagicMock() + mock_vf_module_instance.vf_module_id = "test_vf_module_id" + + mock_vnf_instance = mock.MagicMock() + mock_vnf_instance.vnf_id = "test_vnf_id" + mock_vf_module_instance.vnf_instance = mock_vnf_instance + + mock_service_instance = mock.MagicMock() + mock_service_instance.instance_id = "test_service_instance_id" + mock_vnf_instance.service_instance = mock_service_instance + + VfModuleDeletionRequest.send_request(instance=mock_vf_module_instance) + mock_send_message.assert_called_once() + method, _, url = mock_send_message.call_args[0] + assert method == "DELETE" + assert url == (f"{VfModuleDeletionRequest.base_url}/onap/so/infra/" + f"serviceInstantiation/{VfModuleDeletionRequest.api_version}/" + "serviceInstances/test_service_instance_id/" + "vnfs/test_vnf_id/vfModules/test_vf_module_id") + + +@mock.patch.object(VnfDeletionRequest, "send_message") +def test_vnf_deletion_request(mock_send_message): + mock_vnf_instance = mock.MagicMock() + mock_vnf_instance.vnf_id = "test_vnf_id" + + mock_service_instance = mock.MagicMock() + mock_service_instance.instance_id = "test_service_instance" + mock_vnf_instance.service_instance = mock_service_instance + VnfDeletionRequest.send_request(instance=mock_vnf_instance) + mock_send_message.assert_called_once() + method, _, url = mock_send_message.call_args[0] + assert method == "DELETE" + assert url == (f"{VnfDeletionRequest.base_url}/onap/so/infra/" + f"serviceInstantiation/{VnfDeletionRequest.api_version}/" + "serviceInstances/test_service_instance/" + "vnfs/test_vnf_id") diff --git a/tests/test_so_element.py b/tests/test_so_element.py new file mode 100644 index 0000000..cc866d9 --- /dev/null +++ b/tests/test_so_element.py @@ -0,0 +1,28 @@ +"""Test A&AI Element.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.so.so_element import SoElement +from onapsdk.utils.gui import GuiList + +@mock.patch.object(SoElement, "send_message") +def test_get_guis(send_message_mock): + component = SoElement() + send_message_mock.return_value.status_code = 200 + send_message_mock.return_value.url = "http://so.api.simpledemo.onap.org:30277/" + gui_results = component.get_guis() + assert type(gui_results) == GuiList + assert gui_results.guilist[0].url == send_message_mock.return_value.url + assert gui_results.guilist[0].status == send_message_mock.return_value.status_code diff --git a/tests/test_so_instantiation.py b/tests/test_so_instantiation.py new file mode 100644 index 0000000..5c8f41a --- /dev/null +++ b/tests/test_so_instantiation.py @@ -0,0 +1,1002 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import json +import oyaml as yaml +from collections import namedtuple +from pathlib import Path +from unittest import mock + +import pytest + +from onapsdk.exceptions import APIError, InvalidResponse, ResourceNotFound, StatusError +from onapsdk.sdc.service import Service +from onapsdk.sdnc import NetworkPreload, VfModulePreload +from onapsdk.so.instantiation import ( + NetworkInstantiation, + ServiceInstantiation, + SoService, + SoServicePnf, + SoServiceVfModule, + SoServiceVnf, + VfModuleInstantiation, + VnfInstantiation, + VnfOperation +) +from onapsdk.vid import Vid +from onapsdk.aai.business.owning_entity import OwningEntity + + +@mock.patch.object(ServiceInstantiation, "send_message_json") +def test_service_ala_carte_instantiation(mock_service_instantiation_send_message): + mock_sdc_service = mock.MagicMock() + mock_sdc_service.distributed = False + with pytest.raises(StatusError): + ServiceInstantiation.\ + instantiate_ala_carte(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + service_instance_name="test", + service_subscription=mock.MagicMock()) + mock_sdc_service.distributed = True + service_instance = ServiceInstantiation.\ + instantiate_ala_carte(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + service_instance_name="test", + service_subscription=mock.MagicMock()) + assert service_instance.name == "test" + + service_instance = ServiceInstantiation.\ + instantiate_ala_carte(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + service_subscription=mock.MagicMock()) + assert service_instance.name.startswith("Python_ONAP_SDK_service_instance_") + mock_service_instantiation_send_message.assert_called() + method, _, url = mock_service_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{ServiceInstantiation.base_url}/onap/so/infra/" + f"serviceInstantiation/{ServiceInstantiation.api_version}/serviceInstances") + + +@mock.patch.object(ServiceInstantiation, "send_message_json") +def test_service_macro_instantiation(mock_service_instantiation_send_message): + mock_sdc_service = mock.MagicMock() + mock_sdc_service.distributed = False + with pytest.raises(StatusError): + ServiceInstantiation.\ + instantiate_macro(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + service_instance_name="test", + service_subscription=mock.MagicMock()) + mock_sdc_service.distributed = True + service_instance = ServiceInstantiation.\ + instantiate_macro(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + service_instance_name="test", + service_subscription=mock.MagicMock()) + assert service_instance.name == "test" + + service_instance = ServiceInstantiation.\ + instantiate_macro(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + project=mock.MagicMock(), + so_service=mock.MagicMock()) + assert service_instance.name.startswith("Python_ONAP_SDK_service_instance_") + mock_service_instantiation_send_message.assert_called() + method, _, url = mock_service_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{ServiceInstantiation.base_url}/onap/so/infra/" + f"serviceInstantiation/{ServiceInstantiation.api_version}/serviceInstances") + + so_service_mock = mock.MagicMock() + so_service_mock.instance_name = "SoServiceInstanceName" + service_instance = ServiceInstantiation.\ + instantiate_macro(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + project=mock.MagicMock(), + so_service=so_service_mock) + assert service_instance.name == "SoServiceInstanceName" + mock_service_instantiation_send_message.assert_called() + method, _, url = mock_service_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{ServiceInstantiation.base_url}/onap/so/infra/" + f"serviceInstantiation/{ServiceInstantiation.api_version}/serviceInstances") + + +def test_service_instance_aai_service_instance(): + customer_mock = mock.MagicMock() + service_instantiation = ServiceInstantiation(name="test", + request_id="test_request_id", + instance_id="test_instance_id", + sdc_service=mock.MagicMock(), + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=customer_mock, + owning_entity=mock.MagicMock(), + project=mock.MagicMock()) + status_mock = mock.PropertyMock(return_value=ServiceInstantiation.StatusEnum.IN_PROGRESS) + type(service_instantiation).status = status_mock + with pytest.raises(StatusError): + service_instantiation.aai_service_instance + + status_mock.return_value = return_value=ServiceInstantiation.StatusEnum.COMPLETED + assert service_instantiation.aai_service_instance is not None + + customer_mock.get_service_subscription_by_service_type.side_effect = APIError + with pytest.raises(APIError) as err: + service_instantiation.aai_service_instance + assert err.type == APIError + + +@mock.patch.object(VnfInstantiation, "send_message_json") +def test_vnf_instantiation(mock_vnf_instantiation_send_message): + aai_service_instance_mock = mock.MagicMock() + aai_service_instance_mock.instance_id = "test_instance_id" + vnf_instantiation = VnfInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + sdc_service=mock.MagicMock()) + assert vnf_instantiation.name.startswith("Python_ONAP_SDK_vnf_instance_") + mock_vnf_instantiation_send_message.assert_called_once() + method, _, url = mock_vnf_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{VnfInstantiation.base_url}/onap/so/infra/serviceInstantiation/" + f"{VnfInstantiation.api_version}/serviceInstances/" + f"{aai_service_instance_mock.instance_id}/vnfs") + + vnf_instantiation = VnfInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + vnf_instance_name="test", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + sdc_service=mock.MagicMock()) + assert vnf_instantiation.name == "test" + + +@mock.patch.object(VnfInstantiation, "send_message_json") +def test_vnf_instantiation_with_cr_and_tenant(mock_vnf_instantiation_send_message): + aai_service_instance_mock = mock.MagicMock() + aai_service_instance_mock.instance_id = "test_instance_id" + vnf_instantiation = VnfInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + sdc_service=mock.MagicMock()) + assert vnf_instantiation.name.startswith("Python_ONAP_SDK_vnf_instance_") + mock_vnf_instantiation_send_message.assert_called_once() + method, _, url = mock_vnf_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{VnfInstantiation.base_url}/onap/so/infra/serviceInstantiation/" + f"{VnfInstantiation.api_version}/serviceInstances/" + f"{aai_service_instance_mock.instance_id}/vnfs") + + vnf_instantiation = VnfInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + vnf_instance_name="test", + sdc_service=mock.MagicMock()) + assert vnf_instantiation.name == "test" + + +@mock.patch.object(VnfInstantiation, "send_message_json") +@mock.patch.object(OwningEntity, "get_by_owning_entity_id") +def test_vnf_instantiation_macro(mock_owning_entity_get, mock_vnf_instantiation_send_message): + aai_service_instance_mock = mock.MagicMock() + aai_service_instance_mock.instance_id = "test_instance_id" + + relation_1 = mock.MagicMock() + relation_1.related_to = "owning-entity" + relation_1.relationship_data = [{"relationship-value": "test"}] + relation_2 = mock.MagicMock() + relation_2.related_to = "project" + relation_2.relationship_data = [{"relationship-value": "test"}] + + aai_service_instance_mock.relationships = (item for item in [relation_1, relation_2]) + + vnf_instantiation = VnfInstantiation.\ + instantiate_macro(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + sdc_service=mock.MagicMock()) + assert vnf_instantiation.name.startswith("Python_ONAP_SDK_vnf_instance_") + mock_vnf_instantiation_send_message.assert_called_once() + method, _, url = mock_vnf_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{VnfInstantiation.base_url}/onap/so/infra/serviceInstantiation/" + f"{VnfInstantiation.api_version}/serviceInstances/" + f"{aai_service_instance_mock.instance_id}/vnfs") + + vnf_instantiation = VnfInstantiation. \ + instantiate_macro(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + vnf_instance_name="test", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + sdc_service=mock.MagicMock()) + assert vnf_instantiation.name == "test" + + vnf_instantiation = VnfInstantiation. \ + instantiate_macro(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + sdc_service=mock.MagicMock(), + so_vnf=mock.MagicMock()) + assert vnf_instantiation.name.startswith("Python_ONAP_SDK_service_instance_") + + so_vnf_mock = mock.MagicMock() + so_vnf_mock.instance_name = "SoVnfInstanceName" + vnf_instantiation = VnfInstantiation. \ + instantiate_macro(aai_service_instance=aai_service_instance_mock, + vnf_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + sdc_service=mock.MagicMock(), + so_vnf=so_vnf_mock) + assert vnf_instantiation.name == "SoVnfInstanceName" + + +@mock.patch.object(VnfInstantiation, "send_message_json") +@mock.patch.object(OwningEntity, "get_by_owning_entity_id") +def test_vnf_macro_so_action(mock_owning_entity_get, mock_vnf_instantiation_send_message): + + mock_sdc_service = mock.MagicMock() + with pytest.raises(StatusError): + VnfInstantiation.\ + so_action(vnf_instance=mock.MagicMock(), + operation_type=mock.MagicMock(), + aai_service_instance=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + sdc_service=mock_sdc_service, + so_service=mock.MagicMock()) + + relation_1 = mock.MagicMock() + relation_1.related_to = "owning-entity" + relation_1.relationship_data = [{"relationship-value": "test"}] + relation_2 = mock.MagicMock() + relation_2.related_to = "project" + relation_2.relationship_data = [{"relationship-value": "test"}] + + mock_aai_service_instance = mock.MagicMock() + mock_aai_service_instance.instance_id = mock.MagicMock() + mock_aai_service_instance.relationships = (item for item in [relation_1, relation_2]) + mock_aai_service_instance.service_subscription = mock.MagicMock() + mock_vnf_instance = mock.MagicMock() + mock_vnf_instance.vnf_name = "test_name_update" + mock_vnf_instance.vnf_id = "1234" + + vnf_instance_update = VnfInstantiation.\ + so_action(vnf_instance=mock_vnf_instance, + operation_type=VnfOperation.UPDATE, + aai_service_instance=mock_aai_service_instance, + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + sdc_service=mock_sdc_service, + so_service=mock.MagicMock()) + assert vnf_instance_update.name == "test_name_update" + mock_vnf_instantiation_send_message.assert_called() + method, _, url = mock_vnf_instantiation_send_message.call_args[0] + assert method == "PUT" + assert url == (f"{ServiceInstantiation.base_url}/onap/so/infra/" + f"serviceInstantiation/{ServiceInstantiation.api_version}/serviceInstances/" + f"{mock_aai_service_instance.instance_id}/vnfs/{mock_vnf_instance.vnf_id}") + + mock_vnf_instance = mock.MagicMock() + mock_vnf_instance.vnf_name = "test_name_healthcheck" + + vnf_instance_healthcheck = VnfInstantiation. \ + so_action(vnf_instance=mock_vnf_instance, + operation_type=VnfOperation.HEALTHCHECK, + aai_service_instance=mock_aai_service_instance, + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + sdc_service=mock_sdc_service, + so_service=mock.MagicMock()) + assert vnf_instance_healthcheck.name == "test_name_healthcheck" + mock_vnf_instantiation_send_message.assert_called() + method, _, url = mock_vnf_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{ServiceInstantiation.base_url}/onap/so/infra/" + f"serviceInstantiation/{ServiceInstantiation.api_version}/serviceInstances/" + f"{mock_aai_service_instance.instance_id}/vnfs/{mock_vnf_instance.vnf_id}/healthcheck") + + +@mock.patch.object(NetworkInstantiation, "send_message_json") +@mock.patch.object(NetworkPreload, "send_message_json") +def test_network_instantiation(mock_network_preload, mock_network_instantiation_send_message): + aai_service_instance_mock = mock.MagicMock() + aai_service_instance_mock.instance_id = "test_instance_id" + vnf_instantiation = NetworkInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + network_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock()) + mock_network_preload.assert_called_once() + assert vnf_instantiation.name.startswith("Python_ONAP_SDK_network_instance_") + mock_network_instantiation_send_message.assert_called_once() + method, _, url = mock_network_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{NetworkInstantiation.base_url}/onap/so/infra/serviceInstantiation/" + f"{NetworkInstantiation.api_version}/serviceInstances/" + f"{aai_service_instance_mock.instance_id}/networks") + + network_instantiation = NetworkInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + network_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + network_instance_name="test", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock()) + assert mock_network_preload.call_count == 2 + assert network_instantiation.name == "test" + + +@mock.patch.object(NetworkInstantiation, "send_message_json") +@mock.patch.object(NetworkPreload, "send_message_json") +def test_network_instantiation_with_cr_and_tenant(mock_network_preload, mock_network_instantiation_send_message): + aai_service_instance_mock = mock.MagicMock() + aai_service_instance_mock.instance_id = "test_instance_id" + vnf_instantiation = NetworkInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + network_object=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock()) + mock_network_preload.assert_called_once() + assert vnf_instantiation.name.startswith("Python_ONAP_SDK_network_instance_") + mock_network_instantiation_send_message.assert_called_once() + method, _, url = mock_network_instantiation_send_message.call_args[0] + assert method == "POST" + assert url == (f"{NetworkInstantiation.base_url}/onap/so/infra/serviceInstantiation/" + f"{NetworkInstantiation.api_version}/serviceInstances/" + f"{aai_service_instance_mock.instance_id}/networks") + + network_instantiation = NetworkInstantiation.\ + instantiate_ala_carte(aai_service_instance=aai_service_instance_mock, + network_object=mock.MagicMock(), + line_of_business="test_lob", + platform="test_platform", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + network_instance_name="test") + assert mock_network_preload.call_count == 2 + assert network_instantiation.name == "test" + +@mock.patch.object(Vid, "send_message") +@mock.patch.object(VnfInstantiation, "send_message_json") +@mock.patch("onapsdk.so.instantiation.SdcService") +def test_vnf_instantiation_get_by_vnf_instance_name(mock_sdc_service, mock_send_message_json, mock_send): + mock_sdc_service.return_value.vnfs = [] + mock_send_message_json.return_value = {} + with pytest.raises(InvalidResponse): + VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") + mock_send_message_json.return_value = { + "requestList": [ + { + "request": { + "requestScope": "not_vnf" + } + } + ] + } + with pytest.raises(InvalidResponse): + VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") + mock_send_message_json.return_value = { + "requestList": [ + { + "request": { + "requestScope": "vnf", + "requestType": "updateInstance" + } + } + ] + } + with pytest.raises(InvalidResponse): + VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") + mock_send_message_json.return_value = { + "requestList": [ + { + "request": { + "requestScope": "vnf", + "requestType": "createInstance" + } + } + ] + } + with pytest.raises(ResourceNotFound): + VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") + mock_send_message_json.return_value = { + "requestList": [ + { + "request": { + "requestScope": "vnf", + "requestType": "createInstance", + "requestDetails": { + "relatedInstanceList": [ + { + "relatedInstance": { + "modelInfo": { + "modelType": "service", + "modelName": "test_service" + } + } + } + ] + } + } + } + ] + } + with pytest.raises(ResourceNotFound): + VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") + mock_vnf = mock.MagicMock() + mock_vnf.name = "test_vnf_name" + mock_sdc_service.return_value.vnfs = [mock_vnf] + mock_send_message_json.return_value = { + "requestList": [ + { + "request": { + "requestScope": "vnf", + "requestType": "createInstance", + "requestDetails": { + "modelInfo": { + "modelCustomizationName": "test_fail_vnf_name" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "modelInfo": { + "modelType": "service", + "modelName": "test_service", + } + } + } + ] + } + } + } + ] + } + with pytest.raises(ResourceNotFound): + VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") + mock_sdc_service.return_value.vnfs = [mock_vnf] + mock_send_message_json.return_value = { + "requestList": [ + { + "request": { + "requestScope": "vnf", + "requestType": "createInstance", + "requestDetails": { + "modelInfo": { + "modelCustomizationName": "test_vnf_name" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "modelInfo": { + "modelType": "service", + "modelName": "test_service" + } + } + } + ] + } + } + } + ] + } + assert VnfInstantiation.get_by_vnf_instance_name("test_vnf_instance_name") is not None + + +@mock.patch.object(VfModuleInstantiation, "send_message_json") +@mock.patch.object(VfModulePreload, "upload_vf_module_preload") +def test_vf_module_instantiation(mock_vf_module_preload, mock_send_message_json): + mock_service_instance = mock.MagicMock() + mock_service_instance.instance_id = "1234" + mock_vnf_instance = mock.MagicMock() + mock_vnf_instance.service_instance = mock_service_instance + mock_vnf_instance.vnf_id = "4321" + instantiation = VfModuleInstantiation.\ + instantiate_ala_carte(vf_module=mock.MagicMock(), + vnf_instance=mock_vnf_instance, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock()) + assert instantiation.name.startswith("Python_ONAP_SDK_vf_module_instance_") + mock_send_message_json.assert_called_once() + method, _, url = mock_send_message_json.call_args[0] + assert method == "POST" + assert url == (f"{VfModuleInstantiation.base_url}/onap/so/infra/serviceInstantiation/" + f"{VfModuleInstantiation.api_version}/serviceInstances/1234/vnfs/" + f"4321/vfModules") + + instantiation = VfModuleInstantiation.\ + instantiate_ala_carte(vf_module=mock.MagicMock(), + vnf_instance=mock_vnf_instance, + vf_module_instance_name="test", + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock()) + assert instantiation.name == "test" + + +@mock.patch.object(VfModuleInstantiation, "send_message_json") +@mock.patch.object(VfModulePreload, "upload_vf_module_preload") +def test_vf_module_instantiation_with_cr_and_tenant(mock_vf_module_preload, mock_send_message_json): + mock_service_instance = mock.MagicMock() + mock_service_instance.instance_id = "1234" + mock_vnf_instance = mock.MagicMock() + mock_vnf_instance.service_instance = mock_service_instance + mock_vnf_instance.vnf_id = "4321" + instantiation = VfModuleInstantiation.\ + instantiate_ala_carte(vf_module=mock.MagicMock(), + vnf_instance=mock_vnf_instance, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock()) + assert instantiation.name.startswith("Python_ONAP_SDK_vf_module_instance_") + mock_send_message_json.assert_called_once() + method, _, url = mock_send_message_json.call_args[0] + assert method == "POST" + assert url == (f"{VfModuleInstantiation.base_url}/onap/so/infra/serviceInstantiation/" + f"{VfModuleInstantiation.api_version}/serviceInstances/1234/vnfs/" + f"4321/vfModules") + + instantiation = VfModuleInstantiation.\ + instantiate_ala_carte(vf_module=mock.MagicMock(), + vnf_instance=mock_vnf_instance, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + vf_module_instance_name="test") + assert instantiation.name == "test" + + +def test_instantiation_wait_for_finish(): + with mock.patch.object(ServiceInstantiation, "finished", new_callable=mock.PropertyMock) as mock_finished: + with mock.patch.object(ServiceInstantiation, "completed", new_callable=mock.PropertyMock) as mock_completed: + instantiation = ServiceInstantiation( + name="test", + request_id="test", + instance_id="test", + sdc_service=mock.MagicMock(), + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock() + ) + instantiation.WAIT_FOR_SLEEP_TIME = 0 + mock_finished.side_effect = [False, False, True] + mock_completed.return_value = True + rv = namedtuple("Value", ["return_value"]) + instantiation._wait_for_finish(rv) + assert rv.return_value + +@mock.patch.object(ServiceInstantiation, "send_message_json") +def test_service_instantiation_multicloud(mock_send_message_json): + + mock_sdc_service = mock.MagicMock() + mock_sdc_service.distributed = True + _ = ServiceInstantiation.\ + instantiate_ala_carte(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + service_subscription=mock.MagicMock()) + _, kwargs = mock_send_message_json.call_args + data = json.loads(kwargs["data"]) + assert data["requestDetails"]["requestParameters"]["userParams"] == [] + mock_send_message_json.reset_mock() + + _ = ServiceInstantiation.\ + instantiate_ala_carte(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + enable_multicloud=True, + service_subscription=mock.MagicMock()) + _, kwargs = mock_send_message_json.call_args + data = json.loads(kwargs["data"]) + assert data["requestDetails"]["requestParameters"]["userParams"] == [{"name": "orchestrator", "value": "multicloud"}] + mock_send_message_json.reset_mock() + + _ = ServiceInstantiation.\ + instantiate_macro(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + service_instance_name="test", + service_subscription=mock.MagicMock()) + _, kwargs = mock_send_message_json.call_args + data = json.loads(kwargs["data"]) + assert not any(filter(lambda x: x == {"name": "orchestrator", "value": "multicloud"}, data["requestDetails"]["requestParameters"]["userParams"])) + mock_send_message_json.reset_mock() + + _ = ServiceInstantiation.\ + instantiate_macro(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + service_instance_name="test", + enable_multicloud=True, + service_subscription=mock.MagicMock()) + _, kwargs = mock_send_message_json.call_args + data = json.loads(kwargs["data"]) + assert any(filter(lambda x: x == {"name": "orchestrator", "value": "multicloud"}, data["requestDetails"]["requestParameters"]["userParams"])) + + +@mock.patch.object(ServiceInstantiation, "send_message_json") +def test_service_instantiation_so_service(mock_send_message_json): + mock_sdc_service = mock.MagicMock() + mock_sdc_service.distributed = True + + so_service = SoService( + subscription_service_type="test_so_service", + vnfs=[ + SoServiceVnf( + model_name="test_so_service_vnf_model_name_1", + instance_name="test_so_service_vnf_instance_name_1", + parameters={ + "param_1": "param_1_value", + "param_2": "param_2_value" + } + ), + SoServiceVnf( + model_name="test_so_service_vnf_model_name_2", + instance_name="test_so_service_vnf_instance_name_2", + vf_modules=[ + SoServiceVfModule( + model_name="test_so_service_vf_module_model_name_1", + instance_name="test_so_service_vf_module_instance_name_1", + parameters={ + "vf_module_param_1": "vf_module_param_1_value", + "vf_module_param_2": "vf_module_param_2_value" + } + ), + SoServiceVfModule( + model_name="test_so_service_vf_module_model_name_2", + instance_name="test_so_service_vf_module_instance_name_2", + parameters={ + "vf_module_param_1": "vf_module_param_1_value", + "vf_module_param_2": "vf_module_param_2_value" + } + ), + ] + ) + ], + pnfs=[ + SoServicePnf( + model_name="test_so_service_pnf_model_name_1", + instance_name="test_so_service_pnf_instance_name_1" + ), + SoServicePnf( + model_name="test_so_service_pnf_model_name_2", + instance_name="test_so_service_pnf_instance_name_2" + ) + ] + ) + + _ = ServiceInstantiation.\ + instantiate_macro(sdc_service=mock_sdc_service, + cloud_region=mock.MagicMock(), + tenant=mock.MagicMock(), + customer=mock.MagicMock(), + owning_entity=mock.MagicMock(), + project=mock.MagicMock(), + line_of_business=mock.MagicMock(), + platform=mock.MagicMock(), + service_instance_name="test", + so_service=so_service) + _, kwargs = mock_send_message_json.call_args + data = json.loads(kwargs["data"]) + assert data["requestDetails"]["requestParameters"]["subscriptionServiceType"] == "test_so_service" + assert len(data["requestDetails"]["requestParameters"]["userParams"][1]["service"]["resources"]["vnfs"]) == 2 + assert len(data["requestDetails"]["requestParameters"]["userParams"][1]["service"]["resources"]["pnfs"]) == 2 + vnf_1_data = data["requestDetails"]["requestParameters"]["userParams"][1]["service"]["resources"]["vnfs"][0] + vnf_2_data = data["requestDetails"]["requestParameters"]["userParams"][1]["service"]["resources"]["vnfs"][1] + pnf_1_data = data["requestDetails"]["requestParameters"]["userParams"][1]["service"]["resources"]["pnfs"][0] + pnf_2_data = data["requestDetails"]["requestParameters"]["userParams"][1]["service"]["resources"]["pnfs"][1] + + assert vnf_1_data["instanceName"] == "test_so_service_vnf_instance_name_1" + assert len(vnf_1_data["instanceParams"][0]) == 2 + assert vnf_1_data["instanceParams"][0]["param_1"] == "param_1_value" + assert vnf_1_data["instanceParams"][0]["param_2"] == "param_2_value" + assert len(vnf_1_data["vfModules"]) == 0 + + assert vnf_2_data["instanceName"] == "test_so_service_vnf_instance_name_2" + assert len(vnf_2_data["instanceParams"][0]) == 0 + assert len(vnf_2_data["vfModules"]) == 2 + vf_module_1_data = vnf_2_data["vfModules"][0] + vf_module_2_data = vnf_2_data["vfModules"][1] + + assert vf_module_1_data["instanceName"] == "test_so_service_vf_module_instance_name_1" + assert len(vf_module_1_data["instanceParams"][0]) == 2 + assert vf_module_1_data["instanceParams"][0]["vf_module_param_1"] == "vf_module_param_1_value" + assert vf_module_1_data["instanceParams"][0]["vf_module_param_2"] == "vf_module_param_2_value" + + assert vf_module_2_data["instanceName"] == "test_so_service_vf_module_instance_name_2" + assert len(vf_module_2_data["instanceParams"][0]) == 2 + assert vf_module_2_data["instanceParams"][0]["vf_module_param_1"] == "vf_module_param_1_value" + assert vf_module_2_data["instanceParams"][0]["vf_module_param_2"] == "vf_module_param_2_value" + + assert pnf_1_data["instanceName"] == "test_so_service_pnf_instance_name_1" + + assert pnf_2_data["instanceName"] == "test_so_service_pnf_instance_name_2" + + +def test_so_service_load_from_yaml(): + + so_service_yaml = """ + subscription_service_type: myservice + vnfs: + - model_name: myvfmodel + instance_name: myfirstvnf + parameters: + param1: value1 + processing_priority: 1 + vf_modules: + - instance_name: mysecondvfm + model_name: base + processing_priority: 2 + parameters: + param-vfm1: value-vfm1 + - instance_name: myfirstvfm + model_name: base + processing_priority: 1 + parameters: + param-vfm1: value-vfm1 + - model_name: myvfmodel + instance_name: mysecondvnf + parameters: + param1: value1 + processing_priority: 2 + vf_modules: + - instance_name: myfirstvfm + model_name: base + processing_priority: 1 + parameters: + param-vfm1: value-vfm1 + - instance_name: mysecondvfm + model_name: base + processing_priority: 2 + parameters: + param-vfm1: value-vfm1 + pnfs: + - model_name: mypnfmodel + instance_name: myfirstpnf + """ + so_service = SoService.load(yaml.safe_load(so_service_yaml)) + assert so_service.subscription_service_type == "myservice" + assert not so_service.instance_name + assert len(so_service.vnfs) == 2 + assert len(so_service.pnfs) == 1 + + so_service_vnf_1 = so_service.vnfs[0] + so_service_vnf_2 = so_service.vnfs[1] + so_service_pnf = so_service.pnfs[0] + + assert so_service_vnf_1.model_name == "myvfmodel" + assert so_service_vnf_1.instance_name == "myfirstvnf" + assert so_service_vnf_1.processing_priority == 1 + assert len(so_service_vnf_1.parameters) == 1 + assert so_service_vnf_1.parameters["param1"] == "value1" + assert len(so_service_vnf_1.vf_modules) == 2 + + so_service_vnf_1_vf_module_1 = so_service_vnf_1.vf_modules[0] + so_service_vnf_1_vf_module_2 = so_service_vnf_1.vf_modules[1] + + assert so_service_vnf_1_vf_module_1.model_name == "base" + assert so_service_vnf_1_vf_module_1.instance_name == "mysecondvfm" + assert so_service_vnf_1_vf_module_1.processing_priority == 2 + assert len(so_service_vnf_1_vf_module_1.parameters) == 1 + assert so_service_vnf_1_vf_module_1.parameters["param-vfm1"] == "value-vfm1" + assert so_service_vnf_1_vf_module_2.model_name == "base" + assert so_service_vnf_1_vf_module_2.instance_name == "myfirstvfm" + assert so_service_vnf_1_vf_module_2.processing_priority == 1 + assert len(so_service_vnf_1_vf_module_2.parameters) == 1 + assert so_service_vnf_1_vf_module_2.parameters["param-vfm1"] == "value-vfm1" + + assert so_service_vnf_2.model_name == "myvfmodel" + assert so_service_vnf_2.instance_name == "mysecondvnf" + assert so_service_vnf_2.processing_priority == 2 + assert len(so_service_vnf_2.parameters) == 1 + assert so_service_vnf_2.parameters["param1"] == "value1" + assert len(so_service_vnf_2.vf_modules) == 2 + + so_service_vnf_1_vf_module_1 = so_service_vnf_2.vf_modules[0] + so_service_vnf_1_vf_module_2 = so_service_vnf_2.vf_modules[1] + + assert so_service_vnf_1_vf_module_1.model_name == "base" + assert so_service_vnf_1_vf_module_1.instance_name == "myfirstvfm" + assert so_service_vnf_1_vf_module_1.processing_priority == 1 + assert len(so_service_vnf_1_vf_module_1.parameters) == 1 + assert so_service_vnf_1_vf_module_1.parameters["param-vfm1"] == "value-vfm1" + assert so_service_vnf_1_vf_module_2.model_name == "base" + assert so_service_vnf_1_vf_module_2.instance_name == "mysecondvfm" + assert so_service_vnf_1_vf_module_2.processing_priority == 2 + assert len(so_service_vnf_1_vf_module_2.parameters) == 1 + assert so_service_vnf_1_vf_module_2.parameters["param-vfm1"] == "value-vfm1" + + assert so_service_pnf.model_name == "mypnfmodel" + assert so_service_pnf.instance_name == "myfirstpnf" + + +def test_so_service_load_from_file(): + with Path(Path(__file__).parent, "data/test_so_service_data.yaml").open() as yaml_template: + so_service_data = yaml.safe_load(yaml_template) + service = Service(next(iter(so_service_data.keys()))) + so_service = SoService.load(so_service_data[service.name]) + assert so_service.subscription_service_type == "myservice" + assert not so_service.instance_name + assert len(so_service.vnfs) == 2 + + so_service_vnf_1 = so_service.vnfs[0] + so_service_vnf_2 = so_service.vnfs[1] + + assert so_service_vnf_1.model_name == "myvfmodel" + assert so_service_vnf_1.instance_name == "myfirstvnf" + assert so_service_vnf_1.processing_priority == 1 + assert len(so_service_vnf_1.parameters) == 1 + assert so_service_vnf_1.parameters["param1"] == "value1" + assert len(so_service_vnf_1.vf_modules) == 2 + + so_service_vnf_1_vf_module_1 = so_service_vnf_1.vf_modules[0] + so_service_vnf_1_vf_module_2 = so_service_vnf_1.vf_modules[1] + + assert so_service_vnf_1_vf_module_1.model_name == "base" + assert so_service_vnf_1_vf_module_1.instance_name == "mysecondvfm" + assert so_service_vnf_1_vf_module_1.processing_priority == 2 + assert len(so_service_vnf_1_vf_module_1.parameters) == 1 + assert so_service_vnf_1_vf_module_1.parameters["param-vfm1"] == "value-vfm1" + assert so_service_vnf_1_vf_module_2.model_name == "base" + assert so_service_vnf_1_vf_module_2.instance_name == "myfirstvfm" + assert so_service_vnf_1_vf_module_2.processing_priority == 1 + assert len(so_service_vnf_1_vf_module_2.parameters) == 1 + assert so_service_vnf_1_vf_module_2.parameters["param-vfm1"] == "value-vfm1" + + assert so_service_vnf_2.model_name == "myvfmodel" + assert so_service_vnf_2.instance_name == "mysecondvnf" + assert so_service_vnf_2.processing_priority == 2 + assert len(so_service_vnf_2.parameters) == 1 + assert so_service_vnf_2.parameters["param1"] == "value1" + assert len(so_service_vnf_2.vf_modules) == 2 + + so_service_vnf_1_vf_module_1 = so_service_vnf_2.vf_modules[0] + so_service_vnf_1_vf_module_2 = so_service_vnf_2.vf_modules[1] + + assert so_service_vnf_1_vf_module_1.model_name == "base" + assert so_service_vnf_1_vf_module_1.instance_name == "myfirstvfm" + assert so_service_vnf_1_vf_module_1.processing_priority == 1 + assert len(so_service_vnf_1_vf_module_1.parameters) == 1 + assert so_service_vnf_1_vf_module_1.parameters["param-vfm1"] == "value-vfm1" + assert so_service_vnf_1_vf_module_2.model_name == "base" + assert so_service_vnf_1_vf_module_2.instance_name == "mysecondvfm" + assert so_service_vnf_1_vf_module_2.processing_priority == 2 + assert len(so_service_vnf_1_vf_module_2.parameters) == 1 + assert so_service_vnf_1_vf_module_2.parameters["param-vfm1"] == "value-vfm1" + + +def test_so_service_vnf_load_from_yaml(): + + so_vnf_yaml = """ + model_name: myvnfmodel + instance_name: mynewvnf + parameters: + param1: value1 + vf_modules: + - instance_name: myfirstvfm + model_name: base + processing_priority: 1 + parameters: + param-vfm1: value-vfm1 + - instance_name: mysecondvfm + model_name: second_base + processing_priority: 2 + parameters: + param-vfm2: value-vfm2 + param-vfm3: value-vfm3 + """ + + so_vnf = SoServiceVnf.load(yaml.safe_load(so_vnf_yaml)) + assert so_vnf.model_name == "myvnfmodel" + assert so_vnf.instance_name == "mynewvnf" + + assert len(so_vnf.parameters) == 1 + assert so_vnf.parameters["param1"] == "value1" + + assert len(so_vnf.vf_modules) == 2 + so_vnf_vf_module_1 = so_vnf.vf_modules[0] + so_vnf_vf_module_2 = so_vnf.vf_modules[1] + + assert so_vnf_vf_module_1.model_name == "base" + assert so_vnf_vf_module_1.instance_name == "myfirstvfm" + assert so_vnf_vf_module_1.processing_priority == 1 + assert len(so_vnf_vf_module_1.parameters) == 1 + assert so_vnf_vf_module_1.parameters["param-vfm1"] == "value-vfm1" + + assert so_vnf_vf_module_2.model_name == "second_base" + assert so_vnf_vf_module_2.instance_name == "mysecondvfm" + assert so_vnf_vf_module_2.processing_priority == 2 + assert len(so_vnf_vf_module_2.parameters) == 2 + assert so_vnf_vf_module_2.parameters["param-vfm2"] == "value-vfm2" + assert so_vnf_vf_module_2.parameters["param-vfm3"] == "value-vfm3" diff --git a/tests/test_so_orchestration_request.py b/tests/test_so_orchestration_request.py new file mode 100644 index 0000000..c93189b --- /dev/null +++ b/tests/test_so_orchestration_request.py @@ -0,0 +1,103 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.so.so_element import OrchestrationRequest, SoElement +from onapsdk.utils.headers_creator import headers_so_creator +from onapsdk.onap_service import OnapService + + +IN_PROGRESS = { + "request": { + "requestStatus": { + "requestState": "IN_PROGRESS" + } + } +} +FAILED = { + "request": { + "requestStatus": { + "requestState": "FAILED" + } + } +} +COMPLETE = { + "request": { + "requestStatus": { + "requestState": "COMPLETE" + } + } +} +UNKNOWN = { + "request": { + "requestStatus": { + "requestState": "INVALID" + } + } +} +BAD_RESPONSE = {} + + +@mock.patch.object(OrchestrationRequest, "send_message_json") +def test_orchestration_request_status(mock_send_message): + orchestration_req = OrchestrationRequest(request_id="test") + + mock_send_message.return_value = BAD_RESPONSE + assert orchestration_req.status == OrchestrationRequest.StatusEnum.UNKNOWN + + mock_send_message.return_value = UNKNOWN + assert orchestration_req.status == OrchestrationRequest.StatusEnum.UNKNOWN + + mock_send_message.return_value = FAILED + assert orchestration_req.status == OrchestrationRequest.StatusEnum.FAILED + + mock_send_message.return_value = COMPLETE + assert orchestration_req.status == OrchestrationRequest.StatusEnum.COMPLETED + + mock_send_message.return_value = IN_PROGRESS + assert orchestration_req.status == OrchestrationRequest.StatusEnum.IN_PROGRESS + assert not orchestration_req.finished + assert not orchestration_req.completed + assert not orchestration_req.failed + + mock_send_message.return_value = COMPLETE + assert orchestration_req.finished + assert orchestration_req.completed + assert not orchestration_req.failed + + mock_send_message.return_value = FAILED + assert orchestration_req.finished + assert not orchestration_req.completed + assert orchestration_req.failed + + +#Test the Class SoElement +def test_SoElement_headers(): + """Test the header property""" + element = SoElement() + assert element.headers != headers_so_creator(OnapService.headers) + #check x-transactionid for headers + + +def test_get_subscription_service_type(): + """Test SO Element class method""" + vf_object_name = SoElement.get_subscription_service_type("vf_name") + assert vf_object_name == "vf_name" + + +def test_base_create_url(): + """Test base create url class method""" + assert SoElement._base_create_url() == "{}/onap/so/infra/serviceInstantiation/{}/serviceInstances".\ + format(SoElement.base_url, SoElement.api_version) + diff --git a/tests/test_sp_partner.py b/tests/test_sp_partner.py new file mode 100644 index 0000000..73a4839 --- /dev/null +++ b/tests/test_sp_partner.py @@ -0,0 +1,84 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from onapsdk.aai.business import SpPartner +from onapsdk.exceptions import ResourceNotFound + + +SP_PARTNERS = { + "sp-partner":[ + { + "sp-partner-id":"ff6c945f-89ab-4f14-bafd-0cdd6eac791a", + "url":"http://127.0.0.1", + "resource-version":"1588244348931", + }, + { + "sp-partner-id":"OE-generic", + "callsource":"test-callsource", + "resource-version":"1587388597761" + }, + { + "sp-partner-id":"b3dcdbb0-edae-4384-b91e-2f114472520c", + "url":"http://127.0.0.1", + "callsource":"test-callsource", + "operational-status":"test-operational-status", + "model-customization-id":"test-model-customization-id", + "model-invariant-id":"test-model-invariant-id", + "model-version-id":"test-model-version-id", + "resource-version":"1588145971158" + } + ] +} + + +SP_PARTNER = { + "sp-partner-id":"blablabla", + "url":"http://127.0.0.1", + "callsource":"test-callsource", + "resource-version":"1587388597761" +} + + +@mock.patch.object(SpPartner, "send_message_json") +def test_sp_partner_get_all(mock_send): + mock_send.return_value = SP_PARTNERS + owning_entities = list(SpPartner.get_all()) + assert len(owning_entities) == 3 + sp_partner = owning_entities[0] + assert sp_partner.sp_partner_id == "ff6c945f-89ab-4f14-bafd-0cdd6eac791a" + assert sp_partner.sp_partner_url == "http://127.0.0.1" + assert sp_partner.url == (f"{sp_partner.base_url}{sp_partner.api_version}/" + "business/sp-partners/sp-partner/" + f"{sp_partner.sp_partner_id}") + + +@mock.patch.object(SpPartner, "send_message_json") +def test_sp_partner_get_by_sp_partner_id(mock_send): + mock_send.return_value = SP_PARTNER + sp_partner = SpPartner.get_by_sp_partner_id("blablabla") + assert sp_partner.sp_partner_id == "blablabla" + + +@mock.patch.object(SpPartner, "send_message") +@mock.patch.object(SpPartner, "get_by_sp_partner_id") +def test_sp_partner_create(_, mock_send): + + SpPartner.create( + sp_partner_id="123" + ) + mock_send.assert_called_once_with("PUT", + "Declare A&AI sp partner", + "https://aai.api.sparky.simpledemo.onap.org:30233/aai/v23/business/sp-partners/sp-partner/123", + data='{\n "sp-partner-id": "123"\n \n \n \n \n \n \n}') diff --git a/tests/test_subnet.py b/tests/test_subnet.py new file mode 100644 index 0000000..cc7eced --- /dev/null +++ b/tests/test_subnet.py @@ -0,0 +1,49 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest +from onapsdk.exceptions import ParameterError + +from onapsdk.so.instantiation import Subnet + + +def test_dhcp_subnet(): + with pytest.raises(ParameterError): + Subnet(name="test", + role="test", + start_address="192.168.8.0", + gateway_address="192.168.8.1", + dhcp_enabled="sss" + ) + with pytest.raises(ParameterError): + Subnet(name="test", + role="test", + start_address="192.168.8.0", + gateway_address="192.168.8.1", + dhcp_enabled="Y" + ) + subnet = Subnet(name="test", + role="test", + start_address="192.168.8.0", + gateway_address="192.168.8.1", + dhcp_enabled="Y", + dhcp_start_address="10.8.1.0", + dhcp_end_address="10.8.1.1" + ) + assert subnet.name == "test" + assert subnet.role == "test" + assert subnet.start_address == "192.168.8.0" + assert subnet.gateway_address == "192.168.8.1" + assert subnet.dhcp_enabled == "Y" + assert subnet.dhcp_start_address == "10.8.1.0" + assert subnet.dhcp_end_address == "10.8.1.1" diff --git a/tests/test_tosca_file_handler.py b/tests/test_tosca_file_handler.py new file mode 100644 index 0000000..e288693 --- /dev/null +++ b/tests/test_tosca_file_handler.py @@ -0,0 +1,88 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import json +import oyaml as yaml +import os +import os.path +import unittest + +from onapsdk.exceptions import ValidationError +import onapsdk.utils.tosca_file_handler as tosca_file_handler + + +__author__ = "Morgan Richomme <morgan.richomme@orange.com>" + + +class ToscaFileHandlerTestingBase(unittest.TestCase): + + """The super class which testing classes could inherit.""" + + logging.disable(logging.CRITICAL) + + _root_path = os.getcwd().rsplit('/onapsdk')[0] + _foo_path = _root_path +"/tests/data/service-Ubuntu16-template.yml" + + + def setUp(self): + pass + + def test_get_parameter_from_yaml(self): + with open(self._foo_path) as f: + model = json.dumps(yaml.safe_load(f)) + param = tosca_file_handler.get_parameter_from_yaml( + "metadata", model) + self.assertEqual(param['name'], "ubuntu16") + + def test_get_wrong_parameter_from_yaml(self): + with open(self._foo_path) as f: + model = json.dumps(yaml.safe_load(f)) + with self.assertRaises(ValidationError): + tosca_file_handler.get_parameter_from_yaml( + "wrong_parameter", model) + + def test_get_parameter_from_wrong_yaml(self): + with self.assertRaises(FileNotFoundError): + with open("wrong_path") as f: + model = json.dumps(yaml.safe_load(f)) + tosca_file_handler.get_parameter_from_yaml( + "metadata", model) + + def test_get_random_string_generator(self): + self.assertEqual( + len(tosca_file_handler.random_string_generator()), 6) + + def test_get_vf_list_from_tosca_file(self): + with open(self._foo_path) as f: + model = json.dumps(yaml.safe_load(f)) + vf_list = tosca_file_handler.get_vf_list_from_tosca_file(model) + self.assertEqual(vf_list[0], 'ubuntu16_VF') + + def test_get_modules_list_from_tosca_file(self): + with open(self._foo_path) as f: + model = json.dumps(yaml.safe_load(f)) + vf_modules = tosca_file_handler.get_modules_list_from_tosca_file(model) + self.assertEqual(len(vf_modules), 1) + + # def get_vf_list_from_tosca_file_wrong_model(self): + # with self.assertRaises(FileNotFoundError): + # tosca_file_handler.get_vf_list_from_tosca_file( + # self._root_path + "wrong_path") + +if __name__ == "__main__": + # logging must be disabled else it calls time.time() + # what will break these unit tests. + logging.disable(logging.CRITICAL) + unittest.main(verbosity=2) diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..62bffde --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,46 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os + +import pytest +import time + +from onapsdk.onap_service import OnapService +from onapsdk.utils.mixins import WaitForFinishMixin +from onapsdk.utils import load_json_file + + +class TestWaitForFinish(WaitForFinishMixin, OnapService): + + @property + def completed(self): + return True + + @property + def finished(self): + time.sleep(0.1) + return True + + +def test_wait_for_finish_timeout(): + t = TestWaitForFinish() + with pytest.raises(TimeoutError): + t.wait_for_finish(timeout=0.01) + t.wait_for_finish() + + +def test_load_json_file(): + path_to_event: str = os.path.join(os.getcwd(), "tests/data/utils_load_json_file_test.json") + test_json: str = load_json_file(path_to_event) + assert test_json == '{"event": {"test1": "val1"}}' diff --git a/tests/test_vendor.py b/tests/test_vendor.py new file mode 100644 index 0000000..78c4bad --- /dev/null +++ b/tests/test_vendor.py @@ -0,0 +1,316 @@ +"""Test vendor module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest +from onapsdk.exceptions import RequestError + +from onapsdk.sdc.vendor import Vendor +import onapsdk.constants as const +from onapsdk.sdc.sdc_element import SdcElement + +@mock.patch.object(Vendor, 'send_message_json') +def test_get_all_no_vendors(mock_send): + """Returns empty array if no vendors.""" + mock_send.return_value = {} + assert Vendor.get_all() == [] + mock_send.assert_called_once_with("GET", 'get Vendors', 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-license-models') + +@mock.patch.object(Vendor, 'send_message_json') +def test_get_all_some_vendors(mock_send): + """Returns a list of vendors.""" + mock_send.return_value = {'results':[ + {'name': 'one', 'id': '1234'}, + {'name': 'two', 'id': '1235'}]} + assert len(Vendor.get_all()) == 2 + vendor_1 = Vendor.get_all()[0] + assert vendor_1.name == "one" + assert vendor_1.identifier == "1234" + assert vendor_1.created() == True + vendor_2 = Vendor.get_all()[1] + assert vendor_2.name == "two" + assert vendor_2.identifier == "1235" + assert vendor_2.created() + mock_send.assert_called_with("GET", 'get Vendors', 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-license-models') + +@mock.patch.object(Vendor, 'exists') +def test_init_no_name(mock_exists): + """Check init with no names.""" + mock_exists.return_value = False + vendor = Vendor() + assert isinstance(vendor, SdcElement) + assert vendor._identifier == None + assert vendor._version == None + assert vendor.name == "Generic-Vendor" + assert vendor.created() == False + assert vendor.headers["USER_ID"] == "cs0008" + assert isinstance(vendor._base_url(), str) + assert "sdc1/feProxy/onboarding-api/v1.0" in vendor._base_url() + +def test_init_with_name(): + """Check init with no names.""" + vendor = Vendor(name="YOLO") + assert vendor._identifier == None + assert vendor._version == None + assert vendor.name == "YOLO" + assert vendor.headers["USER_ID"] == "cs0008" + assert isinstance(vendor._base_url(), str) + assert "sdc1/feProxy/onboarding-api/v1.0" in vendor._base_url() + +def test_equality_really_equals(): + """Check two Vendors are equals if name is the same.""" + vendor_1 = Vendor(name="equal") + vendor_1.identifier = "1234" + vendor_2 = Vendor(name="equal") + vendor_2.identifier = "1235" + assert vendor_1 == vendor_2 + +def test_equality_not_equals(): + """Check two Vendors are not equals if name is not the same.""" + vendor_1 = Vendor(name="equal") + vendor_1.identifier = "1234" + vendor_2 = Vendor(name="not_equal") + vendor_2.identifier = "1234" + assert vendor_1 != vendor_2 + +def test_equality_not_equals_not_same_object(): + """Check a Vendor and something different are not equals.""" + vendor_1 = Vendor(name="equal") + vendor_1.identifier = "1234" + vendor_2 = "equal" + assert vendor_1 != vendor_2 + +@mock.patch.object(Vendor, 'get_all') +def test_exists_not_exists(mock_get_all): + """Return False if vendor doesn't exist in SDC.""" + vendor_1 = Vendor(name="one") + vendor_1.identifier = "1234" + mock_get_all.return_value = [vendor_1] + vendor = Vendor(name="two") + assert not vendor.exists() + +@mock.patch.object(Vendor, 'get_all') +def test_exists_exists(mock_get_all): + """Return True if vendor exists in SDC.""" + vendor_1 = Vendor(name="one") + vendor_1.identifier = "1234" + vendor_1.version = "1.1" + mock_get_all.return_value = [vendor_1] + vendor = Vendor(name="one") + assert vendor.exists() + +@mock.patch.object(Vendor, 'get_all') +@mock.patch.object(Vendor, 'send_message_json') +def test_load_created(mock_send, mock_get_all): + mock_send.return_value = {'results': + [{'status': 'state_one', 'id': "5678", "name": "1.0"}], "listCount": 1} + vendor = Vendor(name="one") + vendor.identifier = "1234" + vendor.load() + mock_get_all.assert_not_called() + mock_send.assert_called_once_with('GET', 'get item', 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/items/1234/versions') + assert vendor.status == "state_one" + assert vendor.version == "5678" + +@mock.patch.object(Vendor, 'get_all') +@mock.patch.object(Vendor, 'send_message_json') +def test_load_not_created(mock_send, mock_get_all): + mock_send.return_value = {'results': + [{'status': 'state_one', 'id': "5678", "name": "1.0"}], "listCount": 1} + vendor = Vendor(name="one") + vendor.load() + mock_get_all.return_value = [] + mock_send.assert_not_called() + assert vendor._status == None + assert vendor.version == None + assert vendor._identifier == None + +@mock.patch.object(Vendor, 'exists') +@mock.patch.object(Vendor, 'send_message_json') +def test_create_already_exists(mock_send, mock_exists): + """Do nothing if already created in SDC.""" + vendor = Vendor() + mock_exists.return_value = True + vendor.create() + mock_send.assert_not_called() + +@mock.patch.object(Vendor, 'exists') +@mock.patch.object(Vendor, 'send_message_json') +def test_create_issue_in_creation(mock_send, mock_exists): + """Do nothing if not created but issue during creation.""" + vendor = Vendor() + expected_data = '{\n "iconRef": "icon",\n "vendorName": "Generic-Vendor",\n "description": "vendor"\n}' + mock_exists.return_value = False + mock_send.side_effect = RequestError + with pytest.raises(RequestError) as exc: + vendor.create() + mock_send.assert_called_once_with("POST", "create Vendor", mock.ANY, data=expected_data) + assert vendor.created() == False + +@mock.patch.object(Vendor, 'exists') +@mock.patch.object(Vendor, 'send_message_json') +def test_create_OK(mock_send, mock_exists): + """Create and update object.""" + vendor = Vendor() + expected_data = '{\n "iconRef": "icon",\n "vendorName": "Generic-Vendor",\n "description": "vendor"\n}' + mock_exists.return_value = False + mock_send.return_value = { + 'itemId': "1234", + 'version': {'id': "5678", 'status': 'state_created'}} + vendor.create() + mock_send.assert_called_once_with("POST", "create Vendor", mock.ANY, data=expected_data) + assert vendor.status == const.DRAFT + assert vendor.identifier == "1234" + assert vendor.version == "5678" + +@mock.patch.object(Vendor, 'exists') +@mock.patch.object(Vendor, 'load') +@mock.patch.object(Vendor, 'send_message') +def test_submit_already_certified(mock_send, mock_load, mock_exists): + """Do nothing if already certified.""" + mock_exists.return_value = True + vendor = Vendor() + vendor._status = const.CERTIFIED + vendor.submit() + mock_send.assert_not_called() + +@mock.patch.object(Vendor, 'exists') +@mock.patch.object(Vendor, 'load') +@mock.patch.object(Vendor, 'send_message') +def test_submit_not_created(mock_send, mock_load, mock_exists): + """Do nothing if not created.""" + mock_exists.return_value = False + vendor = Vendor() + vendor.submit() + mock_send.assert_not_called() + +@mock.patch.object(Vendor, 'exists') +@mock.patch.object(Vendor, 'load') +@mock.patch.object(Vendor, 'send_message') +def test_submit_certified_NOK(mock_send, mock_load, mock_exists): + """Don't update status if submission NOK.""" + mock_exists.return_value = True + vendor = Vendor() + vendor._identifier = "12345" + mock_send.side_effect = RequestError + expected_data = '{\n\n "action": "Submit"\n}' + vendor._status = "Draft" + vendor._version = "1234" + with pytest.raises(RequestError) as err: + vendor.submit() + assert err.type == RequestError + mock_send.assert_called_once_with("PUT", "Submit Vendor", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-license-models/12345/versions/1234/actions', data=expected_data) + assert vendor._status != const.CERTIFIED + +@mock.patch.object(Vendor, 'exists') +@mock.patch.object(Vendor, 'load') +@mock.patch.object(Vendor, 'send_message') +def test_submit_certified_OK(mock_send, mock_load, mock_exists): + """Set status to CERTIFIED if submission OK.""" + mock_exists.return_value = True + vendor = Vendor() + vendor._status = "Draft" + vendor._version = "1234" + vendor.identifier = "12345" + mock_send.return_value = mock.Mock() + expected_data = '{\n\n "action": "Submit"\n}' + vendor.submit() + mock_send.assert_called_once_with("PUT", "Submit Vendor", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-license-models/12345/versions/1234/actions', data=expected_data) + assert vendor.status == const.CERTIFIED + +@mock.patch.object(Vendor, 'created') +@mock.patch.object(Vendor, 'load') +def test_version_no_load_no_created(mock_load, mock_created): + mock_created.return_value = False + vendor = Vendor() + assert vendor.version == None + mock_load.assert_not_called() + +@mock.patch.object(Vendor, 'created') +@mock.patch.object(Vendor, 'load') +def test_version_no_load_created(mock_load, mock_created): + mock_created.return_value = True + vendor = Vendor() + vendor._version = "64" + assert vendor.version == "64" + mock_load.assert_not_called() + +@mock.patch.object(Vendor, 'load') +def test_version_with_load(mock_load): + vendor = Vendor() + vendor.identifier = "12345" + assert vendor.version == None + mock_load.assert_called_once() + +@mock.patch.object(Vendor, 'created') +@mock.patch.object(Vendor, 'load') +def test_status_no_load_no_created(mock_load, mock_created): + mock_created.return_value = False + vendor = Vendor() + assert vendor.status == None + mock_load.assert_not_called() + +@mock.patch.object(Vendor, 'created') +@mock.patch.object(Vendor, 'load') +def test_status_no_load_created(mock_load, mock_created): + mock_created.return_value = True + vendor = Vendor() + vendor.identifier = "12345" + vendor._status = "Draft" + assert vendor.status == "Draft" + mock_load.assert_not_called() + +@mock.patch.object(Vendor, 'load') +def test_status_with_load(mock_load): + vendor = Vendor() + vendor.identifier = "12345" + assert vendor.status == None + mock_load.assert_called_once() + +@mock.patch.object(Vendor, 'submit') +@mock.patch.object(Vendor, 'create') +def test_onboard_new_vendor(mock_create, mock_submit): + getter_mock = mock.Mock(wraps=Vendor.status.fget) + mock_status = Vendor.status.getter(getter_mock) + with mock.patch.object(Vendor, 'status', mock_status): + getter_mock.side_effect = [None, const.CERTIFIED, const.CERTIFIED] + vendor = Vendor() + vendor.onboard() + mock_create.assert_called_once() + mock_submit.assert_not_called() + +@mock.patch.object(Vendor, 'submit') +@mock.patch.object(Vendor, 'create') +def test_onboard_created_vendor(mock_create, mock_submit): + getter_mock = mock.Mock(wraps=Vendor.status.fget) + mock_status = Vendor.status.getter(getter_mock) + with mock.patch.object(Vendor, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.DRAFT, None] + vendor = Vendor() + vendor.onboard() + mock_submit.assert_called_once() + mock_create.assert_not_called() + +@mock.patch.object(Vendor, 'submit') +@mock.patch.object(Vendor, 'create') +def test_onboard_whole_vendor(mock_create, mock_submit): + getter_mock = mock.Mock(wraps=Vendor.status.fget) + mock_status = Vendor.status.getter(getter_mock) + with mock.patch.object(Vendor, 'status', mock_status): + getter_mock.side_effect = [None, const.DRAFT, const.DRAFT, None] + vendor = Vendor() + vendor.onboard() + mock_submit.assert_called_once() + mock_create.assert_called_once() diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 0000000..589f949 --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,20 @@ +"""Test version module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import onapsdk.version as version + +def test_version(): + """Check version is the right one.""" + assert version.__version__ == '10.2.0' diff --git a/tests/test_ves.py b/tests/test_ves.py new file mode 100644 index 0000000..17d71d5 --- /dev/null +++ b/tests/test_ves.py @@ -0,0 +1,56 @@ +# Copyright 2022 Orange, Deutsche Telekom AG, Nokia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest.mock import patch +import json + +from onapsdk.ves.ves import Ves, ACTION, POST_HTTP_METHOD + +VERSION = "v7" + +VES_URL = f"http://ves.api.simpledemo.onap.org:30417/eventListener/{VERSION}" +VES_BATCH_URL = f"http://ves.api.simpledemo.onap.org:30417/eventListener/{VERSION}/eventBatch" + +TEST_EVENT = '{"event": {"test": "val"}}' +BASIC_AUTH = {'username': 'dcae@dcae.onap.org', 'password': 'demo123456!'} + + +@patch.object(Ves, "send_message") +def test_should_send_event_to_ves_service(send_message_mock): + # given + + # when + Ves.send_event(VERSION, TEST_EVENT, BASIC_AUTH) + + # then + verify_that_event_was_send_to_ves(TEST_EVENT, send_message_mock, VES_URL) + + +@patch.object(Ves, "send_message") +def test_should_send_event_batch_to_ves_service(send_message_mock): + # given + + # when + Ves.send_batch_event(VERSION, TEST_EVENT, BASIC_AUTH) + + # then + verify_that_event_was_send_to_ves(TEST_EVENT, send_message_mock, VES_BATCH_URL) + + +def verify_that_event_was_send_to_ves(expected_event, send_message_mock, ves_url): + send_message_mock.assert_called_once_with( + POST_HTTP_METHOD, ACTION, ves_url, + basic_auth=BASIC_AUTH, + json=json.loads(expected_event) + ) + send_message_mock.return_value = None diff --git a/tests/test_vf.py b/tests/test_vf.py new file mode 100644 index 0000000..540a377 --- /dev/null +++ b/tests/test_vf.py @@ -0,0 +1,564 @@ +"""Test vf module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import time +from unittest import mock +from unittest.mock import MagicMock +from pathlib import Path + +import pytest + +import onapsdk.constants as const +from onapsdk.exceptions import ParameterError, StatusError, RequestError, ValidationError +from onapsdk.sdc.category_management import ResourceCategory +from onapsdk.sdc.properties import ComponentProperty, NestedInput, Property +from onapsdk.sdc.sdc_resource import SdcResource +from onapsdk.sdc.vf import Vf +from onapsdk.sdc.vsp import Vsp +from onapsdk.sdc.vsp import Vendor + + +@mock.patch.object(Vf, 'send_message_json') +def test_get_all_no_vf(mock_send): + """Returns empty array if no vfs.""" + mock_send.return_value = {} + assert Vf.get_all() == [] + mock_send.assert_called_once_with("GET", 'get Vfs', 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/resources?resourceType=VF') + + +@mock.patch.object(Vf, 'send_message_json') +def test_get_all_some_vfs(mock_send): + """Returns a list of vf.""" + mock_send.return_value = [ + {'resourceType': 'VF', 'name': 'one', 'uuid': '1234', 'invariantUUID': '5678', 'version': '1.0', 'lifecycleState': 'CERTIFIED', 'category': 'Generic', "subCategory": "Abstract"}, + {'resourceType': 'VF', 'name': 'two', 'uuid': '1235', 'invariantUUID': '5679', 'version': '1.0', 'lifecycleState': 'NOT_CERTIFIED_CHECKOUT', 'category': 'Generic', "subCategory": "Abstract"}] + all_vfs = Vf.get_all() + assert len(all_vfs) == 2 + vf_1 = all_vfs[0] + assert vf_1.name == "one" + assert vf_1.identifier == "1234" + assert vf_1.unique_uuid == "5678" + assert vf_1.version == "1.0" + assert vf_1.status == const.CERTIFIED + assert vf_1.created() + vf_2 = all_vfs[1] + assert vf_2.name == "two" + assert vf_2.identifier == "1235" + assert vf_2.unique_uuid == "5679" + assert vf_2.status == const.DRAFT + assert vf_2.version == "1.0" + assert vf_2.created() + mock_send.assert_called_once_with("GET", 'get Vfs', 'https://sdc.api.be.simpledemo.onap.org:30204/sdc/v1/catalog/resources?resourceType=VF') + + +def test_init_no_name(): + """Check init with no names.""" + vf = Vf() + assert isinstance(vf, SdcResource) + assert vf._identifier is None + assert vf._version is None + assert vf.name == "ONAP-test-VF" + assert vf.headers["USER_ID"] == "cs0008" + assert vf.vsp is None + assert isinstance(vf._base_url(), str) + +@mock.patch.object(Vf, 'exists') +def test_init_with_name(mock_exists): + """Check init with no names.""" + mock_exists.return_value = False + vf = Vf(name="YOLO") + assert vf._identifier == None + assert vf._version == None + assert vf.name == "YOLO" + assert vf.created() == False + assert vf.headers["USER_ID"] == "cs0008" + assert vf.vsp == None + assert isinstance(vf._base_url(), str) + + +def test_equality_really_equals(): + """Check two vfs are equals if name is the same.""" + vf_1 = Vf(name="equal") + vf_1.identifier = "1234" + vf_2 = Vf(name="equal") + vf_2.identifier = "1235" + assert vf_1 == vf_2 + + +def test_equality_not_equals(): + """Check two vfs are not equals if name is not the same.""" + vf_1 = Vf(name="equal") + vf_1.identifier = "1234" + vf_2 = Vf(name="not_equal") + vf_2.identifier = "1234" + assert vf_1 != vf_2 + + +def test_equality_not_equals_not_same_object(): + """Check a vf and something different are not equals.""" + vf_1 = Vf(name="equal") + vf_1.identifier = "1234" + vf_2 = SdcResource() + vf_2.name = "equal" + assert vf_1 != vf_2 + + +@mock.patch.object(Vf, 'get_all') +def test_exists_not_exists(mock_get_all): + """Return False if vf doesn't exist in SDC.""" + vf_1 = Vf(name="one") + vf_1.identifier = "1234" + mock_get_all.return_value = [vf_1] + vf = Vf(name="two") + assert not vf.exists() + + +@mock.patch.object(Vf, 'get_all') +def test_exists_exists(mock_get_all): + """Return True if vf exists in SDC.""" + vf_1 = Vf(name="one") + vf_1.identifier = "1234" + vf_1.unique_uuid = "5689" + vf_1.unique_identifier = "71011" + vf_1.status = const.DRAFT + vf_1.version = "1.1" + mock_get_all.return_value = [vf_1] + vf = Vf(name="one") + assert vf.exists() + assert vf.identifier == "1234" + assert vf.unique_uuid == "5689" + assert vf.unique_identifier == "71011" + assert vf.status == const.DRAFT + assert vf.version == "1.1" + + +@mock.patch.object(Vf, 'exists') +def test_load_created(mock_exists): + """Load is a wrapper around exists().""" + vf = Vf(name="one") + vf.load() + mock_exists.assert_called_once() + + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'send_message_json') +def test_create_no_vsp(mock_send, mock_exists): + """Do nothing if no vsp.""" + vf = Vf() + mock_exists.return_value = False + with pytest.raises(ParameterError) as err: + vf.create() + assert err.type == ParameterError + assert str(err.value) == "At least vsp or vendor needs to be given" + + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'send_message_json') +@mock.patch.object(Vf, "category", new_callable=mock.PropertyMock) +def test_create_already_exists(mock_category, mock_send, mock_exists): + """Do nothing if already created in SDC.""" + vf = Vf(vendor=MagicMock()) + vsp = Vsp() + vsp._identifier = "1232" + vf.vsp = vsp + mock_exists.return_value = True + vf.create() + mock_send.assert_not_called() + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'send_message_json') +@mock.patch.object(Vf, "category", new_callable=mock.PropertyMock) +def test_create_issue_in_creation(mock_category, mock_send, mock_exists): + """Do nothing if not created but issue during creation.""" + vf = Vf() + vsp = Vsp() + vendor = Vendor() + vsp._identifier = "1232" + vsp.create_csar = MagicMock(return_value=True) + vsp.vendor = vendor + vf.vsp = vsp + expected_data = '{\n "artifacts": {},\n "attributes": [],\n "capabilities": {},\n "categories": [\n {\n "normalizedName": "generic",\n "name": "Generic",\n "uniqueId": "resourceNewCategory.generic",\n "subcategories": [{"empty": false, "groupings": null, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": null, "type": null, "uniqueId": "resourceNewCategory.generic.abstract", "version": null}],\n "version": null,\n "ownerId": null,\n "empty": false,\n "type": null,\n "icons": null\n }\n ],\n "componentInstances": [],\n "componentInstancesAttributes": {},\n "componentInstancesProperties": {},\n "componentType": "RESOURCE",\n "contactId": "cs0008",\n \n "csarUUID": "None",\n "csarVersion": "1.0",\n \n "deploymentArtifacts": {},\n "description": "VF",\n "icon": "defaulticon",\n "name": "ONAP-test-VF",\n "properties": [],\n "groups": [],\n "requirements": {},\n "resourceType": "VF",\n "tags": ["ONAP-test-VF"],\n "toscaArtifacts": {},\n "vendorName": "Generic-Vendor",\n "vendorRelease": "1.0"\n}' + mock_exists.return_value = False + mock_send.side_effect = RequestError + rc = ResourceCategory( + name="Generic" + ) + rc.normalized_name="generic" + rc.unique_id="resourceNewCategory.generic" + rc.subcategories=[{"empty": False, "groupings": None, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": None, "type": None, "uniqueId": "resourceNewCategory.generic.abstract", "version": None}] + rc.version=None + rc.owner_id=None + rc.empty=False + rc.type=None + rc.icons=None + mock_category.return_value = rc + with pytest.raises(RequestError) as exc: + vf.create() + mock_send.assert_called_once_with("POST", "create Vf", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources', data=expected_data) + assert not vf.created() + + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'send_message_json') +@mock.patch.object(Vf, "category", new_callable=mock.PropertyMock) +def test_create_OK(mock_category, mock_send, mock_exists): + """Create and update object.""" + vf = Vf() + vsp = Vsp() + vendor = Vendor() + vsp._identifier = "1232" + vf.vsp = vsp + vsp.vendor = vendor + vsp._csar_uuid = "1234" + expected_data = '{\n "artifacts": {},\n "attributes": [],\n "capabilities": {},\n "categories": [\n {\n "normalizedName": "generic",\n "name": "Generic",\n "uniqueId": "resourceNewCategory.generic",\n "subcategories": [{"empty": false, "groupings": null, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": null, "type": null, "uniqueId": "resourceNewCategory.generic.abstract", "version": null}],\n "version": null,\n "ownerId": null,\n "empty": false,\n "type": null,\n "icons": null\n }\n ],\n "componentInstances": [],\n "componentInstancesAttributes": {},\n "componentInstancesProperties": {},\n "componentType": "RESOURCE",\n "contactId": "cs0008",\n \n "csarUUID": "1234",\n "csarVersion": "1.0",\n \n "deploymentArtifacts": {},\n "description": "VF",\n "icon": "defaulticon",\n "name": "ONAP-test-VF",\n "properties": [],\n "groups": [],\n "requirements": {},\n "resourceType": "VF",\n "tags": ["ONAP-test-VF"],\n "toscaArtifacts": {},\n "vendorName": "Generic-Vendor",\n "vendorRelease": "1.0"\n}' + mock_exists.return_value = False + mock_send.return_value = {'resourceType': 'VF', 'name': 'one', 'uuid': '1234', 'invariantUUID': '5678', 'version': '1.0', 'uniqueId': '91011', 'lifecycleState': 'NOT_CERTIFIED_CHECKOUT'} + rc = ResourceCategory( + name="Generic" + ) + rc.normalized_name="generic" + rc.unique_id="resourceNewCategory.generic" + rc.subcategories=[{"empty": False, "groupings": None, "icons": ["objectStorage", "compute"], "name": "Abstract", "normalizedName": "abstract", "ownerId": None, "type": None, "uniqueId": "resourceNewCategory.generic.abstract", "version": None}] + rc.version=None + rc.owner_id=None + rc.empty=False + rc.type=None + rc.icons=None + mock_category.return_value = rc + vf.create() + mock_send.assert_called_once_with("POST", "create Vf", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources', data=expected_data) + assert vf.created() + assert vf._status == const.DRAFT + assert vf.identifier == "1234" + assert vf.unique_uuid == "5678" + assert vf.version == "1.0" + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'load') +def test_version_no_load_no_created(mock_load, mock_exists): + """Test versions when not created.""" + mock_exists.return_value = False + vf = Vf() + assert vf.version is None + mock_load.assert_not_called() + +@mock.patch.object(Vf, 'load') +def test_version_no_load_created(mock_load): + """Test versions when created.""" + vf = Vf() + vf.identifier = "1234" + vf._version = "64" + assert vf.version == "64" + mock_load.assert_not_called() + + +@mock.patch.object(Vf, 'load') +def test_version_with_load(mock_load): + """Test versions when not created but with identifier.""" + vf = Vf() + vf.identifier = "1234" + assert vf.version is None + mock_load.assert_called_once() + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'load') +def test_status_no_load_no_created(mock_load, mock_exists): + """Test status when not created.""" + mock_exists.return_value = False + vf = Vf() + assert vf.status is None + + +@pytest.mark.parametrize("status", [const.COMMITED, const.CERTIFIED, const.UPLOADED, const.VALIDATED]) +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'send_message') +def test_submit_not_Commited(mock_send, mock_load, mock_exists, status): + """Do nothing if not created.""" + mock_exists.return_value = False + vf = Vf() + vf._status = status + vf.submit() + mock_send.assert_not_called() + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'send_message') +def test_submit_OK(mock_send, mock_load, mock_exists): + """Don't update status if submission NOK.""" + mock_exists.return_value = True + vf = Vf() + vf._status = const.COMMITED + expected_data = '{\n "userRemarks": "certify"\n}' + vf._version = "1234" + vf._unique_identifier = "12345" + vf.submit() + mock_send.assert_called_once_with( + "POST", "Certify Vf", + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources/12345/lifecycleState/Certify', + data=expected_data) + +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'certify') +@mock.patch.object(Vf, 'submit') +@mock.patch.object(Vf, 'create') +@mock.patch.object(Vf, 'add_resource') +def test_onboard_new_vf(mock_add_resource, mock_create, mock_submit, mock_certify, mock_load): + getter_mock = mock.Mock(wraps=Vf.status.fget) + mock_status = Vf.status.getter(getter_mock) + with mock.patch.object(Vf, 'status', mock_status): + getter_mock.side_effect = [None, const.APPROVED, const.APPROVED, + const.APPROVED, const.APPROVED] + vsp = Vsp() + vf = Vf(vsp=vsp) + vf._time_wait = 0 + vf.onboard() + mock_create.assert_called_once() + mock_add_resource.assert_not_called() + mock_submit.assert_not_called() + mock_certify.assert_not_called() + mock_load.assert_not_called() + +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'submit') +@mock.patch.object(Vf, 'create') +@mock.patch.object(Vf, 'add_resource') +@mock.patch.object(Vf, "certify") +def test_onboard_vf_submit(mock_certify, mock_add_resource, mock_create, mock_submit, mock_load): + getter_mock = mock.Mock(wraps=Vf.status.fget) + mock_status = Vf.status.getter(getter_mock) + with mock.patch.object(Vf, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.DRAFT, + const.CHECKED_IN, const.CHECKED_IN, const.CHECKED_IN, + const.APPROVED, const.APPROVED, const.APPROVED, const.APPROVED] + vf = Vf() + vf._time_wait = 0 + vf.onboard() + mock_create.assert_not_called() + mock_add_resource.assert_not_called() + mock_submit.assert_called_once() + mock_load.assert_not_called() + mock_certify.assert_called_once() + +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'submit') +@mock.patch.object(Vf, 'create') +@mock.patch.object(Vf, 'add_resource') +@mock.patch.object(Vf, "certify") +def test_onboard_vf_load(mock_certify, mock_add_resource, mock_create, mock_submit, mock_load): + getter_mock = mock.Mock(wraps=Vf.status.fget) + mock_status = Vf.status.getter(getter_mock) + with mock.patch.object(Vf, 'status', mock_status): + getter_mock.side_effect = [const.CERTIFIED, const.CERTIFIED, + const.CERTIFIED, const.CERTIFIED, + const.APPROVED, const.APPROVED, + const.APPROVED, const.APPROVED] + vf = Vf() + vf._time_wait = 0 + vf.onboard() + mock_create.assert_not_called() + mock_add_resource.assert_not_called() + mock_submit.assert_not_called() + mock_load.assert_called_once() + mock_certify.assert_not_called() + +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'submit') +@mock.patch.object(Vf, 'create') +@mock.patch.object(Vf, 'add_resource') +@mock.patch.object(Vf, "certify") +def test_onboard_whole_vf(mock_certify, mock_add_resource, mock_create, mock_submit, mock_load): + getter_mock = mock.Mock(wraps=Vf.status.fget) + mock_status = Vf.status.getter(getter_mock) + with mock.patch.object(Vf, 'status', mock_status): + getter_mock.side_effect = [None, const.DRAFT, const.DRAFT, + const.CHECKED_IN, const.CHECKED_IN, const.CHECKED_IN, + const.CERTIFIED, const.CERTIFIED, const.CERTIFIED, const.CERTIFIED, + const.APPROVED, const.APPROVED, const.APPROVED, const.APPROVED] + vsp = Vsp() + vf = Vf(vsp=vsp) + vf._time_wait = 0 + vf.onboard() + mock_create.assert_called_once() + mock_add_resource.assert_not_called() + mock_submit.assert_called_once() + mock_load.assert_called_once() + mock_certify.assert_called_once() + + +@mock.patch.object(Vf, "send_message_json") +def test_add_properties(mock_send_message_json): + vf = Vf(name="test") + vf._identifier = "toto" + vf._unique_identifier = "toto" + vf._status = const.CERTIFIED + with pytest.raises(StatusError): + vf.add_property(Property(name="test", property_type="string")) + vf._status = const.DRAFT + vf.add_property(Property(name="test", property_type="string")) + mock_send_message_json.assert_called_once() + +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'send_message') +def test_add_artifact_to_vf(mock_send_message, mock_load): + """Test VF add artifact""" + vf = Vf(name="test") + vf.status = const.DRAFT + mycbapath = Path(Path(__file__).resolve().parent, "data/vLB_CBA_Python.zip") + + result = vf.add_deployment_artifact(artifact_label="cba", + artifact_type="CONTROLLER_BLUEPRINT_ARCHIVE", + artifact_name="vLB_CBA_Python.zip", + artifact=mycbapath) + mock_send_message.assert_called() + method, description, url = mock_send_message.call_args[0] + assert method == "POST" + assert description == "Add deployment artifact for test sdc resource" + assert url == ("https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources/" + f"{vf.unique_identifier}/artifacts") + + +@mock.patch.object(Vf, "created") +@mock.patch.object(ResourceCategory, "get") +def test_vf_category(mock_resource_category, mock_created): + mock_created.return_value = False + vf = Vf(name="test") + _ = vf.category + mock_resource_category.assert_called_once_with(name="Generic", subcategory="Abstract") + mock_resource_category.reset_mock() + + vf = Vf(name="test", category="Allotted Resource", subcategory="Allotted Resource") + _ = vf.category + mock_resource_category.assert_called_once_with(name="Allotted Resource", subcategory="Allotted Resource") + mock_resource_category.reset_mock() + + vf = Vf(name="test", category="test", subcategory="test") + _ = vf.category + mock_resource_category.assert_called_once_with(name="test", subcategory="test") + mock_resource_category.reset_mock() + + mock_created.return_value = True + _ = vf.category + mock_resource_category.assert_called_once_with(name="test", subcategory="test") + +@mock.patch.object(Vf, "send_message_json") +def test_update_vsp(mock_send): + + vf = Vf(name="test") + vf._unique_identifier = "123" + vsp = MagicMock() + vsp.csar_uuid = "122333" + vsp.human_readable_version = "1.0" + mock_send.return_value = { + "csarUUID": "322111", + "csarVersion": "0.1", + "tags": [], + "categories": [], + "allVersions": [], + "archived": False, + "creationDate": int(time.time()), + "lastUpdateDate": int(time.time()), + } + vf.update_vsp(vsp) + assert mock_send.call_count == 2 + mock_call_kwargs_data = json.loads(mock_send.mock_calls[-1][2]["data"]) # Get kward from `unittest.mock.call` tuple + assert mock_call_kwargs_data["csarUUID"] == "122333" + assert mock_call_kwargs_data["csarVersion"] == "1.0" + +@mock.patch.object(Vf, 'exists') +@mock.patch.object(Vf, 'send_message') +def test_add_resource_not_draft(mock_send, mock_exists): + mock_exists.return_value = False + vf = Vf() + resource = SdcResource() + with pytest.raises(StatusError): + vf.add_resource(resource) + mock_send.assert_not_called() + +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'send_message') +def test_add_resource_bad_result(mock_send, mock_load): + vf = Vf() + vf.unique_identifier = "45" + vf.identifier = "93" + vf.status = const.DRAFT + mock_send.return_value = {} + resource = SdcResource() + resource.unique_identifier = "12" + resource.created = MagicMock(return_value=True) + resource.version = "40" + resource.name = "test" + assert vf.add_resource(resource) is None + mock_send.assert_called_once_with( + 'POST', 'Add SDCRESOURCE to VF', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources/45/resourceInstance', + data='{\n "name": "test",\n "componentVersion": "40",\n "posY": 100,\n "posX": 200,\n "uniqueId": "12",\n "originType": "SDCRESOURCE",\n "componentUid": "12",\n "icon": "defaulticon"\n}') + +@mock.patch.object(Vf, 'load') +@mock.patch.object(Vf, 'send_message') +def test_add_resource_OK(mock_send, mock_load): + vf = Vf() + vf.unique_identifier = "45" + vf.identifier = "93" + vf.status = const.DRAFT + mock_send.return_value = {'yes': 'indeed'} + resource = SdcResource() + resource.unique_identifier = "12" + resource.created = MagicMock(return_value=True) + resource.version = "40" + resource.name = "test" + result = vf.add_resource(resource) + assert result['yes'] == "indeed" + mock_send.assert_called_once_with( + 'POST', 'Add SDCRESOURCE to VF', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/rest/v1/catalog/resources/45/resourceInstance', + data='{\n "name": "test",\n "componentVersion": "40",\n "posY": 100,\n "posX": 200,\n "uniqueId": "12",\n "originType": "SDCRESOURCE",\n "componentUid": "12",\n "icon": "defaulticon"\n}') + +@mock.patch.object(Vf, 'created') +@mock.patch.object(Vf, "send_message_json") +@mock.patch.object(Vf, "resource_inputs_url") +def test_vf_vendor_property(mock_resource_inputs_url, mock_send_message_json, mock_created): + mock_created.return_value = False + vf = Vf() + assert vf.vendor is None + + vsp_mock = MagicMock() + vsp_mock.vendor = MagicMock() + vf.vsp = vsp_mock + assert vf.vendor == vsp_mock.vendor + + vf._vendor = None + mock_created.return_value = True + mock_send_message_json.return_value = {"vendorName": "123"} + assert vf.vendor.name == "123" + +@mock.patch.object(SdcResource, "declare_input") +@mock.patch.object(Vf, "send_message") +def test_vf_declare_input(mock_send_message, mock_sdc_resource_declare_input): + vf = Vf() + prop = Property(name="test_prop", property_type="string") + nested_input = NestedInput(MagicMock(), MagicMock()) + vf.declare_input(prop) + mock_sdc_resource_declare_input.assert_called_once() + mock_send_message.assert_not_called() + mock_sdc_resource_declare_input.reset_mock() + vf.declare_input(nested_input) + mock_sdc_resource_declare_input.assert_called_once() + mock_send_message.assert_not_called() + mock_sdc_resource_declare_input.reset_mock() + vf.declare_input(ComponentProperty("test_unique_id", "test_property_type", "test_name", MagicMock())) + mock_send_message.assert_called() + mock_sdc_resource_declare_input.assert_not_called() diff --git a/tests/test_vid.py b/tests/test_vid.py new file mode 100644 index 0000000..47281ba --- /dev/null +++ b/tests/test_vid.py @@ -0,0 +1,54 @@ +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest.mock import patch + +from onapsdk.vid import ( + OwningEntity, + Project, + LineOfBusiness, + Platform +) + + +@patch.object(LineOfBusiness, "send_message") +def test_line_of_business(send_message_mock): + assert LineOfBusiness.get_create_url() == "https://vid.api.simpledemo.onap.org:30200/vid/maintenance/category_parameter/lineOfBusiness" + + line_of_businnes = LineOfBusiness.create("test") + assert line_of_businnes.name == "test" + + +@patch.object(OwningEntity, "send_message") +def test_owning_entity(send_message_mock): + assert OwningEntity.get_create_url() == "https://vid.api.simpledemo.onap.org:30200/vid/maintenance/category_parameter/owningEntity" + + owning_entity = OwningEntity.create("test") + assert owning_entity.name == "test" + + +@patch.object(Project, "send_message") +def test_project(send_message_mock): + assert Project.get_create_url() == "https://vid.api.simpledemo.onap.org:30200/vid/maintenance/category_parameter/project" + + project = Project.create("test") + assert project.name == "test" + + +@patch.object(Platform, "send_message") +def test_platform(send_message_mock): + assert Platform.get_create_url() == "https://vid.api.simpledemo.onap.org:30200/vid/maintenance/category_parameter/platform" + + platform = Platform.create("test") + assert platform.name == "test" diff --git a/tests/test_vsp.py b/tests/test_vsp.py new file mode 100644 index 0000000..a1aa8a7 --- /dev/null +++ b/tests/test_vsp.py @@ -0,0 +1,799 @@ +"""Test vsp module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock +import json + +import pytest +import requests +from onapsdk.exceptions import APIError, ParameterError, RequestError + +from onapsdk.sdc.vsp import Vsp +from onapsdk.sdc.vendor import Vendor +import onapsdk.constants as const +from onapsdk.sdc.sdc_element import SdcElement + +@mock.patch.object(Vsp, 'send_message_json') +def test_get_all_no_vsp(mock_send): + """Returns empty array if no vsps.""" + mock_send.return_value = {} + assert Vsp.get_all() == [] + mock_send.assert_called_once_with( + "GET", 'get Vsps', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products') + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message_json') +def test_get_all_some_vsps(mock_send, mock_load_status): + """Returns a list of vsp.""" + mock_send.return_value = {'results':[ + {'name': 'one', 'id': '1234', 'vendorName': 'vspOne'}, + {'name': 'two', 'id': '1235', 'vendorName': 'vspOne'}]} + assert len(Vsp.get_all()) == 2 + vsp_1 = Vsp.get_all()[0] + assert vsp_1.name == "one" + assert vsp_1.identifier == "1234" + assert vsp_1.created() + vsp_2 = Vsp.get_all()[1] + assert vsp_2.name == "two" + assert vsp_2.identifier == "1235" + assert vsp_2.vendor == vsp_1.vendor + assert vsp_2.created() + mock_send.assert_called_with( + "GET", 'get Vsps', + 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products') + +@mock.patch.object(Vsp, 'created') +def test_init_no_name(mock_created): + """Check init with no names.""" + mock_created.return_value = False + vsp = Vsp() + assert isinstance(vsp, SdcElement) + assert vsp._identifier == None + assert vsp._version == None + assert vsp.name == "ONAP-test-VSP" + assert vsp.headers["USER_ID"] == "cs0008" + assert vsp.vendor == None + assert isinstance(vsp._base_url(), str) + assert "sdc1/feProxy/onboarding-api/v1.0" in vsp._base_url() + +@mock.patch.object(Vsp, 'exists') +def test_init_with_name(mock_exists): + """Check init with no names.""" + vsp = Vsp(name="YOLO") + mock_exists.return_value = False + assert vsp._identifier == None + assert vsp._version == None + assert vsp.name == "YOLO" + assert vsp.created() == False + assert vsp.headers["USER_ID"] == "cs0008" + assert vsp.vendor == None + assert isinstance(vsp._base_url(), str) + assert "sdc1/feProxy/onboarding-api/v1.0" in vsp._base_url() + +def test_equality_really_equals(): + """Check two vsps are equals if name is the same.""" + vsp_1 = Vsp(name="equal") + vsp_1.identifier = "1234" + vsp_2 = Vsp(name="equal") + vsp_2.identifier = "1235" + assert vsp_1 == vsp_2 + +def test_equality_not_equals(): + """Check two vsps are not equals if name is not the same.""" + vsp_1 = Vsp(name="equal") + vsp_1.identifier = "1234" + vsp_2 = Vsp(name="not_equal") + vsp_2.identifier = "1234" + assert vsp_1 != vsp_2 + +def test_equality_not_equals_not_same_object(): + """Check a vsp and something different are not equals.""" + vsp_1 = Vsp(name="equal") + vsp_1.identifier = "1234" + vsp_2 = Vendor(name="equal") + assert vsp_1 != vsp_2 + +@mock.patch.object(Vsp, 'get_all') +def test_exists_not_exists(mock_get_all): + """Return False if vsp doesn't exist in SDC.""" + vsp_1 = Vsp(name="one") + vsp_1.identifier = "1234" + mock_get_all.return_value = [vsp_1] + vsp = Vsp(name="two") + assert not vsp.exists() + +@mock.patch.object(Vsp, 'get_all') +def test_exists_exists(mock_get_all): + """Return True if vsp exists in SDC.""" + vsp_1 = Vsp(name="one") + vsp_1.identifier = "1234" + vsp_1.version = "1.1" + mock_get_all.return_value = [vsp_1] + vsp = Vsp(name="one") + assert vsp.exists() + +@mock.patch.object(Vsp, 'get_all') +@mock.patch.object(Vsp, 'send_message_json') +def test_load_created(mock_send, mock_get_all): + mock_send.return_value = {'results': + [{'status': 'state_one', 'id': "5678", 'vendorName': 'vspOne', 'name': "1.0"}], "listCount": 1} + vsp = Vsp(name="one") + vsp.identifier = "1234" + vsp.load() + mock_get_all.assert_not_called() + mock_send.assert_called_once_with('GET', 'get item', 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/items/1234/versions') + assert vsp._status == None + assert vsp.version == "5678" + +@mock.patch.object(Vsp, 'get_all') +@mock.patch.object(Vsp, 'send_message_json') +def test_load_not_created(mock_send, mock_get_all): + mock_send.return_value = {'results': + [{'status': 'state_one', 'id': "5678", 'vendorName': 'vspOne', 'name': "1.0"}], "listCount": 1} + vsp = Vsp(name="one") + vsp.load() + mock_get_all.return_value = [] + mock_send.assert_not_called() + assert vsp._status == None + assert vsp.version == None + assert vsp.identifier == None + +@mock.patch.object(Vsp, 'exists') +@mock.patch.object(Vsp, 'send_message_json') +def test_create_no_vendor(mock_send, mock_exists): + """Do nothing if no vendor.""" + vsp = Vsp() + mock_exists.return_value = False + vsp.create() + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'exists') +@mock.patch.object(Vsp, 'send_message_json') +def test_create_already_exists(mock_send, mock_exists): + """Do nothing if already created in SDC.""" + vsp = Vsp() + vendor = Vendor() + vendor._identifier = "1232" + vsp.vendor = vendor + mock_exists.return_value = True + vsp.create() + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'exists') +@mock.patch.object(Vsp, 'send_message_json') +def test_create_issue_in_creation(mock_send, mock_exists): + """Do nothing if not created but issue during creation.""" + vsp = Vsp() + vendor = Vendor() + vendor._identifier = "1232" + vsp.vendor = vendor + expected_data = '{\n "name": "ONAP-test-VSP",\n "description": "vendor software product",\n "icon": "icon",\n "category": "resourceNewCategory.generic",\n "subCategory": "resourceNewCategory.generic.abstract",\n "vendorName": "Generic-Vendor",\n "vendorId": "1232",\n "licensingData": {},\n "onboardingMethod": "NetworkPackage"\n}' + mock_exists.return_value = False + mock_send.side_effect = RequestError + with pytest.raises(RequestError) as exc: + vsp.create() + mock_send.assert_called_once_with("POST", "create Vsp", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products', data=expected_data) + assert vsp.created() == False + +@mock.patch.object(Vsp, 'exists') +@mock.patch.object(Vsp, 'send_message_json') +def test_create_OK(mock_send, mock_exists): + """Create and update object.""" + vsp = Vsp() + vendor = Vendor() + vendor._identifier = "1232" + vsp.vendor = vendor + expected_data = '{\n "name": "ONAP-test-VSP",\n "description": "vendor software product",\n "icon": "icon",\n "category": "resourceNewCategory.generic",\n "subCategory": "resourceNewCategory.generic.abstract",\n "vendorName": "Generic-Vendor",\n "vendorId": "1232",\n "licensingData": {},\n "onboardingMethod": "NetworkPackage"\n}' + mock_exists.return_value = False + mock_send.return_value = { + 'itemId': "1234", + 'version': {'id': "5678", 'status': 'state_created'}} + vsp.create() + mock_send.assert_called_once_with("POST", "create Vsp", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products', data=expected_data) + assert vsp.created() == True + assert vsp._status == const.DRAFT + assert vsp.identifier == "1234" + assert vsp.version == "5678" + +@mock.patch.object(Vsp, 'exists') +@mock.patch.object(Vsp, 'load') +def test_version_no_load_no_created(mock_load, mock_exists): + mock_exists.return_value = False + vsp = Vsp() + assert vsp.version == None + mock_load.assert_not_called() + +@mock.patch.object(Vsp, 'load') +def test_version_no_load_created(mock_load): + vsp = Vsp() + vsp.identifier = "1234" + vsp._version = "64" + assert vsp.version == "64" + mock_load.assert_not_called() + +@mock.patch.object(Vsp, 'load') +def test_version_with_load(mock_load): + vsp = Vsp() + vsp.identifier = "1234" + assert vsp.version == None + mock_load.assert_called_once() + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, 'created') +def test_vendor_not_created_not_vendor(mock_created, mock_details): + mock_created.return_value = False + vsp = Vsp() + assert vsp.vendor == None + mock_details.assert_not_called() + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, 'created') +def test_vendor_not_created_vendor(mock_created, mock_details): + mock_created.return_value = False + vsp = Vsp() + vendor = Vendor() + vsp.vendor = vendor + assert vsp.vendor == vendor + mock_details.assert_not_called() + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, 'created') +def test_vendor_created_not_details(mock_created, mock_details): + mock_created.return_value = True + mock_details.return_value = {} + vsp = Vsp() + assert vsp.vendor == None + mock_details.assert_called_once() + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, 'created') +def test_vendor_created_details(mock_created, mock_details): + mock_created.return_value = True + mock_details.return_value = {'vendorName': 'test'} + vsp = Vsp() + assert vsp.vendor.name == 'test' + mock_details.assert_called_once() + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, 'created') +def test_vendor_created_but_already_vendor(mock_created, mock_details): + mock_created.return_value = True + vsp = Vsp() + vendor = Vendor() + vsp.vendor = vendor + assert vsp.vendor == vendor + mock_details.assert_not_called() + +@mock.patch.object(Vsp, 'exists') +def test_status_no_load_no_created(mock_exists): + mock_exists.return_value = False + vsp = Vsp() + assert vsp.status == None + +@mock.patch.object(Vsp, '_get_item_details') +def test_status_status_is_certified_in_SDC(mock_vsp_items): + vsp = Vsp() + vsp.identifier = "1234" + mock_vsp_items.return_value={'status': const.CERTIFIED} + vsp._status = "Draft" + assert vsp.status == const.CERTIFIED + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, '_get_item_version_details') +@mock.patch.object(Vsp, '_get_item_details') +def test_status_version_is_not_dirty(mock_vsp_items, mock_vsp_items_version, mock_vsp_details): + vsp = Vsp() + vsp.identifier = "1234" + mock_vsp_items.return_value={'status': const.DRAFT} + mock_vsp_items_version.return_value={"state": {'dirty': False}} + mock_vsp_details.return_value={'validationData': "true"} + assert vsp.status == const.COMMITED + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, '_get_item_version_details') +@mock.patch.object(Vsp, '_get_item_details') +def test_status_version_is_dirty_has_validation_data(mock_vsp_items, mock_vsp_items_version, + mock_vsp_details): + vsp = Vsp() + vsp.identifier = "1234" + mock_vsp_items.return_value={'status': const.DRAFT} + mock_vsp_items_version.return_value={"state": {'dirty': True}} + mock_vsp_details.return_value={'validationData': {'some': 'thing'}} + assert vsp.status == const.VALIDATED + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, '_get_item_version_details') +@mock.patch.object(Vsp, '_get_item_details') +def test_status_version_is_dirty_no_validation_data_no_state(mock_vsp_items, mock_vsp_items_version, + mock_vsp_details): + vsp = Vsp() + vsp.identifier = "1234" + mock_vsp_items.return_value={'status': const.DRAFT} + mock_vsp_items_version.return_value={"status": {'dirty': False}} + mock_vsp_details.return_value={'no_validationData': {'some': 'thing'}} + assert vsp.status == const.DRAFT + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, '_get_item_version_details') +@mock.patch.object(Vsp, '_get_item_details') +def test_status_version_is_dirty_no_validation_data_but_state(mock_vsp_items, mock_vsp_items_version, + mock_vsp_details): + vsp = Vsp() + vsp.identifier = "1234" + mock_vsp_items.return_value={'status': const.DRAFT} + mock_vsp_items_version.return_value={"state": {'dirty': True}} + mock_vsp_details.return_value={'no_validationData': {'some': 'thing'}} + assert vsp.status == const.DRAFT + +@mock.patch.object(Vsp, '_get_vsp_details') +@mock.patch.object(Vsp, '_get_item_version_details') +@mock.patch.object(Vsp, '_get_item_details') +def test_status_version_is_dirty_no_validation_data_but_networkPackageName(mock_vsp_items, mock_vsp_items_version, + mock_vsp_details): + vsp = Vsp() + vsp.identifier = "1234" + mock_vsp_items.return_value={'status': const.DRAFT} + mock_vsp_items_version.return_value={"state": {'dirty': True}} + mock_vsp_details.return_value={'no_validationData': {'some': 'thing'}, 'networkPackageName': 'ubuntu16'} + assert vsp.status == const.UPLOADED + + +@mock.patch.object(Vsp, 'exists') +@mock.patch.object(Vsp, 'send_message_json') +def test__get_vsp_details_not_created(mock_send, mock_exists): + mock_exists.return_value = False + vsp = Vsp() + assert vsp._get_vsp_details() == {} + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'load') +@mock.patch.object(Vsp, 'send_message_json') +def test__get_vsp_details_no_version(mock_send, mock_load): + vsp = Vsp() + vsp.identifier = "1234" + mock_send.assert_not_called() + assert vsp._get_vsp_details() == {} + +@mock.patch.object(Vsp, 'send_message_json') +def test__get_vsp_details(mock_send): + vsp = Vsp() + vsp.identifier = "1234" + vsp._version = "4567" + mock_send.return_value = {'return': 'value'} + assert vsp._get_vsp_details() == {'return': 'value'} + mock_send.assert_called_once_with('GET', 'get vsp version', "{}/vendor-software-products/1234/versions/4567".format(vsp._base_url())) + +@pytest.mark.parametrize("status", [const.DRAFT, const.CERTIFIED, const.UPLOADED, const.VALIDATED]) +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_submit_not_Commited(mock_send, mock_status, status): + """Do nothing if not created.""" + vsp = Vsp() + vsp._status = status + vsp.submit() + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_submit_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.COMMITED + expected_data = '{\n\n "action": "Submit"\n}' + vsp._version = "1234" + vsp._identifier = "12345" + vsp.submit() + mock_send.assert_called_once_with("PUT", "Submit Vsp", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/actions', data=expected_data) + +@pytest.mark.parametrize("status", [const.DRAFT, const.COMMITED, const.UPLOADED, const.VALIDATED]) +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_create_csar_not_Certified(mock_send, mock_status, status): + """Do nothing if not created.""" + vsp = Vsp() + vsp._status = status + vsp.create_csar() + mock_send.assert_not_called() + assert vsp.csar_uuid == None + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_create_csar_not_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.CERTIFIED + mock_send.return_value = {} + expected_data = '{\n\n "action": "Create_Package"\n}' + vsp._version = "1234" + vsp._identifier = "12345" + vsp.create_csar() + mock_send.assert_called_once_with("PUT", "Create_Package Vsp", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/actions', data=expected_data) + assert vsp.csar_uuid == None + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_create_csar_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.CERTIFIED + result = requests.Response() + result.status_code = 201 + result._content = json.dumps({'packageId': "64"}).encode('UTF-8') + mock_send.return_value = result + expected_data = '{\n\n "action": "Create_Package"\n}' + vsp._version = "1234" + vsp._identifier = "12345" + vsp.create_csar() + mock_send.assert_called_once_with("PUT", "Create_Package Vsp", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/actions', data=expected_data) + assert vsp.csar_uuid == "64" + +@pytest.mark.parametrize("status", [const.DRAFT, const.CERTIFIED, const.UPLOADED, const.COMMITED]) +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_commit_not_Validated(mock_send, mock_status, status): + """Do nothing if not created.""" + vsp = Vsp() + vsp._status = status + vsp.commit() + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_commit_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.VALIDATED + expected_data = '{\n\n "commitRequest":{"message":"ok"},\n\n "action": "Commit"\n}' + vsp._version = "1234" + vsp._identifier = "12345" + vsp.commit() + mock_send.assert_called_once_with("PUT", "Commit Vsp", 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/items/12345/versions/1234/actions', data=expected_data) + +@pytest.mark.parametrize("status", [const.CERTIFIED, const.COMMITED, const.UPLOADED, const.VALIDATED]) +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_upload_not_Draft(mock_send, mock_status, status): + """Do nothing if not created.""" + vsp = Vsp() + vsp._status = status + vsp.upload_package('data') + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_upload_not_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.DRAFT + mock_send.return_value = None + vsp._version = "1234" + vsp._identifier = "12345" + vsp.upload_package('data') + mock_send.assert_called_once_with('POST', 'upload ZIP for Vsp', "https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/orchestration-template-candidate", files={'upload': 'data'}, headers={'Accept': 'application/json', 'USER_ID': 'cs0008', 'Authorization': 'Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=', 'X-ECOMP-InstanceID': 'onapsdk', 'Accept-Encoding': 'gzip, deflate'}) + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_upload_error_in_response(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.DRAFT + mock_send.return_value = mock.MagicMock(text='{"status": "Failure"}') + vsp._version = "1234" + vsp._identifier = "12345" + with pytest.raises(APIError): + vsp.upload_package('data') + mock_send.assert_called_once_with('POST', 'upload ZIP for Vsp', "https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/orchestration-template-candidate", files={'upload': 'data'}, headers={'Accept': 'application/json', 'USER_ID': 'cs0008', 'Authorization': 'Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=', 'X-ECOMP-InstanceID': 'onapsdk', 'Accept-Encoding': 'gzip, deflate'}) + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message') +def test_upload_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.DRAFT + mock_send.return_value = mock.MagicMock(text='{"status": "Success"}') + vsp._version = "1234" + vsp._identifier = "12345" + vsp.upload_package('data') + mock_send.assert_called_once_with('POST', 'upload ZIP for Vsp', "https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/orchestration-template-candidate", files={'upload': 'data'}, headers={'Accept': 'application/json', 'USER_ID': 'cs0008', 'Authorization': 'Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=', 'X-ECOMP-InstanceID': 'onapsdk', 'Accept-Encoding': 'gzip, deflate'}) + +@pytest.mark.parametrize("status", [const.CERTIFIED, const.COMMITED, const.DRAFT, const.VALIDATED]) +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message_json') +def test_validate_not_Draft(mock_send, mock_status, status): + """Do nothing if not created.""" + vsp = Vsp() + vsp._status = status + vsp.validate() + mock_send.assert_not_called() + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message_json') +def test_validate_not_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.UPLOADED + mock_send.return_value = {} + vsp._version = "1234" + vsp._identifier = "12345" + vsp.validate() + mock_send.assert_called_once_with('PUT', 'Validate artifacts for Vsp', 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/orchestration-template-candidate/process') + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message_json') +def test_validate_not_success(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.UPLOADED + mock_send.return_value = {'status': 'not_success'} + vsp._version = "1234" + vsp._identifier = "12345" + vsp.validate() + mock_send.assert_called_once_with('PUT', 'Validate artifacts for Vsp', 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/orchestration-template-candidate/process') + +@mock.patch.object(Vsp, 'load_status') +@mock.patch.object(Vsp, 'send_message_json') +def test_validate_OK(mock_send, mock_status): + """Don't update status if submission NOK.""" + vsp = Vsp() + vsp._status = const.UPLOADED + mock_send.return_value = {'status': 'Success'} + vsp._version = "1234" + vsp._identifier = "12345" + vsp.validate() + mock_send.assert_called_once_with('PUT', 'Validate artifacts for Vsp', 'https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/12345/versions/1234/orchestration-template-candidate/process') + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +@mock.patch.object(Vsp, 'created') +def test_onboard_new_vsp_no_vendor(mock_created, mock_create, mock_upload_package, + mock_validate, mock_commit, mock_submit, + mock_create_csar): + mock_created.return_value = False + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [None, const.APPROVED, const.APPROVED, + const.APPROVED, const.APPROVED, + const.APPROVED, None] + vsp = Vsp() + with pytest.raises(ParameterError): + vsp.onboard() + mock_create.assert_not_called() + mock_upload_package.assert_not_called() + mock_validate.assert_not_called() + mock_commit.assert_not_called() + mock_submit.assert_not_called() + mock_create_csar.assert_not_called() + + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +@mock.patch.object(Vsp, 'created') +def test_onboard_new_vsp(mock_created, mock_create, mock_upload_package, + mock_validate, mock_commit, mock_submit, + mock_create_csar): + mock_created.return_value = False + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [None, const.APPROVED, const.APPROVED, + const.APPROVED, const.APPROVED, + const.APPROVED, None] + vendor = Vendor() + vsp = Vsp(vendor=vendor) + vsp.onboard() + mock_create.assert_called_once() + mock_upload_package.assert_not_called() + mock_validate.assert_not_called() + mock_commit.assert_not_called() + mock_submit.assert_not_called() + mock_create_csar.assert_not_called() + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +def test_onboard_vsp_upload_no_files(mock_create, mock_upload_package, + mock_validate, mock_commit, mock_submit, + mock_create_csar): + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.DRAFT, const.APPROVED, + const.APPROVED, const.APPROVED, const.APPROVED, + const.APPROVED, None] + vsp = Vsp() + with pytest.raises(ParameterError): + vsp.onboard() + mock_create.assert_not_called() + mock_upload_package.assert_not_called() + mock_validate.assert_not_called() + mock_commit.assert_not_called() + mock_submit.assert_not_called() + mock_create_csar.assert_not_called() + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +def test_onboard_vsp_upload_package(mock_create, mock_upload_package, + mock_validate, mock_commit, mock_submit, + mock_create_csar): + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [const.DRAFT, const.APPROVED, None] + vsp = Vsp(package="yes") + vsp.onboard() + mock_create.assert_not_called() + mock_upload_package.assert_called_once_with("yes") + mock_validate.assert_not_called() + mock_commit.assert_not_called() + mock_submit.assert_not_called() + mock_create_csar.assert_not_called() + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +def test_onboard_new_vsp_validate(mock_create, mock_upload_package, + mock_validate, mock_commit, mock_submit, + mock_create_csar): + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [const.UPLOADED, const.APPROVED, None] + vsp = Vsp() + vsp.onboard() + mock_create.assert_not_called() + mock_upload_package.assert_not_called() + mock_validate.assert_called_once() + mock_commit.assert_not_called() + mock_submit.assert_not_called() + mock_create_csar.assert_not_called() + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +def test_onboard_new_vsp_commit(mock_create, mock_upload_package, + mock_validate, mock_commit, mock_submit, + mock_create_csar): + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [const.VALIDATED, const.APPROVED, None] + vsp = Vsp() + vsp.onboard() + mock_create.assert_not_called() + mock_upload_package.assert_not_called() + mock_validate.assert_not_called() + mock_commit.assert_called_once() + mock_submit.assert_not_called() + mock_create_csar.assert_not_called() + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +def test_onboard_new_vsp_submit(mock_create, mock_upload_package, + mock_validate, mock_commit, mock_submit, + mock_create_csar): + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [const.COMMITED, const.APPROVED, None] + vsp = Vsp() + vsp.onboard() + mock_create.assert_not_called() + mock_upload_package.assert_not_called() + mock_validate.assert_not_called() + mock_commit.assert_not_called() + mock_submit.assert_called_once() + mock_create_csar.assert_not_called() + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +def test_onboard_new_vsp_create_csar(mock_create, + mock_upload_package, mock_validate, + mock_commit, mock_submit, + mock_create_csar): + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [const.CERTIFIED, const.APPROVED, None] + vsp = Vsp() + vsp.onboard() + mock_create.assert_not_called() + mock_upload_package.assert_not_called() + mock_validate.assert_not_called() + mock_commit.assert_not_called() + mock_submit.assert_not_called() + mock_create_csar.assert_called_once() + +@mock.patch.object(Vsp, 'create_csar') +@mock.patch.object(Vsp, 'submit') +@mock.patch.object(Vsp, 'commit') +@mock.patch.object(Vsp, 'validate') +@mock.patch.object(Vsp, 'upload_package') +@mock.patch.object(Vsp, 'create') +@mock.patch.object(Vsp, 'created') +@mock.patch.object(Vsp, 'load') +def test_onboard_whole_vsp(mock_load, mock_created, mock_create, + mock_upload_package, mock_validate, + mock_commit, mock_submit, + mock_create_csar): + getter_mock = mock.Mock(wraps=Vsp.status.fget) + mock_status = Vsp.status.getter(getter_mock) + with mock.patch.object(Vsp, 'status', mock_status): + getter_mock.side_effect = [None, const.DRAFT, const.UPLOADED, const.VALIDATED, + const.COMMITED, const.CERTIFIED, None] + vendor = Vendor() + vsp = Vsp(vendor=vendor, package="yes") + vsp.onboard() + mock_create.assert_called_once() + mock_upload_package.assert_called_once() + mock_validate.assert_called_once() + mock_commit.assert_called_once() + mock_submit.assert_called_once() + mock_create_csar.assert_called_once() + + +@mock.patch.object(Vsp, "status", new_callable=mock.PropertyMock) +@mock.patch.object(Vsp, '_upload_action') +def test_update_package(mock_upload, mock_status): + mock_status.return_value = const.DRAFT + vsp = Vsp(vendor=mock.MagicMock()) + vsp.update_package("new") + mock_upload.assert_not_called() + mock_status.return_value = const.COMMITED + vsp.update_package("new") + mock_upload.assert_called_once() + + +@mock.patch.object(Vsp, "send_message_json") +@mock.patch.object(Vsp, 'load') +def test_create_new_version(mock_load, mock_send): + vsp = Vsp(vendor=mock.MagicMock()) + vsp._identifier = "1232" + vsp._version = "4321" + vsp.create_new_version() + mock_load.assert_called_once() + mock_send.assert_called_once_with("POST", + "Create new VSP version", + "https://sdc.api.fe.simpledemo.onap.org:30207/sdc1/feProxy/onboarding-api/v1.0/items/1232/versions/4321", + data='{"creationMethod": "major", "description": "New VSP version"}') |