diff options
284 files changed, 8092 insertions, 3697 deletions
@@ -37,16 +37,16 @@ committers: company: 'ATT' id: 'ahemli' timezone: 'Asia/Jerusalem' - - name: 'Wojciech Sliwka' - email: 'wojciech.sliwka@nokia.com' - company: 'Nokia' - id: 'wsliwka' - timezone: 'Europe/Warsaw' - name: 'Ofir Sonsino' email: 'os0695@att.com' company: 'ATT' id: 'os0695' timezone: 'Israel/Lod' + - name: 'Eylon Malin' + email: 'eylon.malin@intl.att.com' + company: 'ATT' + id: 'eylonmalin' + timezone: 'Israel/Lod' tsc: approval: 'https://lists.onap.org/pipermail/onap-tsc' changes: @@ -59,3 +59,9 @@ tsc: - type: 'Removal' name: 'Daniel Rose' link: 'https://lists.onap.org/g/onap-tsc/message/4251' + - type: 'Addition' + name: 'Eylon Malin' + link: 'https://lists.onap.org/g/onap-tsc/topic/62892813#5725' + - type: 'Removal' + name: 'Wojciech Sliwka' + link: 'https://lists.onap.org/g/onap-tsc/topic/67968691#5770' diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 03f2a6edf..58fd74b8d 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -3,22 +3,41 @@ VID Release Notes ================= +Version: El-Alto (6.0.x) +------------------------ +**Known Issues** + + +**Resolved Issues** + + +**Security Notes** + +*Fixed Security Issues* + +*Known Security Issues* + + + Version: El-Alto (5.0.x) --------------- +------------------------ +**Known Issues** + + - `↗ <https://jira.onap.org/browse/VID-659>`__ VID generates always the same VF module name during scale out **Resolved Issues** - - `↗ <https://jira.onap.org/browse/VID-520>`_ Remove "Dissociate" button for Macro-orchestrated PNF resources - - `↗ <https://jira.onap.org/browse/VID-517>`_ Added liquidBase for follow changes in DB - - `↗ <https://jira.onap.org/browse/VID-488>`_ Added "Report" popup for common diagnosable cases - - `↗ <https://jira.onap.org/browse/VID-358>`_ vid-mariadb-galera runs in high-availability mode + - `↗ <https://jira.onap.org/browse/VID-520>`__ Remove "Dissociate" button for Macro-orchestrated PNF resources + - `↗ <https://jira.onap.org/browse/VID-517>`__ Added liquidBase for follow changes in DB + - `↗ <https://jira.onap.org/browse/VID-488>`__ Added "Report" popup for common diagnosable cases + - `↗ <https://jira.onap.org/browse/VID-358>`__ vid-mariadb-galera runs in high-availability mode **Security Notes** *Fixed Security Issues* - - `↗ <https://jira.onap.org/browse/OJSI-119>`_ Closed plain-text HTTP endpoint, port 30238 + - `↗ <https://jira.onap.org/browse/OJSI-119>`__ Closed plain-text HTTP endpoint, port 30238 *Known Security Issues* @@ -126,9 +145,9 @@ VID code has been formally scanned during build time using NexusIQ and all Criti Quick Links: -- `VID project page <https://wiki.onap.org/display/DW/Virtual+Infrastructure+Deployment+Project>`_ -- `Passing Badge information for VID <https://bestpractices.coreinfrastructure.org/en/projects/1658>`_ -- `Project Vulnerability Review Table for VID <https://wiki.onap.org/pages/viewpage.action?pageId=45300871>`_ +- `VID project page <https://wiki.onap.org/display/DW/Virtual+Infrastructure+Deployment+Project>`__ +- `Passing Badge information for VID <https://bestpractices.coreinfrastructure.org/en/projects/1658>`__ +- `Project Vulnerability Review Table for VID <https://wiki.onap.org/pages/viewpage.action?pageId=45300871>`__ **Other** @@ -281,7 +300,7 @@ New Features **Security Notes** -VID code has been formally scanned during build time using NexusIQ and all Critical vulnerabilities have been addressed, items that remain open have been assessed for risk and determined to be false positive. The VID open Critical security vulnerabilities and their risk assessment have been documented as part of the `project <https://wiki.onap.org/pages/viewpage.action?pageId=28378623>`_. +VID code has been formally scanned during build time using NexusIQ and all Critical vulnerabilities have been addressed, items that remain open have been assessed for risk and determined to be false positive. The VID open Critical security vulnerabilities and their risk assessment have been documented as part of the `project <https://wiki.onap.org/pages/viewpage.action?pageId=28378623>`__. Quick Links: diff --git a/epsdk-app-onap/pom.xml b/epsdk-app-onap/pom.xml index 8f63a6d0c..0dc8eacea 100755 --- a/epsdk-app-onap/pom.xml +++ b/epsdk-app-onap/pom.xml @@ -25,9 +25,9 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <epsdk.version>2.5.0</epsdk.version> - <jackson.version>2.9.9</jackson.version> - <jackson.databind.version>2.9.9.3</jackson.databind.version> - <springframework.version>5.1.9.RELEASE</springframework.version> + <jackson.version>2.10.1</jackson.version> + <jackson.databind.version>2.10.1</jackson.databind.version> + <springframework.version>5.2.0.RELEASE</springframework.version> <!-- epsdk-core is importing this class, which is only on spring-orm 4 but not in orm 5: org.springframework.orm.hibernate4.HibernateTransactionManager so following orm.version lets epsdk-core find it --> diff --git a/epsdk-app-onap/src/main/resources/catalog.json b/epsdk-app-onap/src/main/resources/catalog.json deleted file mode 100755 index e5fb52136..000000000 --- a/epsdk-app-onap/src/main/resources/catalog.json +++ /dev/null @@ -1,174 +0,0 @@ -{
- "services": {
- "0346aa9f-57b7-458a-9681-daf5b19d52b0": {
- "uuid": "0346aa9f-57b7-458a-9681-daf5b19d52b0",
- "name": "The Worst Service",
- "version": "1.0",
- "toscaModelURL": "sampleTosca.csar",
- "category": "Bad Services",
- "lifecycleState": "NOT_CERTIFIED_CHECKOUT",
- "lastUpdaterUserId": "example@example.org",
- "lastUpdaterFullName": "Example User",
- "distributionStatus": "DISTRIBUTION_REJECTED",
- "artifacts": [],
- "resources": []
- },
- "1346aa9f-57b7-458a-9681-daf5b19d52b1": {
- "uuid": "1346aa9f-57b7-458a-9681-daf5b19d52b1",
- "name": "The Worst Service",
- "version": "1.1",
- "toscaModelURL": "sampleTosca.csar",
- "category": "Bad Services",
- "lifecycleState": "CERTIFIED",
- "lastUpdaterUserId": "example@example.org",
- "lastUpdaterFullName": "Example User",
- "distributionStatus": "DISTRIBUTED",
- "artifacts": [],
- "resources": []
- },
- "3346aa9f-57b7-458a-9681-daf5b19d52b3": {
- "uuid": "3346aa9f-57b7-458a-9681-daf5b19d52b3",
- "name": "Bland Service",
- "version": "1.9",
- "toscaModelURL": "sampleTosca.csar",
- "category": "Neutral Services",
- "lifecycleState": "CERTIFIED",
- "lastUpdaterUserId": "example@example.org",
- "lastUpdaterFullName": "Example User",
- "distributionStatus": "DISTRIBUTION_NOT_APPROVED",
- "artifacts": [],
- "resources": []
- },
- "2346aa9f-57b7-458a-9681-daf5b19d52b2": {
- "uuid": "2346aa9f-57b7-458a-9681-daf5b19d52b2",
- "name": "The Best Service",
- "version": "1.3",
- "toscaModelURL": "sampleTosca.csar",
- "category": "Good Services",
- "lifecycleState": "CERTIFIED",
- "lastUpdaterUserId": "example@example.org",
- "lastUpdaterFullName": "Example User",
- "distributionStatus": "DISTRIBUTION_APPROVED",
- "artifacts": [
- {
- "artifactUUID": "0cf78c81-1246-45e7-a190-eaa309ee5680",
- "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680",
- "artifactName": "The Worst Artifact",
- "artifactType": "HEAT",
- "artifactDescription": "This is the worst artifact",
- "artifactURL": "http://www.openecomp.org/",
- "artifactTimeout": "60",
- "artifactChecksum": "A worthy checksum",
- "artifactVersion": "0.1",
- },
- {
- "artifactUUID": "1cf78c81-1246-45e7-a190-eaa309ee5681",
- "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680",
- "artifactName": "The Worst Artifact",
- "artifactType": "HEAT",
- "artifactDescription": "This is the worst artifact",
- "artifactURL": "http://www.openecomp.org/",
- "artifactTimeout": "60",
- "artifactChecksum": "A worthy checksum",
- "artifactVersion": "0.1",
- },
- {
- "artifactUUID": "2cf78c81-1246-45e7-a190-eaa309ee5682",
- "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680",
- "artifactName": "The Worst Artifact",
- "artifactType": "HEAT",
- "artifactDescription": "This is the worst artifact",
- "artifactURL": "http://www.openecomp.org/",
- "artifactTimeout": "60",
- "artifactChecksum": "A worthy checksum",
- "artifactVersion": "0.1",
- }
- ],
- "resources": []
- }
- },
- "resources": {
- "2f92b5b0-10ff-4cf4-9531-88546fe88a42": {
- "uuid": "2f92b5b0-10ff-4cf4-9531-88546fe88a42",
- "invariantUUID": "df92b5b0-10ff-4cf4-9531-88546fe88a4d",
- "name": "The Worst Resource",
- "version": "0.1",
- "toscaModelURL": "sampleTosca.csar",
- "toscaModel": "http://www.openecomp.org/",
- "toscaResourceName": "The Worst Resource (TOSCA)",
- "category": "Bad Resources",
- "subCategory": "Really Bad Resources",
- "resourceType": "VF",
- "lifecycleState": "CERTIFIED",
- "lastUpdaterUserId": "example@example.org",
- "lastUpdaterFullName": "Example User",
- "artifacts": [
- {
- "artifactUUID": "0cf78c81-1246-45e7-a190-eaa309ee5680",
- "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680",
- "artifactName": "The Worst Artifact",
- "artifactType": "HEAT",
- "artifactDescription": "This is the worst artifact",
- "artifactURL": "http://www.openecomp.org/",
- "artifactTimeout": "60",
- "artifactChecksum": "A worthy checksum",
- "artifactVersion": "0.1",
- },
- {
- "artifactUUID": "1cf78c81-1246-45e7-a190-eaa309ee5681",
- "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680",
- "artifactName": "The Worst Artifact",
- "artifactType": "HEAT",
- "artifactDescription": "This is the worst artifact",
- "artifactURL": "http://www.openecomp.org/",
- "artifactTimeout": "60",
- "artifactChecksum": "A worthy checksum",
- "artifactVersion": "0.1",
- },
- {
- "artifactUUID": "2cf78c81-1246-45e7-a190-eaa309ee5682",
- "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680",
- "artifactName": "The Worst Artifact",
- "artifactType": "HEAT",
- "artifactDescription": "This is the worst artifact",
- "artifactURL": "http://www.openecomp.org/",
- "artifactTimeout": "60",
- "artifactChecksum": "A worthy checksum",
- "artifactVersion": "0.1",
- }
- ]
- },
- "0f92b5b0-10ff-4cf4-9531-88546fe88a40": {
- "uuid": "0f92b5b0-10ff-4cf4-9531-88546fe88a40",
- "invariantUUID": "df92b5b0-10ff-4cf4-9531-88546fe88a4d",
- "name": "The Worst Resource",
- "version": "0.1",
- "toscaModelURL": "sampleTosca.csar",
- "toscaModel": "http://www.openecomp.org/",
- "toscaResourceName": "The Worst Resource (TOSCA)",
- "category": "Bad Resources",
- "subCategory": "Really Bad Resources",
- "resourceType": "VF",
- "lifecycleState": "CERTIFIED",
- "lastUpdaterUserId": "example@example.org",
- "lastUpdaterFullName": "Example User",
- "artifacts": []
- },
- "1f92b5b0-10ff-4cf4-9531-88546fe88a41": {
- "uuid": "1f92b5b0-10ff-4cf4-9531-88546fe88a41",
- "invariantUUID": "df92b5b0-10ff-4cf4-9531-88546fe88a4d",
- "name": "The Worst Resource",
- "version": "0.1",
- "toscaModelURL": "sampleTosca.csar",
- "toscaModel": "http://www.openecomp.org/",
- "toscaResourceName": "The Worst Resource (TOSCA)",
- "category": "Bad Resources",
- "subCategory": "Really Bad Resources",
- "resourceType": "VF",
- "lifecycleState": "CERTIFIED",
- "lastUpdaterUserId": "example@example.org",
- "lastUpdaterFullName": "Example User",
- "artifacts": []
- }
- }
-}
\ No newline at end of file diff --git a/epsdk-app-onap/src/main/resources/sampleTosca.csar b/epsdk-app-onap/src/main/resources/sampleTosca.csar Binary files differdeleted file mode 100755 index 7532f5874..000000000 --- a/epsdk-app-onap/src/main/resources/sampleTosca.csar +++ /dev/null diff --git a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties index 5454724bf..393327d85 100755 --- a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties +++ b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties @@ -136,7 +136,7 @@ mso.restapi.operationalEnvironment.cloudResourcesRequests.status=${mso.restapi.c mso.displayTestAPIOnScreen=true mso.defaultTestAPI=VNF_API -mso.maxOpenedInstantiationRequests=20 +mso.maxOpenedInstantiationRequests=200 mso.asyncPollingIntervalSeconds=1 refreshTimeInstantiationDashboard=10 diff --git a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties index 0987199e3..1e8a0ba15 100755 --- a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties +++ b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system_template.properties @@ -136,7 +136,7 @@ mso.restapi.operationalEnvironment.cloudResourcesRequests.status=${mso.restapi.c mso.displayTestAPIOnScreen=true mso.defaultTestAPI=GR_API -mso.maxOpenedInstantiationRequests=20 +mso.maxOpenedInstantiationRequests=200 mso.asyncPollingIntervalSeconds=1 refreshTimeInstantiationDashboard=10 diff --git a/features.properties.md b/features.properties.md index edf162d74..62ab55ef6 100644 --- a/features.properties.md +++ b/features.properties.md @@ -71,11 +71,6 @@ * Delete Macro service -* FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE - - Enable soft delete for vf-module in view/edit page for a-la-carte only. - - * FLAG_1810_AAI_LOCAL_CACHE Enables the caching of selected AAI responses. @@ -178,6 +173,30 @@ enables showing/hiding (true/false) column with orchestration type in Service Model browser. The types are fetched from aai. -* FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE - Let the user set the order of resource instantiation with the button (Move up / Move down) while using drawing board (new view edit) - for a-la-carte instantiation.
\ No newline at end of file + +* FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI + Any a-la-carte new service deployment will be open in modern UI, besides excluded services : Port mirroring, VLAN Tagging + +* FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS + When flag is true the new popup will be opened with additional options to perform on VFM. + +* FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND, + When flag is true, VID use macro_services_by_invariant_uuid.json file to identify if csar without instantiation type is macro service. + Otherwise, MACRO_SERVICES list in vidConfiguration.js is used to identify if it's a macro service (in ng1 code) + +* FLAG_2002_VNF_PLATFORM_MULTI_SELECT + When flag is true the platform will appear as a multi select field, if false the platform will be dropdown list. + +* FLAG_2004_INSTANTIATION_STATUS_FILTER + When flag is true the user can filter rows in instantiation status by using text input + +* FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE + When flag is true, the user see in instantiation status page, an option to recreate another instance. + This option is enabled only for instantiate jobs. + IF the user click on this option, the previous instantiation is opened in drawing board, + and the user can create another one from this template. + +* FLAG_2002_UNLIMITED_MAX + when flag is true and max_instances is not declare than user can add unlimited VND, NETWORK, VFMODULE, + User can duplicate up to 10 record in single time. + If the flag is false and max_instances is not declare the max will be 1 else max_instances value. diff --git a/vid-app-common/pom.xml b/vid-app-common/pom.xml index 9e5f58dd3..f618ec822 100755 --- a/vid-app-common/pom.xml +++ b/vid-app-common/pom.xml @@ -26,16 +26,16 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <epsdk.version>2.5.0</epsdk.version> - <springframework.version>5.1.9.RELEASE</springframework.version> + <springframework.version>5.2.0.RELEASE</springframework.version> <springframework.orm.version>4.3.22.RELEASE</springframework.orm.version> <!-- epsdk-core is importing this class, which is only on spring-orm 4 but not in orm 5: org.springframework.orm.hibernate4.HibernateTransactionManager so following orm.version lets epsdk-core find it --> <hibernate.version>4.3.11.Final</hibernate.version> - <jackson.version>2.9.9</jackson.version> - <jackson.databind.version>2.9.9.3</jackson.databind.version> + <jackson.version>2.10.1</jackson.version> + <jackson.databind.version>2.10.1</jackson.databind.version> <onap.logging.version>1.6.1</onap.logging.version> - <jersey.version>2.29</jersey.version> + <jersey.version>2.29.1</jersey.version> <surefire.version>2.22.1</surefire.version> <selenium.version>3.141.59</selenium.version> <sonar.coverage.exclusions>**/webapp/**/*,**/*.js</sonar.coverage.exclusions> @@ -54,7 +54,7 @@ <sitePath>content/sites/site/org/onap/vid/${project.version}</sitePath> <aspectj.version>1.8.9</aspectj.version> - <kotlin.version>1.3.30</kotlin.version> + <kotlin.version>1.3.60</kotlin.version> <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget> <eirslett.version>1.6</eirslett.version> diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/OperationalEnvironment.java b/vid-app-common/src/main/java/org/onap/vid/aai/OperationalEnvironment.java index be6c6e51f..71ed1713a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/OperationalEnvironment.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/OperationalEnvironment.java @@ -3,13 +3,14 @@ * VID * ================================================================================ * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 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. @@ -20,37 +21,83 @@ package org.onap.vid.aai; -import org.onap.vid.aai.model.RelationshipList; +import static com.fasterxml.jackson.annotation.JsonProperty.Access.WRITE_ONLY; + +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import org.onap.vid.aai.model.RelationshipList; @JsonIgnoreProperties(ignoreUnknown = true) -public class OperationalEnvironment { - - private String operationalEnvironmentId; - private String operationalEnvironmentName; - private String operationalEnvironmentType; - private String operationalEnvironmentStatus; - private String tenantContext; - private String workloadContext; - private String resourceVersion; - private RelationshipList relationshipList; - - public OperationalEnvironment() { +public final class OperationalEnvironment { + + private final String operationalEnvironmentId; + private final String operationalEnvironmentName; + private final String operationalEnvironmentType; + private final String operationalEnvironmentStatus; + private final String tenantContext; + private final String workloadContext; + private final String resourceVersion; + private final RelationshipList relationshipList; + + public static OperationalEnvironmentBuilder builder() { + return new OperationalEnvironmentBuilder(); + } + + @JsonCreator + OperationalEnvironment( + @JsonProperty(value = "operational-environment-id", access = WRITE_ONLY) String operationalEnvironmentId, + @JsonProperty(value = "operational-environment-name", access = WRITE_ONLY) String operationalEnvironmentName, + @JsonProperty(value = "operational-environment-type", access = WRITE_ONLY) String operationalEnvironmentType, + @JsonProperty(value = "operational-environment-status", access = WRITE_ONLY) String operationalEnvironmentStatus, + @JsonProperty(value = "tenant-context", access = WRITE_ONLY) String tenantContext, + @JsonProperty(value = "workload-context", access = WRITE_ONLY) String workloadContext, + @JsonProperty(value = "resource-version", access = WRITE_ONLY) String resourceVersion, + @JsonProperty(value = "relationship-list", access = WRITE_ONLY) RelationshipList relationshipList) { + this.operationalEnvironmentId = operationalEnvironmentId; + this.operationalEnvironmentName = operationalEnvironmentName; + this.operationalEnvironmentType = operationalEnvironmentType; + this.operationalEnvironmentStatus = operationalEnvironmentStatus; + this.tenantContext = tenantContext; + this.workloadContext = workloadContext; + this.resourceVersion = resourceVersion; + this.relationshipList = relationshipList; } - public OperationalEnvironment(OperationalEnvironmentBuilder builder) { - this.operationalEnvironmentId = builder.operationalEnvironmentId; - this.operationalEnvironmentName = builder.operationalEnvironmentName; - this.operationalEnvironmentType = builder.operationalEnvironmentType; - this.operationalEnvironmentStatus = builder.operationalEnvironmentStatus; - this.tenantContext = builder.tenantContext; - this.workloadContext = builder.workloadContext; - this.resourceVersion = builder.resourceVersion; - this.relationshipList = builder.relationshipList; + public String getOperationalEnvironmentId() { + return operationalEnvironmentId; + } + + public String getOperationalEnvironmentName() { + return operationalEnvironmentName; + } + + public String getOperationalEnvironmentType() { + return operationalEnvironmentType; + } + + public String getOperationalEnvironmentStatus() { + return operationalEnvironmentStatus; + } + + public String getTenantContext() { + return tenantContext; + } + + public String getWorkloadContext() { + return workloadContext; + } + + public String getResourceVersion() { + return resourceVersion; + } + + public RelationshipList getRelationshipList() { + return relationshipList; } public static class OperationalEnvironmentBuilder { + private String operationalEnvironmentId; private String operationalEnvironmentName; private String operationalEnvironmentType; @@ -58,127 +105,65 @@ public class OperationalEnvironment { private String tenantContext; private String workloadContext; private String resourceVersion; + private RelationshipList relationshipList; - public OperationalEnvironmentBuilder setOperationalEnvironmentId( - String operationalEnvironmentId) { + public OperationalEnvironmentBuilder withOperationalEnvironmentId( + String operationalEnvironmentId) { this.operationalEnvironmentId = operationalEnvironmentId; return this; } - public OperationalEnvironmentBuilder setOperationalEnvironmentName( - String operationalEnvironmentName) { + public OperationalEnvironmentBuilder withOperationalEnvironmentName( + String operationalEnvironmentName) { this.operationalEnvironmentName = operationalEnvironmentName; return this; } - public OperationalEnvironmentBuilder setOperationalEnvironmentType( - String operationalEnvironmentType) { + public OperationalEnvironmentBuilder withOperationalEnvironmentType( + String operationalEnvironmentType) { this.operationalEnvironmentType = operationalEnvironmentType; return this; } - public OperationalEnvironmentBuilder setOperationalEnvironmentStatus( - String operationalEnvironmentStatus) { + public OperationalEnvironmentBuilder withOperationalEnvironmentStatus( + String operationalEnvironmentStatus) { this.operationalEnvironmentStatus = operationalEnvironmentStatus; return this; } - public OperationalEnvironmentBuilder setTenantContext(String tenantContext) { + public OperationalEnvironmentBuilder withTenantContext(String tenantContext) { this.tenantContext = tenantContext; return this; } - public OperationalEnvironmentBuilder setWorkloadContext(String workloadContext) { + public OperationalEnvironmentBuilder withWorkloadContext(String workloadContext) { this.workloadContext = workloadContext; return this; } - public OperationalEnvironmentBuilder setResourceVersion(String resourceVersion) { + public OperationalEnvironmentBuilder withResourceVersion(String resourceVersion) { this.resourceVersion = resourceVersion; return this; } - public OperationalEnvironmentBuilder setRelationshipList( - RelationshipList relationshipList) { + public OperationalEnvironmentBuilder withRelationshipList( + RelationshipList relationshipList) { this.relationshipList = relationshipList; return this; } - public OperationalEnvironment createOperationalEnvironment() { - return new OperationalEnvironment(this); + public OperationalEnvironment build() { + return new OperationalEnvironment(operationalEnvironmentId, + operationalEnvironmentName, + operationalEnvironmentType, + operationalEnvironmentStatus, + tenantContext, + workloadContext, + resourceVersion, + relationshipList); } - } - - public String getOperationalEnvironmentId() { - return operationalEnvironmentId; - } - @JsonProperty("operational-environment-id") - public void setJsonOperationalEnvironmentId(String operationalEnvironmentId) { - this.operationalEnvironmentId = operationalEnvironmentId; } - public String getOperationalEnvironmentName() { - return operationalEnvironmentName; - } - - @JsonProperty("operational-environment-name") - public void setJsonOperationalEnvironmentName(String operationalEnvironmentName) { - this.operationalEnvironmentName = operationalEnvironmentName; - } - - public String getOperationalEnvironmentType() { - return operationalEnvironmentType; - } - - @JsonProperty("operational-environment-type") - public void setJsonOperationalEnvironmentType(String operationalEnvironmentType) { - this.operationalEnvironmentType = operationalEnvironmentType; - } - - public String getOperationalEnvironmentStatus() { - return operationalEnvironmentStatus; - } - - @JsonProperty("operational-environment-status") - public void setJsonOperationalEnvironmentStatus(String operationalEnvironmentStatus) { - this.operationalEnvironmentStatus = operationalEnvironmentStatus; - } - - public String getTenantContext() { - return tenantContext; - } - - @JsonProperty("tenant-context") - public void setJsonTenantContext(String tenantContext) { - this.tenantContext = tenantContext; - } - - public String getWorkloadContext() { - return workloadContext; - } - - @JsonProperty("workload-context") - public void setJsonWorkloadContext(String workloadContext) { - this.workloadContext = workloadContext; - } - - public String getResourceVersion() { - return resourceVersion; - } - - @JsonProperty("resource-version") - public void setJsonResourceVersion(String resourceVersion) { - this.resourceVersion = resourceVersion; - } - - public RelationshipList getRelationshipList() { - return relationshipList; - } - - @JsonProperty("relationship-list") - public void setJsonRelationshipList(RelationshipList relationshipList) { - this.relationshipList = relationshipList; - } } diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetOperationalEnvironments/OperationalEnvironmentList.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetOperationalEnvironments/OperationalEnvironmentList.java index 13c6ada2d..6b3fbbd64 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetOperationalEnvironments/OperationalEnvironmentList.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetOperationalEnvironments/OperationalEnvironmentList.java @@ -3,13 +3,14 @@ * VID * ================================================================================ * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 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. @@ -20,30 +21,27 @@ package org.onap.vid.aai.model.AaiGetOperationalEnvironments; -import com.fasterxml.jackson.annotation.JsonAlias; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.onap.vid.aai.OperationalEnvironment; +import static com.fasterxml.jackson.annotation.JsonProperty.Access.WRITE_ONLY; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collections; import java.util.List; +import org.onap.vid.aai.OperationalEnvironment; @JsonIgnoreProperties(ignoreUnknown = true) -public class OperationalEnvironmentList { - - public List<OperationalEnvironment> getOperationalEnvironment() { - return operationalEnvironment; - } +public final class OperationalEnvironmentList { - @JsonAlias("operational-environment") - public void setOperationalEnvironment(List<OperationalEnvironment> operationalEnvironment) { - this.operationalEnvironment = operationalEnvironment; - } + private final List<OperationalEnvironment> operationalEnvironment; - public OperationalEnvironmentList() { + @JsonCreator + public OperationalEnvironmentList( + @JsonProperty(value = "operational-environment", access = WRITE_ONLY) List<OperationalEnvironment> operationalEnvironment) { + this.operationalEnvironment = Collections.unmodifiableList(operationalEnvironment); } - public OperationalEnvironmentList(List<OperationalEnvironment> operationalEnvironment) { - this.operationalEnvironment = operationalEnvironment; + public List<OperationalEnvironment> getOperationalEnvironment() { + return operationalEnvironment; } - - private List<OperationalEnvironment> operationalEnvironment; } diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java index 48736bc01..111a260e1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java @@ -20,14 +20,12 @@ package org.onap.vid.aai.util; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.counting; -import static java.util.stream.Collectors.groupingBy; import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.A_LA_CARTE; import java.util.Map; -import java.util.Objects; +import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; +import org.onap.vid.model.ModelUtil; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.CollectionResource; import org.onap.vid.model.aaiTree.Network; @@ -56,6 +54,13 @@ public class AAITreeConverter { public static final String SERVICE_INSTANCE_SERVICE_INSTANCE_ID = "service-instance.service-instance-id"; public static final String TENANT_TENANT_NAME = "tenant.tenant-name"; + private final ModelUtil modelUtil; + + @Inject + public AAITreeConverter(ModelUtil modelUtil) { + this.modelUtil = modelUtil; + } + public ServiceInstance convertTreeToUIModel(AAITreeNode rootNode, String globalCustomerId, String serviceType, String instantiationType, String instanceRole, String instanceType) { ServiceInstance serviceInstance = new ServiceInstance(); serviceInstance.setInstanceId(rootNode.getId()); @@ -107,13 +112,7 @@ public class AAITreeConverter { } private <T extends Node> Map<String, Long> getExistingCounterMap(Map<String, T> nodeList) { - return nodeList.entrySet().stream() - .map(k -> { - ModelInfo modelInfo = k.getValue().getModelInfo(); - return StringUtils.defaultIfEmpty(modelInfo.getModelCustomizationId(), modelInfo.getModelVersionId()); - }) - .filter(Objects::nonNull) - .collect(groupingBy(identity(), counting())); + return modelUtil.getExistingCounterMap(nodeList, Node::getModelInfo); } private static ModelInfo createModelInfo(AAITreeNode aaiNode) { diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java index d35c8df9c..760eb4251 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java @@ -20,26 +20,39 @@ package org.onap.vid.asdc.parser; +import static java.util.stream.Collectors.toSet; import static org.apache.commons.lang3.StringUtils.equalsAnyIgnoreCase; import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; import static org.apache.commons.lang3.StringUtils.isEmpty; +import static org.hibernate.annotations.common.util.StringHelper.isNotEmpty; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import com.google.common.collect.ImmutableMap; +import java.io.IOException; import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Stream; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.toscaparser.api.NodeTemplate; import org.onap.sdc.toscaparser.api.elements.Metadata; +import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.VidNotions; +import org.onap.vid.model.VidNotions.InstantiationType; +import org.onap.vid.model.VidNotions.InstantiationUI; +import org.onap.vid.model.VidNotions.ModelCategory; import org.onap.vid.properties.Features; import org.togglz.core.manager.FeatureManager; public class VidNotionsBuilder { private final FeatureManager featureManager; + private final Set<UUID> invariantToMacro; //map of service type that are always macro services, and their relevant featureFlag private static final Map<VidNotions.ModelCategory, Features> macroServicesByModelCategory = ImmutableMap.of( @@ -50,15 +63,30 @@ public class VidNotionsBuilder { public VidNotionsBuilder(FeatureManager featureManager) { this.featureManager = featureManager; + invariantToMacro = loadInvariantMacroUUIDsFromFile(); + } + + @NotNull + private Set<UUID> loadInvariantMacroUUIDsFromFile() { + try { + return Stream.of(JACKSON_OBJECT_MAPPER.readValue( + VidNotionsBuilder.class.getResource("/macro_services_by_invariant_uuid.json"), + String[].class + )).map(UUID::fromString).collect(toSet()); + } catch (IOException e) { + throw new GenericUncheckedException(e); + } } VidNotions buildVidNotions(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { VidNotions.ModelCategory modelCategory = suggestModelCategory(csarHelper, serviceModel); + final InstantiationType instantiationType = suggestInstantiationType(serviceModel, modelCategory); return new VidNotions( - suggestInstantiationUI(csarHelper, serviceModel), + suggestInstantiationUI(csarHelper, serviceModel, modelCategory, instantiationType), modelCategory, - suggestViewEditUI(csarHelper, serviceModel), - suggestInstantiationType(serviceModel, modelCategory)); + suggestViewEditUI(csarHelper, serviceModel, modelCategory, instantiationType), + instantiationType + ); } private boolean isMacroTypeByModelCategory(VidNotions.ModelCategory modelCategory) { @@ -67,31 +95,51 @@ public class VidNotionsBuilder { return (featureOfMacroType!=null && featureManager.isActive(featureOfMacroType)); } - VidNotions.InstantiationType suggestInstantiationType(ServiceModel serviceModel, VidNotions.ModelCategory modelCategory) { + InstantiationType suggestInstantiationType(ServiceModel serviceModel, VidNotions.ModelCategory modelCategory) { if (isMacroTypeByModelCategory(modelCategory)) { - return VidNotions.InstantiationType.Macro; + return InstantiationType.Macro; } - if (serviceModel==null || serviceModel.getService()==null || isEmpty(serviceModel.getService().getInstantiationType())) { - return VidNotions.InstantiationType.ClientConfig; + if (serviceModel==null || serviceModel.getService()==null) { + return defaultInstantiationType(); } - String instantiationType = serviceModel.getService().getInstantiationType(); - if (instantiationType.equals(ToscaParserImpl2.Constants.MACRO)) { - return VidNotions.InstantiationType.Macro; + + if (StringUtils.equals(serviceModel.getService().getInstantiationType(), ToscaParserImpl2.Constants.MACRO)) { + return InstantiationType.Macro; } - if (instantiationType.equals(ToscaParserImpl2.Constants.A_LA_CARTE)) { - return VidNotions.InstantiationType.ALaCarte; + + if (StringUtils.equals(serviceModel.getService().getInstantiationType(), ToscaParserImpl2.Constants.A_LA_CARTE)) { + return InstantiationType.ALaCarte; } - return VidNotions.InstantiationType.ClientConfig; + if (!featureManager.isActive(Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND)) + return InstantiationType.ClientConfig; + + return isMacroByInvariantUuid(serviceModel.getService().getInvariantUuid()) ? + InstantiationType.Macro : + InstantiationType.ALaCarte; + } + + @NotNull + private InstantiationType defaultInstantiationType() { + return featureManager.isActive(Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND) ? + InstantiationType.ALaCarte : + InstantiationType.ClientConfig; } //UI route a-la-carte services to old UI only if InstantiationUI is LEGACY //So any other value for InstantiationUI other than LEGACY make UI to route //a-la-carte services to new UI - VidNotions.InstantiationUI suggestInstantiationUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { + VidNotions.InstantiationUI suggestInstantiationUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel, ModelCategory modelCategory, InstantiationType instantiationType) { if(featureManager.isActive(Features.FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI) && isALaCarte(csarHelper)) { return VidNotions.InstantiationUI.ANY_ALACARTE_NEW_UI; } + + if (featureManager.isActive(Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI) && + !isMacro(instantiationType) && + !isAlacarteExcludedByCategory(modelCategory)) { + return InstantiationUI.ANY_ALACARTE_WHICH_NOT_EXCLUDED; + } + if (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && isGrouping(csarHelper)) { return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING; } @@ -115,6 +163,10 @@ public class VidNotionsBuilder { } + private boolean isAlacarteExcludedByCategory(ModelCategory modelCategory) { + return modelCategory==ModelCategory.PORT_MIRRORING || modelCategory==ModelCategory.VLAN_TAGGING ; + } + private boolean isVnfServiceRole(ISdcCsarHelper csarHelper) { final String serviceRole = csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_ROLE ); return StringUtils.equalsIgnoreCase("VNF" , serviceRole); @@ -153,6 +205,12 @@ public class VidNotionsBuilder { if(isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { return VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL; } + if (isPortMirroringService(serviceModel)) { + return ModelCategory.PORT_MIRRORING; + } + if (isVlanTaggingService(serviceModel)) { + return ModelCategory.VLAN_TAGGING; + } if (isInfraStructureVpn(csarHelper)) { return VidNotions.ModelCategory.INFRASTRUCTURE_VPN; } @@ -165,13 +223,13 @@ public class VidNotionsBuilder { return VidNotions.ModelCategory.OTHER; } - VidNotions.InstantiationUI suggestViewEditUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { + VidNotions.InstantiationUI suggestViewEditUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel, ModelCategory modelCategory, InstantiationType instantiationType) { if (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && isGrouping(csarHelper)) { return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING; } if (featureManager.isActive(Features.FLAG_1908_MACRO_NOT_TRANSPORT_NEW_VIEW_EDIT) && - isMacro(serviceModel) && + isMacro(instantiationType) && !isTransportService(csarHelper) && //till new view/edit would support fabric service activation !hasFabricConfiguration(csarHelper)) { @@ -179,7 +237,7 @@ public class VidNotionsBuilder { } if (featureManager.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)) { - VidNotions.InstantiationUI instantiationUISuggestion = suggestInstantiationUI(csarHelper, serviceModel); + VidNotions.InstantiationUI instantiationUISuggestion = suggestInstantiationUI(csarHelper, serviceModel, modelCategory, instantiationType); if (instantiationUISuggestion!=VidNotions.InstantiationUI.LEGACY) { return instantiationUISuggestion; } @@ -188,8 +246,8 @@ public class VidNotionsBuilder { return VidNotions.InstantiationUI.LEGACY; } - private boolean isMacro(ServiceModel serviceModel) { - return ToscaParserImpl2.Constants.MACRO.equals(serviceModel.getService().getInstantiationType()); + private boolean isMacro(InstantiationType instantiationType) { + return instantiationType==InstantiationType.Macro; } private boolean isUuidExactlyHardCoded1ffce89fef3f(ISdcCsarHelper csarHelper) { @@ -232,4 +290,29 @@ public class VidNotionsBuilder { final String serviceRole = csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_ROLE); return StringUtils.equalsIgnoreCase(serviceRole, ToscaParserImpl2.Constants.GROUPING); } + + private boolean isPortMirroringService(ServiceModel serviceModel) { + return (serviceModel.getService()!=null && + StringUtils.equals(serviceModel.getService().getServiceType(), "PORT-MIRROR")); + } + + private boolean isVlanTaggingService(ServiceModel serviceModel) { + if (serviceModel==null || serviceModel.getVnfs()==null) { + return false; + } + + return serviceModel.getVnfs().values().stream().anyMatch( + vnf-> MapUtils.isNotEmpty(vnf.getVfcInstanceGroups()) + ); + + } + + protected boolean isMacroByInvariantUuid(String uuid) { + try { + return invariantToMacro.contains(UUID.fromString(uuid)); + } + catch (IllegalArgumentException | NullPointerException e) { //not a uuid + return false; + } + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java index 6bd98fff6..96e777a13 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.dal.AsyncInstantiationRepository; import org.onap.vid.exceptions.AccessDeniedException; import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.ServiceInfo; @@ -35,8 +36,10 @@ import org.onap.vid.properties.Features; import org.onap.vid.roles.RoleProvider; import org.onap.vid.services.AsyncInstantiationBusinessLogic; import org.onap.vid.services.AuditService; +import org.onap.vid.services.InstantiationTemplatesService; import org.onap.vid.utils.SystemPropertiesWrapper; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -53,21 +56,29 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { public static final String ASYNC_INSTANTIATION = "asyncInstantiation"; protected final AsyncInstantiationBusinessLogic asyncInstantiationBL; + protected final InstantiationTemplatesService instantiationTemplates; + protected final AsyncInstantiationRepository asyncInstantiationRepository; private final SystemPropertiesWrapper systemPropertiesWrapper; private final RoleProvider roleProvider; private final FeatureManager featureManager; - @Autowired - protected AuditService auditService; + protected final AuditService auditService; @Autowired - public AsyncInstantiationController(AsyncInstantiationBusinessLogic asyncInstantiationBL, RoleProvider roleProvider, FeatureManager featureManager, SystemPropertiesWrapper systemPropertiesWrapper) { + public AsyncInstantiationController(AsyncInstantiationBusinessLogic asyncInstantiationBL, + InstantiationTemplatesService instantiationTemplates, + AsyncInstantiationRepository asyncInstantiationRepository, RoleProvider roleProvider, + FeatureManager featureManager, SystemPropertiesWrapper systemPropertiesWrapper, + AuditService auditService) { this.asyncInstantiationBL = asyncInstantiationBL; + this.instantiationTemplates = instantiationTemplates; + this.asyncInstantiationRepository = asyncInstantiationRepository; this.roleProvider = roleProvider; this.featureManager = featureManager; this.systemPropertiesWrapper = systemPropertiesWrapper; + this.auditService = auditService; } /** @@ -76,8 +87,13 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { * @return the services list */ @RequestMapping(method = RequestMethod.GET) - public List<ServiceInfo> getServicesInfo(HttpServletRequest request) { - return asyncInstantiationBL.getAllServicesInfo(); + public List<ServiceInfo> getServicesInfo(HttpServletRequest request, + @RequestParam(value = "serviceModelId", required = false) UUID serviceModelId) { + if (serviceModelId == null) { + return asyncInstantiationBL.getAllServicesInfo(); + } else { + return asyncInstantiationRepository.listServicesByServiceModelId(serviceModelId); + } } @RequestMapping(value = "bulk", method = RequestMethod.POST) @@ -158,6 +174,11 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { return new MsoResponseWrapper2(200, uuids); } + @GetMapping("templateTopology/{jobId}") + public ServiceInstantiation getTemplateTopology(HttpServletRequest request, @PathVariable(value="jobId") UUID jobId) { + return instantiationTemplates.getJobRequestAsTemplate(jobId); + } + @RequestMapping(value = "/auditStatusForRetry/{trackById}", method = RequestMethod.GET) public JobAuditStatus getResourceAuditStatus(HttpServletRequest request, @PathVariable(value="trackById") String trackById) { return auditService.getResourceAuditStatus(trackById); diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java b/vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java index 7233a67e3..f5b325b4a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/LoggerController.java @@ -66,7 +66,7 @@ public class LoggerController extends RestrictedBaseController { this.logfilePathCreator = logfilePathCreator; } - @GetMapping(value = "/{loggerName:audit|audit2019|error|metrics|metrics2019}") + @GetMapping(value = "/{loggerName:audit|audit2019|error|metrics|metrics2019|debug}") public String getLog(@PathVariable String loggerName, HttpServletRequest request, @RequestParam(value="limit", defaultValue = "5000") Integer limit) throws IOException { diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java b/vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java index 44bdc813b..d291f9925 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/OperationalEnvironmentController.java @@ -20,10 +20,21 @@ */ package org.onap.vid.controller; +import static org.onap.vid.utils.Logging.getMethodCallerName; +import static org.onap.vid.utils.Logging.getMethodName; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; import io.joshworks.restclient.http.HttpResponse; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; @@ -42,19 +53,13 @@ import org.onap.vid.utils.SystemPropertiesWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.MissingServletRequestParameterException; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.onap.vid.utils.Logging.getMethodCallerName; -import static org.onap.vid.utils.Logging.getMethodName; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("operationalEnvironment") @@ -64,7 +69,7 @@ public class OperationalEnvironmentController extends VidRestrictedBaseControlle private final MsoBusinessLogic msoBusinessLogic; private final SystemPropertiesWrapper systemPropertiesWrapper; - private static final Pattern RECOVERY_ACTION_MESSAGE_PATTERN = Pattern.compile("from String \"(.*)\": value not"); + private static final Pattern RECOVERY_ACTION_MESSAGE_PATTERN = Pattern.compile("from String \"(.*)\": not one"); @Autowired diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java index 91fb94231..cfb848007 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java @@ -58,7 +58,6 @@ import org.onap.vid.properties.VidProperties; import org.onap.vid.scheduler.SchedulerService; import org.onap.vid.scheduler.SchedulerServiceImpl; import org.onap.vid.services.AAIServiceTree; -import org.onap.vid.services.AAITreeNodeBuilder; import org.onap.vid.services.AaiService; import org.onap.vid.services.AaiServiceImpl; import org.onap.vid.services.ChangeManagementService; @@ -66,9 +65,11 @@ import org.onap.vid.services.PombaService; import org.onap.vid.services.PombaServiceImpl; import org.onap.vid.utils.JoshworksJacksonObjectMapper; import org.onap.vid.utils.Logging; +import org.onap.vid.utils.SystemPropertiesWrapper; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.togglz.core.manager.FeatureManager; @@ -100,8 +101,8 @@ public class WebConfig implements WebMvcConfigurer { @Bean public AaiService getAaiService(AaiClientInterface aaiClient, AaiResponseTranslator aaiResponseTranslator, - AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree, ExecutorService executorService) { - return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService); + AAIServiceTree aaiServiceTree, Logging logging, ExecutorService executorService) { + return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService, logging); } @Bean @@ -222,6 +223,8 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new VidLoggingInterceptor()); + registry.addInterceptor( + new VidLoggingInterceptor(new ControllersUtils(new SystemPropertiesWrapper())) + ).order(Ordered.HIGHEST_PRECEDENCE); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt b/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt index 79c7297a3..c26b88a5e 100644 --- a/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt +++ b/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt @@ -86,13 +86,22 @@ class AsyncInstantiationRepository @Autowired constructor(val dataAccessService: private fun filterByCreationDateAndNotDeleted(): String { val minus3Months = LocalDateTime.now().minusMonths(3) val filterDate = Timestamp.valueOf(minus3Months) + return filterServicesByNotHiddenAndNotDeleted() + + " and created >= '" + filterDate + "' " + } + + private fun filterByServiceModelId(serviceModelUuid: UUID): String { + return filterServicesByNotHiddenAndNotDeleted() + + " and SERVICE_MODEL_ID = '$serviceModelUuid'" + } + + private fun filterServicesByNotHiddenAndNotDeleted(): String { return " WHERE" + " hidden = false" + - " and deleted_at is null" + // don't fetch deleted - - " and created >= '" + filterDate + "' " + " and deleted_at is null" // don't fetch deleted } + private fun orderByCreatedDateAndStatus(): String { return " createdBulkDate DESC ,\n" + " (CASE jobStatus\n" + @@ -144,4 +153,7 @@ class AsyncInstantiationRepository @Autowired constructor(val dataAccessService: .joinToString(" $conditionType ") return dataAccessService.getList(className, " WHERE $condition", orderBy, null) as List<T> } + + fun listServicesByServiceModelId(serviceModelId: UUID): List<ServiceInfo> = + dataAccessService.getList(ServiceInfo::class.java, filterByServiceModelId(serviceModelId), orderByCreatedDateAndStatus(), null) as List<ServiceInfo>; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt index 8ce73d713..2fdd19100 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt @@ -62,13 +62,13 @@ class MacroServiceCommand @Autowired constructor( //Aai return bad response while checking names uniqueness catch (exception : ExceptionWithRequestInfo) { - Logger.error("Failed to check name uniqueness in AAI. VID will try again later", exception) + Logger.error(EELFLoggerDelegate.errorLogger, "Failed to check name uniqueness in AAI. VID will try again later", exception) throw TryAgainException(exception); } //Vid reached to max retries while trying to find unique name in AAI catch (exception : MaxRetriesException) { - Logger.error("Failed to find unused name in AAI", exception) + Logger.error(EELFLoggerDelegate.errorLogger, "Failed to find unused name in AAI", exception) throw AbortingException(exception); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt index b35deb892..e46a24f78 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt @@ -11,7 +11,6 @@ import org.onap.vid.changeManagement.RequestDetailsWrapper import org.onap.vid.model.serviceInstantiation.* import org.onap.vid.mso.model.* import org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails.* -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.UserParamMap import org.onap.vid.mso.rest.SubscriberInfo import org.onap.vid.properties.Features import org.onap.vid.services.AsyncInstantiationBusinessLogic @@ -99,15 +98,17 @@ class MsoRequestBuilder return RequestDetailsWrapper(VnfInstantiationRequestDetails(vnfDetails.modelInfo, cloudConfiguration, requestInfo, null, null, null, null)) } - fun generateVfModuleInstantiationRequest(vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, vgInstanceId: String?, userId: String, testApi: String?): RequestDetailsWrapper<VfModuleInstantiationRequestDetails> { + protected fun generateVfModuleRequestWithRequestParams( + vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, + serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, vgInstanceId: String?, userId: String, + requestParameters: (userParams: List<UserParamTypes>) -> RequestParametersVfModuleOrVolumeGroup + ): RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> { val requestInfo = generateRequestInfo(vfModuleDetails.instanceName, ResourceType.VF_MODULE, vfModuleDetails.isRollbackOnFailure, null, userId) //cloud configuration val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) - //request parameters val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams) - val requestParameters = VfModuleInstantiationRequestDetails.RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload, testApi) //related instance list val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo)) @@ -116,14 +117,44 @@ class MsoRequestBuilder volumeGroupModel.modelType = "volumeGroup" relatedInstanceList.add(RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.volumeGroupInstanceName)) } - return RequestDetailsWrapper(VfModuleInstantiationRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters)) + + return RequestDetailsWrapper(VfModuleOrVolumeGroupRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters(userParams))) + } + + fun generateVfModuleInstantiationRequest( + vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, + serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, + vgInstanceId: String?, userId: String, testApi: String? + ): RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> { + val requestParameters = { userParams: List<UserParamTypes> -> + RequestParametersVfModuleOrVolumeGroupInstantiation(userParams, vfModuleDetails.isUsePreload, testApi) + } + + return generateVfModuleRequestWithRequestParams(vfModuleDetails, serviceModelInfo, serviceInstanceId, + vnfModelInfo, vnfInstanceId, vgInstanceId, userId, requestParameters) } + fun generateVfModuleReplaceRequest( + vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, + serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, + vgInstanceId: String?, userId: String, testApi: String? + ): RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> { + val requestParameters = { userParams: List<UserParamTypes> -> + RequestParametersVfModuleUpgrade(userParams, vfModuleDetails.isUsePreload, testApi, + vfModuleDetails.isRetainAssignments, nullSafeNegate(vfModuleDetails.isRetainVolumeGroups)) + } + + return generateVfModuleRequestWithRequestParams(vfModuleDetails, serviceModelInfo, serviceInstanceId, + vnfModelInfo, vnfInstanceId, vgInstanceId, userId, requestParameters) + } + + private fun nullSafeNegate(booleanValue: Boolean?): Boolean? = booleanValue?.not() + fun generateVolumeGroupInstantiationRequest(vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper<VolumeGroupRequestDetails> { val requestInfo = generateRequestInfo(vfModuleDetails.volumeGroupInstanceName, ResourceType.VOLUME_GROUP, vfModuleDetails.isRollbackOnFailure, null, userId) val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams) - val requestParameters = VfModuleInstantiationRequestDetails.RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload, testApi) + val requestParameters = RequestParametersVfModuleOrVolumeGroupInstantiation(userParams, vfModuleDetails.isUsePreload, testApi) val relatedInstances = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo)) vfModuleDetails.modelInfo.modelType = "volumeGroup" @@ -151,10 +182,10 @@ class MsoRequestBuilder return RequestDetailsWrapper(NetworkInstantiationRequestDetails(networkDetails.modelInfo, cloudConfiguration, requestInfo, null, null, null, null)) } - fun generateDeleteVfModuleRequest(vfModuleDetails: VfModule, userId: String): RequestDetailsWrapper<VfModuleInstantiationRequestDetails> { + fun generateDeleteVfModuleRequest(vfModuleDetails: VfModule, userId: String): RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> { val requestInfo = generateRequestInfo(null, null, null, null, userId) val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) - return RequestDetailsWrapper(VfModuleInstantiationRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, null, null)) + return RequestDetailsWrapper(VfModuleOrVolumeGroupRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, null, null)) } private fun generateServiceName(jobId: UUID?, payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String): String? { @@ -178,7 +209,7 @@ class MsoRequestBuilder try { asyncInstantiationBL.updateServiceInfo(jobId) { x -> x.serviceInstanceName = serviceInstanceName } } catch (e: Exception) { - LOGGER.error("Failed updating service name {} in serviceInfo", serviceInstanceName, e) + LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed updating service name {} in serviceInfo", serviceInstanceName, e) } return serviceInstanceName @@ -264,7 +295,7 @@ class MsoRequestBuilder }.collect(Collectors.toList<VfModuleMacro>()) } - fun aggregateAllInstanceParams(instanceParams: Map<String, String>?, supplementaryParams: Map<String, String>?): List<VfModuleInstantiationRequestDetails.UserParamMap<String, String>> { + fun aggregateAllInstanceParams(instanceParams: Map<String, String>?, supplementaryParams: Map<String, String>?): List<UserParamMap<String, String>> { var instanceParamsFinal: Map<String, String> = instanceParams ?: emptyMap() val supplementaryParamsFinal: Map<String, String> = supplementaryParams ?: emptyMap() diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt index 50eada64f..e60919a34 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt @@ -68,11 +68,11 @@ class MsoResultHandlerService fun handleResponse(sharedData: JobSharedData, msoResponse: RestObject<RequestReferencesContainer>, actionDescription: String): MsoResult { return if (msoResponse.statusCode in 200..399) { val msoResourceIds = MsoResourceIds(msoResponse.get().requestReferences.requestId, msoResponse.get().requestReferences.instanceId) - LOGGER.debug("Successfully sent $actionDescription. Request id: ${msoResourceIds.requestId}") + LOGGER.debug(EELFLoggerDelegate.debugLogger, "Successfully sent $actionDescription. Request id: ${msoResourceIds.requestId}") asyncInstantiationBL.addResourceInfo(sharedData, Job.JobStatus.IN_PROGRESS, msoResourceIds.instanceId) MsoResult(Job.JobStatus.COMPLETED_WITH_NO_ACTION, msoResourceIds) } else { - LOGGER.debug("Failed to $actionDescription. Details: ${msoResponse.raw}") + LOGGER.debug(EELFLoggerDelegate.debugLogger, "Failed to $actionDescription. Details: ${msoResponse.raw}") asyncInstantiationBL.addFailedResourceInfo(sharedData, msoResponse) MsoResult(Job.JobStatus.FAILED) } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt index a266dd002..4477a9f24 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt @@ -23,7 +23,6 @@ package org.onap.vid.job.command import com.fasterxml.jackson.module.kotlin.convertValue import org.apache.commons.lang3.ObjectUtils.defaultIfNull -import org.onap.logging.ref.slf4j.ONAPLogConstants import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate import org.onap.vid.changeManagement.RequestDetailsWrapper import org.onap.vid.exceptions.AbortingException @@ -38,7 +37,6 @@ import org.onap.vid.mso.RestMsoImplementation import org.onap.vid.mso.model.ModelInfo import org.onap.vid.utils.JACKSON_OBJECT_MAPPER import org.onap.vid.utils.getEnumFromMapOfStrings -import org.slf4j.MDC import org.springframework.http.HttpMethod import java.util.* @@ -114,7 +112,7 @@ abstract class ResourceCommand( jobStatus = comulateStatusAndUpdatePropertyIfFinal(jobStatus) try { - Logger.debug("job: ${this.javaClass.simpleName} ${sharedData.jobUuid} $actionPhase ${getActionType()} $internalState $jobStatus $childJobs") + Logger.debug(EELFLoggerDelegate.debugLogger, "job: ${this.javaClass.simpleName} ${sharedData.jobUuid} $actionPhase ${getActionType()} $internalState $jobStatus $childJobs") } catch (e:Exception) { /* do nothing. Just failed to log...*/} if (shallStopJob(jobStatus)) { @@ -123,7 +121,7 @@ abstract class ResourceCommand( } val (nextActionPhase, nextInternalState) = calcNextInternalState(jobStatus, internalState, actionPhase) - Logger.debug("next state for job ${sharedData.jobUuid} is $nextInternalState") + Logger.debug(EELFLoggerDelegate.debugLogger, "next state for job ${sharedData.jobUuid} is $nextInternalState") actionPhase = nextActionPhase internalState = nextInternalState @@ -133,7 +131,7 @@ abstract class ResourceCommand( } jobStatus = getExternalInProgressStatus() - Logger.debug("next status for job ${sharedData.jobUuid} is $jobStatus") + Logger.debug(EELFLoggerDelegate.debugLogger, "next status for job ${sharedData.jobUuid} is $jobStatus") // if (internalState.immediate) return call() //shortcut instead of execute another command return NextCommand(jobStatus, this) } @@ -155,7 +153,7 @@ abstract class ResourceCommand( JobStatus.IN_PROGRESS } catch (exception: AbortingException) { - Logger.error("caught AbortingException. Set job status to FAILED") + Logger.error(EELFLoggerDelegate.errorLogger, "caught AbortingException. Set job status to FAILED") JobStatus.FAILED; } } @@ -362,8 +360,6 @@ abstract class ResourceCommand( } protected fun executeAndHandleMsoInstanceRequest(restCallPlan: MsoRestCallPlan): JobStatus { - //make sure requestIds are unique - MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, UUID.randomUUID().toString()) val msoResponse = restMso.restCall( restCallPlan.httpMethod, RequestReferencesContainer::class.java, diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt index c4680b2bd..875de66d6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt @@ -71,13 +71,13 @@ abstract class RootServiceCommand @Autowired constructor( try { val requests = auditService.retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(serviceInstanceId, requestType, scope) if (requests.isEmpty() || requests[0].requestId == null) { - LOGGER.error("Failed to retrieve requestId with type: $type, scope: $scope for service instanceId $serviceInstanceId ") + LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve requestId with type: $type, scope: $scope for service instanceId $serviceInstanceId ") return Job.JobStatus.FAILED } val createMyselfCommand = planResumeMyselfRestCall(requests[0].requestId, sharedData.userId) return executeAndHandleMsoInstanceRequest(createMyselfCommand) } catch (exception: Exception) { - LOGGER.error("Failed to resume instanceId $serviceInstanceId ", exception) + LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to resume instanceId $serviceInstanceId ", exception) return Job.JobStatus.FAILED } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt index bee42fbd4..731625c53 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt @@ -90,7 +90,7 @@ class VfmoduleCommand @Autowired constructor( val originalRequestWithNewestVfmModelInfo = getRequest().cloneWith(vfmModelInfo) - val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest( + val requestDetailsWrapper = msoRequestBuilder.generateVfModuleReplaceRequest( originalRequestWithNewestVfmModelInfo, serviceModelInfo, serviceInstanceId, vnfModelInfo, vnfInstanceId, null, sharedData.userId, sharedData.testApi) @@ -193,7 +193,7 @@ class VfmoduleCommand @Autowired constructor( val replaceMyselfCommand = planReplaceMyselfRestCall(commandParentData) return executeAndHandleMsoInstanceRequest(replaceMyselfCommand) } catch (exception: Exception) { - LOGGER.error("Failed to replace instanceId ${getRequest().instanceId} ", exception) + LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to replace instanceId ${getRequest().instanceId} ", exception) return Job.JobStatus.FAILED } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt index 6f00f9ae6..48ff7b7ac 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt @@ -61,7 +61,7 @@ class VnfCommand @Autowired constructor( try { childJobs = pushChildrenJobsToBroker(vfModules.filter { filterModuleByNeedToCreateBase(it) }, dataForChild, JobType.VolumeGroupInstantiation) } catch (e: AsdcCatalogException) { - LOGGER.error("Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message , e) + LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message , e) //return Job.JobStatus.FAILED throw e; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java index ad4b8c95a..114c20105 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java @@ -85,7 +85,7 @@ public class DeleteOldJobsSchedulerInitializer { Trigger createTrigger() { int minutes = new Random(System.nanoTime()).nextInt(59); int hours = 6; - logger.info("trigger for DeleteOldJobs is {}:{} ", hours, minutes); + logger.info(EELFLoggerDelegate.debugLogger, "trigger for DeleteOldJobs is {}:{} ", hours, minutes); return TriggerBuilder.newTrigger() .withIdentity("DeleteOldJobsTrigger") diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java index d60ddab8d..ba0a9981e 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java @@ -34,7 +34,7 @@ public class DeleteOldJobsWorker extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) { - LOGGER.info("delete old final jobs that has finished before {} seconds", secondsAgo); + LOGGER.info(EELFLoggerDelegate.debugLogger, "delete old final jobs that has finished before {} seconds", secondsAgo); jobsBrokerService.deleteOldFinalJobs(secondsAgo); } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java index 0b277b4d2..c629a665c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java @@ -20,23 +20,28 @@ package org.onap.vid.job.impl; +import static org.onap.vid.job.Job.JobStatus.FAILED; +import static org.onap.vid.job.Job.JobStatus.STOPPED; +import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE; +import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE; + +import java.util.Optional; +import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; +import org.onap.logging.ref.slf4j.ONAPLogConstants; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.job.*; +import org.onap.vid.job.Job; +import org.onap.vid.job.JobCommand; +import org.onap.vid.job.JobException; +import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.NextCommand; import org.onap.vid.job.command.JobCommandFactory; import org.quartz.JobExecutionContext; +import org.slf4j.MDC; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.stereotype.Component; -import java.util.Optional; -import java.util.UUID; - -import static org.onap.vid.job.Job.JobStatus.FAILED; -import static org.onap.vid.job.Job.JobStatus.STOPPED; -import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE; -import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE; - @Component public class JobWorker extends QuartzJobBean { @@ -80,6 +85,8 @@ public class JobWorker extends QuartzJobBean { } protected Job executeJobAndGetNext(Job job) { + setThreadWithRandomRequestId(); + Object internalState = job.getData().get(INTERNAL_STATE); Object actionPhase = job.getData().get(ACTION_PHASE); LOGGER.debug(EELFLoggerDelegate.debugLogger, "going to execute job {} of {}: {}/{} {}/{}", @@ -96,13 +103,18 @@ public class JobWorker extends QuartzJobBean { return setNextCommandInJob(nextCommand, job); } + private void setThreadWithRandomRequestId() { + //make sure requestIds in outgoing requests are not reused + MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, UUID.randomUUID().toString()); + } + private NextCommand executeCommandAndGetNext(Job job) { NextCommand nextCommand; try { final JobCommand jobCommand = jobCommandFactory.toCommand(job); nextCommand = jobCommand.call(); } catch (Exception e) { - LOGGER.error("error while executing job from queue: {}", e); + LOGGER.error(EELFLoggerDelegate.errorLogger, "error while executing job from queue: {}", e); nextCommand = new NextCommand(FAILED); } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java index 74a729494..51803891a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java @@ -20,6 +20,21 @@ package org.onap.vid.job.impl; +import static org.onap.vid.job.Job.JobStatus.CREATING; +import static org.onap.vid.job.Job.JobStatus.FINAL_STATUS; +import static org.onap.vid.job.Job.JobStatus.IN_PROGRESS; +import static org.onap.vid.job.Job.JobStatus.PENDING_RESOURCE; +import static org.onap.vid.job.Job.JobStatus.RESOURCE_IN_PROGRESS; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; import org.hibernate.SessionFactory; import org.jetbrains.annotations.NotNull; @@ -37,14 +52,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import javax.annotation.PostConstruct; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -import static org.onap.vid.job.Job.JobStatus.*; - @Service public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { @@ -252,7 +259,10 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { Integer age = jobDao.getAge(); jobDao.setAge(age + 1); - logger.debug(EELFLoggerDelegate.debugLogger, "{}/{}", jobDao.getStatus(), jobDao.getType()); + logger.debug(EELFLoggerDelegate.debugLogger, "pushing back jobDao {} of {}: {}/{}", + StringUtils.substring(String.valueOf(jobDao.getUuid()), 0, 8), + StringUtils.substring(String.valueOf(jobDao.getTemplateId()), 0, 8), + jobDao.getStatus(), jobDao.getType()); dataAccessService.saveDomainObject(jobDao, DaoUtils.getPropsMap()); } diff --git a/vid-app-common/src/main/java/org/onap/vid/logging/VidLoggingInterceptor.java b/vid-app-common/src/main/java/org/onap/vid/logging/VidLoggingInterceptor.java index abc7048da..fe8b470ec 100644 --- a/vid-app-common/src/main/java/org/onap/vid/logging/VidLoggingInterceptor.java +++ b/vid-app-common/src/main/java/org/onap/vid/logging/VidLoggingInterceptor.java @@ -24,8 +24,12 @@ import java.net.InetAddress; import java.net.UnknownHostException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; +import org.onap.logging.filter.base.MDCSetup; +import org.onap.logging.filter.base.SimpleMap; import org.onap.logging.filter.spring.LoggingInterceptor; import org.onap.logging.ref.slf4j.ONAPLogConstants.MDCs; +import org.onap.vid.controller.ControllersUtils; import org.slf4j.MDC; import org.springframework.web.servlet.ModelAndView; @@ -34,6 +38,11 @@ public class VidLoggingInterceptor extends LoggingInterceptor { static final String INBOUND_INVO_ID = "InboundInvoId"; private static final String canonicalHostName = getCanonicalName(); + private final ControllersUtils controllersUtils; + + public VidLoggingInterceptor(ControllersUtils controllersUtils) { + this.controllersUtils = controllersUtils; + } private static String getCanonicalName() { try { @@ -45,9 +54,30 @@ public class VidLoggingInterceptor extends LoggingInterceptor { } @Override - protected void additionalPreHandling(HttpServletRequest request) { + protected void additionalPreHandling(HttpServletRequest request) { super.additionalPreHandling(request); storeInboundInvocationId(); + fillPartnerNameWithUserId(request); + } + + void fillPartnerNameWithUserId(HttpServletRequest request) { + String userId = controllersUtils.extractUserId(request); + if (StringUtils.isNotEmpty(userId)) { + MDC.put(MDCs.PARTNER_NAME, userId); + } + } + + @Override + //this method override fix bug in logging library + //that may throw some exceptions, e.g. StringIndexOutOfBoundsException + protected String getBasicAuthUserName(SimpleMap headers) { + try { + return super.getBasicAuthUserName(headers); + } catch (Exception e) { + MDCSetup.logger.error("failed to getBasicAuthUserName", e); + } + + return null; } /* @@ -61,6 +91,7 @@ public class VidLoggingInterceptor extends LoggingInterceptor { public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { restoreInvocationId(); fixServerFQDN(); + fillPartnerNameWithUserId(request); super.postHandle(request, response, handler, modelAndView); } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java b/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java index 45e100fb1..6c56a464b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java @@ -20,39 +20,26 @@ package org.onap.vid.model; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.counting; +import static java.util.stream.Collectors.groupingBy; + +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import org.apache.commons.lang3.StringUtils; +import org.onap.vid.mso.model.ModelInfo; +import org.springframework.stereotype.Component; + +@Component public class ModelUtil { - /** - * Gets the tags for the given element according to the configured namespace - * @param namespaces the namespace list from the configuration - * @param constantValue the constant portion of the tag name, i.e. resource.vf... - * @return the tags - */ - public static String[] getTags ( String[] namespaces, String constantValue ) { - String[] tags; - if ( namespaces == null || namespaces.length == 0 ) { - return null; - } - int le = namespaces.length; - tags = new String[le]; - for ( int i = 0; i < le; i++ ) { - tags[i] = namespaces[i] + constantValue; - } - return (tags); - } - /** - * Determine if a note template type matches a set of configurable tags - * @param type the node template type - * @param tags the model configurable namespaces - * @return true if type starts with a tag in the array, false otherwise - */ - public static boolean isType ( String type, String[] tags ) { - if ( (tags != null) && (tags.length > 0) ) { - for ( int i = 0; i < tags.length; i++ ) { - if ( type.startsWith (tags[i]) ) { - return (true); - } - } - } - return (false); + public <T> Map<String, Long> getExistingCounterMap(Map<String, T> nodeList, Function<T, ModelInfo> modelInfoExtractor) { + return nodeList.values().stream() + .map(it -> { + ModelInfo modelInfo = modelInfoExtractor.apply(it); + return StringUtils.defaultIfEmpty(modelInfo.getModelCustomizationId(), modelInfo.getModelVersionId()); + }) + .filter(Objects::nonNull) + .collect(groupingBy(identity(), counting())); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt b/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt index f67d8fbd9..c6de51c1a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt +++ b/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonValue import com.google.common.base.CaseFormat -class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) +data class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) val instantiationUI: InstantiationUI, val modelCategory: ModelCategory, val viewEditUI: InstantiationUI, @@ -41,7 +41,8 @@ class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) TRANSPORT_SERVICE, SERVICE_WITH_COLLECTION_RESOURCE, A_LA_CARTE_VNF_SERVICE_ROLE, - INFRASTRUCTURE_VPN + INFRASTRUCTURE_VPN, + ANY_ALACARTE_WHICH_NOT_EXCLUDED, ; @JsonValue @@ -59,6 +60,8 @@ class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) Transport, SERVICE_WITH_COLLECTION_RESOURCE, INFRASTRUCTURE_VPN, + PORT_MIRRORING, + VLAN_TAGGING, @JsonProperty("other") OTHER } diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/model/AaiGetOperationalEnvironments/OperationalEnvironmentListTest.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ExistingElementsCounterMaps.java index fb79634a5..de63c2c94 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/model/AaiGetOperationalEnvironments/OperationalEnvironmentListTest.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ExistingElementsCounterMaps.java @@ -7,9 +7,9 @@ * 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. @@ -18,17 +18,17 @@ * ============LICENSE_END========================================================= */ -package org.onap.vid.aai.model.AaiGetOperationalEnvironments; +package org.onap.vid.model.aaiTree; -import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; -import static org.hamcrest.MatcherAssert.assertThat; -import org.junit.Test; +import java.util.Map; -public class OperationalEnvironmentListTest { +public interface ExistingElementsCounterMaps { - @Test - public void shouldHaveValidGettersAndSetters(){ - assertThat(OperationalEnvironmentList.class, hasValidGettersAndSetters()); - } + Map<String, Long> getExistingVNFCounterMap(); + Map<String, Long> getExistingNetworksCounterMap(); + + Map<String, Long> getExistingVnfGroupCounterMap(); + + Map<String, Long> getExistingVRFCounterMap(); } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java index 923be132f..78afe1d45 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java @@ -24,7 +24,7 @@ import java.util.HashMap; import java.util.Map; import org.onap.vid.mso.model.ModelInfo; -public class ServiceInstance extends AbstractNode { +public class ServiceInstance extends AbstractNode implements ExistingElementsCounterMaps { private String globalSubscriberId; private String subscriptionServiceType; @@ -198,6 +198,7 @@ public class ServiceInstance extends AbstractNode { this.validationCounter = validationCounter; } + @Override public Map<String, Long> getExistingVNFCounterMap() { return existingVNFCounterMap; } @@ -206,6 +207,7 @@ public class ServiceInstance extends AbstractNode { this.existingVNFCounterMap = existingVNFCounterMap; } + @Override public Map<String, Long> getExistingNetworksCounterMap() { return existingNetworksCounterMap; } @@ -214,6 +216,7 @@ public class ServiceInstance extends AbstractNode { this.existingNetworksCounterMap = existingNetworksCounterMap; } + @Override public Map<String, Long> getExistingVnfGroupCounterMap() { return existingVnfGroupCounterMap; } @@ -230,6 +233,7 @@ public class ServiceInstance extends AbstractNode { this.vrfs = vrfs; } + @Override public Map<String, Long> getExistingVRFCounterMap() { return existingVRFCounterMap; } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java index 8828faf1d..e7e5783c4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java @@ -21,18 +21,19 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; -import org.apache.commons.lang3.ObjectUtils; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.JobType; -import org.onap.vid.model.VidNotions; -import org.onap.vid.mso.model.ModelInfo; - +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.lang3.ObjectUtils; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; +import org.onap.vid.model.VidNotions; +import org.onap.vid.mso.model.ModelInfo; +import org.onap.vid.utils.jackson.BooleanAsStringSerializer; public class ServiceInstantiation extends BaseResource implements JobAdapter.AsyncJobRequest { @@ -127,6 +128,13 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy this.vidNotions = vidNotions; } + @Override + @JsonSerialize(using=BooleanAsStringSerializer.class) + public boolean isRollbackOnFailure() { + // this override is for the BooleanAsStringSerializer annotation, + // but for Service-Instance level only + return super.isRollbackOnFailure(); + } public String getOwningEntityId() { return owningEntityId; diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiationTemplate.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiationTemplate.java new file mode 100644 index 000000000..17ce1bcc3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiationTemplate.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.model.serviceInstantiation; + +import java.util.Map; +import java.util.Objects; +import org.onap.vid.model.aaiTree.ExistingElementsCounterMaps; + +public class ServiceInstantiationTemplate extends ServiceInstantiation implements ExistingElementsCounterMaps { + + private final Map<String, Long> existingVNFCounterMap; + private final Map<String, Long> existingNetworksCounterMap; + private final Map<String, Long> existingVnfGroupCounterMap; + private final Map<String, Long> existingVRFCounterMap; + + public ServiceInstantiationTemplate( + ServiceInstantiation baseService, + Map<String, Long> vnfCounterMap, + Map<String, Long> networksCounterMap, + Map<String, Long> vnfGroupCounterMap, + Map<String, Long> VRFCounterMap + ) { + super( + baseService.getModelInfo(), baseService.getOwningEntityId(), baseService.getOwningEntityName(), + baseService.getProjectName(), baseService.getGlobalSubscriberId(), baseService.getSubscriberName(), + baseService.getProductFamilyId(), baseService.getInstanceName(), baseService.getSubscriptionServiceType(), + baseService.getLcpCloudRegionId(), baseService.getLcpCloudRegionId(), baseService.getTenantId(), + baseService.getTenantName(), baseService.getAicZoneId(), baseService.getAicZoneName(), + baseService.getVnfs(), baseService.getNetworks(), baseService.getVnfGroups(), baseService.getVrfs(), + baseService.getInstanceParams(), baseService.isPause(), baseService.getBulkSize(), + baseService.isRollbackOnFailure(), baseService.isALaCarte(), baseService.getTestApi(), + baseService.getInstanceId(), Objects.toString(baseService.getAction(), null), + baseService.getTrackById(), baseService.getIsFailed(), baseService.getStatusMessage(), + baseService.getVidNotions() + ); + + this.existingVNFCounterMap = vnfCounterMap; + this.existingNetworksCounterMap = networksCounterMap; + this.existingVnfGroupCounterMap = vnfGroupCounterMap; + this.existingVRFCounterMap = VRFCounterMap; + } + + @Override + public Map<String, Long> getExistingVNFCounterMap() { + return existingVNFCounterMap; + } + + @Override + public Map<String, Long> getExistingNetworksCounterMap() { + return existingNetworksCounterMap; + } + + @Override + public Map<String, Long> getExistingVnfGroupCounterMap() { + return existingVnfGroupCounterMap; + } + + @Override + public Map<String, Long> getExistingVRFCounterMap() { + return existingVRFCounterMap; + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java index 41da85e35..ad5b39e28 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; @@ -42,6 +43,12 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest @JsonInclude(NON_NULL) private Boolean usePreload; private Map<String, String> supplementaryParams; + @JsonInclude(NON_NULL) + private final Boolean retainVolumeGroups; + + @JsonInclude(NON_NULL) + private Boolean retainAssignments; + public VfModule(@JsonProperty("modelInfo") ModelInfo modelInfo, @JsonProperty("instanceName") String instanceName, @JsonProperty("volumeGroupName") String volumeGroupInstanceName, @@ -57,12 +64,16 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest @JsonProperty("trackById") String trackById, @JsonProperty("isFailed") Boolean isFailed, @JsonProperty("statusMessage") String statusMessage, + @Nullable @JsonProperty("retainAssignments") Boolean retainAssignments, + @Nullable @JsonProperty("retainVolumeGroups") Boolean retainVolumeGroups, @JsonProperty("position") Integer position) { super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage, position); this.volumeGroupInstanceName = volumeGroupInstanceName; this.usePreload = usePreload; this.supplementaryParams = supplementaryParams; + this.retainAssignments = retainAssignments; + this.retainVolumeGroups = retainVolumeGroups; } public String getVolumeGroupInstanceName() { @@ -93,6 +104,16 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest return JobType.VfmoduleInstantiation; } + @Nullable + public Boolean isRetainAssignments() { + return retainAssignments; + } + + @Nullable + public Boolean isRetainVolumeGroups() { + return retainVolumeGroups; + } + public VfModule cloneWith(ModelInfo modelInfo) { return new VfModule( modelInfo, @@ -110,6 +131,8 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest this.getTrackById(), this.getIsFailed(), this.getStatusMessage(), + this.isRetainAssignments(), + this.isRetainVolumeGroups(), this.getPosition()); } }
\ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleOrVolumeGroupRequestDetails.kt index 3b6cd1d3d..bba4081dd 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleOrVolumeGroupRequestDetails.kt @@ -17,16 +17,11 @@ * limitations under the License. * ============LICENSE_END========================================================= */ +package org.onap.vid.mso.model -package org.onap.vid.mso.model; - -import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL +import java.util.* /* Based on this model: @@ -98,36 +93,33 @@ import java.util.Map; */ -public class VfModuleInstantiationRequestDetails extends BaseResourceInstantiationRequestDetails { - - public VfModuleInstantiationRequestDetails( - @JsonProperty(value = "modelInfo", required = true) ModelInfo modelInfo, - @JsonProperty(value = "cloudConfiguration", required = true) CloudConfiguration cloudConfiguration, - @JsonProperty(value = "requestInfo", required = true) RequestInfo requestInfo, - @JsonProperty(value = "relatedInstanceList", required = true) List<RelatedInstance> relatedInstanceList, - @JsonProperty(value = "requestParameters", required = true) RequestParametersVfModule requestParameters) - { - super(modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters); - } +data class VfModuleOrVolumeGroupRequestDetails( + val modelInfo: ModelInfo, + val cloudConfiguration: CloudConfiguration, + val requestInfo: RequestInfo, + val relatedInstanceList: List<RelatedInstance>?, + val requestParameters: RequestParametersVfModuleOrVolumeGroup?) + : BaseResourceInstantiationRequestDetails(modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters) - public static class RequestParametersVfModule extends BaseResourceInstantiationRequestDetails.RequestParameters { - @JsonInclude(NON_NULL) private final Boolean usePreload; +open class RequestParametersVfModuleOrVolumeGroup internal constructor( + userParams: List<UserParamTypes>, + @get:JsonInclude(NON_NULL) val isUsePreload: Boolean?, + testApi: String? +) : BaseResourceInstantiationRequestDetails.RequestParameters(userParams, testApi) - public RequestParametersVfModule(List<? extends UserParamTypes> userParams, Boolean usePreload, String testApi) { - super(userParams, testApi); - this.usePreload = usePreload; - } +class RequestParametersVfModuleOrVolumeGroupInstantiation( + userParams: List<UserParamTypes>, + usePreload: Boolean?, + testApi: String? +) : RequestParametersVfModuleOrVolumeGroup(userParams, usePreload, testApi) - public Boolean isUsePreload() { - return usePreload; - } - } +class RequestParametersVfModuleUpgrade( + userParams: List<UserParamTypes>, + usePreload: Boolean?, + testApi: String?, + @get:JsonInclude(NON_NULL) val retainAssignments: Boolean?, + @get:JsonInclude(NON_NULL) val rebuildVolumeGroups: Boolean? +) : RequestParametersVfModuleOrVolumeGroup(userParams, usePreload, testApi) - public static class UserParamMap<K,V> extends HashMap<K,V> implements UserParamTypes, Map<K,V> { - - public UserParamMap() { - super(); - } - } -} +class UserParamMap<K, V> : HashMap<K, V>(), UserParamTypes, MutableMap<K, V> diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/VolumeGroupRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/VolumeGroupRequestDetails.java index e1a5e56dd..a637f85dc 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/VolumeGroupRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/VolumeGroupRequestDetails.java @@ -21,7 +21,6 @@ package org.onap.vid.mso.model; import com.fasterxml.jackson.annotation.JsonProperty; - import java.util.List; public class VolumeGroupRequestDetails extends BaseResourceInstantiationRequestDetails { @@ -31,7 +30,7 @@ public class VolumeGroupRequestDetails extends BaseResourceInstantiationRequestD @JsonProperty(value = "cloudConfiguration", required = true) CloudConfiguration cloudConfiguration, @JsonProperty(value = "requestInfo", required = true) RequestInfo requestInfo, @JsonProperty(value = "relatedInstanceList", required = true) List<RelatedInstance> relatedInstanceList, - @JsonProperty(value = "requestParameters", required = true) VfModuleInstantiationRequestDetails.RequestParametersVfModule requestParameters) + @JsonProperty(value = "requestParameters", required = true) RequestParametersVfModuleOrVolumeGroup requestParameters) { super(modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters); } diff --git a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java index abee30025..990ec60c9 100644 --- a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java +++ b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java @@ -29,8 +29,6 @@ public enum Features implements Feature { * Use /docs/feature-flags.md for details */ - CREATE_INSTANCE_TEST, - EMPTY_DRAWING_BOARD_TEST, FLAG_ADD_MSO_TESTAPI_FIELD, FLAG_SERVICE_MODEL_CACHE, FLAG_NETWORK_TO_ASYNC_INSTANTIATION, @@ -38,8 +36,6 @@ public enum Features implements Feature { FLAG_UNASSIGN_SERVICE, FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS, FLAG_SHOW_VERIFY_SERVICE, // AKA POMBA - FLAG_DEFAULT_VNF, - FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD, FLAG_RESTRICTED_SELECT, FLAG_5G_IN_NEW_INSTANTIATION_UI, FLAG_ASYNC_ALACARTE_VNF, @@ -51,7 +47,6 @@ public enum Features implements Feature { FLAG_ENABLE_WEBPACK_MODERN_UI, FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY, FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST, - FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE, FLAG_1810_AAI_LOCAL_CACHE, FLAG_1810_IDENTIFY_SERVICE_FOR_NEW_UI, FLAG_1902_NEW_VIEW_EDIT, @@ -80,7 +75,14 @@ public enum Features implements Feature { FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT, FLAG_FLASH_CLOUD_REGION_AND_NF_ROLE_OPTIONAL_SEARCH, FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE, - FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE + FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI, + FLAG_2002_VNF_PLATFORM_MULTI_SELECT, + FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, + FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND, + FLAG_2004_INSTANTIATION_STATUS_FILTER, + FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE, + FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER, + FLAG_2002_UNLIMITED_MAX, ; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java index d62d5d5d4..7b0e5f56f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java @@ -20,8 +20,25 @@ package org.onap.vid.services; +import static java.util.Comparator.comparing; +import static java.util.stream.Collectors.toSet; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.inject.Inject; +import javax.ws.rs.core.Response; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.util.AAITreeConverter; @@ -36,19 +53,6 @@ import org.onap.vid.utils.Tree; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; -import javax.inject.Inject; -import javax.ws.rs.core.Response; -import java.util.*; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ExecutorService; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.util.Comparator.comparing; -import static java.util.stream.Collectors.toSet; -import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; -import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; - @Component public class AAIServiceTree { @@ -207,12 +211,14 @@ public class AAIServiceTree { Map<String, String> modelNameByModelVersionId = new HashMap<>(); JsonNode models = getModels(aaiClient, invariantIDs); - for (JsonNode model: models) { - JsonNode modelVersions = model.get("model-vers").get("model-ver"); - for (JsonNode modelVersion: modelVersions) { - final String modelVersionId = modelVersion.get("model-version-id").asText(); - modelVersionByModelVersionId.put(modelVersionId, modelVersion.get("model-version").asText()); - modelNameByModelVersionId.put(modelVersionId, modelVersion.get("model-name").asText()); + if (models!=null) { + for (JsonNode model : models) { + JsonNode modelVersions = model.get("model-vers").get("model-ver"); + for (JsonNode modelVersion : modelVersions) { + final String modelVersionId = modelVersion.get("model-version-id").asText(); + modelVersionByModelVersionId.put(modelVersionId, modelVersion.get("model-version").asText()); + modelNameByModelVersionId.put(modelVersionId, modelVersion.get("model-name").asText()); + } } } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java index c8434609e..209f37025 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java @@ -59,6 +59,7 @@ import org.onap.vid.model.aaiTree.FailureAAITreeNode; import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.mso.model.CloudConfiguration; import org.onap.vid.properties.VidProperties; +import org.onap.vid.utils.Logging; import org.onap.vid.utils.Streams; import org.onap.vid.utils.Tree; import org.onap.vid.utils.Unchecked; @@ -71,7 +72,8 @@ import org.springframework.stereotype.Component; public class AAITreeNodeBuilder { private static final String RESULTS = "results"; - private AaiClientInterface aaiClient; + private final AaiClientInterface aaiClient; + private final Logging logging; private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAITreeNodeBuilder.class); @@ -97,8 +99,9 @@ public class AAITreeNodeBuilder { } @Inject - public AAITreeNodeBuilder(AaiClientInterface aaiClient) { + public AAITreeNodeBuilder(AaiClientInterface aaiClient, Logging logging) { this.aaiClient = aaiClient; + this.logging = logging; } List<AAITreeNode> buildNode(NodeType nodeType, @@ -296,13 +299,7 @@ public class AAITreeNodeBuilder { } private <V> Callable<V> withCopyOfMDC(Callable<V> callable) { - //in order to be able to write the correct data while creating the node on a new thread - // save a copy of the current thread's context map, with keys and values of type String. - final Map<String, String> copyOfParentMDC = MDC.getCopyOfContextMap(); - return () -> { - MDC.setContextMap(copyOfParentMDC); - return callable.call(); - }; + return logging.withMDC(MDC.getCopyOfContextMap(), callable); } private List<AAITreeNode> getChildNode(ExecutorService threadPool, ConcurrentSkipListSet<AAITreeNode> nodesAccumulator, diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java index b64a233c7..b3ac16884 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java @@ -87,7 +87,9 @@ import org.onap.vid.model.aaiTree.VpnBinding; import org.onap.vid.model.aaiTree.VpnBindingKt; import org.onap.vid.roles.RoleValidator; import org.onap.vid.utils.Intersection; +import org.onap.vid.utils.Logging; import org.onap.vid.utils.Tree; +import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; @@ -104,6 +106,7 @@ public class AaiServiceImpl implements AaiService { private AaiResponseTranslator aaiResponseTranslator; private AAIServiceTree aaiServiceTree; private ExecutorService executorService; + private final Logging logging; private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class); @@ -113,12 +116,13 @@ public class AaiServiceImpl implements AaiService { AaiClientInterface aaiClient, AaiResponseTranslator aaiResponseTranslator, AAIServiceTree aaiServiceTree, - ExecutorService executorService) + ExecutorService executorService, Logging logging) { this.aaiClient = aaiClient; this.aaiResponseTranslator = aaiResponseTranslator; this.aaiServiceTree = aaiServiceTree; this.executorService = executorService; + this.logging = logging; } private List<Service> convertModelToService(Model model) { @@ -523,10 +527,12 @@ public class AaiServiceImpl implements AaiService { .map(RelatedVnf::from) .collect(Collectors.toList()); + final Map<String, String> copyOfParentMDC = MDC.getCopyOfContextMap(); + try { return executorService.submit(() -> convertedVnfs.parallelStream() - .map(this::enrichRelatedVnfWithCloudRegionAndTenant) + .map(logging.withMDC(copyOfParentMDC, this::enrichRelatedVnfWithCloudRegionAndTenant)) .collect(Collectors.toList()) ).get(); } catch (Exception e) { diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java index 1202fc9e3..bb1121339 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java @@ -20,6 +20,10 @@ package org.onap.vid.services; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; import org.onap.vid.aai.model.ResourceType; import org.onap.vid.job.Job; import org.onap.vid.job.impl.JobSharedData; @@ -28,11 +32,6 @@ import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import java.util.function.Consumer; - public interface AsyncInstantiationBusinessLogic { List<String> PARAMS_TO_IGNORE = Arrays.asList("vnf_name", "vf_module_name"); diff --git a/vid-app-common/src/main/java/org/onap/vid/services/InstantiationTemplatesService.java b/vid-app-common/src/main/java/org/onap/vid/services/InstantiationTemplatesService.java new file mode 100644 index 000000000..aa0031104 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/InstantiationTemplatesService.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.services; + +import static java.util.Collections.emptyMap; +import static java.util.Objects.requireNonNull; + +import java.util.Map; +import java.util.UUID; +import javax.inject.Inject; +import org.onap.vid.dal.AsyncInstantiationRepository; +import org.onap.vid.model.ModelUtil; +import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiationTemplate; +import org.springframework.stereotype.Component; + +@Component +public class InstantiationTemplatesService { + + private final ModelUtil modelUtil; + private final AsyncInstantiationRepository asyncInstantiationRepository; + + @Inject + public InstantiationTemplatesService(ModelUtil modelUtil, + AsyncInstantiationRepository asyncInstantiationRepository) { + this.modelUtil = modelUtil; + this.asyncInstantiationRepository = asyncInstantiationRepository; + } + + public ServiceInstantiationTemplate getJobRequestAsTemplate(UUID jobId) { + ServiceInstantiation jobRequest = requireNonNull(asyncInstantiationRepository.getJobRequest(jobId)); + + return new ServiceInstantiationTemplate( + jobRequest, + counterMap(jobRequest.getVnfs()), + counterMap(jobRequest.getNetworks()), + counterMap(jobRequest.getVnfGroups()), + emptyMap() // model info for VRF is not stored + ); + } + + private <T extends BaseResource> Map<String, Long> counterMap(Map<String, T> nodesToCount) { + return modelUtil.getExistingCounterMap( + nodesToCount, BaseResource::getModelInfo + ); + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/utils/Logging.java b/vid-app-common/src/main/java/org/onap/vid/utils/Logging.java index 0d8e58878..43f059d54 100644 --- a/vid-app-common/src/main/java/org/onap/vid/utils/Logging.java +++ b/vid-app-common/src/main/java/org/onap/vid/utils/Logging.java @@ -33,8 +33,11 @@ import com.google.common.collect.ImmutableList; import io.joshworks.restclient.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.function.Function; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; import org.apache.commons.io.IOUtils; @@ -42,6 +45,8 @@ import org.apache.commons.lang3.StringUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.utils.Unchecked.UncheckedThrowingSupplier; +import org.slf4j.MDC; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestContextHolder; @@ -197,5 +202,29 @@ public class Logging { } } + /** + * in order to be able to write the correct data while creating the node on a new thread save a copy of the current + * thread's context map, with keys and values of type String. + */ + public <T> Callable<T> withMDC(Map<String, String> copyOfParentMDC, Callable<T> callable) { + return () -> withMDCInternal(copyOfParentMDC, callable::call); + } + + /** + * in order to be able to write the correct data while creating the node on a new thread save a copy of the current + * thread's context map, with keys and values of type String. + */ + public <T, U> Function<T, U> withMDC(Map<String, String> copyOfParentMDC, Function<T, U> function) { + return t -> withMDCInternal(copyOfParentMDC, () -> function.apply(t)); + } + + <T> T withMDCInternal(Map<String, String> copyOfParentMDC, UncheckedThrowingSupplier<T> supplier) { + try { + MDC.setContextMap(copyOfParentMDC); + return supplier.get(); + } finally { + MDC.clear(); + } + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/utils/Unchecked.java b/vid-app-common/src/main/java/org/onap/vid/utils/Unchecked.java index 23127b61a..9fb15f690 100644 --- a/vid-app-common/src/main/java/org/onap/vid/utils/Unchecked.java +++ b/vid-app-common/src/main/java/org/onap/vid/utils/Unchecked.java @@ -20,10 +20,11 @@ package org.onap.vid.utils; -import org.onap.vid.exceptions.GenericUncheckedException; - import java.net.URI; import java.net.URISyntaxException; +import java.util.function.Supplier; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.onap.vid.exceptions.GenericUncheckedException; public class Unchecked { private Unchecked() { @@ -39,5 +40,19 @@ public class Unchecked { } } + @FunctionalInterface + public interface UncheckedThrowingSupplier<T> extends Supplier<T> { + + @Override + default T get() { + try { + return getThrows(); + } catch (Exception e) { + return ExceptionUtils.rethrow(e); + } + } + + T getThrows() throws Exception; + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/utils/LoggingTest.java b/vid-app-common/src/main/java/org/onap/vid/utils/jackson/BooleanAsStringSerializer.java index 87fe36372..a61044294 100644 --- a/vid-app-common/src/test/java/org/onap/vid/utils/LoggingTest.java +++ b/vid-app-common/src/main/java/org/onap/vid/utils/jackson/BooleanAsStringSerializer.java @@ -7,9 +7,9 @@ * 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. @@ -18,37 +18,22 @@ * ============LICENSE_END========================================================= */ -package org.onap.vid.utils; +package org.onap.vid.utils.jackson; -import com.att.eelf.configuration.EELFLogger; -import org.junit.Test; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; -public class LoggingTest { +public class BooleanAsStringSerializer extends JsonSerializer<Boolean> { - @Test - public void testGetMethodName() throws Exception { - String result; - - // default test - result = Logging.getMethodName(); + /** + * Annotate a Jackson getter with <code>@JsonSerialize(using=BooleanAsStringSerializer.class)</code> + * to get a boolean value be serialized as quoted string. + */ + @Override + public void serialize(Boolean bool, JsonGenerator generator, SerializerProvider provider) throws IOException { + // bool is guaranteed not to be null + generator.writeString(bool.toString()); } - - @Test - public void testGetMethodCallerName() throws Exception { - String result; - - // default test - result = Logging.getMethodCallerName(); - } - - @Test - public void testGetRequestsLogger() throws Exception { - String serverName = ""; - EELFLogger result; - - // default test - result = Logging.getRequestsLogger(serverName); - } - - } diff --git a/vid-app-common/src/main/resources/catalog.json b/vid-app-common/src/main/resources/catalog.json deleted file mode 100644 index 20c7d5769..000000000 --- a/vid-app-common/src/main/resources/catalog.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "services": { - "0346aa9f-57b7-458a-9681-daf5b19d52b0": { - "uuid": "0346aa9f-57b7-458a-9681-daf5b19d52b0", - "name": "The Worst Service", - "version": "1.0", - "toscaModelURL": "sampleTosca.csar", - "category": "Bad Services", - "lifecycleState": "NOT_CERTIFIED_CHECKOUT", - "lastUpdaterUserId": "example@example.org", - "lastUpdaterFullName": "Example User", - "distributionStatus": "DISTRIBUTION_REJECTED", - "artifacts": [], - "resources": [] - }, - "1346aa9f-57b7-458a-9681-daf5b19d52b1": { - "uuid": "1346aa9f-57b7-458a-9681-daf5b19d52b1", - "name": "The Worst Service", - "version": "1.1", - "toscaModelURL": "sampleTosca.csar", - "category": "Bad Services", - "lifecycleState": "CERTIFIED", - "lastUpdaterUserId": "example@example.org", - "lastUpdaterFullName": "Example User", - "distributionStatus": "DISTRIBUTED", - "artifacts": [], - "resources": [] - }, - "3346aa9f-57b7-458a-9681-daf5b19d52b3": { - "uuid": "3346aa9f-57b7-458a-9681-daf5b19d52b3", - "name": "Bland Service", - "version": "1.9", - "toscaModelURL": "sampleTosca.csar", - "category": "Neutral Services", - "lifecycleState": "CERTIFIED", - "lastUpdaterUserId": "example@example.org", - "lastUpdaterFullName": "Example User", - "distributionStatus": "DISTRIBUTION_NOT_APPROVED", - "artifacts": [], - "resources": [] - }, - "2346aa9f-57b7-458a-9681-daf5b19d52b2": { - "uuid": "2346aa9f-57b7-458a-9681-daf5b19d52b2", - "name": "The Best Service", - "version": "1.3", - "toscaModelURL": "sampleTosca.csar", - "category": "Good Services", - "lifecycleState": "CERTIFIED", - "lastUpdaterUserId": "example@example.org", - "lastUpdaterFullName": "Example User", - "distributionStatus": "DISTRIBUTION_APPROVED", - "artifacts": [ - { - "artifactUUID": "0cf78c81-1246-45e7-a190-eaa309ee5680", - "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680", - "artifactName": "The Worst Artifact", - "artifactType": "HEAT", - "artifactDescription": "This is the worst artifact", - "artifactURL": "http://www.openecomp.org/", - "artifactTimeout": "60", - "artifactChecksum": "A worthy checksum", - "artifactVersion": "0.1" - }, - { - "artifactUUID": "1cf78c81-1246-45e7-a190-eaa309ee5681", - "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680", - "artifactName": "The Worst Artifact", - "artifactType": "HEAT", - "artifactDescription": "This is the worst artifact", - "artifactURL": "http://www.openecomp.org/", - "artifactTimeout": "60", - "artifactChecksum": "A worthy checksum", - "artifactVersion": "0.1" - }, - { - "artifactUUID": "2cf78c81-1246-45e7-a190-eaa309ee5682", - "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680", - "artifactName": "The Worst Artifact", - "artifactType": "HEAT", - "artifactDescription": "This is the worst artifact", - "artifactURL": "http://www.openecomp.org/", - "artifactTimeout": "60", - "artifactChecksum": "A worthy checksum", - "artifactVersion": "0.1" - } - ], - "resources": [] - } - }, - "resources": { - "2f92b5b0-10ff-4cf4-9531-88546fe88a42": { - "uuid": "2f92b5b0-10ff-4cf4-9531-88546fe88a42", - "invariantUUID": "df92b5b0-10ff-4cf4-9531-88546fe88a4d", - "name": "The Worst Resource", - "version": "0.1", - "toscaModelURL": "sampleTosca.csar", - "toscaModel": "http://www.openecomp.org/", - "toscaResourceName": "The Worst Resource (TOSCA)", - "category": "Bad Resources", - "subCategory": "Really Bad Resources", - "resourceType": "VF", - "lifecycleState": "CERTIFIED", - "lastUpdaterUserId": "example@example.org", - "lastUpdaterFullName": "Example User", - "artifacts": [ - { - "artifactUUID": "0cf78c81-1246-45e7-a190-eaa309ee5680", - "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680", - "artifactName": "The Worst Artifact", - "artifactType": "HEAT", - "artifactDescription": "This is the worst artifact", - "artifactURL": "http://www.openecomp.org/", - "artifactTimeout": "60", - "artifactChecksum": "A worthy checksum", - "artifactVersion": "0.1" - }, - { - "artifactUUID": "1cf78c81-1246-45e7-a190-eaa309ee5681", - "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680", - "artifactName": "The Worst Artifact", - "artifactType": "HEAT", - "artifactDescription": "This is the worst artifact", - "artifactURL": "http://www.openecomp.org/", - "artifactTimeout": "60", - "artifactChecksum": "A worthy checksum", - "artifactVersion": "0.1" - }, - { - "artifactUUID": "2cf78c81-1246-45e7-a190-eaa309ee5682", - "generatedFromUUID": "3cf78c81-1246-45e7-a190-eaa309ee5680", - "artifactName": "The Worst Artifact", - "artifactType": "HEAT", - "artifactDescription": "This is the worst artifact", - "artifactURL": "http://www.openecomp.org/", - "artifactTimeout": "60", - "artifactChecksum": "A worthy checksum", - "artifactVersion": "0.1" - } - ] - }, - "0f92b5b0-10ff-4cf4-9531-88546fe88a40": { - "uuid": "0f92b5b0-10ff-4cf4-9531-88546fe88a40", - "invariantUUID": "df92b5b0-10ff-4cf4-9531-88546fe88a4d", - "name": "The Worst Resource", - "version": "0.1", - "toscaModelURL": "sampleTosca.csar", - "toscaModel": "http://www.openecomp.org/", - "toscaResourceName": "The Worst Resource (TOSCA)", - "category": "Bad Resources", - "subCategory": "Really Bad Resources", - "resourceType": "VF", - "lifecycleState": "CERTIFIED", - "lastUpdaterUserId": "example@example.org", - "lastUpdaterFullName": "Example User", - "artifacts": [] - }, - "1f92b5b0-10ff-4cf4-9531-88546fe88a41": { - "uuid": "1f92b5b0-10ff-4cf4-9531-88546fe88a41", - "invariantUUID": "df92b5b0-10ff-4cf4-9531-88546fe88a4d", - "name": "The Worst Resource", - "version": "0.1", - "toscaModelURL": "sampleTosca.csar", - "toscaModel": "http://www.openecomp.org/", - "toscaResourceName": "The Worst Resource (TOSCA)", - "category": "Bad Resources", - "subCategory": "Really Bad Resources", - "resourceType": "VF", - "lifecycleState": "CERTIFIED", - "lastUpdaterUserId": "example@example.org", - "lastUpdaterFullName": "Example User", - "artifacts": [] - } - } -}
\ No newline at end of file diff --git a/vid-app-common/src/main/resources/macro_services_by_invariant_uuid.json b/vid-app-common/src/main/resources/macro_services_by_invariant_uuid.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/vid-app-common/src/main/resources/macro_services_by_invariant_uuid.json @@ -0,0 +1 @@ +[] diff --git a/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties b/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties index 0815accbb..2a0cb5b88 100644 --- a/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties +++ b/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties @@ -1,7 +1,5 @@ FLAG_ENABLE_WEBPACK_MODERN_UI = true FLAG_ASYNC_JOBS = true -CREATE_INSTANCE_TEST = false -EMPTY_DRAWING_BOARD_TEST = false FLAG_ADD_MSO_TESTAPI_FIELD = true FLAG_UNASSIGN_SERVICE = true FLAG_COLLECTION_RESOURCE_SUPPORT = true @@ -10,11 +8,8 @@ FLAG_SERVICE_MODEL_CACHE = true FLAG_SHOW_ASSIGNMENTS = true FLAG_HANDLE_SO_WORKFLOWS = true FLAG_CREATE_ERROR_REPORTS = true - FLAG_SHOW_VERIFY_SERVICE = true FLAG_DUPLICATE_VNF = true -FLAG_DEFAULT_VNF = true -FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD = true FLAG_RESTRICTED_SELECT = false FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS = true FLAG_A_LA_CARTE_AUDIT_INFO=true @@ -27,7 +22,6 @@ FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF = true FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI=false FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST=true FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY=true -FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE = false FLAG_1810_AAI_LOCAL_CACHE = true FLAG_1902_NEW_VIEW_EDIT= false FLAG_EXP_USE_DEFAULT_HOST_NAME_VERIFIER = false @@ -38,3 +32,4 @@ FLAG_FLASH_REDUCED_RESPONSE_CHANGEMG = false FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE = false FLAG_SHOW_ORCHESTRATION_TYPE = false FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE = false +FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI = false diff --git a/vid-app-common/src/main/webapp/WEB-INF/conf/onap.features.properties b/vid-app-common/src/main/webapp/WEB-INF/conf/onap.features.properties index 709de9566..58f677abc 100644 --- a/vid-app-common/src/main/webapp/WEB-INF/conf/onap.features.properties +++ b/vid-app-common/src/main/webapp/WEB-INF/conf/onap.features.properties @@ -1,6 +1,5 @@ FLAG_PNP_INSTANTIATION = true -CREATE_INSTANCE_TEST = false FLAG_ADD_MSO_TESTAPI_FIELD = true FLAG_UNASSIGN_SERVICE = true FLAG_SERVICE_MODEL_CACHE = true @@ -10,7 +9,6 @@ FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS = true FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS = true FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST = true FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY = true -FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE = false FLAG_1810_AAI_LOCAL_CACHE = true FLAG_EXP_USE_DEFAULT_HOST_NAME_VERIFIER = false FLAG_HANDLE_SO_WORKFLOWS = true @@ -22,11 +20,8 @@ FLAG_SHOW_ORCHESTRATION_TYPE = false FLAG_COLLECTION_RESOURCE_SUPPORT = false FLAG_ENABLE_WEBPACK_MODERN_UI = false FLAG_ASYNC_JOBS = false -EMPTY_DRAWING_BOARD_TEST = false FLAG_NETWORK_TO_ASYNC_INSTANTIATION = false FLAG_DUPLICATE_VNF = false -FLAG_DEFAULT_VNF = false -FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD = false FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF = false FLAG_A_LA_CARTE_AUDIT_INFO = false FLAG_5G_IN_NEW_INSTANTIATION_UI = false diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js b/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js index 3575c382d..9cdd5ceb9 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js @@ -197,6 +197,7 @@ appDS2 WELCOME_PATH: "welcome.htm", IS_PERMITTED_SUB_PATH: "&isPermitted=", SERVICE_POPUP_IFRAME_URL: "app/ui/#/servicePopup?serviceModelId=", + INSTANTIATION_TEMPLATES_IFRAME_URL: "app/ui/#/instantiationTemplatesPopup?serviceModelId=", SUB_INTERFACE_POPUP_IFRAME_URL: "app/ui/#/vlan?", VERIFY_SERVICE_URL: "rest/models/services/verifyService", @@ -256,7 +257,6 @@ appDS2 FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS: "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS", FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST: "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST", FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY: "FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY", - FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE: "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE", FLAG_HANDLE_SO_WORKFLOWS: "FLAG_HANDLE_SO_WORKFLOWS", FLAG_CREATE_ERROR_REPORTS: "FLAG_CREATE_ERROR_REPORTS", FLAG_FLASH_CLOUD_REGION_AND_NF_ROLE_OPTIONAL_SEARCH: "FLAG_FLASH_CLOUD_REGION_AND_NF_ROLE_OPTIONAL_SEARCH", @@ -265,6 +265,7 @@ appDS2 FLAG_FLASH_REPLACE_VF_MODULE: "FLAG_FLASH_REPLACE_VF_MODULE", FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT: "FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT", FLAG_SHOW_ORCHESTRATION_TYPE: "FLAG_SHOW_ORCHESTRATION_TYPE", + FLAG_2004_INSTANTIATION_TEMPLATES_POPUP : "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP" } }; diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js index 9037b99f4..673d2f6c4 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js @@ -358,24 +358,14 @@ populate_popup_vfModule(serviceObject, vfModule, vnf);
- if (featureFlags.isOn(COMPONENT.FEATURE_FLAGS.FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE)) {
-
- if (DataService.getLoggedInUserId()) {
- openVfModuleWithHomingDataModal(COMPONENT.DELETE, vfModule);
- }
- else {
- AaiService.getLoggedInUserID(function (response) {
- var userID = response.data;
- DataService.setLoggedInUserId(userID);
- openVfModuleWithHomingDataModal(COMPONENT.DELETE, vfModule);
- });
- }
+ if (DataService.getLoggedInUserId()) {
+ openVfModuleWithHomingDataModal(COMPONENT.DELETE, vfModule);
}
else {
- $scope.$broadcast(COMPONENT.DELETE_RESUME_COMPONENT, {
- componentId: COMPONENT.VF_MODULE,
- callbackFunction: deleteOrResumeCallback,
- dialogMethod: COMPONENT.DELETE
+ AaiService.getLoggedInUserID(function (response) {
+ var userID = response.data;
+ DataService.setLoggedInUserId(userID);
+ openVfModuleWithHomingDataModal(COMPONENT.DELETE, vfModule);
});
}
console.log("Removing VF-Module", vfModule);
@@ -1013,8 +1003,7 @@ var isVfc = false;
_.map($scope.service.model.vnfs, function (value, key) {
- if (value.uuid == vnf.uuid) {
- if (!_.isEmpty(value.vfcInstanceGroups)) {
+ if (value.uuid == vnf.uuid && !_.isEmpty(value.vfcInstanceGroups)) {
isVfc = true;
var queryData = {
serviceModelId: $scope.service.model.service.uuid,
@@ -1030,7 +1019,6 @@ $scope.$broadcast(COMPONENT.IFRAME_DIALOG, queryData);
return;
}
- }
});
DataService.setSubscriberName($scope.service.instance.subscriberName);
@@ -1244,25 +1232,14 @@ DataService.setVfModuleInstanceName(vfModule.object[FIELD.ID.VF_MODULE_NAME]);
setCurrentServiceModelInfoFromScope();
- if (featureFlags.isOn(COMPONENT.FEATURE_FLAGS.FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE)) {
-
- if (DataService.getLoggedInUserId()) {
- openVfModuleWithHomingDataModal(COMPONENT.RESUME, vfModule);
- }
- else {
- AaiService.getLoggedInUserID(function (response) {
- var userID = response.data;
- DataService.setLoggedInUserId(userID);
- openVfModuleWithHomingDataModal(COMPONENT.RESUME, vfModule);
- });
- }
+ if (DataService.getLoggedInUserId()) {
+ openVfModuleWithHomingDataModal(COMPONENT.RESUME, vfModule);
}
else {
- $scope.$broadcast(COMPONENT.DELETE_RESUME_COMPONENT, {
- componentId: COMPONENT.VF_MODULE,
- volumeGroups: vfModule.volumeGroups,
- callbackFunction: deleteOrResumeCallback,
- dialogMethod: COMPONENT.RESUME
+ AaiService.getLoggedInUserID(function (response) {
+ var userID = response.data;
+ DataService.setLoggedInUserId(userID);
+ openVfModuleWithHomingDataModal(COMPONENT.RESUME, vfModule);
});
}
};
diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js index bf3d54af0..110f24ec6 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js @@ -489,8 +489,7 @@ appDS2.controller("aaiSubscriberController", ["COMPONENT", "FIELD", "PARAMETER", if (model && model.vnfs && !_.isEmpty(model.vnfs)) {
Object.keys(model.vnfs).forEach(function (key) {
var vnf = model.vnfs[key];
- if (vnf.vfcInstanceGroups && !_.isEmpty(vnf.vfcInstanceGroups)) {
- if (vnf.uuid === genericVnf.modelVersionId) {
+ if (vnf.vfcInstanceGroups && !_.isEmpty(vnf.vfcInstanceGroups) && vnf.uuid === genericVnf.modelVersionId) {
AaiService.getInstanceGroupsByVNFInstanceId(genericVnf.nodeId,
function (response) { //success
handleGetRelatedInstanceGroupsResponseForVnf(response, genericVnf);
@@ -502,7 +501,6 @@ appDS2.controller("aaiSubscriberController", ["COMPONENT", "FIELD", "PARAMETER", }
)
}
- }
});
}
}
@@ -797,11 +795,9 @@ appDS2.controller("aaiSubscriberController", ["COMPONENT", "FIELD", "PARAMETER", };
$scope.isShowAssignmentsEnabled = function () {
- if (featureFlags.isOn(COMPONENT.FEATURE_FLAGS.FLAG_SHOW_ASSIGNMENTS)) {
- if ($scope.serviceOrchestrationStatus) {
+ if (featureFlags.isOn(COMPONENT.FEATURE_FLAGS.FLAG_SHOW_ASSIGNMENTS) && $scope.serviceOrchestrationStatus) {
return $scope.serviceOrchestrationStatus.toLowerCase() === 'assigned';
}
- }
return false;
};
diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/creationDialogController.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/creationDialogController.js index 15627835e..a35411dd1 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/controller/creationDialogController.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/creationDialogController.js @@ -1,409 +1,413 @@ -/*-
- * ============LICENSE_START=======================================================
- * VID
- * ================================================================================
- * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- */
-
-"use strict";
-
-var creationDialogController = function (COMPONENT, FIELD, PARAMETER, $scope, $http, $timeout, $log,
- CreationService, UtilityService, DataService, VIDCONFIGURATION, $location, $uibModal, featureFlags) {
-
- $scope.isDialogVisible = false;
- $scope.isServiceError = false;
- $scope.summaryControl = {};
- $scope.userProvidedControl = {};
-
-
- var callbackFunction = undefined;
- var componentId = undefined;
-
- $scope.showReportWindow = function() {
-
- let errorMsg;
-
- if($scope.error !== undefined && $scope.error != null) {
- errorMsg = $scope.error;
- } else {
- errorMsg = "";
- }
-
- const modalWindow = $uibModal.open({
- templateUrl: 'app/vid/scripts/modals/report-modal/report-modal.html',
- controller: 'reportModalController',
- controllerAs: 'vm',
- resolve: {
- errorMsg: function () {
- return errorMsg;
- }
- }
- });
-
- $scope.isDialogVisible = false;
- $scope.popup.isVisible = false;
- };
-
- $scope.isShowErrorReport = function() {
- return featureFlags.isOn(COMPONENT.FEATURE_FLAGS.FLAG_CREATE_ERROR_REPORTS);
- };
-
- $scope.shouldShowOldPopup = function () {
- return !DataService.getShouldIncludeInAsyncInstantiationFlow();
- };
-
- function receiveMessage(event) {
- if (event.data == 'closeIframe') {
- window.removeEventListener("message", receiveMessage, false);
-
- $scope.cancel();
- }
- else if (event.data.eventId == 'submitIframe') {
- {
- $location.path('/servicePlanning').search({serviceModelId: event.data.data.serviceModelId});
- }
- }
- $scope.$apply();
- }
-
- $scope.$on(COMPONENT.CREATE_COMPONENT, function (event, request) {
- $scope.isSpinnerVisible = true;
- $scope.isErrorVisible = false;
- $scope.isDataVisible = false;
- $scope.isConfirmEnabled = false;
- $scope.isDialogVisible = true;
- $scope.popup.isVisible = true;
-
-
- if (!$scope.shouldShowOldPopup()) {
- $scope.url = COMPONENT.SERVICE_POPUP_IFRAME_URL + request.modelNameVersionId + "&isCreate=true&r=" + Math.random();
- window.addEventListener("message", receiveMessage, false);
-
- }
- else {
- callbackFunction = request.callbackFunction;
- componentId = request.componentId;
- CreationService.initializeComponent(request.componentId);
-
- CreationService.setHttpErrorHandler(function (response) {
- $scope.isServiceError = true;
- showError(FIELD.ERROR.SYSTEM_FAILURE, UtilityService
- .getHttpErrorMessage(response));
- });
-
- $scope.componentName = CreationService.getComponentDisplayName();
-
- CreationService.getParameters(handleGetParametersResponse);
- }
-
- });
-
- var handleGetParametersResponse = function (parameters) {
- $scope.summaryControl.setList(parameters.summaryList);
- $scope.userProvidedControl.setList(parameters.userProvidedList);
-
- $scope.isSpinnerVisible = false;
- $scope.isDataVisible = true;
- $scope.isConfirmEnabled = true;
- };
-
- var validateInstanceName = function (iname) {
- var patt1 = /^([a-z])+([0-9a-z\-_\.]*)$/i;
-
- if (iname == null) {
- return false;
- }
- if (!iname.match(patt1)) {
- return false;
- }
- return true;
- };
- var validateMap = function (mname) {
- var patt1 = /^{(\s*\w+\s*:\s*\w+\s*)(\s*,\s*\w+\s*:\s*\w+\s*)*}$/im;
- if (mname == null) {
- return true;
- }
- if (!mname.match(patt1)) {
- return false;
- }
- return true;
- };
-
- var validateList = function (lname) {
- var patt1 = /^\[(\s*\w+\s*)(\s*,\s*\w+\s*)*\]$/i;
- if (lname == null) {
- return true;
- }
- if (!lname.match(patt1)) {
- return false;
- }
- return true;
- };
-
- $scope.userParameterChanged = function (id) {
- CreationService.updateUserParameterList(id, $scope.userProvidedControl);
- };
-
- $scope.confirm = function () {
-
- var requiredFields = $scope.userProvidedControl.getRequiredFields();
- if (requiredFields !== "") {
- showError(FIELD.ERROR.MISSING_DATA, requiredFields);
- return;
- }
-
- var isUploadAvailable = false;
- var uploadIndex = 0;
- var paramList = $scope.userProvidedControl.getList();
- var isAnyError = false;
- for (var i = 0; i < paramList.length; i++) {
- if (paramList[i].id === FIELD.ID.SUPPLEMENTORY_DATA_FILE) {
- isUploadAvailable = true;
- uploadIndex = i;
- }
- if (paramList[i].id === FIELD.ID.UPLOAD_SUPPLEMENTORY_DATA_FILE && paramList[i].value && document.getElementById(FIELD.ID.SUPPLEMENTORY_DATA_FILE).value == '') {
- isAnyError = true;
- }
- }
-
- if (isUploadAvailable && isAnyError) {
- showError(FIELD.ERROR.MISSING_DATA, FIELD.ERROR.MISSING_FILE);
-
- } else if (isUploadAvailable && document.getElementById(FIELD.ID.SUPPLEMENTORY_DATA_FILE).value != '') {
- var errorMsg = "";
- var fileInput = document.getElementById(FIELD.ID.SUPPLEMENTORY_DATA_FILE);
- var file = fileInput.files[0];
- var reader = new FileReader();
- reader.onload = function (e) {
- try {
- paramList[uploadIndex].value = JSON.parse(reader.result);
- FIELD.PARAMETER.SUPPLEMENTORY_DATA_FILE['value'] = paramList[uploadIndex].value;
-
- var instanceName = "";
-
- if (DataService.getALaCarte()) {
- if (paramList != null) {
- for (var i = 0; i < paramList.length; i++) {
- if (paramList[i].id === FIELD.ID.INSTANCE_NAME) {
- instanceName = paramList[i].value;
- break;
- }
- }
- }
- var isValid = validateInstanceName(instanceName);
- if (isValid) {
- $scope.isErrorVisible = false;
- } else {
- showError(FIELD.ERROR.INVALID_INSTANCE_NAME + instanceName,
- FIELD.ERROR.INSTANCE_NAME_VALIDATE);
- return;
- }
- }
- var arbitraryParametersList = DataService.getArbitraryParameters();
- var p = null;
- if (UtilityService.hasContents(arbitraryParametersList)) {
- for (var i = 0; i < arbitraryParametersList.length; i++) {
- p = arbitraryParametersList[i];
- if (p.type === PARAMETER.MAP) {
- //validate a map: { <entry_key_1>: <entry_value_1>, ... , <entry_key_n>: <entry_value_n> }
- // need to find the value in paramList
- for (var j = 0; j < paramList.length; j++) {
- if (paramList[j].id === p.id) {
- p.value = paramList[j].value;
- var isValid = validateMap(p.value);
- if (isValid) {
- $scope.isErrorVisible = false;
- break;
- }
- else {
- showError(FIELD.ERROR.INVALID_MAP + p.id,
- FIELD.ERROR.MAP_VALIDATE);
- return;
- }
- }
- }
- } else if (p.type === PARAMETER.LIST) {
- //validate a list: { value or a list of comma separated values }
- // need to find the value in paramList
- for (var j = 0; j < paramList.length; j++) {
- if (paramList[j].id === p.id) {
- p.value = paramList[j].value;
- var isValid = validateList(p.value);
- if (isValid) {
- $scope.isErrorVisible = false;
- break;
- }
- else {
- showError(FIELD.ERROR.INVALID_LIST + p.id,
- FIELD.ERROR.LIST_VALIDATE);
- return;
- }
- }
- }
- }
- }
- }
- var requestDetails = CreationService
- .getMsoRequestDetails($scope.userProvidedControl.getList());
-
- $scope.isDialogVisible = false;
-
- $scope.$broadcast(COMPONENT.MSO_CREATE_REQ, {
- url: CreationService.getMsoUrl(),
- requestDetails: requestDetails,
- componentId: componentId,
- callbackFunction: function (response) {
- if (response.isSuccessful) {
- $scope.popup.isVisible = false;
- runCallback(response);
- } else {
- $scope.isDialogVisible = false;
- $scope.popup.isVisible = false;
- }
- }
- });
-
- } catch (e) {
- errorMsg = errorMsg + FIELD.ERROR.INVALID_DATA_FORMAT;
- }
- if (errorMsg !== "") {
- showError(FIELD.ERROR.SYSTEM_FAILURE, errorMsg);
-
- }
- };
- reader.readAsText(file);
- } else {
-
- var paramList = $scope.userProvidedControl.getList();
- var instanceName = "";
-
- if (DataService.getALaCarte()) {
- if (paramList != null) {
- for (var i = 0; i < paramList.length; i++) {
- if (paramList[i].id === FIELD.ID.INSTANCE_NAME) {
- instanceName = paramList[i].value;
- break;
- }
- }
- }
- var isValid = validateInstanceName(instanceName);
- if (isValid) {
- $scope.isErrorVisible = false;
- } else {
- showError(FIELD.ERROR.INVALID_INSTANCE_NAME + instanceName,
- FIELD.ERROR.INSTANCE_NAME_VALIDATE);
- return;
- }
- }
- var arbitraryParametersList = DataService.getArbitraryParameters();
- var p = null;
- if (UtilityService.hasContents(arbitraryParametersList)) {
- for (var i = 0; i < arbitraryParametersList.length; i++) {
- p = arbitraryParametersList[i];
- if (p.type === PARAMETER.MAP) {
- //validate a map: { <entry_key_1>: <entry_value_1>, ... , <entry_key_n>: <entry_value_n> }
- // need to find the value in paramList
- for (var j = 0; j < paramList.length; j++) {
- if (paramList[j].id === p.id) {
- p.value = paramList[j].value;
- var isValid = validateMap(p.value);
- if (isValid) {
- $scope.isErrorVisible = false;
- break;
- }
- else {
- showError(FIELD.ERROR.INVALID_MAP + p.id,
- FIELD.ERROR.MAP_VALIDATE);
- return;
- }
- }
- }
- } else if (p.type === PARAMETER.LIST) {
- //validate a list: { value or a list of comma separated values }
- // need to find the value in paramList
- for (var j = 0; j < paramList.length; j++) {
- if (paramList[j].id === p.id) {
- p.value = paramList[j].value;
- var isValid = validateList(p.value);
- if (isValid) {
- $scope.isErrorVisible = false;
- break;
- }
- else {
- showError(FIELD.ERROR.INVALID_LIST + p.id,
- FIELD.ERROR.LIST_VALIDATE);
- return;
- }
- }
- }
- }
- }
- }
- var requestDetails = CreationService
- .getMsoRequestDetails($scope.userProvidedControl.getList());
-
- $scope.isDialogVisible = false;
-
- $scope.$broadcast(COMPONENT.MSO_CREATE_REQ, {
- url: CreationService.getMsoUrl(),
- requestDetails: requestDetails,
- componentId: componentId,
- callbackFunction: function (response) {
- if (response.isSuccessful) {
- $scope.popup.isVisible = false;
- runCallback(response);
- } else {
- $scope.isDialogVisible = false;
- $scope.popup.isVisible = false;
- }
- }
- });
- }
- };
-
- $scope.cancel = function () {
- $scope.isDialogVisible = false;
- $scope.popup.isVisible = false;
- runCallback(false);
- };
-
-
- var runCallback = function (response) {
- if (angular.isFunction(callbackFunction)) {
- callbackFunction({
- isSuccessful: response.isSuccessful,
- control: $scope.userProvidedControl.getList(),
- instanceId: response.instanceId
- });
- }
- };
-
- var showError = function (summary, details) {
- var message = summary;
- if (UtilityService.hasContents(details)) {
- message += " (" + details + ")";
- }
- $scope.isSpinnerVisible = false;
- $scope.isErrorVisible = true;
- $scope.error = message;
- }
-
-};
-
-appDS2.controller("creationDialogController", ["COMPONENT", "FIELD", "PARAMETER", "$scope", "$http",
- "$timeout", "$log", "CreationService", "UtilityService", "DataService", "VIDCONFIGURATION", "$location",
- "$uibModal", "featureFlags",
- creationDialogController]);
+/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var creationDialogController = function (COMPONENT, FIELD, PARAMETER, $scope, $http, $timeout, $log, + CreationService, UtilityService, DataService, VIDCONFIGURATION, $location, $uibModal, featureFlags) { + + $scope.isDialogVisible = false; + $scope.isServiceError = false; + $scope.summaryControl = {}; + $scope.userProvidedControl = {}; + + + var callbackFunction = undefined; + var componentId = undefined; + + $scope.showReportWindow = function() { + + let errorMsg; + + if($scope.error !== undefined && $scope.error != null) { + errorMsg = $scope.error; + } else { + errorMsg = ""; + } + + const modalWindow = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/report-modal/report-modal.html', + controller: 'reportModalController', + controllerAs: 'vm', + resolve: { + errorMsg: function () { + return errorMsg; + } + } + }); + + $scope.isDialogVisible = false; + $scope.popup.isVisible = false; + }; + + $scope.isShowErrorReport = function() { + return featureFlags.isOn(COMPONENT.FEATURE_FLAGS.FLAG_CREATE_ERROR_REPORTS); + }; + + $scope.shouldShowOldPopup = function () { + return !DataService.getShouldIncludeInAsyncInstantiationFlow(); + }; + + function receiveMessage(event) { + if (event.data == 'closeIframe') { + window.removeEventListener("message", receiveMessage, false); + + $scope.cancel(); + } + else if (event.data.eventId == 'submitIframe') { + { + $location.path('/servicePlanning').search({serviceModelId: event.data.data.serviceModelId}); + } + } else if (event.data.eventId == 'showPreviousInstantiations') { + { + $location.path('/instantiationStatus').search({filterText: event.data.data.serviceModelId}); + } + } + $scope.$apply(); + } + + $scope.$on(COMPONENT.CREATE_COMPONENT, function (event, request) { + $scope.isSpinnerVisible = true; + $scope.isErrorVisible = false; + $scope.isDataVisible = false; + $scope.isConfirmEnabled = false; + $scope.isDialogVisible = true; + $scope.popup.isVisible = true; + + + if (!$scope.shouldShowOldPopup()) { + $scope.url = COMPONENT.SERVICE_POPUP_IFRAME_URL + request.modelNameVersionId + "&isCreate=true&r=" + Math.random(); + window.addEventListener("message", receiveMessage, false); + + } + else { + callbackFunction = request.callbackFunction; + componentId = request.componentId; + CreationService.initializeComponent(request.componentId); + + CreationService.setHttpErrorHandler(function (response) { + $scope.isServiceError = true; + showError(FIELD.ERROR.SYSTEM_FAILURE, UtilityService + .getHttpErrorMessage(response)); + }); + + $scope.componentName = CreationService.getComponentDisplayName(); + + CreationService.getParameters(handleGetParametersResponse); + } + + }); + + var handleGetParametersResponse = function (parameters) { + $scope.summaryControl.setList(parameters.summaryList); + $scope.userProvidedControl.setList(parameters.userProvidedList); + + $scope.isSpinnerVisible = false; + $scope.isDataVisible = true; + $scope.isConfirmEnabled = true; + }; + + var validateInstanceName = function (iname) { + var patt1 = /^([a-z])+([0-9a-z\-_\.]*)$/i; + + if (iname == null) { + return false; + } + if (!iname.match(patt1)) { + return false; + } + return true; + }; + var validateMap = function (mname) { + var patt1 = /^{(\s*\w+\s*:\s*\w+\s*)(\s*,\s*\w+\s*:\s*\w+\s*)*}$/im; + if (mname == null) { + return true; + } + if (!mname.match(patt1)) { + return false; + } + return true; + }; + + var validateList = function (lname) { + var patt1 = /^\[(\s*\w+\s*)(\s*,\s*\w+\s*)*\]$/i; + if (lname == null) { + return true; + } + if (!lname.match(patt1)) { + return false; + } + return true; + }; + + $scope.userParameterChanged = function (id) { + CreationService.updateUserParameterList(id, $scope.userProvidedControl); + }; + + $scope.confirm = function () { + + var requiredFields = $scope.userProvidedControl.getRequiredFields(); + if (requiredFields !== "") { + showError(FIELD.ERROR.MISSING_DATA, requiredFields); + return; + } + + var isUploadAvailable = false; + var uploadIndex = 0; + var paramList = $scope.userProvidedControl.getList(); + var isAnyError = false; + for (var i = 0; i < paramList.length; i++) { + if (paramList[i].id === FIELD.ID.SUPPLEMENTORY_DATA_FILE) { + isUploadAvailable = true; + uploadIndex = i; + } + if (paramList[i].id === FIELD.ID.UPLOAD_SUPPLEMENTORY_DATA_FILE && paramList[i].value && document.getElementById(FIELD.ID.SUPPLEMENTORY_DATA_FILE).value == '') { + isAnyError = true; + } + } + + if (isUploadAvailable && isAnyError) { + showError(FIELD.ERROR.MISSING_DATA, FIELD.ERROR.MISSING_FILE); + + } else if (isUploadAvailable && document.getElementById(FIELD.ID.SUPPLEMENTORY_DATA_FILE).value != '') { + var errorMsg = ""; + var fileInput = document.getElementById(FIELD.ID.SUPPLEMENTORY_DATA_FILE); + var file = fileInput.files[0]; + var reader = new FileReader(); + reader.onload = function (e) { + try { + paramList[uploadIndex].value = JSON.parse(reader.result); + FIELD.PARAMETER.SUPPLEMENTORY_DATA_FILE['value'] = paramList[uploadIndex].value; + + var instanceName = ""; + + if (DataService.getALaCarte()) { + if (paramList != null) { + for (var i = 0; i < paramList.length; i++) { + if (paramList[i].id === FIELD.ID.INSTANCE_NAME) { + instanceName = paramList[i].value; + break; + } + } + } + var isValid = validateInstanceName(instanceName); + if (isValid) { + $scope.isErrorVisible = false; + } else { + showError(FIELD.ERROR.INVALID_INSTANCE_NAME + instanceName, + FIELD.ERROR.INSTANCE_NAME_VALIDATE); + return; + } + } + var arbitraryParametersList = DataService.getArbitraryParameters(); + var p = null; + if (UtilityService.hasContents(arbitraryParametersList)) { + for (var i = 0; i < arbitraryParametersList.length; i++) { + p = arbitraryParametersList[i]; + if (p.type === PARAMETER.MAP) { + //validate a map: { <entry_key_1>: <entry_value_1>, ... , <entry_key_n>: <entry_value_n> } + // need to find the value in paramList + for (var j = 0; j < paramList.length; j++) { + if (paramList[j].id === p.id) { + p.value = paramList[j].value; + var isValid = validateMap(p.value); + if (isValid) { + $scope.isErrorVisible = false; + break; + } + else { + showError(FIELD.ERROR.INVALID_MAP + p.id, + FIELD.ERROR.MAP_VALIDATE); + return; + } + } + } + } else if (p.type === PARAMETER.LIST) { + //validate a list: { value or a list of comma separated values } + // need to find the value in paramList + for (var j = 0; j < paramList.length; j++) { + if (paramList[j].id === p.id) { + p.value = paramList[j].value; + var isValid = validateList(p.value); + if (isValid) { + $scope.isErrorVisible = false; + break; + } + else { + showError(FIELD.ERROR.INVALID_LIST + p.id, + FIELD.ERROR.LIST_VALIDATE); + return; + } + } + } + } + } + } + var requestDetails = CreationService + .getMsoRequestDetails($scope.userProvidedControl.getList()); + + $scope.isDialogVisible = false; + + $scope.$broadcast(COMPONENT.MSO_CREATE_REQ, { + url: CreationService.getMsoUrl(), + requestDetails: requestDetails, + componentId: componentId, + callbackFunction: function (response) { + if (response.isSuccessful) { + $scope.popup.isVisible = false; + runCallback(response); + } else { + $scope.isDialogVisible = false; + $scope.popup.isVisible = false; + } + } + }); + + } catch (e) { + errorMsg = errorMsg + FIELD.ERROR.INVALID_DATA_FORMAT; + } + if (errorMsg !== "") { + showError(FIELD.ERROR.SYSTEM_FAILURE, errorMsg); + + } + }; + reader.readAsText(file); + } else { + + var paramList = $scope.userProvidedControl.getList(); + var instanceName = ""; + + if (DataService.getALaCarte()) { + if (paramList != null) { + for (var i = 0; i < paramList.length; i++) { + if (paramList[i].id === FIELD.ID.INSTANCE_NAME) { + instanceName = paramList[i].value; + break; + } + } + } + var isValid = validateInstanceName(instanceName); + if (isValid) { + $scope.isErrorVisible = false; + } else { + showError(FIELD.ERROR.INVALID_INSTANCE_NAME + instanceName, + FIELD.ERROR.INSTANCE_NAME_VALIDATE); + return; + } + } + var arbitraryParametersList = DataService.getArbitraryParameters(); + var p = null; + if (UtilityService.hasContents(arbitraryParametersList)) { + for (var i = 0; i < arbitraryParametersList.length; i++) { + p = arbitraryParametersList[i]; + if (p.type === PARAMETER.MAP) { + //validate a map: { <entry_key_1>: <entry_value_1>, ... , <entry_key_n>: <entry_value_n> } + // need to find the value in paramList + for (var j = 0; j < paramList.length; j++) { + if (paramList[j].id === p.id) { + p.value = paramList[j].value; + var isValid = validateMap(p.value); + if (isValid) { + $scope.isErrorVisible = false; + break; + } + else { + showError(FIELD.ERROR.INVALID_MAP + p.id, + FIELD.ERROR.MAP_VALIDATE); + return; + } + } + } + } else if (p.type === PARAMETER.LIST) { + //validate a list: { value or a list of comma separated values } + // need to find the value in paramList + for (var j = 0; j < paramList.length; j++) { + if (paramList[j].id === p.id) { + p.value = paramList[j].value; + var isValid = validateList(p.value); + if (isValid) { + $scope.isErrorVisible = false; + break; + } + else { + showError(FIELD.ERROR.INVALID_LIST + p.id, + FIELD.ERROR.LIST_VALIDATE); + return; + } + } + } + } + } + } + var requestDetails = CreationService + .getMsoRequestDetails($scope.userProvidedControl.getList()); + + $scope.isDialogVisible = false; + + $scope.$broadcast(COMPONENT.MSO_CREATE_REQ, { + url: CreationService.getMsoUrl(), + requestDetails: requestDetails, + componentId: componentId, + callbackFunction: function (response) { + if (response.isSuccessful) { + $scope.popup.isVisible = false; + runCallback(response); + } else { + $scope.isDialogVisible = false; + $scope.popup.isVisible = false; + } + } + }); + } + }; + + $scope.cancel = function () { + $scope.isDialogVisible = false; + $scope.popup.isVisible = false; + runCallback(false); + }; + + + var runCallback = function (response) { + if (angular.isFunction(callbackFunction)) { + callbackFunction({ + isSuccessful: response.isSuccessful, + control: $scope.userProvidedControl.getList(), + instanceId: response.instanceId + }); + } + }; + + var showError = function (summary, details) { + var message = summary; + if (UtilityService.hasContents(details)) { + message += " (" + details + ")"; + } + $scope.isSpinnerVisible = false; + $scope.isErrorVisible = true; + $scope.error = message; + } + +}; + +appDS2.controller("creationDialogController", ["COMPONENT", "FIELD", "PARAMETER", "$scope", "$http", + "$timeout", "$log", "CreationService", "UtilityService", "DataService", "VIDCONFIGURATION", "$location", + "$uibModal", "featureFlags", + creationDialogController]); diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java index 560e6cb5f..7bfc8a68a 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/AAITreeConverterTest.java @@ -20,32 +20,41 @@ */ package org.onap.vid.aai; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.A_LA_CARTE; +import static org.testng.Assert.assertNull; + import com.google.common.collect.ImmutableList; +import java.util.List; import org.mockito.InjectMocks; import org.mockito.MockitoAnnotations; +import org.mockito.Spy; import org.onap.vid.aai.util.AAITreeConverter; import org.onap.vid.model.Action; -import org.onap.vid.model.aaiTree.*; +import org.onap.vid.model.ModelUtil; +import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.CollectionResource; +import org.onap.vid.model.aaiTree.Network; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.model.aaiTree.ServiceInstance; +import org.onap.vid.model.aaiTree.VfModule; +import org.onap.vid.model.aaiTree.Vnf; import org.onap.vid.mso.model.CloudConfiguration; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.util.List; - -import static org.hamcrest.CoreMatchers.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.emptyOrNullString; -import static org.hamcrest.Matchers.hasKey; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.A_LA_CARTE; -import static org.testng.Assert.assertNull; - public class AAITreeConverterTest { + @Spy + private ModelUtil modelUtil; + @InjectMocks private AAITreeConverter aaiTreeConverter; diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/OperationalEnvironmentTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/OperationalEnvironmentTest.java index 076c46284..063b2220c 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/OperationalEnvironmentTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/OperationalEnvironmentTest.java @@ -22,73 +22,94 @@ package org.onap.vid.aai; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Assert; -import org.onap.vid.aai.model.RelationshipList; -import org.testng.annotations.Test; +import static org.assertj.core.api.Assertions.assertThat; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; - -import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; -import static org.assertj.core.api.Assertions.assertThat; +import org.onap.vid.aai.model.RelationshipList; +import org.testng.annotations.Test; public class OperationalEnvironmentTest { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private static final String OPERATIONAL_ENVIRONMENT_TEST = "{\n" + - "\"operational-environment-id\": \"environmentId\",\n" + - "\"operational-environment-name\": \"environmentName\",\n" + - "\"operational-environment-type\": \"environmentType\",\n" + - "\"operational-environment-status\": \"environmentStatus\",\n" + - "\"tenant-context\": \"tenantContext\",\n" + - "\"workload-context\": \"workloadContext\",\n" + - "\"resource-version\": \"resourceVersion\",\n" + - "\"relationship-list\": {\n" + - "\"relationship\": []\n" + - "}\n" + - "}"; + private static final String OPERATIONAL_ENVIRONMENT_JSON_DASHES = "{\n" + + "\"operational-environment-id\": \"testEnvironmentId\",\n" + + "\"operational-environment-name\": \"testEnvironmentName\",\n" + + "\"operational-environment-type\": \"testEnvironmentType\",\n" + + "\"operational-environment-status\": \"testEnvironmentStatus\",\n" + + "\"tenant-context\": \"testTenantContext\",\n" + + "\"workload-context\": \"testWorkloadContext\",\n" + + "\"resource-version\": \"testResourceVersion\",\n" + + "\"relationship-list\": {\n" + + "\"relationship\": []\n" + + "}\n" + + "}"; + + private static final String OPERATIONAL_ENVIRONMENT_JSON_CAMELCASE = "{\n" + + "\"operationalEnvironmentId\": \"testEnvironmentId\",\n" + + "\"operationalEnvironmentName\": \"testEnvironmentName\",\n" + + "\"operationalEnvironmentType\": \"testEnvironmentType\",\n" + + "\"operationalEnvironmentStatus\": \"testEnvironmentStatus\",\n" + + "\"tenantContext\": \"testTenantContext\",\n" + + "\"workloadContext\": \"testWorkloadContext\",\n" + + "\"resourceVersion\": \"testResourceVersion\",\n" + + "\"relationshipList\": {\n" + + "\"relationship\": []\n" + + "}\n" + + "}"; @Test - public void shouldCreateProperOperationalEnvironmentWithConstructor(){ - RelationshipList relationshipList = new RelationshipList(); - relationshipList.relationship = new ArrayList<>(); + public void shouldProperlyConvertJsonToOperationalEnvironment_whenJsonPropertyNamesContainDashSeparators() + throws IOException { + assertOperationalEnvironmentDeserialization(OPERATIONAL_ENVIRONMENT_JSON_DASHES); + } + + @Test + public void shouldProperlyConvertJsonToOperationalEnvironment_whenJsonPropertyNamesAreCamelCase() + throws IOException { + assertOperationalEnvironmentDeserialization(OPERATIONAL_ENVIRONMENT_JSON_CAMELCASE); + } + private void assertOperationalEnvironmentDeserialization(String operationalEnvironmentTestDashes) + throws IOException { OperationalEnvironment operationalEnvironment = - new OperationalEnvironment.OperationalEnvironmentBuilder() - .setOperationalEnvironmentId("testId") - .setOperationalEnvironmentName("testEnvName") - .setOperationalEnvironmentType("testEnvType") - .setOperationalEnvironmentStatus("testEnvStatus") - .setTenantContext("testTenant").setWorkloadContext("testWorkload") - .setResourceVersion("testResource").setRelationshipList(relationshipList) - .createOperationalEnvironment(); - - assertThat(operationalEnvironment.getOperationalEnvironmentId()).isEqualTo("testId"); - assertThat(operationalEnvironment.getWorkloadContext()).isEqualTo("testWorkload"); + OBJECT_MAPPER.readValue(operationalEnvironmentTestDashes, OperationalEnvironment.class); + + assertThat(operationalEnvironment.getOperationalEnvironmentId()).isEqualTo("testEnvironmentId"); + assertThat(operationalEnvironment.getOperationalEnvironmentName()).isEqualTo("testEnvironmentName"); + assertThat(operationalEnvironment.getOperationalEnvironmentType()).isEqualTo("testEnvironmentType"); + assertThat(operationalEnvironment.getOperationalEnvironmentStatus()).isEqualTo("testEnvironmentStatus"); + assertThat(operationalEnvironment.getTenantContext()).isEqualTo("testTenantContext"); + assertThat(operationalEnvironment.getWorkloadContext()).isEqualTo("testWorkloadContext"); + assertThat(operationalEnvironment.getResourceVersion()).isEqualTo("testResourceVersion"); assertThat(operationalEnvironment.getRelationshipList().getRelationship()).hasSize(0); - assertThat(operationalEnvironment.getResourceVersion()).isEqualTo("testResource"); - assertThat(operationalEnvironment.getTenantContext()).isEqualTo("testTenant"); - assertThat(operationalEnvironment.getOperationalEnvironmentType()).isEqualTo("testEnvType"); - assertThat(operationalEnvironment.getOperationalEnvironmentStatus()).isEqualTo("testEnvStatus"); - assertThat(operationalEnvironment.getOperationalEnvironmentName()).isEqualTo("testEnvName"); } @Test - public void shouldProperlyConvertJsonToOperationalEnvironment() throws IOException { - OperationalEnvironment operationalEnvironment = - OBJECT_MAPPER.readValue(OPERATIONAL_ENVIRONMENT_TEST, OperationalEnvironment.class); + public void shouldSerializeToJson_usingActualPropertyNameAsJsonLogicalProperty() throws JsonProcessingException { + RelationshipList relationshipList = new RelationshipList(); + relationshipList.relationship = new ArrayList<>(); - assertThat(operationalEnvironment.getOperationalEnvironmentId()).isEqualTo("environmentId"); - assertThat(operationalEnvironment.getWorkloadContext()).isEqualTo("workloadContext"); - assertThat(operationalEnvironment.getRelationshipList().getRelationship()).hasSize(0); - assertThat(operationalEnvironment.getResourceVersion()).isEqualTo("resourceVersion"); - assertThat(operationalEnvironment.getTenantContext()).isEqualTo("tenantContext"); - assertThat(operationalEnvironment.getOperationalEnvironmentType()).isEqualTo("environmentType"); - assertThat(operationalEnvironment.getOperationalEnvironmentStatus()).isEqualTo("environmentStatus"); - assertThat(operationalEnvironment.getOperationalEnvironmentName()).isEqualTo("environmentName"); + OperationalEnvironment operationalEnvironment = createOperationalEnvironment(relationshipList); + + assertThat(OPERATIONAL_ENVIRONMENT_JSON_CAMELCASE) + .isEqualToIgnoringWhitespace(OBJECT_MAPPER.writeValueAsString(operationalEnvironment)); } + private OperationalEnvironment createOperationalEnvironment(RelationshipList relationshipList) { + return new OperationalEnvironment.OperationalEnvironmentBuilder() + .withOperationalEnvironmentId("testEnvironmentId") + .withOperationalEnvironmentName("testEnvironmentName") + .withOperationalEnvironmentType("testEnvironmentType") + .withOperationalEnvironmentStatus("testEnvironmentStatus") + .withTenantContext("testTenantContext") + .withWorkloadContext("testWorkloadContext") + .withResourceVersion("testResourceVersion") + .withRelationshipList(relationshipList) + .build(); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java index edf7d0862..0f6f25c7b 100644 --- a/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/asdc/parser/VidNotionsBuilderTest.java @@ -23,6 +23,7 @@ package org.onap.vid.asdc.parser; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; @@ -56,6 +57,7 @@ import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; import org.onap.sdc.toscaparser.api.NodeTemplate; import org.onap.sdc.toscaparser.api.Property; import org.onap.sdc.toscaparser.api.elements.Metadata; +import org.onap.vid.asdc.parser.ToscaParserImpl2.Constants; import org.onap.vid.model.CR; import org.onap.vid.model.Network; import org.onap.vid.model.Node; @@ -72,6 +74,9 @@ import org.togglz.core.manager.FeatureManager; public class VidNotionsBuilderTest { + private static final String MACRO_SERVICE_INVARIANT_UUID = "2efab359-cdd4-4da2-9b79-61df990796c2"; + private static final String NOT_MACRO_SERVICE_INVARIANT_UUID = "5d854f6b-759c-4aa6-b472-7e4bb1c003d4"; + @InjectMocks VidNotionsBuilder vidNotionsBuilder; @@ -96,7 +101,7 @@ public class VidNotionsBuilderTest { public void VLNetworkWithPropertyNetworkTechnologyOVS_UIHintIsPositive() { ISdcCsarHelper csarHelper = mockForNonLegacyInstantiationUI(); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ALaCarte), is(InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS)); assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel) , is(ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL)); } @@ -117,20 +122,87 @@ public class VidNotionsBuilderTest { } @DataProvider + public static Object[][] identifyInvariantFeatureFlagDataProvider() { + return new Object[][] { + {false, null, InstantiationType.ClientConfig}, + {false, mock(ServiceModel.class), InstantiationType.ClientConfig}, + {true, null, InstantiationType.ALaCarte}, + {true, mock(ServiceModel.class), InstantiationType.ALaCarte}, + }; + } + + @Test(dataProvider = "identifyInvariantFeatureFlagDataProvider") + public void whenCsarIsEmpty_suggestInstantiationType_byFeatureFlag( + boolean isFlagActive, ServiceModel serviceModel, InstantiationType expectedType) { + when(featureManagerMock.isActive(Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND)).thenReturn(isFlagActive); + if (serviceModel!=null) { + when(serviceModel.getService()).thenReturn(null); + } + assertEquals(expectedType, vidNotionsBuilder.suggestInstantiationType(serviceModel, null)); + } + + @DataProvider + public static Object[][] noMacroNoAlaCarteDataProvider() { + return new Object[][] { + {Constants.CLIENT_CONFIG}, + {"don't know you"}, + {null}, + }; + } + + @Test(dataProvider = "noMacroNoAlaCarteDataProvider") + public void givenNoMacroNorALaCarte_when_FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND_isOff_then_suggestInstantiationType_ClientConfig(String instantiationType) { + ServiceModel serviceModel = mockServiceModelInstantiationTypeAndInvariant(MACRO_SERVICE_INVARIANT_UUID, instantiationType); + when(featureManagerMock.isActive(Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND)).thenReturn(false); + assertEquals(InstantiationType.ClientConfig , vidNotionsBuilder.suggestInstantiationType(serviceModel, null)); + } + + @NotNull + private ServiceModel mockServiceModelInstantiationTypeAndInvariant(String invariantUUID, String instantiationType) { + ServiceModel serviceModel = mock(ServiceModel.class); + Service service = mock(Service.class); + when(serviceModel.getService()).thenReturn(service); + when(service.getInstantiationType()).thenReturn(instantiationType); + when(service.getInvariantUuid()).thenReturn(invariantUUID); + return serviceModel; + } + + @DataProvider + public static Object[][] instantiationTypeByInvariantDataProvider() { + return new Object[][] { + {null, MACRO_SERVICE_INVARIANT_UUID, InstantiationType.Macro}, + {null, NOT_MACRO_SERVICE_INVARIANT_UUID, InstantiationType.ALaCarte}, + {Constants.CLIENT_CONFIG, MACRO_SERVICE_INVARIANT_UUID, InstantiationType.Macro}, + {Constants.BOTH, NOT_MACRO_SERVICE_INVARIANT_UUID, InstantiationType.ALaCarte}, + }; + } + + @Test(dataProvider = "instantiationTypeByInvariantDataProvider") + public void givenNoMacroNorALaCarte_givenFlagIsOn_suggestInstantiationTypeByInvariant( + String givenInstantiationType, String invariantUUID, InstantiationType expectedType + ) { + when(featureManagerMock.isActive(Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND)).thenReturn(true); + ServiceModel serviceModel = mockServiceModelInstantiationTypeAndInvariant(invariantUUID, givenInstantiationType); + assertEquals(expectedType, vidNotionsBuilder.suggestInstantiationType(serviceModel, null)); + } + + @DataProvider public static Object[][] anyAlacarteDataProvider() { return new Object[][] { - {"A-La-Carte", InstantiationUI.ANY_ALACARTE_NEW_UI}, - {"Macro", InstantiationUI.LEGACY}, + {InstantiationType.ALaCarte, InstantiationUI.ANY_ALACARTE_NEW_UI}, + {InstantiationType.Macro, InstantiationUI.LEGACY}, }; } @Test(dataProvider = "anyAlacarteDataProvider") - public void FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI_is_active_UIHintIsPositive(String instantiationType, InstantiationUI expectedInstantiationUI) { + public void FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI_is_active_UIHintIsPositive(InstantiationType instantiationType, InstantiationUI expectedInstantiationUI) { initServiceModelAndscarHelperWithMocks(); + String instantiationTypeAsString = instantiationType==InstantiationType.ALaCarte ? "A-La-Carte" : "Macro"; + when(featureManagerMock.isActive(Features.FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI)).thenReturn(true); when(csarHelper.getServiceMetadata()).thenReturn(new Metadata(ImmutableMap.of( - "instantiationType", instantiationType + "instantiationType", instantiationTypeAsString ))); NodeTemplate nodeTemplate = mock(NodeTemplate.class); @@ -141,7 +213,7 @@ public class VidNotionsBuilderTest { when(csarHelper.getServiceVlList()).thenReturn(ImmutableList.of(nodeTemplate)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(expectedInstantiationUI)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, instantiationType), is(expectedInstantiationUI)); } @Test @@ -157,7 +229,7 @@ public class VidNotionsBuilderTest { when(csarHelper.getServiceVlList()).thenReturn(ImmutableList.of(nodeTemplate)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ALaCarte), is(InstantiationUI.LEGACY)); assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel) , is(ModelCategory.OTHER)); } @@ -167,7 +239,7 @@ public class VidNotionsBuilderTest { assertThat(vidNotionsBuilder.isALaCarte(csarHelper), is(false)); assertThat(vidNotionsBuilder.hasAnyNetworkWithPropertyEqualsToAnyOf(csarHelper, "unexpected_property_name"), is(false)); assertThat(vidNotionsBuilder.hasAnyNetworkWithPropertyEqualsToAnyOf(csarHelper, "network_technology","Standard-SR-IOV"), is(true)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ClientConfig), is(InstantiationUI.LEGACY)); } @Test @@ -175,7 +247,7 @@ public class VidNotionsBuilderTest { initServiceModelAndscarHelperWithRealCsar("/csars/service-fabric-configuration.zip"); assertThat(vidNotionsBuilder.isALaCarte(csarHelper), is(false)); assertThat(vidNotionsBuilder.hasFabricConfiguration(csarHelper), is(true)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ClientConfig), is(InstantiationUI.LEGACY)); } @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) @@ -185,7 +257,7 @@ public class VidNotionsBuilderTest { when(featureManagerMock.isActive(Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI)).thenReturn(flagValue); assertThat(vidNotionsBuilder.isALaCarte(csarHelper), is(false)); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(flagValue ? InstantiationUI.TRANSPORT_SERVICE : InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ClientConfig), is(flagValue ? InstantiationUI.TRANSPORT_SERVICE : InstantiationUI.LEGACY)); assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel), is(ModelCategory.Transport)); } @@ -193,10 +265,59 @@ public class VidNotionsBuilderTest { public void withoutMocks_givenZippedToscaFileOfInfraStructureVpn_InstantiationUIIsRight(boolean flagValue) throws SdcToscaParserException, IOException { initServiceModelAndscarHelperWithRealCsar("/csars/service-Infravpn-csar.zip"); when(featureManagerMock.isActive(Features.FLAG_1908_INFRASTRUCTURE_VPN)).thenReturn(flagValue); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(flagValue ? InstantiationUI.INFRASTRUCTURE_VPN : InstantiationUI.LEGACY)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ClientConfig), is(flagValue ? InstantiationUI.INFRASTRUCTURE_VPN : InstantiationUI.LEGACY)); assertThat(vidNotionsBuilder.suggestModelCategory(csarHelper, serviceModel), is(ModelCategory.INFRASTRUCTURE_VPN)); } + @Test() + public void withoutMocks_givenToscaOfPortMirroring_InstantiationUIIsLegacyAndCategoryIsPortMirroring() throws SdcToscaParserException, IOException { + initServiceModelAndscarHelperWithRealCsar("/csars/portMirroringService.zip"); + when(featureManagerMock.isActive(Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI)).thenReturn(true); + assertThat(vidNotionsBuilder.buildVidNotions(csarHelper, serviceModel), + equalTo(new VidNotions(InstantiationUI.LEGACY, ModelCategory.PORT_MIRRORING, InstantiationUI.LEGACY, InstantiationType.ClientConfig))); + + } + + @Test() + public void withoutMocks_givenToscaOfVLanTagging_InstantiationUIIsLegacyAndCategoryIsVlanTagging() throws SdcToscaParserException, IOException { + initServiceModelAndscarHelperWithRealCsar("/csars/service-VdorotheaSrv-csar.zip"); + when(featureManagerMock.isActive(Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI)).thenReturn(true); + assertThat(vidNotionsBuilder.buildVidNotions(csarHelper, serviceModel), + equalTo(new VidNotions(InstantiationUI.LEGACY, ModelCategory.VLAN_TAGGING, InstantiationUI.LEGACY, InstantiationType.ALaCarte))); + } + + @Test + public void withoutMocks_givenToscaWithoutTypeAndFlagOn_InstantiationUIisAlacarte() + throws SdcToscaParserException, IOException { + initServiceModelAndscarHelperWithRealCsar("/csars/service-Vocg1804Svc.zip"); + when(featureManagerMock.isActive(Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI)).thenReturn(true); + assertThat(vidNotionsBuilder.buildVidNotions(csarHelper, serviceModel), + equalTo(new VidNotions( + InstantiationUI.ANY_ALACARTE_WHICH_NOT_EXCLUDED, + ModelCategory.OTHER, + InstantiationUI.LEGACY, + InstantiationType.ClientConfig))); + } + + @DataProvider + public static Object[][] anyAlaCarteDataProvider() { + return new Object[][] { + {true, InstantiationType.ALaCarte, InstantiationUI.ANY_ALACARTE_WHICH_NOT_EXCLUDED}, + {false, InstantiationType.ALaCarte, InstantiationUI.LEGACY}, + {true, InstantiationType.Macro, InstantiationUI.LEGACY}, + {true, InstantiationType.ClientConfig, InstantiationUI.ANY_ALACARTE_WHICH_NOT_EXCLUDED}, + {true, null, InstantiationUI.ANY_ALACARTE_WHICH_NOT_EXCLUDED}, + }; + } + + @Test(dataProvider = "anyAlaCarteDataProvider") + public void testAnyAlaCarteNewUI_byInstantiationTypeAndFeatureFlag(boolean flag, InstantiationType instantiationType, InstantiationUI expected) { + initServiceModelAndscarHelperWithMocks(); + //mockInstantiationType(serviceModel, instantiationType); + when(featureManagerMock.isActive(Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI)).thenReturn(flag); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, instantiationType), is(expected)); + } + @Test public void uuidIsExactly1ffce89fEtc_UIHintIsPositive() { initServiceModelAndscarHelperWithMocks(); @@ -205,7 +326,7 @@ public class VidNotionsBuilderTest { "UUID", "95eb2c44-bff2-4e8b-ad5d-8266870b7717" ))); when(featureManagerMock.isActive(Features.FLAG_5G_IN_NEW_INSTANTIATION_UI)).thenReturn(true); - assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel), is(InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de)); + assertThat(vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ClientConfig), is(InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de)); } @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) @@ -216,6 +337,12 @@ public class VidNotionsBuilderTest { assertThat(vidNotionsBuilder.buildVidNotions(csarHelper, serviceModel), hasProperty("instantiationUI", is(InstantiationUI.LEGACY))); } + private void mockInstantiationType(ServiceModel serviceModel, String instantiationType) { + Service mockService = mock(Service.class); + when(serviceModel.getService()).thenReturn(mockService); + when(mockService.getInstantiationType()).thenReturn(instantiationType); + } + @DataProvider public static Object[][] ServiceRoleTypesDataProvider() { return new Object[][] { @@ -232,7 +359,7 @@ public class VidNotionsBuilderTest { "serviceRole", serviceRole ))); - assertThat(vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel), is(expectedViewEditUI)); + assertThat(vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ClientConfig), is(expectedViewEditUI)); } @DataProvider @@ -256,11 +383,9 @@ public class VidNotionsBuilderTest { when(featureManagerMock.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)).thenReturn(isFlag1902NewViewEdit); ServiceModel serviceModel = mock(ServiceModel.class); - Service service = mock(Service.class); - when(serviceModel.getService()).thenReturn(service); - when(service.getInstantiationType()).thenReturn(ToscaParserImpl2.Constants.A_LA_CARTE); + mockInstantiationType(serviceModel, Constants.A_LA_CARTE); - InstantiationUI result = vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel); + InstantiationUI result = vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ClientConfig); assertEquals(expectedViewEditUi, result); } @@ -302,9 +427,7 @@ public class VidNotionsBuilderTest { @Test(dataProvider="toscaParserInstantiationTypeToVidNotion") public void testSuggestInstantiationTypeWhenInstantiationUiLegacy(String toscaParserInstantiationType, InstantiationType expectedInstantiationType) { ServiceModel serviceModel = mock(ServiceModel.class); - Service service = mock(Service.class); - when(serviceModel.getService()).thenReturn(service); - when(service.getInstantiationType()).thenReturn(toscaParserInstantiationType); + mockInstantiationType(serviceModel, toscaParserInstantiationType); assertEquals(expectedInstantiationType, vidNotionsBuilder.suggestInstantiationType(serviceModel, ModelCategory.OTHER)); } @@ -326,9 +449,7 @@ public class VidNotionsBuilderTest { boolean isFeatureOn, InstantiationType expectedInstantiationType) { ServiceModel serviceModel = mock(ServiceModel.class); - Service service = mock(Service.class); - when(serviceModel.getService()).thenReturn(service); - when(service.getInstantiationType()).thenReturn(ToscaParserImpl2.Constants.A_LA_CARTE); + mockInstantiationType(serviceModel, Constants.A_LA_CARTE); when(featureManagerMock.isActive(featureFlag)).thenReturn(isFeatureOn); assertEquals(expectedInstantiationType, vidNotionsBuilder.suggestInstantiationType(serviceModel, instantiationUI)); } @@ -378,9 +499,7 @@ public class VidNotionsBuilderTest { @Test public void whenInstantiationTypeInServiceModelIsNull_thenInstantiationTypeIsClientConfig() { initServiceModelAndscarHelperWithMocks(); - Service service = mock(Service.class); - when(serviceModel.getService()).thenReturn(service); - when(service.getInstantiationType()).thenReturn(null); + mockInstantiationType(serviceModel, null); assertEquals( InstantiationType.ClientConfig, vidNotionsBuilder.suggestInstantiationType(serviceModel, ModelCategory.OTHER)); } @@ -420,7 +539,7 @@ public class VidNotionsBuilderTest { emptyMap() : ImmutableMap.of(ToscaParserImpl2.Constants.SERVICE_ROLE, serviceRole) )); - assertEquals(expectedViewEditUi, vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel)); + assertEquals(expectedViewEditUi, vidNotionsBuilder.suggestInstantiationUI(csarHelper, serviceModel, ModelCategory.OTHER, InstantiationType.ALaCarte)); } private static NodeTemplate mockNodeTemplateChild(boolean withFabricConfiguration) { @@ -474,14 +593,32 @@ public class VidNotionsBuilderTest { initServiceModelAndscarHelperWithMocks(); Service service = mock(Service.class); - String instantiationType = isMacro ? ToscaParserImpl2.Constants.MACRO : ToscaParserImpl2.Constants.A_LA_CARTE; + InstantiationType instantiationType = isMacro ? InstantiationType.Macro : InstantiationType.ALaCarte; when(serviceModel.getService()).thenReturn(service); - when(service.getInstantiationType()).thenReturn(instantiationType); when(featureManagerMock.isActive(Features.FLAG_1908_MACRO_NOT_TRANSPORT_NEW_VIEW_EDIT)).thenReturn(flagActive); when(featureManagerMock.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)).thenReturn(false); when(csarHelper.getServiceMetadata()).thenReturn(new Metadata(isTransport ? ImmutableMap.of(ToscaParserImpl2.Constants.SERVICE_TYPE, "TRANSPORT") : emptyMap() )); - assertEquals(expectedViewEditUi, vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel)); + assertEquals(expectedViewEditUi, vidNotionsBuilder.suggestViewEditUI(csarHelper, serviceModel, ModelCategory.OTHER, instantiationType)); + } + + @DataProvider + public static Object[][] invariantUuidToMacroDataProvider() { + return new Object[][]{ + {"117f5f1a-1b47-4ae1-ae04-489c9a7ada28", true}, + {"117F5f1a-1b47-4AE1-ae04-489C9A7ada28", true}, + {MACRO_SERVICE_INVARIANT_UUID, true}, + {"67e09a1f-9e42-4b63-8dee-bc60bae50de1", false}, + {"67e09A1F-9E42-4b63-8Dee-bc60bae50de1", false}, + {NOT_MACRO_SERVICE_INVARIANT_UUID, false}, + {"I'm not a uuid", false}, + {null, false}, + }; + } + + @Test(dataProvider = "invariantUuidToMacroDataProvider") + public void testIsMacroByInvariantUuid(String uuid, boolean expectedIsMacro) { + assertEquals(expectedIsMacro, vidNotionsBuilder.isMacroByInvariantUuid(uuid)); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java index 5a2eb59d2..bf33eff94 100644 --- a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java @@ -42,10 +42,13 @@ import com.xebialabs.restito.semantics.Condition; import com.xebialabs.restito.server.StubServer; import io.joshworks.restclient.http.HttpResponse; import io.joshworks.restclient.http.JsonNode; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Collections; import java.util.Map; import org.glassfish.grizzly.http.Method; import org.glassfish.grizzly.http.util.HttpStatus; +import org.jetbrains.annotations.NotNull; import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; import org.testng.annotations.AfterMethod; @@ -76,11 +79,20 @@ public class SyncRestClientForHttpServerTest { syncRestClient.destroy(); } + @NotNull + private String getTestUrl(String protocol) { + try { + return new URI(protocol, null, "127.0.0.1" , stubServer.getPort(), "/test", null, null).toString(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + @Test public void testJsonResponseFromGet() throws JsonProcessingException { // given stubGetCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .get(url, Collections.emptyMap(), Collections.emptyMap()); @@ -97,7 +109,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromGet() throws JsonProcessingException { // given stubGetCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> testModelHttpResponse = syncRestClient .get(url, Collections.emptyMap(), Collections.emptyMap(), SyncRestClientModel.TestModel.class); @@ -114,7 +126,7 @@ public class SyncRestClientForHttpServerTest { public void testJsonResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.post(url, Collections.emptyMap(), testObject); // then @@ -130,7 +142,7 @@ public class SyncRestClientForHttpServerTest { public void test404JsonResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .post(url, Collections.emptyMap(), NOT_EXISTING_OBJECT); @@ -146,7 +158,7 @@ public class SyncRestClientForHttpServerTest { // given stubPostCall(); Map headers = ImmutableMap.<String, String>builder().put("Authorization", "Basic anyHash").build(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.post(url, headers, testObject); // then @@ -160,7 +172,7 @@ public class SyncRestClientForHttpServerTest { public void testFailedJsonResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when stubServer.stop(); syncRestClient.post(url, Collections.emptyMap(), testObject); @@ -170,7 +182,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> objectHttpResponse = syncRestClient .post(url, Collections.emptyMap(), testObject, SyncRestClientModel.TestModel.class); @@ -187,7 +199,7 @@ public class SyncRestClientForHttpServerTest { public void testJsonResponseFromPut() throws JsonProcessingException { // given stubPutCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.put(url, Collections.emptyMap(), testObject); // then @@ -203,7 +215,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromPut() throws JsonProcessingException { // given stubPutCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> modelHttpResponse = syncRestClient .put(url, Collections.emptyMap(), testObject, SyncRestClientModel.TestModel.class); @@ -220,7 +232,7 @@ public class SyncRestClientForHttpServerTest { public void testJsonResponseFromDelete() throws JsonProcessingException { // given stubDeleteCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.delete(url, Collections.emptyMap()); // then @@ -236,7 +248,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromDelete() throws JsonProcessingException { // given stubDeleteCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> modelHttpResponse = syncRestClient .delete(url, Collections.emptyMap(), SyncRestClientModel.TestModel.class); @@ -253,8 +265,8 @@ public class SyncRestClientForHttpServerTest { public void testRedirectToHttp() throws JsonProcessingException { // given stubGetCall(); - String secured_url = "https://0.0.0.0:" + stubServer.getPort() + "/test"; - String available_url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String secured_url = getTestUrl("https");; + String available_url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .get(secured_url, Collections.emptyMap(), Collections.emptyMap()); diff --git a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java index 645b5eac0..27cd81e70 100644 --- a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java @@ -42,8 +42,8 @@ import com.xebialabs.restito.semantics.Condition; import com.xebialabs.restito.server.StubServer; import io.joshworks.restclient.http.HttpResponse; import io.joshworks.restclient.http.JsonNode; - -import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -55,13 +55,13 @@ import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; - import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.ssl.SSLContextBuilder; import org.glassfish.grizzly.http.Method; +import org.jetbrains.annotations.NotNull; import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; import org.testng.annotations.AfterMethod; @@ -91,12 +91,21 @@ public class SyncRestClientForHttpsServerTest { stubServer.stop(); } + @NotNull + private String getTestUrl(String protocol) { + try { + return new URI(protocol, null, "127.0.0.1" , stubServer.getPort(), "/test", null, null).toString(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + @Test public void testJsonResponseFromGet() throws JsonProcessingException { // given stubGetCall(); - String securedUrl = "https://0.0.0.0:" + stubServer.getPort() + "/test"; - String notSecuredUrl = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String securedUrl = getTestUrl("https"); + String notSecuredUrl = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .get(securedUrl, Collections.emptyMap(), Collections.emptyMap()); @@ -115,8 +124,8 @@ public class SyncRestClientForHttpsServerTest { // given stubServer.run(); stubGetCall(); - String securedUrl = "https://0.0.0.0:" + stubServer.getPort() + "/test"; - String notSecuredUrl = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String securedUrl = getTestUrl("https"); + String notSecuredUrl = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> testModelHttpResponse = syncRestClient .get(securedUrl, Collections.emptyMap(), Collections.emptyMap(), SyncRestClientModel.TestModel.class); diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java b/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java index 51bdec882..521102383 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java @@ -57,8 +57,10 @@ import org.onap.vid.aai.AaiResponseTranslator; import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigData; import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigDataError; import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigDataOk; +import org.onap.vid.aai.OperationalEnvironment; import org.onap.vid.aai.model.AaiGetAicZone.AicZones; import org.onap.vid.aai.model.AaiGetAicZone.Zone; +import org.onap.vid.aai.model.AaiGetOperationalEnvironments.OperationalEnvironmentList; import org.onap.vid.aai.model.AaiGetPnfs.Pnf; import org.onap.vid.aai.model.PortDetailsTranslator.PortDetails; import org.onap.vid.aai.model.PortDetailsTranslator.PortDetailsError; @@ -561,5 +563,27 @@ public class AaiControllerTest { .andExpect(content().string(expectedResponse)); } + @Test + public void getOperationalEnvironments_shouldReturnOkResponse() throws Exception { + String operationalEnvironmentType = "testEnvType"; + String operationalEnvironmentStatus = "testEnvStatus"; + OperationalEnvironmentList operationalEnvironmentList = new OperationalEnvironmentList( + ImmutableList.of(OperationalEnvironment.builder() + .withOperationalEnvironmentType(operationalEnvironmentType) + .withOperationalEnvironmentStatus(operationalEnvironmentStatus) + .build())); + AaiResponse<OperationalEnvironmentList> aaiResponse = new AaiResponse<>(operationalEnvironmentList, null, + HttpStatus.OK.value()); + given(aaiService.getOperationalEnvironments(operationalEnvironmentType, operationalEnvironmentStatus)) + .willReturn(aaiResponse); + + mockMvc.perform(get("/get_operational_environments") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .param("operationalEnvironmentType", operationalEnvironmentType) + .param("operationalEnvironmentStatus", operationalEnvironmentStatus)) + .andExpect(status().isOk()) + .andExpect(content().json(objectMapper.writeValueAsString(aaiResponse))); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java b/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java index fcc314a3c..681f9d1ab 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/LocalWebConfig.java @@ -40,7 +40,6 @@ import org.onap.vid.asdc.AsdcClient; import org.onap.vid.asdc.parser.ToscaParserImpl2; import org.onap.vid.asdc.parser.VidNotionsBuilder; import org.onap.vid.services.AAIServiceTree; -import org.onap.vid.services.AAITreeNodeBuilder; import org.onap.vid.services.AaiService; import org.onap.vid.services.AaiServiceImpl; import org.onap.vid.services.VidService; @@ -72,8 +71,8 @@ public class LocalWebConfig { @Bean public AaiService getAaiService(AaiClientInterface aaiClient, AaiResponseTranslator aaiResponseTranslator, - AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree, ExecutorService executorService) { - return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService); + AAIServiceTree aaiServiceTree, Logging logging, ExecutorService executorService) { + return new AaiServiceImpl(aaiClient, aaiResponseTranslator, aaiServiceTree, executorService, logging); } @Bean diff --git a/vid-app-common/src/test/java/org/onap/vid/controller/LoggerControllerTest.java b/vid-app-common/src/test/java/org/onap/vid/controller/LoggerControllerTest.java index fdc0f44d1..f0d840929 100644 --- a/vid-app-common/src/test/java/org/onap/vid/controller/LoggerControllerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/controller/LoggerControllerTest.java @@ -108,4 +108,19 @@ public class LoggerControllerTest { .andExpect(content().string("")) .andExpect(status().isOk()); } + + @Test + public void shouldReturnEmptyString_whenDebugLogFileIsEmpty() throws Exception { + List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1")); + + given(provider.getUserRoles(argThat(req -> req.getRequestedSessionId().equals("id1")))).willReturn(list); + given(provider.userPermissionIsReadLogs(list)).willReturn(true); + given(creator.getLogfilePath("debug")).willReturn(EMPTY_LOG_PATH); + + mockMvc.perform(get("/logger/debug") + .with(req -> {req.setRequestedSessionId("id1"); + return req;})) + .andExpect(content().string("")) + .andExpect(status().isOk()); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java b/vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java index be5a44e82..012c37f4d 100644 --- a/vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/dal/AsyncInstantiationRepositoryTest.java @@ -20,18 +20,23 @@ package org.onap.vid.dal; +import static java.util.stream.Collectors.toList; import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.core.IsEqual.equalTo; +import static org.onap.vid.job.Job.JobStatus.COMPLETED; import com.google.common.collect.ImmutableList; +import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.stream.Collectors; import javax.inject.Inject; import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.util.SystemProperties; @@ -39,6 +44,7 @@ import org.onap.vid.config.DataSourceConfig; import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig; import org.onap.vid.job.Job; import org.onap.vid.model.ResourceInfo; +import org.onap.vid.model.ServiceInfo; import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.rest.AsyncRequestStatus; import org.onap.vid.mso.rest.RequestStatus; @@ -46,6 +52,7 @@ import org.onap.vid.services.AsyncInstantiationBaseTest; import org.onap.vid.utils.TimeUtils; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class}) @@ -53,19 +60,56 @@ public class AsyncInstantiationRepositoryTest extends AsyncInstantiationBaseTest @Inject private DataAccessService dataAccessService; + private AsyncInstantiationRepository asyncInstantiationRepository; @BeforeClass void initServicesInfoService() { + asyncInstantiationRepository = new AsyncInstantiationRepository(dataAccessService); createInstanceParamsMaps(); + createNewTestServicesInfoWithServiceModelID(); + } + + private void createNewTestServicesInfoWithServiceModelID() { + + LocalDateTime NOW = LocalDateTime.now(); + + addNewServiceInfo(UUID.randomUUID(), "abc", "1", NOW.minusYears(1L), NOW, COMPLETED, false, false, + MODEL_UUID); + addNewServiceInfo(UUID.randomUUID(), "abc", "2", NOW, NOW, COMPLETED, false, false, + MODEL_UUID_2); + addNewServiceInfo(UUID.randomUUID(), "abc", "3", NOW, NOW, COMPLETED, false, false, + MODEL_UUID); + addNewServiceInfo(UUID.randomUUID(), "abc", "hidden", NOW, NOW, COMPLETED, true, false, + MODEL_UUID); + } + + @DataProvider + public static Object[][] listServicesByServiceModelIdDataProvider() { + return new Object[][]{ + { "services info filtered by MODEL_UUID not hidden , ordered by newer first", MODEL_UUID, "3", "1" }, + { "services info filtered by MODEL_UUID2", MODEL_UUID_2, "2" }, + }; + } + + @Test(dataProvider = "listServicesByServiceModelIdDataProvider") + public void testListServicesByServiceModelId(String desc, String modelUUID, String... expectedResult) { + List<ServiceInfo> serviceInfoListResult = asyncInstantiationRepository.listServicesByServiceModelId(UUID.fromString(modelUUID)); + assertThat(desc, serviceInfoListResult.stream().map(ServiceInfo::getServiceInstanceName).collect(toList()), + contains(expectedResult)); + } + + @Test + public void whenFilterServiceByNotExistUUID_emptyListIsReturned() { + List<ServiceInfo> serviceInfoListResult = asyncInstantiationRepository.listServicesByServiceModelId(UUID.randomUUID()); + assertThat(serviceInfoListResult, is(empty())); } @Test public void whenSaveNewRequest_thenRequestIsRetrieved() { - AsyncInstantiationRepository underTest = new AsyncInstantiationRepository(dataAccessService); ServiceInstantiation serviceInstantiation = generateALaCarteWithVnfsServiceInstantiationPayload(); UUID jobUuid = UUID.randomUUID(); - underTest.addJobRequest(jobUuid, serviceInstantiation); - ServiceInstantiation stored = underTest.getJobRequest(jobUuid); + asyncInstantiationRepository.addJobRequest(jobUuid, serviceInstantiation); + ServiceInstantiation stored = asyncInstantiationRepository.getJobRequest(jobUuid); assertThat(stored, jsonEquals(serviceInstantiation).when(IGNORING_ARRAY_ORDER)); } @@ -77,7 +121,6 @@ public class AsyncInstantiationRepositoryTest extends AsyncInstantiationBaseTest @Test public void getResourceInfoByRootJobId_returnsMapOfjobIdResources(){ - AsyncInstantiationRepository underTest = new AsyncInstantiationRepository(dataAccessService); UUID jobId1= UUID.randomUUID(); UUID jobId2= UUID.randomUUID(); AsyncRequestStatus errorMessage= createAsyncRequestStatus("MSO failed resource", "FAILED"); @@ -90,14 +133,16 @@ public class AsyncInstantiationRepositoryTest extends AsyncInstantiationBaseTest new ResourceInfo("ffffff",jobId2, "66f3123a-f9a8-4591-b481-ghfgh6767567", Job.JobStatus.COMPLETED, null) ); for(ResourceInfo info: requestInfoList){ - underTest.saveResourceInfo(info); + asyncInstantiationRepository.saveResourceInfo(info); } - Map<String, ResourceInfo> storedByTrackId = underTest.getResourceInfoByRootJobId(jobId1); + Map<String, ResourceInfo> storedByTrackId = asyncInstantiationRepository.getResourceInfoByRootJobId(jobId1); assertThat(storedByTrackId.values(), hasSize(4)); assertThat(storedByTrackId.get("aaaaaa").getInstanceId(), equalTo("64f3123a-f9a8-4591-b481-d662134bcb52")); assertThat(storedByTrackId.get("cccccc").getErrorMessage().request.requestStatus.getStatusMessage(), equalTo("MSO failed resource")); assertThat(storedByTrackId.get("cccccc").getErrorMessage().request.requestStatus.getRequestState(), equalTo("FAILED")); assertThat(storedByTrackId.get("dddddd").getErrorMessage(), equalTo(null)); - assertThat(storedByTrackId.values(), jsonEquals(requestInfoList.stream().filter(i-> i.getRootJobId().equals(jobId1)).collect(Collectors.toList())).when(IGNORING_ARRAY_ORDER)); + assertThat(storedByTrackId.values(), + jsonEquals(requestInfoList.stream().filter(i -> i.getRootJobId().equals(jobId1)).collect( + toList())).when(IGNORING_ARRAY_ORDER)); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java index 986f5d0f5..db856d757 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java @@ -319,8 +319,8 @@ public class ResourceCommandTest { } static VfModule createVfModule(Action action) { - return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, false, false, null, null, null, null, - null); + return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, + false, false, null, null, null, null, null, null, null); } static Network createNetwork(Action action) { diff --git a/vid-app-common/src/test/java/org/onap/vid/logging/VidLoggingInterceptorTest.java b/vid-app-common/src/test/java/org/onap/vid/logging/VidLoggingInterceptorTest.java index fc78ed714..c31d00df8 100644 --- a/vid-app-common/src/test/java/org/onap/vid/logging/VidLoggingInterceptorTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/logging/VidLoggingInterceptorTest.java @@ -20,10 +20,22 @@ package org.onap.vid.logging; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static org.onap.vid.logging.VidLoggingInterceptor.INBOUND_INVO_ID; import static org.testng.Assert.assertEquals; +import static org.testng.AssertJUnit.assertNull; +import java.util.HashMap; +import javax.servlet.http.HttpServletRequest; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.logging.filter.base.SimpleHashMap; +import org.onap.logging.filter.base.SimpleMap; import org.onap.logging.ref.slf4j.ONAPLogConstants; +import org.onap.logging.ref.slf4j.ONAPLogConstants.MDCs; +import org.onap.vid.controller.ControllersUtils; import org.slf4j.MDC; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -32,17 +44,58 @@ public class VidLoggingInterceptorTest { private VidLoggingInterceptor interceptor; + @Mock + private ControllersUtils controllersUtils; + @BeforeMethod public void setup() { - interceptor = new VidLoggingInterceptor(); + MockitoAnnotations.initMocks(this); + interceptor = new VidLoggingInterceptor(controllersUtils); MDC.clear(); } @Test public void testAdditionalPreHandling() { - MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, "987"); - interceptor.additionalPreHandling(null); - assertEquals(MDC.get(INBOUND_INVO_ID), "987"); + + //given + final String invoID = "987"; + MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invoID); + MDC.put(MDCs.PARTNER_NAME, "wrongPartnerName"); + final String myUserId = "myUserId"; + when(controllersUtils.extractUserId(any(HttpServletRequest.class))) + .thenReturn(myUserId); + + //when + interceptor.additionalPreHandling(mock(HttpServletRequest.class)); + + //then + assertEquals(MDC.get(INBOUND_INVO_ID), invoID); + assertEquals(MDC.get(MDCs.PARTNER_NAME), myUserId); + } + + @Test + public void whenNoUserId_previousPartnerNameIsPreserved() { + //given + final String prevPartnerName = "prevPartnerName"; + MDC.put(MDCs.PARTNER_NAME, prevPartnerName); + final HttpServletRequest mockedRequest = mock(HttpServletRequest.class); + when(controllersUtils.extractUserId(any(HttpServletRequest.class))) + .thenReturn(""); + + //when + interceptor.additionalPreHandling(mockedRequest); + + //then + assertEquals(MDC.get(MDCs.PARTNER_NAME), prevPartnerName); + + } + + @Test + public void givenNotValidAuthorizationHeader_whenGetBasicAuthUserName_noExceptionIsThrown() { + HashMap<String, String> hashMap = new HashMap<>(); + hashMap.put("Authorization","abcdefghi"); + SimpleMap headers = new SimpleHashMap(hashMap); + assertNull(interceptor.getBasicAuthUserName(headers)); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/model/ModelUtilTest.java b/vid-app-common/src/test/java/org/onap/vid/model/ModelUtilTest.java index 0dd6e32a9..922a59200 100644 --- a/vid-app-common/src/test/java/org/onap/vid/model/ModelUtilTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/model/ModelUtilTest.java @@ -7,9 +7,9 @@ * 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. @@ -20,49 +20,81 @@ package org.onap.vid.model; -import org.junit.Assert; -import org.junit.Test; +import static java.util.Collections.emptyMap; +import static java.util.function.Function.identity; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.anEmptyMap; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.onap.vid.mso.model.ModelInfo; +import org.testng.annotations.Test; public class ModelUtilTest { - private ModelUtil createTestSubject() { - return new ModelUtil(); - } + private final ModelUtil testSubject = new ModelUtil(); + + private ModelInfo modelWithCustomizationId(String id) { + ModelInfo result = new ModelInfo(); + result.setModelCustomizationId(id); + return result; + } + + private ModelInfo modelWithModelVersionId(String id) { + ModelInfo result = new ModelInfo(); + result.setModelVersionId(id); + return result; + } - - @Test - public void testGetTags() throws Exception { - String[] namespaces; - String constantValue = "test"; - String[] result; + private ModelInfo modelWithNullValues() { + return new ModelInfo(); + } - // test 1 - namespaces = null; - result = ModelUtil.getTags(namespaces, constantValue); - Assert.assertNull(result); + @Test + public void getExistingCounterMap_trivialCase() { + Map<String, Long> existingCounterMap = + testSubject.getExistingCounterMap( + ImmutableMap.of( + "a", modelWithCustomizationId("model_1"), + "b", modelWithCustomizationId("model_1"), + "c", modelWithCustomizationId("model_2") + ), + identity() + ); - // test 2 - namespaces = new String[] { "" }; - result = ModelUtil.getTags(namespaces, constantValue); - Assert.assertArrayEquals(new String[] { constantValue }, result); - } + assertThat(existingCounterMap, jsonEquals(ImmutableMap.of( + "model_1", 2, + "model_2", 1 + ))); + } - - @Test - public void testIsType() throws Exception { - String type = "a"; - String[] tags; - boolean result; + @Test + public void getExistingCounterMap_givenMixOfIdsAndNulls_resultContainsIdsAndOmitsNulls() { + Map<String, Long> existingCounterMap = + testSubject.getExistingCounterMap( + ImmutableMap.of( + "a", modelWithCustomizationId("model_1"), + "b", modelWithModelVersionId("model_1"), + "c", modelWithModelVersionId("model_2"), + "d", modelWithNullValues() + ), + identity() + ); - // test 1 - tags = null; - result = ModelUtil.isType(type, tags); - Assert.assertEquals(false, result); + assertThat(existingCounterMap, jsonEquals(ImmutableMap.of( + "model_1", 2, + "model_2", 1 + ))); + } - // test 2 - tags = new String[] { "a" }; - result = ModelUtil.isType(type, tags); - Assert.assertEquals(true, result); - } + @Test + public void getExistingCounterMap_handleEmptyCollections() { + assertThat(testSubject.getExistingCounterMap( + emptyMap(), + any -> modelWithCustomizationId("foo") + ), is(anEmptyMap())); + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java index a159efd30..a73a5a7bd 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceIntegrativeTest.java @@ -44,9 +44,11 @@ import org.onap.vid.aai.util.AAIRestInterface; import org.onap.vid.aai.util.AAITreeConverter; import org.onap.vid.aai.util.CacheProvider; import org.onap.vid.aai.util.TestWithAaiClient; +import org.onap.vid.model.ModelUtil; import org.onap.vid.model.aaiTree.Network; import org.onap.vid.model.aaiTree.VpnBinding; import org.onap.vid.testUtils.TestUtils; +import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -56,19 +58,20 @@ public class AAIServiceIntegrativeTest extends TestWithAaiClient { private AAIRestInterface aaiRestInterface; private AaiServiceImpl aaiServiceWithoutMocks; + private Logging logging = new Logging(); private AaiServiceImpl createAaiServiceWithoutMocks(AAIRestInterface aaiRestInterface, CacheProvider cacheProvider) { AaiClient aaiClient = new AaiClient(aaiRestInterface, null, cacheProvider); ExecutorService executorService = MoreExecutors.newDirectExecutorService(); AAIServiceTree aaiServiceTree = new AAIServiceTree( aaiClient, - new AAITreeNodeBuilder(aaiClient), - new AAITreeConverter(), + new AAITreeNodeBuilder(aaiClient, logging), + new AAITreeConverter(new ModelUtil()), null, null, executorService ); - return new AaiServiceImpl(aaiClient, null, aaiServiceTree, executorService); + return new AaiServiceImpl(aaiClient, null, aaiServiceTree, executorService, logging); } @BeforeMethod diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java index a956468f3..0d2d51cee 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeIntegrativeTest.java @@ -37,8 +37,10 @@ import java.io.IOException; import java.net.URI; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.function.Function; import javax.ws.rs.core.Response; import org.mockito.Mock; import org.onap.vid.aai.AaiClientInterface; @@ -48,12 +50,14 @@ import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.asdc.parser.ServiceModelInflator; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.Action; +import org.onap.vid.model.ModelUtil; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.FailureAAITreeNode; import org.onap.vid.model.aaiTree.ServiceInstance; import org.onap.vid.model.aaiTree.Vnf; import org.onap.vid.testUtils.TestUtils; +import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -75,9 +79,12 @@ public class AAIServiceTreeIntegrativeTest { @Mock ServiceModelInflator serviceModelInflator; + @Mock + Logging logging; + private AAITreeNodeBuilder aaiTreeNodeBuilder; - private AAITreeConverter aaiTreeConverter = new AAITreeConverter(); + private AAITreeConverter aaiTreeConverter = new AAITreeConverter(new ModelUtil()); private ExecutorService executorService = Executors.newFixedThreadPool(10); @@ -87,7 +94,6 @@ public class AAIServiceTreeIntegrativeTest { private String serviceType = "vWINIFRED"; private String serviceInstanceId = "62888f15-6d24-4f7b-92a7-c3f35beeb215"; - //TODO Amichai: if in the future it is neede, add here the SUFFIX to the URL: "?format=simple" private String serviceInstanceRequestUri = "business/customers/customer/" + globalCustomerID + "/service-subscriptions/service-subscription/" + @@ -292,7 +298,13 @@ public class AAIServiceTreeIntegrativeTest { @BeforeMethod public void initMocks() { TestUtils.initMockitoMocks(this); - aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClient); + reboundLoggingWithMdcMock(); + aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClient, logging); + } + + private void reboundLoggingWithMdcMock() { + when(logging.withMDC(any(), any(Callable.class))).thenAnswer(invocation -> invocation.getArgument(1)); + when(logging.withMDC(any(), any(Function.class))).thenAnswer(invocation -> invocation.getArgument(1)); } public void getServiceInstanceTreeAndAssert(boolean isDuplicatedKeysInTenantRelation) throws IOException, AsdcCatalogException { diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeTest.java index ada1f857e..be195c89b 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAIServiceTreeTest.java @@ -51,10 +51,12 @@ import org.onap.vid.aai.AaiClient; import org.onap.vid.aai.util.AAITreeConverter; import org.onap.vid.asdc.parser.ServiceModelInflator; import org.onap.vid.asdc.parser.ServiceModelInflator.Names; +import org.onap.vid.model.ModelUtil; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.mso.model.CloudConfiguration; import org.onap.vid.testUtils.TestUtils; +import org.onap.vid.utils.Logging; import org.onap.vid.utils.Unchecked; import org.springframework.http.HttpMethod; import org.testng.annotations.BeforeTest; @@ -199,8 +201,8 @@ public class AAIServiceTreeTest { ExecutorService executorService = MoreExecutors.newDirectExecutorService(); AAIServiceTree aaiServiceTree = new AAIServiceTree( aaiClientMock, - new AAITreeNodeBuilder(aaiClientMock), - new AAITreeConverter(), + new AAITreeNodeBuilder(aaiClientMock, new Logging()), + new AAITreeConverter(new ModelUtil()), null, null, executorService diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java index c2a3f5d61..2c954b297 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java @@ -20,7 +20,20 @@ package org.onap.vid.services; -import com.fasterxml.jackson.core.JsonProcessingException; +import static java.util.Comparator.comparing; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; +import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; +import static org.onap.vid.services.AAIServiceTree.AAI_TREE_PATHS; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -28,7 +41,14 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.MoreExecutors; - +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.mockito.Mock; @@ -41,37 +61,15 @@ import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.mso.model.CloudConfiguration; +import org.onap.vid.testUtils.TestUtils; +import org.onap.vid.utils.Logging; import org.onap.vid.utils.Tree; import org.onap.vid.utils.Unchecked; -import org.onap.vid.testUtils.TestUtils; import org.springframework.http.HttpMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static java.util.Comparator.comparing; -import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; -import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; -import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.when; -import static org.onap.vid.services.AAIServiceTree.AAI_TREE_PATHS; -import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - public class AAITreeNodeBuilderTest { private AAITreeNodeBuilder aaiTreeNodeBuilder; @@ -80,13 +78,14 @@ public class AAITreeNodeBuilderTest { private AaiClientInterface aaiClientMock; private ExecutorService executorService; + private Logging logging = new Logging(); private static final ObjectMapper mapper = new ObjectMapper(); @BeforeClass public void initMocks() { MockitoAnnotations.initMocks(this); - aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClientMock); + aaiTreeNodeBuilder = new AAITreeNodeBuilder(aaiClientMock, logging); executorService = MoreExecutors.newDirectExecutorService(); } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java index 9df99faa6..d3b2a48b1 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java @@ -42,6 +42,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.function.Function; import javax.ws.rs.core.Response; import org.apache.http.HttpStatus; import org.jetbrains.annotations.NotNull; @@ -88,6 +89,7 @@ import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.RelatedVnf; import org.onap.vid.model.aaiTree.ServiceInstance; import org.onap.vid.roles.RoleValidator; +import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; @RunWith(MockitoJUnitRunner.class) @@ -131,6 +133,8 @@ public class AaiServiceImplTest { @Mock private AaiResponseTranslator aaiResponseTranslator; @Mock + private Logging logging; + @Mock private AAIServiceTree aaiServiceTree; @Spy private ExecutorService executorService = Executors.newFixedThreadPool(1); @@ -504,6 +508,7 @@ public class AaiServiceImplTest { when(aaiServiceTree.buildAAITree(anyString(), isNull(), eq(HttpMethod.GET), any(), anyBoolean())) .thenReturn(Collections.singletonList(testedTree)); when(aaiClient.getCloudRegionAndTenantByVnfId(anyString())).thenReturn(regionsAndTenants); + when(logging.withMDC(any(), any(Function.class))).thenAnswer(invocation -> invocation.getArgument(1)); List<RelatedVnf> actualGroupMembers = aaiService.searchGroupMembers(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, INVARIANT_ID, GROUP_TYPE_FAILING, GROUP_ROLE_FAILING); diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java index 9c0260e85..d41ce87bf 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java @@ -22,6 +22,8 @@ package org.onap.vid.services; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -32,9 +34,12 @@ import static org.onap.vid.model.VidNotions.ModelCategory; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -43,9 +48,14 @@ import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.inject.Inject; +import org.hibernate.SessionFactory; +import org.onap.portalsdk.core.domain.FusionObject; +import org.onap.portalsdk.core.service.DataAccessService; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.ExceptionWithRequestInfo; +import org.onap.vid.job.Job.JobStatus; import org.onap.vid.model.Action; +import org.onap.vid.model.ServiceInfo; import org.onap.vid.model.VidNotions; import org.onap.vid.model.serviceInstantiation.InstanceGroup; import org.onap.vid.model.serviceInstantiation.Network; @@ -57,13 +67,19 @@ import org.onap.vid.mso.model.ModelInfo; import org.onap.vid.mso.rest.AsyncRequestStatus; import org.onap.vid.mso.rest.RequestStatus; import org.onap.vid.properties.Features; +import org.onap.vid.services.AsyncInstantiationBusinessLogicTest.ServiceInfoComparator; +import org.onap.vid.utils.DaoUtils; import org.onap.vid.utils.TimeUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.togglz.core.manager.FeatureManager; public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests { + public static final String MODEL_UUID = "337be3fc-293e-43ec-af0b-cf932dad07e6"; + public static final String MODEL_UUID_2 = "ce052844-22ba-4030-a838-822f2b39eb9b"; + public static final String OWNING_ENTITY_ID = "038d99af-0427-42c2-9d15-971b99b9b489"; public static final String JULIO_ERICKSON = "JULIO ERICKSON"; public static final String PROJECT_NAME = "{some project name}"; @@ -90,6 +106,12 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests protected HashMap<String, String> vfModuleInstanceParamsMapWithParamsToRemove; protected HashMap<String, String> vnfInstanceParamsMapWithParamsToRemove; + protected int serviceCount = 0; + + + @Inject + protected DataAccessService dataAccessService; + @Inject protected FeatureManager featureManager; @@ -99,6 +121,56 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests @Inject protected CloudOwnerService cloudOwnerService; + @Autowired + protected SessionFactory sessionFactory; + + + protected static Date toDate(LocalDateTime localDateTime) { + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + } + + protected HashMap<String, Object> getPropsMap() { + HashMap<String, Object> props = new HashMap<>(); + props.put(FusionObject.Parameters.PARAM_USERID, 0); + return props; + } + + + private void setCreateDateToServiceInfo(UUID jobUuid, LocalDateTime createDate) { + List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, getPropsMap()); + DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> { + serviceInfoList.stream() + .filter(serviceInfo -> jobUuid.equals(serviceInfo.getJobId())) + .forEach(serviceInfo -> { + serviceInfo.setCreated(toDate(createDate)); + session.saveOrUpdate(serviceInfo); + }); + return 1; + }); + } + + protected void addNewServiceInfo(UUID uuid, String userId, String serviceName, LocalDateTime createDate, + LocalDateTime statusModifiedDate, JobStatus status, boolean isHidden, boolean retryEnabled, + String modelUUID) { + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setJobId(uuid); + serviceInfo.setUserId(userId); + serviceInfo.setServiceInstanceName(serviceName); + serviceInfo.setStatusModifiedDate(toDate(statusModifiedDate)); + serviceInfo.setJobStatus(status); + serviceInfo.setPause(false); + serviceInfo.setOwningEntityId("1234"); + serviceInfo.setCreatedBulkDate(toDate(createDate)); + serviceInfo.setRetryEnabled(retryEnabled); + serviceInfo.setServiceModelId(modelUUID); + serviceInfo.setHidden(isHidden); + dataAccessService.saveDomainObject(serviceInfo, getPropsMap()); + setCreateDateToServiceInfo(uuid, createDate); + serviceCount++; + + } + + public ServiceInstantiation generateMockMacroServiceInstantiationPayload(boolean isPause, Map<String, Vnf> vnfs, int bulkSize, boolean isUserProvidedNaming, String projectName, boolean rollbackOnFailure) { return generateMockServiceInstantiationPayload(isPause, vnfs, Collections.EMPTY_MAP, Collections.EMPTY_MAP, bulkSize, isUserProvidedNaming, projectName, rollbackOnFailure, false, null, Action.Create, null); } @@ -172,20 +244,22 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests vfModuleInfo.setModelVersion("10.0"); return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", instanceParams, supplementaryParams, false, true, null, UUID.randomUUID().toString(), null, null, - null); + null, null, null); } return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), null, null, null, - instanceParams, supplementaryParams, false, false, null, UUID.randomUUID().toString(), null, null, null); + instanceParams, supplementaryParams, false, false, null, UUID.randomUUID().toString(), null, + null, null, null, null); } protected ModelInfo createVfModuleModelInfo(String modelName, String modelVersion, String modelVersionId, String modelInvariantId, String modelCustomizationId, String modelCustomizationName) { return createModelInfo("vfModule", modelName, modelVersion, modelVersionId, modelInvariantId, modelCustomizationId, modelCustomizationName); } - protected VfModule createVfModuleForReplace(ModelInfo vfModuleModelInfo, String instanceName, String lcpCloudRegionId, String tenantId) { + protected VfModule createVfModuleForReplace(ModelInfo vfModuleModelInfo, String instanceName, + String lcpCloudRegionId, String tenantId, Boolean retainAssignments, Boolean retainVolumeGroups, Map<String, String> supplementaryParams) { return new VfModule( vfModuleModelInfo, instanceName, null, Action.Upgrade.name(), lcpCloudRegionId, null, tenantId, - null, null, true, null, null, UUID.randomUUID().toString(), null, null, null); + null, supplementaryParams, true, null, null, UUID.randomUUID().toString(), null, null, retainAssignments, retainVolumeGroups, null); } protected ModelInfo createVnfModelInfo(boolean isAlacarte) { diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java index c1a6abc73..d1124f3a8 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java @@ -37,13 +37,13 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Every.everyItem; import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; @@ -93,10 +93,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; import java.util.stream.IntStream; -import javax.inject.Inject; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.time.DateUtils; -import org.hibernate.SessionFactory; import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.mockito.ArgumentCaptor; @@ -104,8 +102,6 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; -import org.onap.portalsdk.core.domain.FusionObject; -import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.model.ResourceType; @@ -143,7 +139,6 @@ import org.onap.vid.properties.Features; import org.onap.vid.testUtils.TestUtils; import org.onap.vid.utils.DaoUtils; import org.onap.vid.utils.TimeUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.testng.Assert; import org.testng.annotations.AfterMethod; @@ -155,8 +150,7 @@ import org.testng.annotations.Test; @ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class}) public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseTest { - @Inject - private DataAccessService dataAccessService; + @Mock private JobAdapter jobAdapterMock; @@ -168,15 +162,11 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT private AuditService auditService; - @Autowired - private SessionFactory sessionFactory; private AsyncInstantiationBusinessLogicImpl asyncInstantiationBL; protected MsoRequestBuilder msoRequestBuilder; - private int serviceCount = 0; - private static final String UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE = "Failed to retrieve class .*ServiceInfo with jobId .* from table. no resource found"; @@ -209,6 +199,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT Mockito.reset(aaiClient); Mockito.reset(jobAdapterMock); Mockito.reset(jobsBrokerServiceMock); + Mockito.reset(asyncInstantiationRepository); mockAaiClientAnyNameFree(); enableAddCloudOwnerOnMsoRequest(); } @@ -236,13 +227,15 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT uuid = UUID.randomUUID(); addNewJob(uuid); createdDate = NOW.minusYears(1); - addNewServiceInfo(uuid, userId, "Old", createdDate, createdDate, COMPLETED, false, false); + addNewServiceInfo(uuid, userId, "Old", createdDate, createdDate, COMPLETED, false, false, + MODEL_UUID); uuid = UUID.randomUUID(); addNewJob(uuid); createdDate = NOW.minusDays(20); modifiedDate = NOW.minusDays(19); - addNewServiceInfo(uuid, userId, "Hidden", createdDate, modifiedDate, PAUSE, true, false); + addNewServiceInfo(uuid, userId, "Hidden", createdDate, modifiedDate, PAUSE, true, false, + MODEL_UUID); createNewTestServicesInfo(String.valueOf(userId)); } @@ -257,20 +250,26 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT addNewJob(uuid); createdDate = NOW.minusDays(40); - addNewServiceInfo(uuid, userId, "service instance 5", createdDate, createdDate, COMPLETED, false, false); - addNewServiceInfo(uuid, userId, "service instance 6", createdDate, createdDate, STOPPED, false, false); + addNewServiceInfo(uuid, userId, "service instance 5", createdDate, createdDate, COMPLETED, false, false, + MODEL_UUID); + addNewServiceInfo(uuid, userId, "service instance 6", createdDate, createdDate, STOPPED, false, false, + MODEL_UUID); uuid = UUID.randomUUID(); addNewJob(uuid); createdDate = NOW.minusDays(20); modifiedDate = NOW.minusDays(10); - addNewServiceInfo(uuid, userId, "service instance 4", createdDate, modifiedDate, STOPPED, false, false); - addNewServiceInfo(uuid, userId, "service instance 2", createdDate, modifiedDate, COMPLETED, false, false); - addNewServiceInfo(uuid, userId, "service instance 3", createdDate, modifiedDate, PAUSE, false, false); + addNewServiceInfo(uuid, userId, "service instance 4", createdDate, modifiedDate, STOPPED, false, false, + MODEL_UUID); + addNewServiceInfo(uuid, userId, "service instance 2", createdDate, modifiedDate, COMPLETED, false, false, + MODEL_UUID); + addNewServiceInfo(uuid, userId, "service instance 3", createdDate, modifiedDate, PAUSE, false, false, + MODEL_UUID); modifiedDate = NOW.minusDays(19); - addNewServiceInfo(uuid, userId, "service instance 1", createdDate, modifiedDate, FAILED, false, false); + addNewServiceInfo(uuid, userId, "service instance 1", createdDate, modifiedDate, FAILED, false, false, + MODEL_UUID); // Job to a different user @@ -278,10 +277,13 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT addNewJob(uuid); createdDate = NOW.minusMonths(2); - addNewServiceInfo(uuid, "2221", "service instance 7", createdDate, createdDate, COMPLETED, false, false); + addNewServiceInfo(uuid, "2221", "service instance 7", createdDate, createdDate, COMPLETED, false, false, + MODEL_UUID); } + + private UUID createServicesInfoWithDefaultValues(Job.JobStatus status) { LocalDateTime NOW = LocalDateTime.now(); @@ -290,7 +292,8 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT uuid = UUID.randomUUID(); addNewJob(uuid, status); - addNewServiceInfo(uuid, null, "service instance 1", NOW, NOW, status, false, false); + addNewServiceInfo(uuid, null, "service instance 1", NOW, NOW, status, false, false, + MODEL_UUID); return uuid; @@ -303,9 +306,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT return expectedOrderServiceInfo; } - private static Date toDate(LocalDateTime localDateTime) { - return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); - } + private LocalDateTime fromDate(Date date) { return Instant.ofEpochMilli(date.getTime()) @@ -313,25 +314,6 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT .toLocalDateTime(); } - private void addNewServiceInfo(UUID uuid, String userId, String serviceName, LocalDateTime createDate, LocalDateTime statusModifiedDate, JobStatus status, boolean isHidden, boolean retryEnabled) { - ServiceInfo serviceInfo = new ServiceInfo(); - serviceInfo.setJobId(uuid); - serviceInfo.setUserId(userId); - serviceInfo.setServiceInstanceName(serviceName); - serviceInfo.setStatusModifiedDate(toDate(statusModifiedDate)); - serviceInfo.setJobStatus(status); - serviceInfo.setPause(false); - serviceInfo.setOwningEntityId("1234"); - serviceInfo.setCreatedBulkDate(toDate(createDate)); - serviceInfo.setRetryEnabled(retryEnabled); - - serviceInfo.setHidden(isHidden); - dataAccessService.saveDomainObject(serviceInfo, getPropsMap()); - setCreateDateToServiceInfo(uuid, createDate); - serviceCount++; - - } - private void setCreateDateToServiceInfo(UUID jobUuid, LocalDateTime createDate) { List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, getPropsMap()); DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> { @@ -357,7 +339,9 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT } private ServiceInstantiation addOriginalService(UUID jobId, String userID){ - addNewServiceInfo(jobId, userID, "name", LocalDateTime.now(), LocalDateTime.now(), COMPLETED_WITH_ERRORS, false, true); + addNewServiceInfo(jobId, userID, "name", LocalDateTime.now(), LocalDateTime.now(), COMPLETED_WITH_ERRORS, false, + true, + MODEL_UUID); assertThat(asyncInstantiationRepository.getServiceInfoByJobId(jobId).isRetryEnabled(), is(true)); ServiceInstantiation originalServiceInstantiation = prepareServiceInstantiation(true, 1); doReturn(originalServiceInstantiation).when(asyncInstantiationRepository).getJobRequest(jobId); @@ -469,11 +453,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT when(aaiClient.isNodeTypeExistsByName(uniqueName, serviceInstance)).thenReturn(true); } - private HashMap<String, Object> getPropsMap() { - HashMap<String, Object> props = new HashMap<>(); - props.put(FusionObject.Parameters.PARAM_USERID, 0); - return props; - } + @DataProvider @@ -1387,4 +1367,5 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT assertThat(path, equalTo("/serviceInstantiation/v7/serviceInstances/myService/vnfs/myVNF/vfModules/myVFModule/replace")); } + } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/InstantiationTemplatesServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/services/InstantiationTemplatesServiceTest.java new file mode 100644 index 000000000..f09ea313c --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/services/InstantiationTemplatesServiceTest.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.vid.services; + +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.anEmptyMap; +import static org.hamcrest.Matchers.hasProperty; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.UUID; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.onap.vid.dal.AsyncInstantiationRepository; +import org.onap.vid.model.ModelUtil; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiationTemplate; +import org.onap.vid.model.serviceInstantiation.Vnf; +import org.onap.vid.testUtils.TestUtils; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class InstantiationTemplatesServiceTest { + + @Mock + private AsyncInstantiationRepository asyncInstantiationRepository; + + @Mock + private ModelUtil modelUtil; + + @InjectMocks + private InstantiationTemplatesService instantiationTemplatesService; + + @BeforeMethod + public void initMocks() { + TestUtils.initMockitoMocks(this); + } + + @Test + public void getJobRequestAsTemplate_whenIsCalled_asyncInstantiationRepositoryGetJobRequestIsInvoked() { + UUID jobId = UUID.randomUUID(); + ServiceInstantiation serviceInstantiationMock = mock(ServiceInstantiation.class, RETURNS_DEEP_STUBS); + doReturn(serviceInstantiationMock).when(asyncInstantiationRepository).getJobRequest(jobId); + + // When... + instantiationTemplatesService.getJobRequestAsTemplate(jobId); + + verify(asyncInstantiationRepository).getJobRequest(jobId); + } + + @Test + public void getJobRequestAsTemplate_givenModelUtilReturnsValue_thenVnfCounterMapIsPopulatedWithThatValue() { + Map<String, Integer> dummyNonEmptyMap = ImmutableMap.of("dummyKey", 9); + ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class, RETURNS_DEEP_STUBS); + doReturn(serviceInstantiation).when(asyncInstantiationRepository).getJobRequest(any()); + + // Given... + when(modelUtil.getExistingCounterMap(any(), any())).thenAnswer( + // return empty counterMap if argument is an empty map; otherwise return a mocked response + invocation -> ((Map)invocation.getArgument(0)).size() == 0 // isEmpty() does not work on mocks + ? ImmutableMap.of() + : dummyNonEmptyMap + ); + + // only vnf will have a non-empty value + when(serviceInstantiation.getVnfs()).thenReturn(ImmutableMap.of("1", mock(Vnf.class))); + + // When... + ServiceInstantiationTemplate result = instantiationTemplatesService.getJobRequestAsTemplate(UUID.randomUUID()); + + assertThat(result, hasProperty("existingVNFCounterMap", jsonEquals(dummyNonEmptyMap))); + assertThat(result, hasProperty("existingNetworksCounterMap", anEmptyMap())); + assertThat(result, hasProperty("existingVnfGroupCounterMap", anEmptyMap())); + assertThat(result, hasProperty("existingVRFCounterMap", anEmptyMap())); + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/MsoRequestBuilderTest.java b/vid-app-common/src/test/java/org/onap/vid/services/MsoRequestBuilderTest.java index a7e2d553d..cb59129c3 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/MsoRequestBuilderTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/MsoRequestBuilderTest.java @@ -22,6 +22,7 @@ package org.onap.vid.services; import static com.google.common.collect.Maps.newHashMap; import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals; import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; @@ -74,8 +75,9 @@ import org.onap.vid.mso.model.ModelInfo; import org.onap.vid.mso.model.NetworkInstantiationRequestDetails; import org.onap.vid.mso.model.ServiceDeletionRequestDetails; import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails; +import org.onap.vid.mso.model.UserParamMap; import org.onap.vid.mso.model.VfModuleMacro; +import org.onap.vid.mso.model.VfModuleOrVolumeGroupRequestDetails; import org.onap.vid.mso.model.VnfInstantiationRequestDetails; import org.onap.vid.mso.model.VolumeGroupRequestDetails; import org.onap.vid.properties.Features; @@ -370,7 +372,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest { when(aaiClient.isNodeTypeExistsByName(eq("vmxnjr001_AVPN_base_vRE_BV_expansion"), eq(ResourceType.VF_MODULE))).thenReturn(false); String expected = IOUtils.toString(this.getClass().getResource(fileName), "UTF-8"); - final RequestDetailsWrapper<VfModuleInstantiationRequestDetails> result = msoRequestBuilder.generateVfModuleInstantiationRequest( + final RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> result = msoRequestBuilder.generateVfModuleInstantiationRequest( vfModule, siModelInfo, serviceInstanceId, vnfModelInfo, vnfInstanceId, volumeGroupInstanceId, "pa0916", "VNF_API"); MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); @@ -390,8 +392,8 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest { } @Test(dataProvider = "expectedAggregatedParams") - public void testAggregateInstanceParamsAndSuppFile(Map<String, String> instanceParams, Map<String, String> suppParams, List<VfModuleInstantiationRequestDetails.UserParamMap<String, String>> expected) { - List<VfModuleInstantiationRequestDetails.UserParamMap<String, String>> aggParams = msoRequestBuilder.aggregateAllInstanceParams(instanceParams, suppParams); + public void testAggregateInstanceParamsAndSuppFile(Map<String, String> instanceParams, Map<String, String> suppParams, List<UserParamMap<String, String>> expected) { + List<UserParamMap<String, String>> aggParams = msoRequestBuilder.aggregateAllInstanceParams(instanceParams, suppParams); assertThat("Aggregated params are not as expected", aggParams, equalTo(expected)); } @@ -565,7 +567,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest { " }" + "}"; VfModule vfModuleDetails = createVfModule("201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0", VF_MODULE_0_MODEL_VERSION_ID, VF_MODULE_0_MODEL_CUSTOMIZATION_NAME, null, new HashMap<>(), "vmxnjr001_AVPN_base_vPE_BV_base", null, true); - RequestDetailsWrapper<VfModuleInstantiationRequestDetails> result = + RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> result = msoRequestBuilder.generateDeleteVfModuleRequest(vfModuleDetails, "az2018"); MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); } @@ -609,24 +611,67 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest { assertThat(result, jsonEquals(expected).when(IGNORING_ARRAY_ORDER)); } + @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils.class) + public void generateReplaceVfModuleRequest_whenRetainAssignmentsProvidedFromFrontend_retainAssignmentsToMsoIsTheSame(boolean retainAssignments) { + + assertThat(generatedVfModuleReplaceRequest(retainAssignments, null, null), + jsonPartEquals("requestDetails.requestParameters.retainAssignments", retainAssignments)); + } + + @Test + public void generateReplaceVfModuleRequest_whenRetainVolumeGroupIsTrue_rebuildVolumeGroupIsFalse() { + boolean retainVolumeGroups = true; + + assertThat(generatedVfModuleReplaceRequest(null, retainVolumeGroups, null), + jsonPartEquals("requestDetails.requestParameters.rebuildVolumeGroups", false)); + } + + @Test + public void generateReplaceVfModuleRequest_whenThereAreSupplementaryParams_thenTheyAreAddToUserParams() { + + String expectedParams = "[{" + + " \"vre_a_volume_size_0\" : \"100\"," + + " \"vmx_int_net_len\" : \"24\"," + + " \"availability_zone_0\": \"abc\"" + + " }]"; + + Map<String, String> supplementaryParams = ImmutableMap.of( + "vre_a_volume_size_0", "100", + "vmx_int_net_len", "24", + "availability_zone_0", "abc" + ); + + assertThat(generatedVfModuleReplaceRequest(null, null, supplementaryParams), + jsonPartEquals("requestDetails.requestParameters.userParams", expectedParams)); + } + @Test public void generateReplaceVfModuleRequest_verifyResultAsExpected() { + Boolean retainVolumeGroups = null; + Boolean retainAssignments = null; + String expected = TestUtils.readFileAsString("/payload_jsons/vfmodule/replace_vfmodule__payload_to_mso.json"); + assertThat(generatedVfModuleReplaceRequest(retainAssignments, retainVolumeGroups, null), jsonEquals(expected).when(IGNORING_ARRAY_ORDER)); + } + + private RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> generatedVfModuleReplaceRequest( + Boolean retainAssignments, Boolean retainVolumeGroups, Map<String, String> supplementaryParams) { when(featureManager.isActive(Features.FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST)).thenReturn(true); when(aaiClient.getCloudOwnerByCloudRegionId("regionOne")).thenReturn("irma-aic"); ModelInfo vfModuleModelInfo = createVfModuleModelInfo("newest-model-name-vfm", "newest-model-version-vfm", "newest-model-uuid-vfm", "f7a867f2-596b-4f4a-a128-421e825a6190", "newest-model-customization-uuid-vfm","newest-model-customization-name-vfm" ); - VfModule vfModuleDetails = createVfModuleForReplace(vfModuleModelInfo, "replace_module", "regionOne", "0422ffb57ba042c0800a29dc85ca70f8"); + VfModule vfModuleDetails = createVfModuleForReplace(vfModuleModelInfo, "replace_module", "regionOne", "0422ffb57ba042c0800a29dc85ca70f8", + retainAssignments, retainVolumeGroups, supplementaryParams); ModelInfo serviceModelInfo = createServiceModelInfo("newest-model-name-service", "newest-model-version-service", "newest-model-uuid-service", "b16a9398-ffa3-4041-b78c-2956b8ad9c7b", null, null ); ModelInfo vnfModelInfo = createVnfModelInfo("newest-model-name-vnf", "newest-model-version-vnf", "newest-model-uuid-vnf", "23122c9b-dd7f-483f-bf0a-e069303db2f7", "newest-model-customization-uuid-vnf", "newest-model-customization-name-vnf" ); - RequestDetailsWrapper<VfModuleInstantiationRequestDetails> result = - msoRequestBuilder.generateVfModuleInstantiationRequest(vfModuleDetails, serviceModelInfo, "e9993045-cc96-4f3f-bf9a-71b2a400a956", vnfModelInfo, "5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5", null,"az2016", "GR_API"); - - assertThat(result, jsonEquals(expected).when(IGNORING_ARRAY_ORDER)); + return msoRequestBuilder.generateVfModuleReplaceRequest(vfModuleDetails, serviceModelInfo, + "e9993045-cc96-4f3f-bf9a-71b2a400a956", vnfModelInfo, + "5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5", null, "az2016", "GR_API" + ); } -}
\ No newline at end of file +} diff --git a/vid-app-common/src/test/java/org/onap/vid/utils/LoggingUtilsTest.java b/vid-app-common/src/test/java/org/onap/vid/utils/LoggingUtilsTest.java index 6cbb14ac2..c2a1f2877 100644 --- a/vid-app-common/src/test/java/org/onap/vid/utils/LoggingUtilsTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/utils/LoggingUtilsTest.java @@ -21,7 +21,11 @@ package org.onap.vid.utils; import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.matchesPattern; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.Mockito.mock; @@ -33,12 +37,15 @@ import com.att.eelf.configuration.EELFLogger; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.common.collect.ImmutableMap; import io.joshworks.restclient.http.HttpResponse; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; +import java.util.concurrent.Callable; +import java.util.function.Function; import javax.crypto.BadPaddingException; import javax.net.ssl.SSLHandshakeException; import javax.ws.rs.ProcessingException; @@ -46,6 +53,7 @@ import org.apache.commons.io.IOUtils; import org.mockito.ArgumentCaptor; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.testUtils.TestUtils; +import org.slf4j.MDC; import org.springframework.http.HttpMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -196,6 +204,71 @@ public class LoggingUtilsTest { assertThat(Logging.exceptionToDescription(exceptionToDescribe), matchesRegEx(expectedButDotsEscaped)); } + @Test + public void testWithMDCInternal_whenGivenProvider_functionShouldBeExtractedWithMdc() { + Object myAnything = new Object(); + + Object result = logginService.withMDCInternal(ImmutableMap.of("my key", "my value"), + () -> { + assertThat("MDC values should be installed when extracting the supplier", + MDC.getCopyOfContextMap(), hasEntry("my key", "my value")); + return myAnything; + } + ); + + assertThat("withMDCInternal should extract my function", result, is(sameInstance(myAnything))); + assertThat("MDC values should be removed", MDC.getCopyOfContextMap(), not(hasEntry("k", "v"))); + } + + @Test + public void testWithMDC_whenGivenFunction_functionShouldBeEncapsulated() { + // Given + String[] stringsArray = {"before"}; + + Function<String, Integer> myFunction = s -> { + assertThat("MDC values should be installed when inside myFunction", + MDC.getCopyOfContextMap(), hasEntry("my key", "my value")); + stringsArray[0] = s; + return 42; + }; + + // When + Function<String, Integer> functionWithMDC = + logginService.withMDC(ImmutableMap.of("my key", "my value"), myFunction); + + + assertThat("invocation of function must not happen yet", stringsArray[0], is("before")); + + Integer result = functionWithMDC.apply("after"); + + assertThat("invocation of my function should have been deferred", stringsArray[0], is("after")); + assertThat("apply should return function's value", result, is(42)); + } + + @Test + public void testWithMDC_whenGivenCallable_callableShouldBeEncapsulated() throws Exception { + // Given + String[] stringsArray = {"before"}; + + Callable<Integer> myCallable = () -> { + assertThat("MDC values should be installed when inside myCallable", + MDC.getCopyOfContextMap(), hasEntry("my key", "my value")); + stringsArray[0] = "after"; + return 42; + }; + + // When + Callable<Integer> callableWithMDC = logginService.withMDC(ImmutableMap.of("my key", "my value"), myCallable); + + + assertThat("invocation of callable must not happen yet", stringsArray[0], is("before")); + + Integer result = callableWithMDC.call(); + + assertThat("invocation of my callable should have been deferred", stringsArray[0], is("after")); + assertThat("apply should return function's value", result, is(42)); + } + private static String escapeBrackets(String in) { return in.replaceAll("[\\(\\[\\{\\)]", "\\\\$0"); } diff --git a/vid-app-common/src/test/resources/csars/portMirroringService.zip b/vid-app-common/src/test/resources/csars/portMirroringService.zip Binary files differnew file mode 100644 index 000000000..c074f31bd --- /dev/null +++ b/vid-app-common/src/test/resources/csars/portMirroringService.zip diff --git a/vid-app-common/src/test/resources/csars/service-Vocg1804Svc.zip b/vid-app-common/src/test/resources/csars/service-Vocg1804Svc.zip Binary files differnew file mode 100644 index 000000000..05e0a2974 --- /dev/null +++ b/vid-app-common/src/test/resources/csars/service-Vocg1804Svc.zip diff --git a/vid-app-common/src/test/resources/macro_services_by_invariant_uuid.json b/vid-app-common/src/test/resources/macro_services_by_invariant_uuid.json new file mode 100644 index 000000000..3afb9321a --- /dev/null +++ b/vid-app-common/src/test/resources/macro_services_by_invariant_uuid.json @@ -0,0 +1,4 @@ +[ + "117f5f1a-1b47-4ae1-ae04-489c9a7ada28", + "2efab359-cdd4-4da2-9b79-61df990796c2" +] diff --git a/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__fe_input_cypress.json b/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__fe_input_cypress.json index 9571a2d13..748b5f267 100644 --- a/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__fe_input_cypress.json +++ b/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__fe_input_cypress.json @@ -1,6 +1,6 @@ { "action": "None_Upgrade", - "isDirty": true, + "isDirty": false, "vnfs": { "d520268f-7489-4662-be59-f81495b3a069": { "action": "None_Upgrade", @@ -33,6 +33,9 @@ "xbitestmodulereplace0..XbiTestModuleReplace..base_ocg..module-0": { "b0732bed-3ddf-43cc-b193-7f18db84e476": { "action": "None_Upgrade", + "retainAssignments" : false, + "retainVolumeGroups" : false, + "sdncPreLoad" : true, "instanceName": "PST-VfMod-Replace-5-Vfmod", "instanceId": "b0732bed-3ddf-43cc-b193-7f18db84e476", "orchStatus": "Active", @@ -57,7 +60,10 @@ "platformName": null, "trackById": "b0732bed-3ddf-43cc-b193-7f18db84e476", "isBase": true, - "volumeGroupName": null + "volumeGroupName": null, + "supplementaryFile": null, + "supplementaryFile_hidden": null, + "supplementaryFile_hidden_content" : null } } }, @@ -113,4 +119,4 @@ "viewEditUI": "legacy", "instantiationType": "ALaCarte" } -}
\ No newline at end of file +} diff --git a/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__payload_to_mso.json b/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__payload_to_mso.json index a9a9eda7d..45b89f730 100644 --- a/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__payload_to_mso.json +++ b/vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__payload_to_mso.json @@ -33,6 +33,9 @@ } ], "requestParameters": { + "retainAssignments": false, + "rebuildVolumeGroups":true, + "usePreload" : true, "userParams": [], "testApi": "VNF_API" }, diff --git a/vid-app-common/src/test/resources/sampleTosca.csar b/vid-app-common/src/test/resources/sampleTosca.csar Binary files differdeleted file mode 100644 index d9c469a15..000000000 --- a/vid-app-common/src/test/resources/sampleTosca.csar +++ /dev/null diff --git a/vid-automation/TestNg-ApiTest.xml b/vid-automation/TestNg-ApiTest.xml index 641f3eba6..e0ca82cb8 100644 --- a/vid-automation/TestNg-ApiTest.xml +++ b/vid-automation/TestNg-ApiTest.xml @@ -20,6 +20,10 @@ "underDevelopment" }; + String [] testClassesToRunAlways = new String [] { + "LoggerFormatTest" + }; + String [] classes1 = new String [] { "AsyncInstantiationALaCarteApiTest" }; @@ -34,6 +38,10 @@ if (methodClass.contains("org.onap.vid.api.Base")) return true; + for (c: testClassesToRunAlways) { + if (methodClass.endsWith(c)) return true; // repeat in any selectPart value + } + for (c: classes1) { if (methodClass.endsWith(c)) return selectPart==1; } diff --git a/vid-automation/src/main/java/org/onap/sdc/ci/tests/execute/setup/SetupCDTest.java b/vid-automation/src/main/java/org/onap/sdc/ci/tests/execute/setup/SetupCDTest.java index bb6a19a36..b3be16a42 100644 --- a/vid-automation/src/main/java/org/onap/sdc/ci/tests/execute/setup/SetupCDTest.java +++ b/vid-automation/src/main/java/org/onap/sdc/ci/tests/execute/setup/SetupCDTest.java @@ -20,10 +20,12 @@ package org.onap.sdc.ci.tests.execute.setup; +import com.aventstack.extentreports.ExtentTest; +import com.aventstack.extentreports.Status; import java.io.File; import java.io.IOException; import java.util.UUID; - +import net.lightbody.bmp.core.har.Har; import org.onap.sdc.ci.tests.datatypes.Configuration; import org.onap.sdc.ci.tests.datatypes.User; import org.onap.sdc.ci.tests.datatypes.UserCredentials; @@ -44,11 +46,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import com.aventstack.extentreports.ExtentTest; -import com.aventstack.extentreports.Status; - -import net.lightbody.bmp.core.har.Har; - public abstract class SetupCDTest extends DriverFactory { private static final String RE_RUN = "<html><font color=\"red\">ReRun - </font></html>"; @@ -172,7 +169,7 @@ public abstract class SetupCDTest extends DriverFactory { return url; } - public static void navigateToUrl(String url) throws Exception { + public static void navigateToUrl(String url) { try { System.out.println("Deleting cookies..."); deleteCookies(); @@ -282,7 +279,7 @@ public abstract class SetupCDTest extends DriverFactory { } } - public void navigateAndLogin(UserCredentials userCredentials) throws Exception { + public void navigateAndLogin(UserCredentials userCredentials) { int refreshAttempts = getWindowTest().getRefreshAttempts() != 0 ? getWindowTest().getRefreshAttempts() : 0; setRefreshAttempts(refreshAttempts); setUser(userCredentials); @@ -300,7 +297,7 @@ public abstract class SetupCDTest extends DriverFactory { return user; } - protected void reloginWithNewRole(UserCredentials userCredentials) throws Exception { + protected void reloginWithNewRole(UserCredentials userCredentials) { System.out.println(String.format("Setup before relogin with the userId %s", userCredentials.getUserId())); navigateAndLogin(userCredentials); } @@ -353,4 +350,4 @@ public abstract class SetupCDTest extends DriverFactory { StartTest.main(testSuiteArr); } -}
\ No newline at end of file +} diff --git a/vid-automation/src/main/java/org/onap/sdc/ci/tests/utilities/GeneralUIUtils.java b/vid-automation/src/main/java/org/onap/sdc/ci/tests/utilities/GeneralUIUtils.java index b10636bf1..e834c15ac 100644 --- a/vid-automation/src/main/java/org/onap/sdc/ci/tests/utilities/GeneralUIUtils.java +++ b/vid-automation/src/main/java/org/onap/sdc/ci/tests/utilities/GeneralUIUtils.java @@ -475,6 +475,18 @@ public final class GeneralUIUtils { return element; } + public static boolean isOptionSelectedInMultiSelect(String dataTestId, String option) { + GeneralUIUtils.ultimateWait(); + List<WebElement> selectedElements = getDriver().findElements(By.xpath("//*[@data-tests-id='" + dataTestId + "']//span[@class='c-label']")); + + + for (WebElement selectedElement : selectedElements) { + if (selectedElement.getText().equals(option)) { + return true; + } + } + return false; + } public static WebElement getSelectedElementFromDropDown(String dataTestId){ GeneralUIUtils.ultimateWait();; WebElement selectedElement = new Select (getDriver().findElement(By.xpath("//*[@data-tests-id='" + dataTestId + "']"))).getFirstSelectedOption(); diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/aaf/AAFGetUrlServicePreset.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/aaf/AAFGetUrlServicePreset.java index b3376e61a..c3914660e 100644 --- a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/aaf/AAFGetUrlServicePreset.java +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/aaf/AAFGetUrlServicePreset.java @@ -2,6 +2,7 @@ package org.onap.simulator.presetGenerator.presets.aaf; import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset; import org.springframework.http.HttpMethod; +import vid.automation.test.services.SimulatorApi; public class AAFGetUrlServicePreset extends BasePreset { @Override @@ -11,7 +12,11 @@ public class AAFGetUrlServicePreset extends BasePreset { @Override public String getReqPath() { - return "/locate/com.att.aaf.service:2.0"; + return "/locate/" + regexAafServerName() + ":2.0"; + } + + private String regexAafServerName() { + return "([a-z-]+\\.)*[a-z-]+"; } @Override @@ -21,6 +26,22 @@ public class AAFGetUrlServicePreset extends BasePreset { @Override public Object getResponseBody() { - return "{\"endpoint\":[{\"name\":\"com.att.aaf.service\",\"major\": 2,\"minor\": 0,\"patch\": 19,\"pkg\": 21,\"latitude\": 38.627346,\"longitude\": -90.19377,\"protocol\": \"http\",\"subprotocol\": [],\"hostname\": \"127.0.0.1\",\"port\": 1080}]}"; + return "" + + "{" + + " \"endpoint\": [{" + + " \"name\": \"aaf-service\"," + + " \"major\": 2," + + " \"minor\": 0," + + " \"patch\": 19," + + " \"pkg\": 21," + + " \"latitude\": 38.627346," + + " \"longitude\": -90.19377," + + " \"protocol\": \"http\"," + + " \"subprotocol\": []," + + " \"port\": " + SimulatorApi.getSimulatedResponsesPort() + "," + + " \"hostname\": \"" + SimulatorApi.getSimulatorHost() + "\"" + + " }" + + " ]" + + "}"; } } diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateMacroPre1806Post.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateMacroPre1806Post.java index 29e1365af..e2f342f0e 100644 --- a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateMacroPre1806Post.java +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateMacroPre1806Post.java @@ -25,7 +25,7 @@ public class PresetMSOCreateMacroPre1806Post extends PresetMSOBaseCreateInstance " }," + " \"modelInfo\": {" + " \"modelType\": \"service\"," + - " \"modelInvariantId\": \"d27e42cf-087e-4d31-88ac-6c4b7585f800\"," + + " \"modelInvariantId\": \"a8dcd72d-d44d-44f2-aa85-53aa9ca99cba\"," + " \"modelVersionId\": \"4d71990b-d8ad-4510-ac61-496288d9078e\"," + " \"modelName\": \"vidmacrofalsenaming\"," + " \"modelVersion\": \"1.0\"" + diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceAlacarte5GServiceWithNetwork.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceAlacarte.java index 40c18fa55..180aaefd1 100644 --- a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceAlacarte5GServiceWithNetwork.java +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceAlacarte.java @@ -1,16 +1,20 @@ package org.onap.simulator.presetGenerator.presets.mso; -import java.util.Map; - import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys.SERVICE_NAME; -public class PresetMSOCreateServiceInstanceAlacarte5GServiceWithNetwork extends PresetMSOCreateServiceInstanceGen2WithNames { +import java.util.Map; +import vid.automation.test.infra.ModelInfo; + +public class PresetMSOCreateServiceInstanceAlacarte extends PresetMSOCreateServiceInstanceGen2WithNames { private final String requestorId; + protected final ModelInfo modelInfo; - public PresetMSOCreateServiceInstanceAlacarte5GServiceWithNetwork(Map<Keys, String> names, String requestId, String requestorId) { - super(names, 0, requestId); + public PresetMSOCreateServiceInstanceAlacarte(Map<Keys, String> names, String requestId, String responseInstanceId, + String requestorId, ModelInfo modelInfo) { + super(names, 0, requestId, responseInstanceId); this.requestorId = requestorId; + this.modelInfo = modelInfo; } @Override @@ -22,13 +26,7 @@ public class PresetMSOCreateServiceInstanceAlacarte5GServiceWithNetwork extends public Object getRequestBody() { return "{" + " \"requestDetails\": {" + - " \"modelInfo\": {" + - " \"modelInvariantId\": \"16e56d12-40b3-4db1-a40e-d48c36679e2e\"," + - " \"modelVersionId\": \"4659e8bd-0920-4eed-8ec5-550b4c8dceeb\"," + - " \"modelName\": \"SR-IOV Provider-1\"," + - " \"modelType\": \"service\"," + - " \"modelVersion\": \"1.0\"" + - " }," + + modelInfo.createMsoModelInfo()+ " \"owningEntity\": {" + " \"owningEntityId\": \"d61e6f2d-12fa-4cc2-91df-7c244011d6fc\"," + " \"owningEntityName\": \"WayneHolland\"" + diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteCypress.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteCypress.java index 7b434d559..2a353a38b 100644 --- a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteCypress.java +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteCypress.java @@ -1,12 +1,10 @@ package org.onap.simulator.presetGenerator.presets.mso; import com.google.common.collect.ImmutableMap; - import java.util.Map; -public class PresetMSOCreateVfModuleALaCarteCypress extends PresetMSOBaseCreateInstancePost { - private String serviceInstanceId; - private String vnfInstanceId; +public class PresetMSOCreateVfModuleALaCarteCypress extends PresetMSOCreateVfModuleBase { + protected final Map<Keys, String> names; public enum Keys { @@ -34,25 +32,13 @@ public class PresetMSOCreateVfModuleALaCarteCypress extends PresetMSOBaseCreateI .build(); public PresetMSOCreateVfModuleALaCarteCypress(String overrideRequestId, String serviceInstanceId, String vnfInstanceId, Map<Keys, String> names, String testApi, boolean withTestApi) { - super(overrideRequestId); - this.vnfInstanceId = vnfInstanceId; - this.serviceInstanceId = serviceInstanceId; + super(overrideRequestId, DEFAULT_INSTANCE_ID, serviceInstanceId, vnfInstanceId, "vfModule"); this.names = names; this.msoTestApi = testApi; this.withTestApi = withTestApi; } @Override - public boolean isStrictMatch() { - return true; - } - - @Override - public String getReqPath() { - return getRootPath() + "/serviceInstantiation/v./serviceInstances/" + serviceInstanceId + "/vnfs/" + vnfInstanceId + "/vfModules"; - } - - @Override public Object getRequestBody() { return "" + "{" + diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteE2E.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteE2E.java new file mode 100644 index 000000000..89744a723 --- /dev/null +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteE2E.java @@ -0,0 +1,89 @@ +package org.onap.simulator.presetGenerator.presets.mso; + +import org.apache.commons.lang3.ObjectUtils; +import vid.automation.test.infra.ModelInfo; +import vid.automation.test.infra.ModelInfoWithCustomization; + +public class PresetMSOCreateVfModuleALaCarteE2E extends PresetMSOCreateVfModuleBase { + + protected final String requestorId; + protected final ModelInfo serviceModelInfo; + private final String instanceName; + private final ModelInfoWithCustomization resourceModelInfo; + private final String relatedInstance; + + public PresetMSOCreateVfModuleALaCarteE2E( + String overrideRequestId, + String responseInstanceId, + String serviceInstanceId, + String vnfInstanceId, + String requestorId, + ModelInfo serviceModelInfo, + String instanceName, + ModelInfoWithCustomization resourceModelInfo, + String relatedInstance) { + super(overrideRequestId, responseInstanceId, serviceInstanceId, vnfInstanceId, resourceModelInfo.resourceType); + this.requestorId = requestorId; + this.serviceModelInfo = serviceModelInfo; + this.instanceName = instanceName; + this.resourceModelInfo = resourceModelInfo; + this.relatedInstance = relatedInstance; + } + + @Override + public Object getRequestBody() { + return "{" + + " \"requestDetails\": {" + + resourceModelInfo.createMsoModelInfo() + + " \"cloudConfiguration\": {" + + " \"lcpCloudRegionId\": \"hvf6\"," + + addCloudOwnerIfNeeded() + + " \"tenantId\": \"bae71557c5bb4d5aac6743a4e5f1d054\"" + + " }," + + " \"requestInfo\": {" + + addInstanceName() + + " \"source\": \"VID\"," + + " \"suppressRollback\": false," + + " \"requestorId\": \""+requestorId+"\"" + + " }," + + " \"relatedInstanceList\": [{" + + " \"relatedInstance\": {" + + serviceModelInfo.createMsoModelInfo() + + " \"instanceId\": \""+serviceInstanceId+"\"" + + " }" + + " }, {" + + " \"relatedInstance\": {" + + " \"modelInfo\": {" + + " \"modelCustomizationName\": \"vOCG_1804_VF 0\"," + + " \"modelCustomizationId\": \"e9ed1da0-c078-426a-8e84-6f4e85eace59\"," + + " \"modelInvariantId\": \"db23d71a-4cb4-4030-9c9b-e3f886c2b35c\"," + + " \"modelVersionId\": \"aca3f7b1-15f9-45a5-b182-b8b5aca84a76\"," + + " \"modelName\": \"vOCG_1804_VF\"," + + " \"modelType\": \"vnf\"," + + " \"modelVersion\": \"4.0\"" + + " }," + + " \"instanceId\": \""+vnfInstanceId+"\"" + + " }" + + " }" + addRelatedInstance() + + " ]," + + " \"requestParameters\": {" + + " \"userParams\": [{" + + " \"param\": \"ABCD\"," + + " \"vnf_instance_name\": \"sample\"" + + " }" + + " ]," + + " \"testApi\": \"VNF_API\"" + + " }" + + " }" + + "}"; + } + + private String addInstanceName() { + return instanceName==null ? "" : + "\"instanceName\": \""+instanceName+"\","; + } + + private String addRelatedInstance() { + return ObjectUtils.defaultIfNull(relatedInstance, ""); + } +} diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleBase.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleBase.java new file mode 100644 index 000000000..7c148fa08 --- /dev/null +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleBase.java @@ -0,0 +1,25 @@ +package org.onap.simulator.presetGenerator.presets.mso; + +public class PresetMSOCreateVfModuleBase extends PresetMSOBaseCreateInstancePost { + + private final String resourceType; + protected String serviceInstanceId; + protected String vnfInstanceId; + + public PresetMSOCreateVfModuleBase(String requestId, String responseInstanceId, String serviceInstanceId, String vnfInstanceId, String resourceType) { + super(requestId, responseInstanceId); + this.serviceInstanceId = serviceInstanceId; + this.vnfInstanceId = vnfInstanceId; + this.resourceType = resourceType; + } + + @Override + public boolean isStrictMatch() { + return true; + } + + @Override + public String getReqPath() { + return getRootPath() + String.format("/serviceInstantiation/v./serviceInstances/%s/vnfs/%s/%ss",serviceInstanceId, vnfInstanceId, resourceType); + } +} diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteCypress2.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteCypress2.java index 96424e803..da1c3ffcf 100644 --- a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteCypress2.java +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteCypress2.java @@ -24,7 +24,7 @@ public class PresetMSOCreateVnfALaCarteCypress2 extends PresetMSOCreateVnfBase { "{\"lcpCloudRegionId\":\"just another region\"," + addCloudOwnerIfNeeded() + "\"tenantId\":\"092eb9e8e4b7412e8787dd091bc58e86\"}," + - "\"platform\":{\"platformName\":\"xxx1\"}," + + "\"platform\":{\"platformName\":\"xxx1,platform\"}," + "\"modelInfo\":" + "{\"modelCustomizationId\":\"1da7b585-5e61-4993-b95e-8e6606c81e45\"," + "\"modelCustomizationName\":\"2017-488_PASQUALE-vPE 0\"," + diff --git a/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteE2E.java b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteE2E.java new file mode 100644 index 000000000..dba42f32f --- /dev/null +++ b/vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteE2E.java @@ -0,0 +1,67 @@ +package org.onap.simulator.presetGenerator.presets.mso; + +import vid.automation.test.infra.ModelInfo; + +public class PresetMSOCreateVnfALaCarteE2E extends PresetMSOCreateVnfBase { + + private final String requestorId; + protected String lineOfBusinessName; + protected final ModelInfo serviceModelInfo; + + public PresetMSOCreateVnfALaCarteE2E( + String overrideRequestId, + String serviceInstanceId, + String vnfInstanceId, + String lineOfBusinessName, + String requestorId, + ModelInfo serviceModelInfo) { + super(overrideRequestId, serviceInstanceId, vnfInstanceId); + this.lineOfBusinessName = lineOfBusinessName; + this.requestorId = requestorId; + this.serviceModelInfo = serviceModelInfo; + } + + @Override + public Object getRequestBody() { + return "{" + + " \"requestDetails\": {" + + " \"modelInfo\": {" + + " \"modelCustomizationName\": \"vOCG_1804_VF 0\"," + + " \"modelCustomizationId\": \"e9ed1da0-c078-426a-8e84-6f4e85eace59\"," + + " \"modelInvariantId\": \"db23d71a-4cb4-4030-9c9b-e3f886c2b35c\"," + + " \"modelVersionId\": \"aca3f7b1-15f9-45a5-b182-b8b5aca84a76\"," + + " \"modelName\": \"vOCG_1804_VF\"," + + " \"modelType\": \"vnf\"," + + " \"modelVersion\": \"4.0\"" + + " }," + + " \"cloudConfiguration\": {" + + " \"lcpCloudRegionId\": \"some legacy region\"," + + addCloudOwnerIfNeeded() + + " \"tenantId\": \"092eb9e8e4b7412e8787dd091bc58e86\"" + + " }," + + " \"requestInfo\": {" + + " \"source\": \"VID\"," + + " \"suppressRollback\": false," + + " \"requestorId\": \""+requestorId+"\"" + + " }," + + " \"platform\": {" + + " \"platformName\": \"platform\"" + + " }," + + " \"lineOfBusiness\": {" + + " \"lineOfBusinessName\": \""+lineOfBusinessName+"\"" + + " }," + + " \"relatedInstanceList\": [{" + + " \"relatedInstance\": {" + + serviceModelInfo.createMsoModelInfo() + + " \"instanceId\": \""+serviceInstanceId+"\"" + + " }" + + " }" + + " ]," + + " \"requestParameters\": {" + + " \"userParams\": []," + + " \"testApi\": \"VNF_API\"" + + " }" + + " }" + + "}"; + } +} diff --git a/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java b/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java index 66bde727e..5e1310535 100644 --- a/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java +++ b/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java @@ -1,8 +1,34 @@ package org.onap.vid.api; +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toMap; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasSize; +import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys; +import static org.testng.Assert.assertNotNull; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; +import static vid.automation.test.utils.ExtendedHamcrestMatcher.hasItemsFromCollection; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.Uninterruptibles; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -38,33 +64,6 @@ import vid.automation.test.model.ServiceAction; import vid.automation.test.services.AsyncJobsService; import vid.automation.test.services.SimulatorApi; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static java.lang.Boolean.FALSE; -import static java.lang.Boolean.TRUE; -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toMap; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.hasSize; -import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys; -import static org.testng.Assert.assertNotNull; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; -import static vid.automation.test.utils.ExtendedHamcrestMatcher.hasItemsFromCollection; - public class AsyncInstantiationBase extends BaseMsoApiTest { public static final String CREATE_BULK_OF_ALACARTE_REQUEST_WITH_VNF = "asyncInstantiation/vidRequestCreateALaCarteWithVnf.json"; @@ -507,7 +506,7 @@ public class AsyncInstantiationBase extends BaseMsoApiTest { .filter(serviceInfo -> serviceInfo.jobId.equals(jobId)) .findFirst().orElse(null); Assert.assertNotNull(serviceInfoFromDB); - Assert.assertEquals(serviceInfoDataReflected(expectedServiceInfo), serviceInfoDataReflected(serviceInfoFromDB)); + Assert.assertEquals(serviceInfoDataReflected(serviceInfoFromDB), serviceInfoDataReflected(expectedServiceInfo)); assertTrue("actual service instance doesn't contain template service name:" + expectedServiceInfo.serviceInstanceName, serviceInfoFromDB.serviceInstanceName.contains(expectedServiceInfo.serviceInstanceName)); diff --git a/vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java b/vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java index 3778e4b16..4819b813f 100644 --- a/vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java +++ b/vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java @@ -8,7 +8,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.hamcrest.Matchers.not; -//import com.automation.common.report_portal_integration.listeners.ReportPortalListener; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -21,7 +20,6 @@ import java.util.Properties; import java.util.Random; import java.util.TimeZone; import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -39,6 +37,7 @@ import vid.automation.reportportal.ReportPortalListenerDelegator; import vid.automation.test.infra.FeaturesTogglingConfiguration; import vid.automation.test.services.UsersService; import vid.automation.test.utils.CookieAndJsonHttpHeadersInterceptor; +import vid.automation.test.utils.InsecureHttpsClient; @Listeners(ReportPortalListenerDelegator.class) public class BaseApiTest { @@ -51,16 +50,16 @@ public class BaseApiTest { @SuppressWarnings("WeakerAccess") protected Client client; protected Random random; - protected final RestTemplate restTemplate = new RestTemplate(); + protected final RestTemplate restTemplate = InsecureHttpsClient.newRestTemplate(); protected final UsersService usersService = new UsersService(); - protected final RestTemplate restTemplateErrorAgnostic = new RestTemplate(); + protected final RestTemplate restTemplateErrorAgnostic = InsecureHttpsClient.newRestTemplate(); @BeforeClass public void init() { uri = getUri(); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); - client = ClientBuilder.newClient(); + client = InsecureHttpsClient.newJaxrsClient(); client.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); random = new Random(System.currentTimeMillis()); FeaturesTogglingConfiguration.initializeFeatureManager(); @@ -69,7 +68,8 @@ public class BaseApiTest { private URI getUri() { String host = System.getProperty("VID_HOST", "127.0.0.1"); int port = Integer.valueOf(System.getProperty("VID_PORT", "8080")); - return new JerseyUriBuilder().host(host).port(port).scheme("http").path("vid").build(); + String protocol = System.getProperty("VID_PROTOCOL", "http"); + return new JerseyUriBuilder().host(host).port(port).scheme(protocol).path("vid").build(); } public void login() { @@ -77,9 +77,20 @@ public class BaseApiTest { } public void login(UserCredentials userCredentials) { + final List<ClientHttpRequestInterceptor> interceptors = loginWithChosenRESTClient(userCredentials, restTemplate); + restTemplateErrorAgnostic.setInterceptors(interceptors); + restTemplateErrorAgnostic.setErrorHandler(new DefaultResponseErrorHandler() { + @Override + public boolean hasError(ClientHttpResponse response) { + return false; + } + }); + } + + public List<ClientHttpRequestInterceptor> loginWithChosenRESTClient(UserCredentials userCredentials,RestTemplate givenRestTemplate) { final List<ClientHttpRequestInterceptor> interceptors = singletonList(new CookieAndJsonHttpHeadersInterceptor(getUri(), userCredentials)); - restTemplate.setInterceptors(interceptors); - restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { + givenRestTemplate.setInterceptors(interceptors); + givenRestTemplate.setErrorHandler(new DefaultResponseErrorHandler() { @Override public void handleError(ClientHttpResponse response) throws IOException { try { @@ -90,14 +101,7 @@ public class BaseApiTest { } } }); - - restTemplateErrorAgnostic.setInterceptors(interceptors); - restTemplateErrorAgnostic.setErrorHandler(new DefaultResponseErrorHandler() { - @Override - public boolean hasError(ClientHttpResponse response) { - return false; - } - }); + return interceptors; } diff --git a/vid-automation/src/main/java/vid/automation/test/Constants.java b/vid-automation/src/main/java/vid/automation/test/Constants.java index 689c46387..7256f0a2e 100644 --- a/vid-automation/src/main/java/vid/automation/test/Constants.java +++ b/vid-automation/src/main/java/vid/automation/test/Constants.java @@ -303,7 +303,7 @@ public class Constants { }}; } - public static final String CREATE_SERVICE_INSTANCE_MACRO_MODAL = "Set a new service instance"; + } @@ -506,6 +506,7 @@ public class Constants { public static final String PROJECT_SELECT_TEST_ID = "project"; public static final String OWNING_ENTITY_SELECT_TEST_ID = "owningEntity"; public static final String PLATFORM_SELECT_TEST_ID = "platform"; + public static final String PLATFORM_MULTI_SELECT_TEST_ID = "multi-selectPlatform"; public static final String LOB_SELECT_TEST_ID = "lineOfBusiness"; } diff --git a/vid-automation/src/main/java/vid/automation/test/infra/Features.java b/vid-automation/src/main/java/vid/automation/test/infra/Features.java index 329bb4a89..289151b88 100644 --- a/vid-automation/src/main/java/vid/automation/test/infra/Features.java +++ b/vid-automation/src/main/java/vid/automation/test/infra/Features.java @@ -5,8 +5,6 @@ import org.togglz.core.context.FeatureContext; public enum Features implements Feature { - CREATE_INSTANCE_TEST, - EMPTY_DRAWING_BOARD_TEST, FLAG_ADD_MSO_TESTAPI_FIELD, FLAG_SERVICE_MODEL_CACHE, FLAG_NETWORK_TO_ASYNC_INSTANTIATION, @@ -14,8 +12,6 @@ public enum Features implements Feature { FLAG_UNASSIGN_SERVICE, FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS, FLAG_SHOW_VERIFY_SERVICE, - FLAG_DEFAULT_VNF, - FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD, FLAG_RESTRICTED_SELECT, FLAG_5G_IN_NEW_INSTANTIATION_UI, FLAG_ASYNC_ALACARTE_VNF, @@ -27,7 +23,6 @@ public enum Features implements Feature { FLAG_ENABLE_WEBPACK_MODERN_UI, FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY, FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST, - FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE, FLAG_1810_AAI_LOCAL_CACHE, FLAG_1810_IDENTIFY_SERVICE_FOR_NEW_UI, FLAG_1902_NEW_VIEW_EDIT, @@ -55,7 +50,11 @@ public enum Features implements Feature { FLAG_FLASH_REDUCED_RESPONSE_CHANGEMG, FLAG_FLASH_CLOUD_REGION_AND_NF_ROLE_OPTIONAL_SEARCH, FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE, - FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE + FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI, + FLAG_2002_VNF_PLATFORM_MULTI_SELECT, + FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, + FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND, + FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER, ; public boolean isActive() { diff --git a/vid-automation/src/main/java/vid/automation/test/infra/Get.java b/vid-automation/src/main/java/vid/automation/test/infra/Get.java index 9bcad7b64..1e0c94844 100644 --- a/vid-automation/src/main/java/vid/automation/test/infra/Get.java +++ b/vid-automation/src/main/java/vid/automation/test/infra/Get.java @@ -97,6 +97,9 @@ public class Get { return GeneralUIUtils.getSelectedElementFromDropDown(dataTestId).getText(); } + public static Boolean isOptionSelectedInMultiSelect(String dataTestId, String option) { + return GeneralUIUtils.isOptionSelectedInMultiSelect(dataTestId, option); + } public static List<WebElement> byClass(String className) { return GeneralUIUtils.getWebElementsListByContainsClassName(className); diff --git a/vid-automation/src/main/java/vid/automation/test/infra/ModelInfo.java b/vid-automation/src/main/java/vid/automation/test/infra/ModelInfo.java index 59e48013c..546b80b05 100644 --- a/vid-automation/src/main/java/vid/automation/test/infra/ModelInfo.java +++ b/vid-automation/src/main/java/vid/automation/test/infra/ModelInfo.java @@ -2,9 +2,8 @@ package vid.automation.test.infra; import com.google.common.collect.ImmutableList; -public class ModelInfo { - public final String modelVersionId; //aka model uuid - public final String modelInvariantId; +public class ModelInfo extends ModelInfoBase { + public final String zipFileName; public static class ModelInfoWithMultipleVersions { @@ -32,8 +31,11 @@ public class ModelInfo { } public ModelInfo(String modelVersionId, String modelInvariantId, String zipFileName) { - this.modelVersionId = modelVersionId; - this.modelInvariantId = modelInvariantId; + this(modelVersionId, modelInvariantId, zipFileName, null, null); + } + + public ModelInfo(String modelVersionId, String modelInvariantId, String zipFileName, String modelName, String modelVersion) { + super(modelVersionId, modelInvariantId, modelName, modelVersion, "service"); this.zipFileName = zipFileName; } @@ -50,16 +52,22 @@ public class ModelInfo { public static final ModelInfo macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetails = new ModelInfo ("1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd", "cdb90b57-ed78-4d44-a5b4-7f43a02ec632", "csar-noDynamicFields-ecompNamingFalse-fullModelDetails-1a80c596.zip"); public static final ModelInfo macroSriovWithDynamicFieldsEcompNamingFalsePartialModelDetailsVnfEcompNamingFalse = new ModelInfo("6b528779-44a3-4472-bdff-9cd15ec93450", "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0" , "csar-withDynamicFields-ecompNamingFalse-partialModelDetails-vnfEcompNamingFalse.zip"); public static final ModelInfo macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetailsVnfEcompNamingFalse = new ModelInfo("4a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd", "4140a873-00bb-4f57-ac46-0494cc9e674a", "csar-noDynamicFields-ecompNamingFalse-fullModelDetails-1a80c596-vnfEcompNamingFalse.zip"); - public static final ModelInfo aLaCarteNetworkProvider5G = new ModelInfo("4659e8bd-0920-4eed-8ec5-550b4c8dceeb", "16e56d12-40b3-4db1-a40e-d48c36679e2e", "service-SrIovProvider1-csar.zip"); + public static final ModelInfo aLaCarteNetworkProvider5G = new ModelInfo("4659e8bd-0920-4eed-8ec5-550b4c8dceeb", "16e56d12-40b3-4db1-a40e-d48c36679e2e", "service-SrIovProvider1-csar.zip", "SR-IOV Provider-1", "1.0"); public static final ModelInfo pasqualeVmxVpeBvService488Annotations = new ModelInfo("f4d84bb4-a416-4b4e-997e-0059973630b9", "598e3f9e-3244-4d8f-a8e0-0e5d7a29eda9", "service-PasqualeVmxVpeBvService488-csar-annotations.zip"); public static final ModelInfo macroDrawingBoardComplexService = new ModelInfo("6e59c5de-f052-46fa-aa7e-2fca9d674c44","cfef8302-d90f-475f-87cc-3f49a62ef14c", "service-Complexservice-csar.zip" ); public static final ModelInfo aLaCarteServiceCreationTest = new ModelInfo("f913c5d0-206e-45c2-9284-1c68f4e67dc7", "45e61192-876c-4e28-9139-5a0c47410379", "serviceCreationTest.zip"); + public static final ModelInfo aLaCarteServiceCreationNewUI = new ModelInfo("f3862254-8df2-4a0a-8137-0a9fe985860c", "d1068db8-b933-4919-8972-8bc1aed366c8", "service-Vocg1804Svc.zip", "vOCG_1804_SVC", "1.0"); + public static final ModelInfo aLaCarteServiceOldVersionTest = new ModelInfo("04743c62-ab58-41a0-bc53-1052ef1c094a", "5d353b28-e5b7-419b-98e8-cad5d258be13", "serviceCreationTest04743c62-ab58-41a0-bc53-1052ef1c094a.zip"); public static final ModelInfo aLaCarteVnfGroupingService = new ModelInfo("4117a0b6-e234-467d-b5b9-fe2f68c8b0fc", "7ee41ce4-4827-44b0-a48e-2707a59905d2", "csar15782222_instantiationTypeAlacarte_VnfGrouping.zip"); public static final ModelInfo serviceFabricSriovService = new ModelInfo("253f1467-fe68-4e80-ba71-308000caec31", "c15fe228-7d40-4f99-afa7-10abeedf9aac", "service-fabric-SriovService-csar.zip"); public static final ModelInfo infrastructureVpnService = new ModelInfo("f028b2e2-7080-4b13-91b2-94944d4c42d8", "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb", "service-Infravpn-csar.zip"); public static final ModelInfo collectionResourceService = new ModelInfo("abd0cb02-5f97-42cd-be93-7dd3e31a6a64", "04bdd793-32ed-4045-adea-4e096304a067", "csar_collection_resource.zip"); public static final ModelInfo collectionResourceForResume = new ModelInfo("6e0bec91-09f3-43aa-9cf3-e617cd0146be", "f6342be5-d66b-4d03-a1aa-c82c3094c4ea", "csar_collection_resource_for_resume.zip"); public static final ModelInfo transportWithPnfsService = new ModelInfo("12550cd7-7708-4f53-a09e-41d3d6327ebc", "561faa57-7bbb-40ec-a81c-c0d4133e98d4", "csarTransportWithPnfs.zip"); + public static final ModelInfo serviceWithInstantiationTypeMacro = new ModelInfo( + "fca0674c-f825-44bc-a87f-41ba7a0b4ab7", + "44173a37-0fce-486b-84be-40582bf3e40b", + "csar15782222_instantiationTypeMacro_invariantUUIDAlacarte_withoutNetworks.zip"); public static final ImmutableList<ModelInfo> superSetOfModelInfos = buildModelInfos(); public static ImmutableList<ModelInfo> buildModelInfos() { @@ -81,8 +89,11 @@ public class ModelInfo { .add(transportWithPnfsService) .add(collectionResourceService) .add(collectionResourceForResume) + .add(aLaCarteServiceCreationNewUI) + .add(serviceWithInstantiationTypeMacro) .build(); } + } diff --git a/vid-automation/src/main/java/vid/automation/test/infra/ModelInfoBase.java b/vid-automation/src/main/java/vid/automation/test/infra/ModelInfoBase.java new file mode 100644 index 000000000..e26339667 --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/infra/ModelInfoBase.java @@ -0,0 +1,34 @@ +package vid.automation.test.infra; + +public class ModelInfoBase { + + public final String modelVersionId; //aka model uuid + public final String modelInvariantId; + public final String modelName; + public final String modelVersion; + public final String resourceType; + + public ModelInfoBase(String modelVersionId, String modelInvariantId, String modelName, String modelVersion, String resourceType) { + this.modelVersionId = modelVersionId; + this.modelInvariantId = modelInvariantId; + this.modelName = modelName; + this.modelVersion = modelVersion; + this.resourceType = resourceType; + } + + public String createMsoModelInfo() { + return + " \"modelInfo\": {" + + " \"modelInvariantId\": \""+modelInvariantId+"\"," + + " \"modelVersionId\": \""+modelVersionId+"\"," + + " \"modelName\": \""+modelName+"\"," + + " \"modelType\": \""+resourceType+"\"," + + addAdditionalFields() + + " \"modelVersion\": \""+modelVersion+"\"" + + " },"; + } + + protected String addAdditionalFields() { + return ""; + } +} diff --git a/vid-automation/src/main/java/vid/automation/test/infra/ModelInfoWithCustomization.java b/vid-automation/src/main/java/vid/automation/test/infra/ModelInfoWithCustomization.java new file mode 100644 index 000000000..8ee690f7c --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/infra/ModelInfoWithCustomization.java @@ -0,0 +1,20 @@ +package vid.automation.test.infra; + +public class ModelInfoWithCustomization extends ModelInfoBase { + + public final String modelCustomizationName; + public final String modelCustomizationId; + + public ModelInfoWithCustomization(String modelVersionId, String modelInvariantId, String modelName, String modelVersion, String resourceType, + String modelCustomizationName, String modelCustomizationId) { + super(modelVersionId, modelInvariantId, modelName, modelVersion, resourceType); + this.modelCustomizationName = modelCustomizationName; + this.modelCustomizationId = modelCustomizationId; + } + + @Override + protected String addAdditionalFields() { + return "\"modelCustomizationName\": \""+modelCustomizationName+"\"," + + "\"modelCustomizationId\": \""+modelCustomizationId+"\","; + } +} diff --git a/vid-automation/src/main/java/vid/automation/test/infra/SelectOption.java b/vid-automation/src/main/java/vid/automation/test/infra/SelectOption.java index cd766c5bf..096ff47d9 100644 --- a/vid-automation/src/main/java/vid/automation/test/infra/SelectOption.java +++ b/vid-automation/src/main/java/vid/automation/test/infra/SelectOption.java @@ -67,14 +67,29 @@ public class SelectOption { } public static void selectOptionsFromMultiselectById(String multiSelectId, List<String> options) { - Click.byId(multiSelectId); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - throw new RuntimeException(e); + WebElement multiselectComponent = Get.byXpath("//*[@data-tests-id='" + multiSelectId +"']//div[contains(@class, 'c-btn')]"); + if(multiselectComponent != null){ + multiselectComponent.click(); + try { + Thread.sleep(1000); + for(String option:options) { + String multiSelectOptionPath = "//label[@data-tests-id='" + multiSelectId + "-" + option + "']"; + WebElement multiSelelctOption = Get.byXpath(multiSelectOptionPath); + if(multiSelelctOption != null){ + multiSelelctOption.click(); + } + } + multiselectComponent.click(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } - for(String option:options) { - Click.byClassAndVisibleText(Constants.MULTI_SELECT_UNSELECTED_CLASS, option); + } + + public static void selectFirstOptionsFromMultiselect(String multiSelectId){ + WebElement multiSelectOption = Get.byXpath("//*[@data-tests-id='" + multiSelectId +"']//label[contains(@class, 'multiSelectOption')]"); + if(multiSelectOption != null){ + SelectOption.selectOptionsFromMultiselectById(multiSelectId, ImmutableList.of(multiSelectOption.getText())); } } } diff --git a/vid-automation/src/main/java/vid/automation/test/sections/DeployMacroDialogBase.java b/vid-automation/src/main/java/vid/automation/test/sections/DeployMacroDialogBase.java deleted file mode 100644 index 270f53e97..000000000 --- a/vid-automation/src/main/java/vid/automation/test/sections/DeployMacroDialogBase.java +++ /dev/null @@ -1,12 +0,0 @@ -package vid.automation.test.sections; - -public abstract class DeployMacroDialogBase extends VidBasePage { - - public abstract void assertTitle(); - public abstract void closeDialog(); - public abstract void assertDialogExists(); - public abstract void clickOwningEntitySelect(); - public abstract void clickProjectSelect(); - - -} diff --git a/vid-automation/src/main/java/vid/automation/test/sections/InstantiationStatusPage.java b/vid-automation/src/main/java/vid/automation/test/sections/InstantiationStatusPage.java index 1bb095fda..4bd380841 100644 --- a/vid-automation/src/main/java/vid/automation/test/sections/InstantiationStatusPage.java +++ b/vid-automation/src/main/java/vid/automation/test/sections/InstantiationStatusPage.java @@ -1,5 +1,16 @@ package vid.automation.test.sections; +import static java.util.stream.Collectors.toMap; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.testng.Assert.assertEquals; + +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; @@ -10,20 +21,9 @@ import org.openqa.selenium.support.ui.WebDriverWait; import vid.automation.test.Constants; import vid.automation.test.infra.Click; import vid.automation.test.infra.Get; +import vid.automation.test.infra.Input; import vid.automation.test.infra.Wait; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static java.util.stream.Collectors.toMap; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.testng.Assert.assertEquals; - public abstract class InstantiationStatusPage extends VidBasePage { public static final String refreshButtonId = "refresh-btn"; @@ -40,6 +40,11 @@ public abstract class InstantiationStatusPage extends VidBasePage { return wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//*[table]//tbody/tr"))).size(); } + public static void verifyInstantiationStatusFilterValue(String serviceModelId) { + final String filterValue = Input.getValueByTestId("instantiation-status-filter"); + assertEquals(filterValue, serviceModelId); + } + public static WebElement assertInstantiationStatusRow(String spanIdSelector, Map<String, String> fieldsIdsAndExpected) { try { WebElement newTrRow = getInstantiationStatusRow(spanIdSelector); diff --git a/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployDialogBase.java b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployDialogBase.java new file mode 100644 index 000000000..5101a8438 --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployDialogBase.java @@ -0,0 +1,21 @@ +package vid.automation.test.sections.deploy; + +import vid.automation.test.sections.VidBasePage; + +public abstract class DeployDialogBase extends VidBasePage { + + public abstract void closeDialog(); + + public abstract void assertDialog(); + + public abstract void waitForDialogToLoad(); + + public abstract String getModelVersionId(); + + public void waitForDialogAssertAndClose() { + waitForDialogToLoad(); + assertDialog(); + closeDialog(); + } + +} diff --git a/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIALaCarteDialog.java b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIALaCarteDialog.java new file mode 100644 index 000000000..c4338551b --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIALaCarteDialog.java @@ -0,0 +1,12 @@ +package vid.automation.test.sections.deploy; + +import static org.testng.AssertJUnit.assertFalse; + +public class DeployModernUIALaCarteDialog extends DeployModernUIBase { + + @Override + public void assertDialog() { + super.assertDialog(); + assertFalse(isLcpRegionExist()); + } +} diff --git a/vid-automation/src/main/java/vid/automation/test/sections/DeployMacroDialog.java b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIBase.java index e7288ea79..747f4ebde 100644 --- a/vid-automation/src/main/java/vid/automation/test/sections/DeployMacroDialog.java +++ b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIBase.java @@ -1,20 +1,28 @@ -package vid.automation.test.sections; +package vid.automation.test.sections.deploy; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.WebElement; import vid.automation.test.Constants; +import vid.automation.test.infra.Exists; +import vid.automation.test.infra.Get; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +public abstract class DeployModernUIBase extends DeployDialogBase { -public class DeployMacroDialog extends DeployMacroDialogBase { - String dialogTitle = Constants.BrowseASDC.CREATE_SERVICE_INSTANCE_MACRO_MODAL; @Override - public void assertTitle(){ + public void waitForDialogToLoad() { + goToIframe(); + } + String dialogTitle = "Set a new service instance"; + + public void assertTitle(){ WebElement modalTitle = GeneralUIUtils.getWebElementByTestID(Constants.CREATE_MODAL_TITLE_ID, 30); assertThat(modalTitle.getText(), containsString(dialogTitle)); } + @Override public void closeDialog(){ GeneralUIUtils.ultimateWait(); @@ -23,17 +31,29 @@ public class DeployMacroDialog extends DeployMacroDialogBase { } @Override - public void assertDialogExists() { + public void assertDialog() { assertTitle(); } @Override + public String getModelVersionId() { + return Get.byTestId("model-item-value-uuid").getText(); + } + + protected boolean isLcpRegionExist() { + return Exists.byTestId(Constants.ViewEdit.LCP_REGION_SELECT_TESTS_ID); + } + public void clickOwningEntitySelect() { GeneralUIUtils.clickOnElementByTestId(Constants.OwningEntity.OWNING_ENTITY_SELECT_TEST_ID); } - @Override public void clickProjectSelect() { GeneralUIUtils.clickOnElementByTestId(Constants.OwningEntity.PROJECT_SELECT_TEST_ID); } + + public void clickPreviousInstantiationButton() { + GeneralUIUtils.clickOnElementByTestIdWithoutWait("ShowPreviousInstancesButton"); + } + } diff --git a/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIMacroDialog.java b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIMacroDialog.java new file mode 100644 index 000000000..33b4b05ef --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIMacroDialog.java @@ -0,0 +1,13 @@ +package vid.automation.test.sections.deploy; + +import static org.testng.Assert.assertTrue; + +public class DeployModernUIMacroDialog extends DeployModernUIBase { + + @Override + public void assertDialog() { + super.assertDialog(); + assertTrue(isLcpRegionExist()); + } + +} diff --git a/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldALaCarteDialog.java b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldALaCarteDialog.java new file mode 100644 index 000000000..aad4c9fb2 --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldALaCarteDialog.java @@ -0,0 +1,9 @@ +package vid.automation.test.sections.deploy; + +public class DeployOldALaCarteDialog extends DeployOldDialogBase { + + @Override + public String getTitle() { + return "a la carte"; + } +} diff --git a/vid-automation/src/main/java/vid/automation/test/sections/DeployMacroDialogOld.java b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldDialogBase.java index e0e391b4d..59c013a09 100644 --- a/vid-automation/src/main/java/vid/automation/test/sections/DeployMacroDialogOld.java +++ b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldDialogBase.java @@ -1,42 +1,42 @@ -package vid.automation.test.sections; +package vid.automation.test.sections.deploy; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import org.junit.Assert; import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.WebElement; import vid.automation.test.Constants; +import vid.automation.test.infra.Get; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; - -public class DeployMacroDialogOld extends DeployMacroDialogBase { - String dialogTitle = "macro"; +public abstract class DeployOldDialogBase extends DeployDialogBase { @Override - public void assertTitle(){ - WebElement modalTitle = GeneralUIUtils.getWebElementByTestID(Constants.CREATE_MODAL_TITLE_ID, 30); - assertThat(modalTitle.getText().toLowerCase(), containsString(dialogTitle)); + public void waitForDialogToLoad() { + GeneralUIUtils.ultimateWait(); } @Override public void closeDialog(){ - GeneralUIUtils.ultimateWait(); clickCancelButtonByTestID(); } @Override - public void assertDialogExists(){ + public void assertDialog(){ + assertTitle(); boolean byText = GeneralUIUtils.findAndWaitByText(Constants.BrowseASDC.CREATE_SERVICE_INSTANCE, 15); Assert.assertTrue(byText); } - @Override - public void clickOwningEntitySelect(){ - GeneralUIUtils.clickOnElementByTestId(Constants.OwningEntity.OWNING_ENTITY_SELECT_TEST_ID); + public void assertTitle(){ + WebElement modalTitle = GeneralUIUtils.getWebElementByTestID(Constants.CREATE_MODAL_TITLE_ID, 30); + assertThat(modalTitle.getText().toLowerCase(), containsString(getTitle())); } @Override - public void clickProjectSelect(){ - GeneralUIUtils.clickOnElementByTestId(Constants.OwningEntity.PROJECT_SELECT_TEST_ID); + public String getModelVersionId() { + return Get.byTestId("Service UUID").getText(); } + public abstract String getTitle(); } diff --git a/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldMacroDialog.java b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldMacroDialog.java new file mode 100644 index 000000000..73ae4c55a --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployOldMacroDialog.java @@ -0,0 +1,9 @@ +package vid.automation.test.sections.deploy; + +public class DeployOldMacroDialog extends DeployOldDialogBase { + + @Override + public String getTitle() { + return "macro"; + } +} diff --git a/vid-automation/src/main/java/vid/automation/test/services/AsyncJobsService.java b/vid-automation/src/main/java/vid/automation/test/services/AsyncJobsService.java index 35849b481..05d6553d3 100644 --- a/vid-automation/src/main/java/vid/automation/test/services/AsyncJobsService.java +++ b/vid-automation/src/main/java/vid/automation/test/services/AsyncJobsService.java @@ -1,16 +1,18 @@ package vid.automation.test.services; import com.google.common.collect.ImmutableList; -import vid.automation.test.utils.DB_CONFIG; - import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.List; +import vid.automation.test.utils.DB_CONFIG; public class AsyncJobsService { + private static final String MUTE_JOB_STATEMENT = + "UPDATE `vid_job` SET `TAKEN_BY`='muteAllAsyncJobs', `JOB_STATUS`=CONCAT('MUTED_', `JOB_STATUS`), `AGE`=`AGE`+5 "; + public void dropAllAsyncJobs() { runStatementsInDb(ImmutableList.of( "DELETE FROM `vid_service_info`", @@ -44,7 +46,11 @@ public class AsyncJobsService { public void muteAllAsyncJobs() { - runStatementInDb("UPDATE `vid_job` SET `TAKEN_BY`='muteAllAsyncJobs', `JOB_STATUS`=CONCAT('MUTED_', `JOB_STATUS`), `AGE`=`AGE`+5 WHERE `TAKEN_BY` is NULL or `TAKEN_BY`<>'muteAllAsyncJobs'"); + runStatementInDb(MUTE_JOB_STATEMENT + "WHERE `TAKEN_BY` is NULL or `TAKEN_BY`<>'muteAllAsyncJobs'"); + } + + public void muteAsyncJobById(String uuid) { + runStatementInDb(MUTE_JOB_STATEMENT + String.format("WHERE JOB_ID='%s'",uuid)); } public void dropAllFromNameCounter() { diff --git a/vid-automation/src/main/java/vid/automation/test/services/SimulatorApi.java b/vid-automation/src/main/java/vid/automation/test/services/SimulatorApi.java index 6e15b7b52..c8ac7ead9 100644 --- a/vid-automation/src/main/java/vid/automation/test/services/SimulatorApi.java +++ b/vid-automation/src/main/java/vid/automation/test/services/SimulatorApi.java @@ -56,17 +56,24 @@ public class SimulatorApi { public List<StringWrapper> values; } + public static class BodyWrapper { + public String value; + } + public static class HttpRequest { public StringWrapper path; + public BodyWrapper body; public List<RecordedHeaders> headers; } public static class RecordedRequests { public String path; + public String body; public Map<String, List<String>> headers; - public RecordedRequests(String path, Map<String, List<String>> headers) { + public RecordedRequests(String path, String body, Map<String, List<String>> headers) { this.path = path; + this.body = body; this.headers = headers; } @@ -82,7 +89,7 @@ public class SimulatorApi { ImmutableList.of(dropTestApiFieldFromString(), dropFieldCloudOwnerFromString()); static { - String host = System.getProperty("SIM_HOST", System.getProperty("VID_HOST", "127.0.0.1")); + String host = getSimulatorHost(); Integer port = Integer.valueOf(System.getProperty("SIM_PORT", System.getProperty("VID_PORT", "8080"))); //port for registration uri = new JerseyUriBuilder().host(host).port(port).scheme("http").path("vidSimulator").build(); client = ClientBuilder.newClient(); @@ -94,10 +101,18 @@ public class SimulatorApi { jacksonJsonProvider.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); client.register(jacksonJsonProvider); - Integer simulationPort = Integer.valueOf(System.getProperty("SIMULATION_PORT", "1080")); //port getting simulated responses + Integer simulationPort = getSimulatedResponsesPort(); simulationUri = new JerseyUriBuilder().host(host).port(simulationPort).scheme("http").build(); } + public static String getSimulatorHost() { + return System.getProperty("SIM_HOST", System.getProperty("VID_HOST", "127.0.0.1")); + } + + public static Integer getSimulatedResponsesPort() { + return Integer.valueOf(System.getProperty("SIMULATION_PORT", "1080")); + } + public static URI getSimulationUri() { return simulationUri; } @@ -180,6 +195,7 @@ public class SimulatorApi { List<HttpRequest> rawRequests = retrieveRecordedHttpRequests(); return rawRequests.stream().map(request->new RecordedRequests( request.path.value, + request.body != null && request.body != null ? request.body.value : "", request.headers.stream().collect( Collectors.toMap( x->x.name.value, diff --git a/vid-automation/src/main/java/vid/automation/test/test/BrowseASDCTest.java b/vid-automation/src/main/java/vid/automation/test/test/BrowseASDCTest.java index eb08c1f2a..f6b883ac1 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/BrowseASDCTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/BrowseASDCTest.java @@ -1,49 +1,68 @@ package vid.automation.test.test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static vid.automation.test.infra.Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI; +import static vid.automation.test.infra.Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI; +import static vid.automation.test.infra.Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND; +import static vid.automation.test.infra.Features.FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER; +import static vid.automation.test.infra.Features.FLAG_5G_IN_NEW_INSTANTIATION_UI; +import static vid.automation.test.infra.Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION; +import static vid.automation.test.infra.Features.FLAG_SHOW_ORCHESTRATION_TYPE; +import static vid.automation.test.infra.ModelInfo.aLaCarteForBrowseSdc; +import static vid.automation.test.infra.ModelInfo.aLaCarteServiceCreationTest; +import static vid.automation.test.infra.ModelInfo.instantiationTypeAlacarte_vidNotionsInstantiationUIByUUID; +import static vid.automation.test.infra.ModelInfo.macroForBrowseSdc; +import static vid.automation.test.sections.VidBasePage.goOutFromIframe; +import static vid.automation.test.sections.VidBasePage.goToIframe; + import com.google.common.collect.ImmutableList; +import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.hamcrest.Matchers; +import org.jetbrains.annotations.NotNull; +import org.onap.sdc.ci.tests.datatypes.UserCredentials; +import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetServicesGet; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIServiceDesignAndCreationPut; import org.onap.simulator.presetGenerator.presets.ecompportal_att.PresetGetSessionSlotCheckIntervalGet; -import org.onap.sdc.ci.tests.datatypes.UserCredentials; -import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.testng.Assert; +import org.testng.SkipException; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.Constants; -import vid.automation.test.infra.*; +import vid.automation.test.infra.Click; +import vid.automation.test.infra.Exists; +import vid.automation.test.infra.FeatureTogglingTest; +import vid.automation.test.infra.Get; +import vid.automation.test.infra.ModelInfo; +import vid.automation.test.infra.SelectOption; import vid.automation.test.model.Service; import vid.automation.test.model.User; -import vid.automation.test.sections.*; +import vid.automation.test.sections.BrowseASDCPage; +import vid.automation.test.sections.InstantiationStatusPage; +import vid.automation.test.sections.SideMenu; +import vid.automation.test.sections.ViewEditPage; +import vid.automation.test.sections.deploy.DeployDialogBase; +import vid.automation.test.sections.deploy.DeployModernUIALaCarteDialog; +import vid.automation.test.sections.deploy.DeployModernUIMacroDialog; +import vid.automation.test.sections.deploy.DeployOldALaCarteDialog; +import vid.automation.test.sections.deploy.DeployOldMacroDialog; import vid.automation.test.services.ServicesService; import vid.automation.test.services.SimulatorApi; -import java.util.List; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static vid.automation.test.infra.Features.FLAG_5G_IN_NEW_INSTANTIATION_UI; -import static vid.automation.test.infra.Features.FLAG_SHOW_ORCHESTRATION_TYPE; -import static vid.automation.test.infra.Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI; -import static vid.automation.test.infra.ModelInfo.*; - public class BrowseASDCTest extends CreateInstanceDialogBaseTest { private final String invariantUUIDAlacarte = aLaCarteForBrowseSdc.modelInvariantId; private final String invariantUUIDMacro = macroForBrowseSdc.modelInvariantId; - private final String instantiationTypeNameAlacarte = "a la carte"; - private final String instantiationTypeNameMacro = "macro"; - private final String oldMacro = "old macro"; - private final String newAlacarte = "new a la carte"; public static final String modelInvariantUUID1 = "aeababbc-010b-4a60-8df7-e64c07389466"; public static final String modelInvariantUUID2 = "aa2f8e9c-9e47-4b15-a95c-4a9385599abc"; public static final String modelInvariantUUID3 = "d849c57d-b6fe-4843-8349-4ab8bbb08d71"; @@ -69,7 +88,7 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { return new UserCredentials(user.credentials.userId, user.credentials.password, Constants.Users.EMANUEL_EMANUEL, "", ""); } - @Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) + //@Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) public void testPNFOnCreatePopup() { Service service = servicesService.getService("f39389e4-2a9c-4085-8ac3-04aea9c651be"); BrowseASDCPage browseASDCPage = new BrowseASDCPage(); @@ -85,12 +104,9 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { validateServiceCreationDialog(service); } -// @BeforeMethod -// public void clearSimulator() { -// SimulatorApi.clearAll(); -// } - @Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) + + //@Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) private void testPNFMacroInstantation() throws Exception { User user = usersService.getUser(Constants.Users.EMANUEL_EMANUEL); relogin(user.credentials); @@ -126,89 +142,97 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { } @Test - private void browseServiceModel_deployServiceALaCarteByBackendInput_creationPopupIsALaCarte() throws Exception { + private void browseServiceModel_deployServiceALaCarteByBackendInput_creationPopupIsALaCarte() { // model uuid should be of macro deployServiceAndAssertInstantiationType( "csar15782222_instantiationTypeAlacarte_invariantUUIDMacro.zip", invariantUUIDMacro, - instantiationTypeNameAlacarte + getAlacarteDialogByFlagValue() ); } + @NotNull + public static DeployDialogBase getAlacarteDialogByFlagValue() { + return FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI.isActive() ? + new DeployModernUIALaCarteDialog() : + new DeployOldALaCarteDialog(); + } + @Test @FeatureTogglingTest(FLAG_5G_IN_NEW_INSTANTIATION_UI) - private void browseServiceModel_deployServiceALaCarteByBackendInputHintNewUI_creationPopupIsAngular2() throws Exception { + private void browseServiceModel_deployServiceALaCarteByBackendInputHintNewUI_creationPopupIsAngular2() { deployServiceAndAssertInstantiationType( instantiationTypeAlacarte_vidNotionsInstantiationUIByUUID, - newAlacarte + new DeployModernUIALaCarteDialog() ); } @Test - private void browseServiceModel_deployServiceALaCarteBecauseNotOnMACRO_SERVICESConfig_creationPopupIsALaCarte() throws Exception { + private void browseServiceModel_deployServiceALaCarteBecauseNotOnMACRO_SERVICESConfig_creationPopupIsALaCarte() { deployServiceAndAssertInstantiationType( "csar15782222_instantiationTypeEmpty_invariantUUIDAlacarte.zip", invariantUUIDAlacarte, - instantiationTypeNameAlacarte + getAlacarteDialogByFlagValue() ); } @Test - private void browseServiceModel_deployServiceMacroByBackendInput_creationPopupIsMacro() throws Exception { + private void browseServiceModel_deployServiceMacroByBackendInput_creationPopupIsMacro() { deployServiceAndAssertInstantiationType( - "csar15782222_instantiationTypeMacro_invariantUUIDAlacarte_withoutNetworks.zip", - invariantUUIDAlacarte, - instantiationTypeNameMacro + ModelInfo.serviceWithInstantiationTypeMacro, + new DeployModernUIMacroDialog() ); } @Test - private void browseServiceModel_deployServiceMacroByMACRO_SERVICESConfig_creationPopupIsOldMacro() throws Exception { + private void browseServiceModel_deployServiceMacroByMACRO_SERVICESConfig_creationPopupIsOldMacro() { + if (FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI.isActive() && + ! FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND.isActive()) { + throw new SkipException("some 2002 flags shall come along together"); + } deployServiceAndAssertInstantiationType( "csar15782222_invariantUUIDMacro.zip", invariantUUIDMacro, - oldMacro - + new DeployOldMacroDialog() ); } @Test - private void browseServiceModel_deployServiceMacroWithPnf_creationPopupIsOldMacro() throws Exception { + private void browseServiceModel_deployServiceMacroWithPnf_creationPopupIsOldMacro() { deployServiceAndAssertInstantiationType( "csar15782222_instantiationTypeMacroWithPnf.zip", invariantUUIDMacro, - oldMacro - + new DeployOldMacroDialog() ); } @Test - @FeatureTogglingTest(flagActive = false, value = FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI) - public void browseServiceModel_deployServiceMacroWithCR_creationPopupIsOldMacro() throws Exception { + public void browseServiceModel_deployServiceMacroWithCR_creationPopupIsOldMacro() { deployServiceAndAssertInstantiationType( - "csar15782222_instantiationTypeMacroWithCR.zip", - invariantUUIDMacro, - oldMacro - + ModelInfo.collectionResourceService, + FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI.isActive() ? + new DeployModernUIMacroDialog() : + new DeployOldMacroDialog() ); } @Test - private void browseServiceModel_deployServiceMacroWithNetwork_creationPopupIsMacroByFF() throws Exception { - String macroInstantiationAccordingFF = Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION.isActive() ? instantiationTypeNameMacro : oldMacro; + private void browseServiceModel_deployServiceMacroWithNetwork_creationPopupIsMacroByFF() { deployServiceAndAssertInstantiationType( "csar15782222_instantiationTypeMacroWithNetwork.zip", invariantUUIDMacro, - macroInstantiationAccordingFF + FLAG_NETWORK_TO_ASYNC_INSTANTIATION.isActive() ? + new DeployModernUIMacroDialog() : + new DeployOldMacroDialog() ); } - private void deployServiceAndAssertInstantiationType(String modelZipFileName, String modelInvariantId, String expectedInstantiationType) throws Exception { - deployServiceAndAssertInstantiationType(new ModelInfo("4d71990b-d8ad-4510-ac61-496288d9078e", modelInvariantId, modelZipFileName), expectedInstantiationType); + private void deployServiceAndAssertInstantiationType(String modelZipFileName, String modelInvariantId, DeployDialogBase deployDialog) { + deployServiceAndAssertInstantiationType(new ModelInfo("4d71990b-d8ad-4510-ac61-496288d9078e", modelInvariantId, modelZipFileName), deployDialog); } - private void deployServiceAndAssertInstantiationType(ModelInfo modelInfo, String expectedInstantiationType) throws Exception { + private void deployServiceAndAssertInstantiationType(ModelInfo modelInfo, DeployDialogBase deployDialog) { registerExpectationForLegacyServiceDeployment(modelInfo, "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"); User user = usersService.getUser(Constants.Users.EMANUEL_EMANUEL); @@ -219,19 +243,13 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { GeneralUIUtils.ultimateWait(); browseASDCPage.clickDeployServiceButtonByServiceUUID(modelInfo.modelVersionId); - DeployMacroDialogBase macroDialog = null; - if (expectedInstantiationType.equals(instantiationTypeNameAlacarte)) { - GeneralUIUtils.ultimateWait(); - browseASDCPage.clickCancelButtonByTestID(); - } else { //macro - macroDialog = expectedInstantiationType.equals(oldMacro) ? new DeployMacroDialogOld() : getMacroDialog(); - macroDialog.assertTitle(); - macroDialog.closeDialog(); - } + + deployDialog.waitForDialogAssertAndClose(); } + @FeatureTogglingTest(value = FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI, flagActive = false) @Test - private void testServiceInstantiationAlaCarte() throws Exception { + private void testServiceInstantiationAlaCarte() { User user = usersService.getUser(Constants.Users.EMANUEL_EMANUEL); relogin(user.credentials); @@ -283,7 +301,10 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { @DataProvider public static Object[][] filterTexts() { - return new Object[][]{{serviceName},{modelInvariantId},{serviceUuid}}; + return new Object[][]{ + {serviceName}, + {modelInvariantId}, + {serviceUuid}}; } @Test(dataProvider = "filterTexts") @@ -300,15 +321,43 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { @Test private void testCategoryParamsDropdownsExistsInCreationDialog() throws Exception { - BrowseASDCPage browseASDCPage = registerSimulatorAndGoToBrowseSDC(); - Service service = servicesService.getService("2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd"); - browseASDCPage.clickDeployServiceButtonByServiceUUID(service.uuid); - DeployMacroDialogBase deployMacroDialog = getMacroDialog(); - deployMacroDialog.assertDialogExists(); + String serviceId = "2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd"; + + DeployModernUIMacroDialog deployMacroDialog = getDeployModernUIMacroDialog(serviceId); + deployMacroDialog.assertDialog(); deployMacroDialog.clickProjectSelect(); deployMacroDialog.clickOwningEntitySelect(); } + private DeployModernUIMacroDialog getDeployModernUIMacroDialog(String serviceId) { + BrowseASDCPage browseASDCPage = registerSimulatorAndGoToBrowseSDC(); + Service service = servicesService.getService(serviceId); + browseASDCPage.clickDeployServiceButtonByServiceUUID(service.uuid); + DeployModernUIMacroDialog deployMacroDialog = new DeployModernUIMacroDialog(); + deployMacroDialog.waitForDialogToLoad(); + return deployMacroDialog; + } + + @Test + @FeatureTogglingTest(FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER) + public void testClickPreviousInstantiationsInCreationDialog() { + try { + String serviceId = "2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd"; + DeployModernUIMacroDialog deployMacroDialog = getDeployModernUIMacroDialog(serviceId); + deployMacroDialog.clickPreviousInstantiationButton(); + + //exit form deploy dialog + goOutFromIframe(); + //go into Instantiation Status page + goToIframe(); + + InstantiationStatusPage.verifyInstantiationStatusFilterValue(serviceId); + } + finally { + goOutFromIframe(); + } + } + private BrowseASDCPage registerSimulatorAndGoToBrowseSDC() { SimulatorApi.registerExpectation(SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET, "ecompportal_getSessionSlotCheckInterval.json", @@ -324,7 +373,7 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { return new BrowseASDCPage(); } - @Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) + //@Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) private void testOwningEntityRequiredAndProjectOptional() throws Exception { User user = usersService.getUser(Constants.Users.SILVIA_ROBBINS_TYLER_SILVIA); relogin(user.credentials); @@ -358,7 +407,7 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { assertSuccessfulServiceInstanceCreation(); } - @Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) + //@Test(groups = {"shouldBeMigratedToWorkWithSimulator"}) protected void testLineOfBusinessOptionalAndPlatformRequired() throws Exception { User user = usersService.getUser(Constants.Users.SILVIA_ROBBINS_TYLER_SILVIA); @@ -404,8 +453,7 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest { browseASDCPage.clickConfirmButton(); GeneralUIUtils.findAndWaitByText("Missing data", 5); - - Click.onFirstSelectOptionById(Constants.OwningEntity.PLATFORM_SELECT_TEST_ID); + SelectOption.selectFirstTwoOptionsFromMultiselectById("multi-selectPlatform"); viewEditPage.clickConfirmButton(); assertSuccessfulVNFCreation(); diff --git a/vid-automation/src/main/java/vid/automation/test/test/CreateNewInstanceTest.java b/vid-automation/src/main/java/vid/automation/test/test/CreateNewInstanceTest.java index b57d18789..be96e6992 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/CreateNewInstanceTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/CreateNewInstanceTest.java @@ -1,11 +1,12 @@ package vid.automation.test.test; +import java.io.IOException; +import java.util.List; import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.WebElement; import org.testng.Assert; import org.testng.annotations.Test; import vid.automation.test.Constants; -import vid.automation.test.infra.Features; import vid.automation.test.infra.Get; import vid.automation.test.infra.SelectOption; import vid.automation.test.model.Service; @@ -16,24 +17,15 @@ import vid.automation.test.services.BulkRegistration; import vid.automation.test.services.ServicesService; import vid.automation.test.services.SimulatorApi; -import java.io.IOException; -import java.util.List; - public class CreateNewInstanceTest extends CreateInstanceDialogBaseTest { private ServicesService servicesService = new ServicesService(); public CreateNewInstanceTest() throws IOException { } - @Test + @Test(groups = { "underDevelopment" }) private void testCreateNewServiceInstance() throws Exception { - if (!Features.CREATE_INSTANCE_TEST.isActive()) { - - // time bomb, as it fails on pipeline and I don't know how to fix it - return; - } - SimulatorApi.clearAll(); BulkRegistration.createNewServiceInstance("SILVIA ROBBINS"); diff --git a/vid-automation/src/main/java/vid/automation/test/test/EnvironmentsTest.java b/vid-automation/src/main/java/vid/automation/test/test/EnvironmentsTest.java index 03378b615..962a1de53 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/EnvironmentsTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/EnvironmentsTest.java @@ -1,6 +1,13 @@ package vid.automation.test.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static vid.automation.test.Constants.TestEnvironments.REFRESH_BUTTON; + import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; import org.junit.Assert; import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.WebElement; @@ -9,7 +16,13 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.Constants; -import vid.automation.test.infra.*; +import vid.automation.test.infra.Click; +import vid.automation.test.infra.Exists; +import vid.automation.test.infra.Features; +import vid.automation.test.infra.Get; +import vid.automation.test.infra.Input; +import vid.automation.test.infra.SelectOption; +import vid.automation.test.infra.Wait; import vid.automation.test.model.Environment; import vid.automation.test.sections.SideMenu; import vid.automation.test.sections.TestEnvironmentPage; @@ -17,12 +30,6 @@ import vid.automation.test.sections.VidBasePage; import vid.automation.test.services.SimulatorApi; import vid.automation.test.utils.ReadFile; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.*; -import static vid.automation.test.Constants.TestEnvironments.REFRESH_BUTTON; - /* @@ -349,7 +356,7 @@ public class EnvironmentsTest extends VidBaseTestCase { } @Test - public void testApplicationEnvironmentActivationBadManifestStructure() throws Exception { + public void testApplicationEnvironmentActivationBadManifestStructure() { testApplicationEnvironmentActivationBadManifestStructure("bad_manifest_structure.json", "Manifest structure is wrong"); testApplicationEnvironmentActivationBadManifestStructure("manifest_with_wrong_recovery_action.json", "Wrong value for RecoveryAction in manifest. Allowed options are: abort, retry, skip. Wrong value is: leave"); diff --git a/vid-automation/src/main/java/vid/automation/test/test/HealthStatusTest.java b/vid-automation/src/main/java/vid/automation/test/test/HealthStatusTest.java index 2bb97aa2e..b8f90c22d 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/HealthStatusTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/HealthStatusTest.java @@ -1,30 +1,27 @@ package vid.automation.test.test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET; + import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; import org.onap.simulator.presetGenerator.presets.ecompportal_att.PresetGetSessionSlotCheckIntervalGet; -import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.remote.RemoteWebElement; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.infra.Click; import vid.automation.test.infra.Get; -import vid.automation.test.infra.Wait; import vid.automation.test.sections.VidBasePage; import vid.automation.test.services.SimulatorApi; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.testng.Assert.assertTrue; -import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET; - public class HealthStatusTest extends VidBaseTestCase { private VidBasePage vidBasePage = new VidBasePage(); @@ -45,7 +42,7 @@ public class HealthStatusTest extends VidBaseTestCase { public void testAaiHealthStatus(Collection<BasePreset> presets, String cssName, String description, int httpCode) throws IOException { SimulatorApi.registerExpectationFromPresets(presets, CLEAR_THEN_SET); refreshStatus(); - assertTrue(Wait.waitByClassAndTextXpathOnly(cssName, "AAI", 10)); //instead of ultimate wait + GeneralUIUtils.ultimateWait(); //instead of assertTrue(Wait.waitByClassAndTextXpathOnly(cssName, "AAI", 10)) RemoteWebElement componentName = (RemoteWebElement)Get.byTestId("component-name-AAI"); assertThat("Wrong component name", componentName.getText(), equalTo("AAI")); assertThat("Wrong css for component name", componentName.getAttribute("class"), containsString(cssName)); diff --git a/vid-automation/src/main/java/vid/automation/test/test/NewServiceInstanceTest.java b/vid-automation/src/main/java/vid/automation/test/test/NewServiceInstanceTest.java index a701f1029..5a9dc2c01 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/NewServiceInstanceTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/NewServiceInstanceTest.java @@ -1,12 +1,12 @@ package vid.automation.test.test; -//import com.automation.common.report_portal_integration.annotations.Step; - +import static java.util.Collections.emptyList; import static junit.framework.TestCase.assertNull; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN6_TO_ATT_AIC; import static org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId.PRESET_SOME_LEGACY_REGION_TO_ATT_AIC; import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet.COMPLETE; import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet.DEFAULT_SERVICE_INSTANCE_ID; @@ -17,6 +17,7 @@ import static vid.automation.test.infra.Features.FLAG_1908_COLLECTION_RESOURCE_N import static vid.automation.test.infra.Features.FLAG_1908_INFRASTRUCTURE_VPN; import static vid.automation.test.infra.Features.FLAG_1908_MACRO_NOT_TRANSPORT_NEW_VIEW_EDIT; import static vid.automation.test.infra.Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI; +import static vid.automation.test.infra.Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI; import static vid.automation.test.infra.Features.FLAG_5G_IN_NEW_INSTANTIATION_UI; import static vid.automation.test.infra.Features.FLAG_ENABLE_WEBPACK_MODERN_UI; import static vid.automation.test.infra.ModelInfo.aLaCarteNetworkProvider5G; @@ -53,18 +54,20 @@ import org.apache.commons.lang3.mutable.MutableInt; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.hamcrest.Matchers; +import org.jetbrains.annotations.NotNull; import org.onap.sdc.ci.tests.datatypes.UserCredentials; import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; -import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetL3NetworksByCloudRegionSpecificState; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetTenants; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetVpnsByType; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIPostNamedQueryForViewEdit; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOBaseCreateInstancePost; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateNetworkALaCarte5G; -import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstanceAlacarte5GServiceWithNetwork; +import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstanceAlacarte; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstanceGen2WithNamesAlacarteGroupingService; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstanceGen2WithNamesEcompNamingFalse; +import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateVfModuleALaCarteE2E; +import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateVnfALaCarteE2E; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestsGet5GServiceInstanceAndNetwork; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestsGet5GServiceInstanceAndNetwork.ResponseDetails; @@ -86,6 +89,7 @@ import vid.automation.test.infra.Features; import vid.automation.test.infra.Get; import vid.automation.test.infra.Input; import vid.automation.test.infra.ModelInfo; +import vid.automation.test.infra.ModelInfoWithCustomization; import vid.automation.test.infra.SelectOption; import vid.automation.test.infra.Wait; import vid.automation.test.model.Service; @@ -229,12 +233,13 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.FALSE, true, true, true, "2017-488_PASQUALE-vPE 0", - "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, 1, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5"); + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", + 0, 1, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5", false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetails, false); final String serviceInstanceName = createMacroService(serviceData, true); - createVnf(serviceData, true, true, serviceInstanceName); + createVnf(serviceData, true, serviceInstanceName); createVfModule(serviceData, serviceInstanceName, false, false); @@ -277,7 +282,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { IS_GENERATED_NAMING.FALSE, false, true, false, "2017-488_PASQUALE-vPE 0", "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, 1, ImmutableList.of("Bandwidth", "Bandwidth units"), - "25284168-24bb-4698-8cb4-3f509146eca5"); + "25284168-24bb-4698-8cb4-3f509146eca5", false); // this is the instance-name that createMacroService is going to use String serviceInstanceName = randomAlphabetic + "instancename"; @@ -289,7 +294,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { }); doReduxStep(reduxStates, randomAlphabetic, startInStep, reduxForStep, i, mode, () -> - createVnf(serviceData, false, true, serviceInstanceName) + createVnf(serviceData, false, serviceInstanceName) ); final String vnfInstanceName2 = randomAlphabetic + "instanceName"; @@ -297,7 +302,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { doReduxStep(reduxStates, randomAlphabetic, startInStep, reduxForStep, i, mode, () -> createVnf(new VnfData(vnfName2 + " 0", "afacccf6-397d-45d6-b5ae-94c39734b168", vnfInstanceName2, false), - false, Features.FLAG_DEFAULT_VNF.isActive(), serviceInstanceName) + false, serviceInstanceName) ); doReduxStep(reduxStates, randomAlphabetic, startInStep, reduxForStep, i, mode, () -> @@ -329,7 +334,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { .build(); registerExpectationFromPresets(ImmutableList.of( // although "some legacy region" is provided for vnf, Service's region "hvf6" overrides it - PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN6_TO_ATT_AIC, + PRESET_MTN6_TO_ATT_AIC, new PresetMSOCreateServiceInstanceGen2WithNamesEcompNamingFalse(vars, 0, request1), new PresetMSOCreateServiceInstanceGen2WithNamesEcompNamingFalse(vars, 1, request2) ), SimulatorApi.RegistrationStrategy.APPEND); @@ -345,13 +350,13 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { @Test @FeatureTogglingTest(FLAG_1908_INFRASTRUCTURE_VPN) public void createNewServiceInstance_infraStructureVpn() { - String requestId = UUID.randomUUID().toString(); - String instanceId = UUID.randomUUID().toString(); + String requestId = uuid(); + String instanceId = uuid(); prepareServicePreset(infrastructureVpnService, false); SimulatorApi.registerExpectationFromPresets(ImmutableList.of( - PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN6_TO_ATT_AIC, + PRESET_MTN6_TO_ATT_AIC, new PresetAAIGetL3NetworksByCloudRegionSpecificState("irma-aic", "hvf6", "bae71557c5bb4d5aac6743a4e5f1d054"), new PresetAAIGetVpnsByType() ), APPEND); @@ -361,7 +366,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.TRUE_BUT_GIVE_NAME_EITHER_WAY, true, true, false, null, - null, 0, 1, new ArrayList<>(), null); + null, 0, 1, new ArrayList<>(), null, false); final String serviceInstanceName = createMacroService(serviceData, false); SimulatorApi.registerExpectationFromPresets(ImmutableList.of( @@ -388,11 +393,11 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { @FeatureTogglingTest(FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI) public void createNewServiceInstance_collectionResource() { prepareServicePreset(collectionResourceService, false); - String requestId = UUID.randomUUID().toString(); - String instanceId = UUID.randomUUID().toString(); + String requestId = uuid(); + String instanceId = uuid(); SimulatorApi.registerExpectationFromPresets(ImmutableList.of( - PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN6_TO_ATT_AIC, + PRESET_MTN6_TO_ATT_AIC, PresetMsoCreateMacroCommonPre1806.ofCollectionResource(requestId, instanceId), new PresetMSOOrchestrationRequestGet(COMPLETE, requestId) ), APPEND); @@ -402,7 +407,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.TRUE, true, true, false, null, - null, 0, 1, new ArrayList<>(), null); + null, 0, 1, new ArrayList<>(), null, false); createMacroService(serviceData, false, randomAlphabetic(5), true, 1); drawingBoardPage.deploy(); @@ -413,8 +418,8 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { @FeatureTogglingTest(FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI) public void createNewServiceInstance_transportService() { prepareServicePreset(transportWithPnfsService, false); - String requestId = UUID.randomUUID().toString(); - String instanceId = UUID.randomUUID().toString(); + String requestId = uuid(); + String instanceId = uuid(); SimulatorApi.registerExpectationFromPresets(ImmutableList.of( PresetMsoCreateMacroCommonPre1806.ofTransportService(requestId, instanceId), @@ -426,7 +431,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.TRUE, true, true, false, null, - null, 0, 1, new ArrayList<>(), null); + null, 0, 1, new ArrayList<>(), null, false); createMacroService(serviceData, false, randomAlphabetic(5), false, 1); drawingBoardPage.deploy(); @@ -443,7 +448,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { aLaCarteVnfGroupingService.modelVersionId, ImmutableList.of(), IS_GENERATED_NAMING.FALSE, false, true, false, - null, null, 0, 1, ImmutableList.of(), null); + null, null, 0, 1, ImmutableList.of(), null, false); prepareServicePreset(aLaCarteVnfGroupingService, false); createALaCarteService(serviceData, randomAlphabetic); @@ -529,11 +534,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { //@Step("edit vf module and just set name") private void editVfModuleAndJustSetName(String vfModuleName, String vfModuleUUID) { - if (Features.FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD.isActive()) { - hoverAndClickEditButton(vfModuleUUID + "-" + vfModuleName); - } else { - drawingBoardPage.clickAddButtonByNodeName(vfModuleName); - } + hoverAndClickEditButton(vfModuleUUID + "-" + vfModuleName); Input.text("VF instance name ZERO", "instanceName"); Click.byTestId(VNF_SET_BUTTON_TEST_ID); } @@ -545,12 +546,12 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.FALSE, true, false, true, "2017-488_PASQUALE-vPE 0", - vfModule0Name, 1, 1, new ArrayList<>(), vfModule0UUID); + vfModule0Name, 1, 1, new ArrayList<>(), vfModule0UUID, false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetails, false); final String serviceInstanceName = createMacroService(serviceData, true); - createVnf(serviceData, true, true, serviceInstanceName); + createVnf(serviceData, true, serviceInstanceName); createVfModule(serviceData, serviceInstanceName, true, false); } @@ -562,12 +563,12 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.FALSE, false, false, false, "2017-488_PASQUALE-vPE 0", - vfModule0Name, 1, 1, new ArrayList<>(), vfModule0UUID); + vfModule0Name, 1, 1, new ArrayList<>(), vfModule0UUID, false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetailsVnfEcompNamingFalse, false); final String serviceInstanceName = createMacroService(serviceData, true); - createVnf(serviceData, true, true, serviceInstanceName); + createVnf(serviceData, true, serviceInstanceName); createVfModule(serviceData, serviceInstanceName, true, false); } @@ -579,35 +580,149 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.FALSE, false, true, false, "2017-488_PASQUALE-vPE 0", - "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, 1, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5"); + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, 1, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5", false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetailsVnfEcompNamingFalse, false); final String serviceInstanceName = createMacroService(serviceData, true); - createVnf(serviceData, true, true, serviceInstanceName); + createVnf(serviceData, true, serviceInstanceName); clickRemoveVfModule(vfModule0UUID, vfModule0Name); createVfModule(serviceData, serviceInstanceName, false, true); } + @Test + @FeatureTogglingTest(FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI) + public void createNewServiceInstance_aLaCarte_WithVnf() { + final ModelInfo serviceModelInfo = ModelInfo.aLaCarteServiceCreationNewUI; + String serviceInstanceName = "ALaCarteWithVnf"+randomAlphabetic(5); + String vnfInstanceName= "VnfForALaCarte"+randomAlphabetic(5); + VnfData vnfData = new VnfData("vOCG_1804_VF 0", "aca3f7b1-15f9-45a5-b182-b8b5aca84a76", vnfInstanceName, true); + VfData vfmData = new VfData("vocg_1804_vf0..Vocg1804Vf..base_ocg..module-0", false, 1, 1, emptyList(), "815db6e5-bdfd-4cb6-9575-82c36df8747a", null); + ServiceData serviceData = new ServiceData(IS_GENERATED_NAMING.TRUE, vnfData, vfmData, true); + + resetGetServicesCache(); + + prepareServicePreset(serviceModelInfo, true); + + String requestorID = getUserCredentials().getUserId(); + + String serviceRequestId = uuid(); + String serviceInstanceId = uuid(); + String vnfRequestId = uuid(); + String vnfInstanceId = uuid(); + String vfm0RequestId = uuid(); + String vfm0InstanceId = uuid(); + String vg1RequestId = uuid(); + String vg1InstanceId = uuid(); + String vfm1RequestId = uuid(); + String vfm1InstanceId = uuid(); + String vfm12RequestId = uuid(); + String vfm12InstanceId = uuid(); + + ModelInfoWithCustomization vfm0 = new ModelInfoWithCustomization( + "815db6e5-bdfd-4cb6-9575-82c36df8747a", + "e9c795c8-6b98-4db3-bd90-a84b8ca5181b", + "Vocg1804Vf..base_ocg..module-0", + "4", + "vfModule", + "Vocg1804Vf..base_ocg..module-0", + "a7b333d7-7633-4197-b40d-80fcfcadee94"); + + ModelInfoWithCustomization vg1 = new ModelInfoWithCustomization( + "9c219e70-1177-494b-8977-1395c9f9168c", + "0ad14d60-98b6-4575-a9b8-458a796c3f98", + "Vocg1804Vf..ocgmgr..module-1", + "4", + "volumeGroup", + "Vocg1804Vf..ocgmgr..module-1", + "f332f3ce-434d-4084-a1e7-5261c16d4940" + ); + + ModelInfoWithCustomization vfm1 = new ModelInfoWithCustomization( + "9c219e70-1177-494b-8977-1395c9f9168c", + "0ad14d60-98b6-4575-a9b8-458a796c3f98", + "Vocg1804Vf..ocgmgr..module-1", + "4", + "vfModule", + "Vocg1804Vf..ocgmgr..module-1", + "f332f3ce-434d-4084-a1e7-5261c16d4940" + ); + + ModelInfoWithCustomization vfm12 = new ModelInfoWithCustomization( + "b601eef4-62fd-4201-a788-ae30e06a1aec", + "e3cb8b85-7a3c-4897-b20b-70640c26d671", + "Vocg1804Vf..ocgapp_001..module-12", + "2", + "vfModule", + "Vocg1804Vf..ocgapp_001..module-12", + "fcc82961-865e-4d38-9c7a-207c511405b6" + ); + + final String vgName = "vg_for_module1"; + + String vgRelatedInstance = ",{\"relatedInstance\": {" + + " \"modelInfo\": {" + + " \"modelType\": \"volumeGroup\"" + + " }," + + " \"instanceId\": \""+vg1InstanceId+"\"," + + " \"instanceName\": \""+vgName+"\"" + + " }}"; + + + registerExpectationFromPresets( + ImmutableList.of( + new PresetMSOCreateServiceInstanceAlacarte( + ImmutableMap.of(Keys.SERVICE_NAME, serviceInstanceName), + serviceRequestId, serviceInstanceId, + requestorID, serviceModelInfo), + PRESET_SOME_LEGACY_REGION_TO_ATT_AIC, + new PresetMSOOrchestrationRequestGet(COMPLETE, serviceRequestId), + new PresetMSOCreateVnfALaCarteE2E(vnfRequestId, serviceInstanceId, vnfInstanceId, "ONAP", requestorID, serviceModelInfo), + new PresetMSOOrchestrationRequestGet(COMPLETE, vnfRequestId), + PRESET_MTN6_TO_ATT_AIC, + new PresetMSOCreateVfModuleALaCarteE2E(vfm0RequestId, vfm0InstanceId, serviceInstanceId, vnfInstanceId, requestorID, serviceModelInfo, null, vfm0, null), + new PresetMSOOrchestrationRequestGet(COMPLETE, vfm0RequestId), + new PresetMSOCreateVfModuleALaCarteE2E(vg1RequestId, vg1InstanceId, serviceInstanceId, vnfInstanceId, requestorID, serviceModelInfo, vgName, vg1, null), + new PresetMSOOrchestrationRequestGet(COMPLETE, vg1RequestId), + new PresetMSOCreateVfModuleALaCarteE2E(vfm1RequestId, vfm1InstanceId, serviceInstanceId, vnfInstanceId, requestorID, serviceModelInfo, null, vfm1, vgRelatedInstance), + new PresetMSOOrchestrationRequestGet(COMPLETE, vfm1RequestId), + new PresetMSOCreateVfModuleALaCarteE2E(vfm12RequestId, vfm12InstanceId, serviceInstanceId, vnfInstanceId, requestorID, serviceModelInfo, null, vfm12, null), + new PresetMSOOrchestrationRequestGet(COMPLETE, vfm12RequestId) + ), + APPEND + ); + + loadServicePopup(serviceModelInfo.modelVersionId); + fillALaCarteServicePopup(serviceInstanceName); + + createVnf(vnfData, false, serviceInstanceName); + createVfModule(serviceData, serviceInstanceName, true, false); + serviceData.vfData = new VfData("vocg_1804_vf0..Vocg1804Vf..ocgmgr..module-1", true, 0, 1, emptyList(), "9c219e70-1177-494b-8977-1395c9f9168c", vgName); + createVfModule(serviceData, serviceInstanceName, false, false); + serviceData.vfData = new VfData("vocg_1804_vf0..Vocg1804Vf..ocgapp_001..module-12", true, 0, 1, emptyList(), "b601eef4-62fd-4201-a788-ae30e06a1aec", null); + createVfModule(serviceData, serviceInstanceName, false, false); + drawingBoardPage.deploy(); + drawingBoardPage.verifyServiceCompletedOnTime(serviceInstanceName, "service "+serviceInstanceName); + } @Test @FeatureTogglingTest(FLAG_5G_IN_NEW_INSTANTIATION_UI) - public void createNewServiceInstance_aLaCarte_validPopupDataAndUI() { + public void createNewServiceInstance_aLaCarte_withNetwork_validPopupDataAndUI() { String serviceInstanceName = "NcService"+randomAlphabetic(5); String networkInstanceName= "NcNetowrk"+randomAlphabetic(5); String defactoNetworkInstanceName = "ExtVL"+networkInstanceName; - BrowseASDCPage browseASDCPage = new BrowseASDCPage(); + prepareServicePreset(aLaCarteNetworkProvider5G, true); - String serviceRequestId = UUID.randomUUID().toString(); - String networkRequestId = UUID.randomUUID().toString(); + String serviceRequestId = uuid(); + String networkRequestId = uuid(); String requestorID = getUserCredentials().getUserId(); registerExpectationFromPresets( ImmutableList.of( - new PresetMSOCreateServiceInstanceAlacarte5GServiceWithNetwork( + new PresetMSOCreateServiceInstanceAlacarte( ImmutableMap.of(Keys.SERVICE_NAME, serviceInstanceName), - serviceRequestId, - requestorID), + serviceRequestId, DEFAULT_SERVICE_INSTANCE_ID, + requestorID, aLaCarteNetworkProvider5G), new PresetMSOOrchestrationRequestGet(COMPLETE, serviceRequestId), PRESET_SOME_LEGACY_REGION_TO_ATT_AIC, new PresetMSOCreateNetworkALaCarte5G(networkRequestId, DEFAULT_SERVICE_INSTANCE_ID, defactoNetworkInstanceName, requestorID), @@ -620,6 +735,16 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { APPEND ); loadServicePopup(aLaCarteNetworkProvider5G.modelVersionId); + fillALaCarteServicePopup(serviceInstanceName); + VnfData networkData = new VnfData("SR-IOV Provider-1", "840ffc47-e4cf-46de-8e23-525fd8c6fdc3", defactoNetworkInstanceName, false); + createNetwork(networkData, false, false, serviceInstanceName); + + drawingBoardPage.deploy(); + drawingBoardPage.verifyServiceCompletedOnTime(serviceInstanceName, "service "+serviceInstanceName); + } + + private void fillALaCarteServicePopup(String serviceInstanceName) { + BrowseASDCPage browseASDCPage = new BrowseASDCPage(); WebElement instanceNameInput = Get.byId("instanceName"); instanceNameInput.sendKeys(serviceInstanceName); VidBasePage.selectSubscriberById("e433710f-9217-458d-a79d-1c7aff376d89"); @@ -631,11 +756,6 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { Click.byTestId("form-set"); VidBasePage.goOutFromIframe(); browseASDCPage.goToIframe(); - VnfData networkData = new VnfData("SR-IOV Provider-1", "840ffc47-e4cf-46de-8e23-525fd8c6fdc3", defactoNetworkInstanceName, false); - createNetwork(networkData, false, false, serviceInstanceName); - - drawingBoardPage.deploy(); - drawingBoardPage.verifyServiceCompletedOnTime(serviceInstanceName, "service "+serviceInstanceName); } @Test @@ -647,12 +767,12 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { serviceDynamicFields, IS_GENERATED_NAMING.TRUE, true, true, false, "2017-488_PASQUALE-vPE 0", - "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, 1, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5"); + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, 1, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5", false); prepareServicePreset(macroSriovWithDynamicFieldsEcompNamingTruePartialModelDetails, false); final String serviceInstanceName = createMacroService(serviceData, true); - createVnf(serviceData, true, true, serviceInstanceName); + createVnf(serviceData, true, serviceInstanceName); clickRemoveVfModule(vfModule0UUID, vfModule0Name); createVfModule(serviceData, serviceInstanceName, false, false); @@ -1019,23 +1139,23 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { } //@Step("create vnf") - private void createVnf(ServiceData serviceData, boolean tryCancelsAndReentries, boolean addedByDefault, String serviceInstanceName) { - createVnf(serviceData.vnfData, tryCancelsAndReentries, addedByDefault, serviceInstanceName); + private void createVnf(ServiceData serviceData, boolean tryCancelsAndReentries, String serviceInstanceName) { + createVnf(serviceData.vnfData, tryCancelsAndReentries, serviceInstanceName); } private void createNetwork(VnfData vnfData, boolean tryCancelsAndReentries, boolean addedByDefault, String serviceInstanceName) { createVnf(vnfData, tryCancelsAndReentries, addedByDefault, serviceInstanceName, true); } - private void createVnf(VnfData vnfData, boolean tryCancelsAndReentries, boolean addedByDefault, String serviceInstanceName) { - createVnf(vnfData, tryCancelsAndReentries, addedByDefault, serviceInstanceName, false); + private void createVnf(VnfData vnfData, boolean tryCancelsAndReentries, String serviceInstanceName) { + createVnf(vnfData, tryCancelsAndReentries, true, serviceInstanceName, false); } private void createVnf(VnfData vnfData, boolean tryCancelsAndReentries, boolean addedByDefault, String serviceInstanceName, boolean isNetwork) { BrowseASDCPage browseASDCPage = new BrowseASDCPage(); String nodeToEdit = extractNodeToEdit(vnfData); - if (addedByDefault && Features.FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD.isActive()) { + if (addedByDefault) { hoverAndClickEditButton(nodeToEdit); } else { drawingBoardPage.clickAddButtonByNodeName(vnfData.vnfName); @@ -1065,7 +1185,11 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { assertSetButtonDisabled(VNF_SET_BUTTON_TEST_ID); - browseASDCPage.selectPlatform("platform"); + if(isNetwork){ + browseASDCPage.selectPlatform("platform"); + }else { + SelectOption.selectOptionsFromMultiselectById("multi-selectPlatform", ImmutableList.of("platform")); + } browseASDCPage.selectLineOfBusiness("ONAP"); assertSetButtonEnabled(VNF_SET_BUTTON_TEST_ID); @@ -1094,7 +1218,9 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { assertThat(Get.selectedOptionText(Constants.ViewEdit.LCP_REGION_SELECT_TESTS_ID), startsWith("AAIAIC25")); Assert.assertEquals(Get.selectedOptionText(Constants.ViewEdit.TENANT_SELECT_TESTS_ID), "USP-SIP-IC-24335-T-01"); Assert.assertEquals(Get.selectedOptionText(Constants.ViewEdit.LINE_OF_BUSINESS_SELECT_TESTS_ID), "ONAP"); - Assert.assertEquals(Get.selectedOptionText(Constants.OwningEntity.PLATFORM_SELECT_TEST_ID), "platform"); + + Assert.assertTrue(Get.isOptionSelectedInMultiSelect(Constants.OwningEntity.PLATFORM_MULTI_SELECT_TEST_ID, "platform")); + Click.byTestId(Constants.CANCEL_BUTTON_TEST_ID); GeneralUIUtils.ultimateWait(); } else { @@ -1170,20 +1296,36 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { Input.text("VF instance name", "instanceName"); } - if (serviceData.vfData.vgEnabled) { - browseASDCPage.setInputText("volumeGroupName", "_abc"); - Assert.assertEquals(isElementByIdRequired("volumeGroupName-label"), false, "volume Group name input should be always optional"); - } else { - Assert.assertNull(Get.byTestId("volumeGroupName"), "volumeGroupName input should be invisible when vgEnabled == false"); + if (!serviceData.vfData.vgEnabled || (!serviceData.isALaCarte && serviceData.vnfData.isGeneratedNaming)) { + Assert.assertNull(Get.byTestId("volumeGroupName"), "volumeGroupName input should be invisible " + + "when vgEnabled is false or when vgEnabled is true and EcompGenName is true " + + "(was: serviceData.vfData.vgEnabled=>" + serviceData.vfData.vgEnabled + ", serviceData.isGeneratedNaming=>" + IS_GENERATED_NAMING.FALSE + ")"); + } + else { + Assert.assertFalse(isElementByIdRequired("volumeGroupName-label"), + "volume Group name input should be always optional"); + if (serviceData.vfData.vgName!=null) { + browseASDCPage.setInputText("volumeGroupName", serviceData.vfData.vgName); + } } + + Wait.waitByTestId("model-item-value-subscriberName", 10); Assert.assertEquals(Get.byTestId("model-item-value-subscriberName").getText(), "SILVIA ROBBINS", "Subscriber name should be shown in vf module"); Assert.assertEquals(Get.byTestId("model-item-value-min").getText(), Integer.toString(serviceData.vfData.vfMin), "Min should be shown"); Assert.assertEquals(Get.byTestId("model-item-value-max").getText(), Integer.toString(serviceData.vfData.vfMax), "Max should be shown"); - if (!serviceData.vnfData.isGeneratedNaming) { + if (serviceData.isGeneratedNaming!=IS_GENERATED_NAMING.TRUE) { Wait.byText(serviceInstanceName); Assert.assertEquals(Get.byTestId("model-item-value-serviceName").getText(), serviceInstanceName, "Service name should be shown in vf module"); } + + if (serviceData.isALaCarte) { + String lcpRegion = "hvf6"; + Wait.waitByClassAndText("lcpRegionOption", lcpRegion, 30); + viewEditPage.selectLcpRegion(lcpRegion, AIC); + browseASDCPage.selectTenant("bae71557c5bb4d5aac6743a4e5f1d054"); + } + validateDynamicFields(serviceData.vfData.dynamicFields); uploadSupplementaryFile("invalid-file.json", false, browseASDCPage, setButtonTestId); @@ -1195,13 +1337,11 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { } private void clickEditVfModule(ServiceData serviceData) { - if (Features.FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD.isActive()) { - hoverAndClickEditButton(serviceData.vfData.uuid + "-" + serviceData.vfData.vfName); - } + hoverAndClickEditButton(serviceData.vfData.uuid + "-" + serviceData.vfData.vfName); } private void clickAddVfModule(ServiceData serviceData, boolean addedByDefault) { - if (Features.FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD.isActive() && addedByDefault) { + if (addedByDefault) { return; } System.out.println("VFModule should be added 'manually'"); @@ -1216,10 +1356,8 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { } private void clickRemoveVfModule(String vfModuleId, String vfModuleName) { - if (Features.FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD.isActive()) { - System.out.println("will remove " + vfModule0Name); - hoverAndClickDeleteButton(vfModuleId + "-" + vfModuleName); - } + System.out.println("will remove " + vfModule0Name); + hoverAndClickDeleteButton(vfModuleId + "-" + vfModuleName); } private void assertPauseOnPausePointsVisibility(boolean visibility) { @@ -1232,6 +1370,12 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { } } + @NotNull + private String uuid() { + return UUID.randomUUID().toString(); + } + + private void assertNotificationAreaVisibilityBehaviourAndSetBulkSize(int size) { WebElement webElement = Get.byId("notification-area"); Assert.assertNull(webElement, "notification area should be invisible if only 1 qty."); @@ -1259,21 +1403,33 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { } static class ServiceData { - ServiceData(String modelUuid, List<String> dynamicFields, IS_GENERATED_NAMING isServiceGeneratedNaming, boolean isVnfGeneratedNaming, boolean isVgEnabled, boolean multiStageDesign, String vnfName, String vfName, int vfMin, int vfMax, List<String> vfModuleDynamicFields, String vfVersionId) { + + ServiceData(String modelUuid, List<String> dynamicFields, IS_GENERATED_NAMING isServiceGeneratedNaming, + boolean isVnfGeneratedNaming, boolean isVgEnabled, boolean multiStageDesign, String vnfName, + String vfName, int vfMin, int vfMax, List<String> vfModuleDynamicFields, String vfVersionId, boolean isALaCarte) { this.modelUuid = modelUuid; this.dynamicFields = dynamicFields; this.isGeneratedNaming = isServiceGeneratedNaming; this.multiStageDesign = multiStageDesign; + this.isALaCarte = isALaCarte; this.vnfData = new VnfData(vnfName, "69e09f68-8b63-4cc9-b9ff-860960b5db09", "VNF instance name", isVnfGeneratedNaming); - this.vfData = new VfData(vfName, isVgEnabled, vfMin, vfMax, vfModuleDynamicFields, vfVersionId); + this.vfData = new VfData(vfName, isVgEnabled, vfMin, vfMax, vfModuleDynamicFields, vfVersionId, "_abc"); } - final String modelUuid; - final List<String> dynamicFields; - final IS_GENERATED_NAMING isGeneratedNaming; - final boolean multiStageDesign; - final VnfData vnfData; - final VfData vfData; + public ServiceData(IS_GENERATED_NAMING isGeneratedNaming, VnfData vnfData, VfData vfData, boolean isALaCarte) { + this.isGeneratedNaming = isGeneratedNaming; + this.vnfData = vnfData; + this.vfData = vfData; + this.isALaCarte = isALaCarte; + } + + String modelUuid; + List<String> dynamicFields; + IS_GENERATED_NAMING isGeneratedNaming; + boolean multiStageDesign; + VnfData vnfData; + VfData vfData; + boolean isALaCarte; enum IS_GENERATED_NAMING { TRUE, FALSE, TRUE_BUT_GIVE_NAME_EITHER_WAY} } @@ -1294,13 +1450,14 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { private static class VfData { - VfData(String vfName, boolean vgEnabled, int vfMin, int vfMax, List<String> dynamicFields, String uuid) { + VfData(String vfName, boolean vgEnabled, int vfMin, int vfMax, List<String> dynamicFields, String uuid, String vgName) { this.vfName = vfName; this.vgEnabled = vgEnabled; this.vfMin = vfMin; this.vfMax = vfMax; this.dynamicFields = dynamicFields; this.uuid = uuid; + this.vgName = vgName; } final int vfMin; @@ -1309,6 +1466,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { final String vfName; final boolean vgEnabled; final List<String> dynamicFields; + final String vgName; } diff --git a/vid-automation/src/main/java/vid/automation/test/test/PreviousVersionsPopupTest.java b/vid-automation/src/main/java/vid/automation/test/test/PreviousVersionsPopupTest.java index c52dd6bac..beef5d966 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/PreviousVersionsPopupTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/PreviousVersionsPopupTest.java @@ -1,29 +1,36 @@ package vid.automation.test.test; +import static org.testng.Assert.assertEquals; +import static vid.automation.test.infra.ModelInfo.ModelInfoWithMultipleVersions.modelInfoWithMultipleVersions; +import static vid.automation.test.infra.ModelInfo.serviceWithOneVersion; + import com.google.common.collect.ImmutableList; import org.junit.Assert; +import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset; -import org.onap.simulator.presetGenerator.presets.aai.*; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetNetworkZones; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetServicesGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubDetailsGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubDetailsWithoutInstancesGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIServiceDesignAndCreationPut; import org.onap.simulator.presetGenerator.presets.ecompportal_att.PresetGetSessionSlotCheckIntervalGet; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstancePost; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet; import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceMetadataGet; import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceToscaModelGet; -import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.By; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.infra.Click; import vid.automation.test.infra.Get; +import vid.automation.test.infra.ModelInfo; import vid.automation.test.sections.BrowseASDCPage; -import vid.automation.test.sections.CreateNewInstancePage; import vid.automation.test.sections.PreviousVersionDialog; import vid.automation.test.sections.SideMenu; +import vid.automation.test.sections.deploy.DeployDialogBase; import vid.automation.test.services.SimulatorApi; -import static vid.automation.test.infra.ModelInfo.ModelInfoWithMultipleVersions.modelInfoWithMultipleVersions; -import static vid.automation.test.infra.ModelInfo.serviceWithOneVersion; - public class PreviousVersionsPopupTest extends CreateInstanceDialogBaseTest{ BrowseASDCPage browseASDCPage = new BrowseASDCPage(); @@ -79,17 +86,16 @@ public class PreviousVersionsPopupTest extends CreateInstanceDialogBaseTest{ } @Test private void openPreviousVersionPopup_deployOldVersion_creationPopupIsALaCarte(){ - String expectedPopupIsALaCarteName = "Create Service Instance -- a la carte"; prepareSimulatorWithThreeVersionsBeforeBrowseASDCService(); - CreateNewInstancePage newInstance= new CreateNewInstancePage(); + registerExpectationForLegacyServiceDeployment(ModelInfo.aLaCarteServiceOldVersionTest, "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"); newVersionDialog = new PreviousVersionDialog(); navigateToBrowseAsdcAndClickPreviousButton(); newVersionDialog.clickDeployServiceButtonByServiceUUID(modelVersionId2); - assertNewInstanceFormOpened(createModalTitleTestId,expectedPopupIsALaCarteName); - newInstance.clickCancelButtonByTestID(); - GeneralUIUtils.ultimateWait(); - newVersionDialog.clickCancelButton(); - + final DeployDialogBase deployDialog = BrowseASDCTest.getAlacarteDialogByFlagValue(); + deployDialog.waitForDialogToLoad(); + deployDialog.assertDialog(); + assertEquals(deployDialog.getModelVersionId(), modelVersionId2); + deployDialog.closeDialog(); } private void navigateToBrowseAsdcAndClickPreviousButton() { diff --git a/vid-automation/src/main/java/vid/automation/test/test/SanityMacroDeployTest.java b/vid-automation/src/main/java/vid/automation/test/test/SanityMacroDeployTest.java index ba951bc55..032e729a2 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/SanityMacroDeployTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/SanityMacroDeployTest.java @@ -1,5 +1,10 @@ package vid.automation.test.test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static vid.automation.test.infra.ModelInfo.macroForBrowseSdc; +import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND; + import com.google.common.collect.ImmutableList; import org.junit.Assert; import org.onap.sdc.ci.tests.datatypes.UserCredentials; @@ -17,11 +22,6 @@ import vid.automation.test.sections.BrowseASDCPage; import vid.automation.test.sections.SideMenu; import vid.automation.test.services.SimulatorApi; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static vid.automation.test.infra.ModelInfo.macroForBrowseSdc; -import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND; - public class SanityMacroDeployTest extends CreateInstanceDialogBaseTest { static final String NEW_INSTANCE_NAME = "New Instance Name"; @@ -150,7 +150,7 @@ public class SanityMacroDeployTest extends CreateInstanceDialogBaseTest { Assert.assertEquals(currElem.getText(), RESOURCE_DESCRIPTION); currElem = GeneralUIUtils.getWebElementByTestID(Constants.SERVICE_INVARIANT_UUID, 30); - Assert.assertEquals(currElem.getText(), macroForBrowseSdc.modelInvariantId); + Assert.assertEquals(currElem.getText(), "a8dcd72d-d44d-44f2-aa85-53aa9ca99cba"); currElem = GeneralUIUtils.getWebElementByTestID(Constants.SERVICE_VERSION, 30); Assert.assertEquals(currElem.getText(), SERVICE_VERSION); diff --git a/vid-automation/src/main/java/vid/automation/test/test/VidBaseTestCase.java b/vid-automation/src/main/java/vid/automation/test/test/VidBaseTestCase.java index a45f25853..41ede9a3f 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/VidBaseTestCase.java +++ b/vid-automation/src/main/java/vid/automation/test/test/VidBaseTestCase.java @@ -1,17 +1,59 @@ package vid.automation.test.test; -//import com.automation.common.report_portal_integration.annotations.Step; -//import com.automation.common.report_portal_integration.listeners.ReportPortalListener; -//import com.automation.common.report_portal_integration.screenshots.WebDriverScreenshotsProvider; +import static java.util.Collections.emptySet; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toSet; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet.COMPLETE; +import static org.testng.Assert.assertEquals; +import static org.testng.AssertJUnit.fail; +import static vid.automation.test.utils.TestHelper.GET_SERVICE_MODELS_BY_DISTRIBUTION_STATUS; +import static vid.automation.test.utils.TestHelper.GET_TENANTS; + import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; +import java.io.File; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; import org.glassfish.jersey.uri.internal.JerseyUriBuilder; import org.junit.Assert; import org.onap.sdc.ci.tests.datatypes.Configuration; +import org.onap.sdc.ci.tests.datatypes.UserCredentials; +import org.onap.sdc.ci.tests.execute.setup.SetupCDTest; +import org.onap.sdc.ci.tests.utilities.FileHandling; +import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset; import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset; -import org.onap.simulator.presetGenerator.presets.aai.*; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAICloudRegionAndSourceFromConfigurationPut; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetNetworkZones; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetPortMirroringSourcePorts; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetServicesGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubDetailsGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubDetailsWithoutInstancesGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetTenants; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIPostNamedQueryForViewEdit; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIServiceDesignAndCreationPut; import org.onap.simulator.presetGenerator.presets.ecompportal_att.EcompPortalPresetsUtils; import org.onap.simulator.presetGenerator.presets.ecompportal_att.PresetGetSessionSlotCheckIntervalGet; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstanceGen2; @@ -19,10 +61,6 @@ import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInst import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet; import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceMetadataGet; import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceToscaModelGet; -import org.onap.sdc.ci.tests.datatypes.UserCredentials; -import org.onap.sdc.ci.tests.execute.setup.SetupCDTest; -import org.onap.sdc.ci.tests.utilities.FileHandling; -import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebElement; @@ -36,47 +74,36 @@ import org.testng.annotations.Test; import vid.automation.reportportal.ReportPortalListenerDelegator; import vid.automation.test.Constants; import vid.automation.test.Constants.ViewEdit; -import vid.automation.test.infra.*; +import vid.automation.test.infra.Click; +import vid.automation.test.infra.Exists; +import vid.automation.test.infra.Features; +import vid.automation.test.infra.Get; +import vid.automation.test.infra.ModelInfo; +import vid.automation.test.infra.SelectOption; +import vid.automation.test.infra.Wait; import vid.automation.test.model.Credentials; import vid.automation.test.model.User; -import vid.automation.test.sections.*; +import vid.automation.test.sections.LoginExternalPage; +import vid.automation.test.sections.SearchExistingPage; +import vid.automation.test.sections.SideMenu; +import vid.automation.test.sections.VidBasePage; +import vid.automation.test.sections.ViewEditPage; +import vid.automation.test.sections.deploy.DeployModernUIMacroDialog; import vid.automation.test.services.CategoryParamsService; import vid.automation.test.services.SimulatorApi; import vid.automation.test.services.UsersService; import vid.automation.test.utils.CookieAndJsonHttpHeadersInterceptor; import vid.automation.test.utils.DB_CONFIG; +import vid.automation.test.utils.InsecureHttpsClient; import vid.automation.test.utils.TestConfigurationHelper; import vid.automation.test.utils.TestHelper; -import java.io.File; -import java.lang.reflect.Method; -import java.net.URI; -import java.net.URISyntaxException; -import java.sql.*; -import java.util.*; -import java.util.concurrent.TimeUnit; - -import static java.util.Collections.emptySet; -import static java.util.Collections.singletonList; -import static java.util.stream.Collectors.*; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.collection.IsEmptyCollection.empty; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet.COMPLETE; -import static org.testng.Assert.assertEquals; -import static org.testng.AssertJUnit.fail; -import static vid.automation.test.utils.TestHelper.GET_SERVICE_MODELS_BY_DISTRIBUTION_STATUS; -import static vid.automation.test.utils.TestHelper.GET_TENANTS; - @Listeners(ReportPortalListenerDelegator.class) public class VidBaseTestCase extends SetupCDTest{ protected final UsersService usersService = new UsersService(); protected final CategoryParamsService categoryParamsService = new CategoryParamsService(); - protected final RestTemplate restTemplate = new RestTemplate(); + protected final RestTemplate restTemplate = InsecureHttpsClient.newRestTemplate(); protected final URI uri; protected final URI envUrI; @@ -229,7 +256,7 @@ public class VidBaseTestCase extends SetupCDTest{ return presets; } - protected void relogin(Credentials credentials) throws Exception { + protected void relogin(Credentials credentials) { // `getWindowTest().getPreviousUser()` is SetupCDTest's state of previous user used if (!credentials.userId.equals(getWindowTest().getPreviousUser())) { UserCredentials userCredentials = new UserCredentials(credentials.userId, @@ -485,12 +512,6 @@ public class VidBaseTestCase extends SetupCDTest{ assertThat(String.format(Constants.ServiceModelInfo.METADETA_ERROR_MESSAGE, elementTestId), infoItemText, is(value)); } - public DeployMacroDialogBase getMacroDialog(){ - VidBasePage vidBasePage =new VidBasePage(); - vidBasePage.goToIframe(); - return new DeployMacroDialog(); - } - protected void loadServicePopup(ModelInfo modelInfo) { loadServicePopup(modelInfo.modelVersionId); } @@ -503,7 +524,7 @@ public class VidBaseTestCase extends SetupCDTest{ } protected void loadServicePopupOnBrowseASDCPage(String modelVersionId ) { - DeployMacroDialog deployMacroDialog = new DeployMacroDialog(); + DeployModernUIMacroDialog deployMacroDialog = new DeployModernUIMacroDialog(); VidBasePage.goOutFromIframe(); deployMacroDialog.clickDeployServiceButtonByServiceUUID(modelVersionId); deployMacroDialog.goToIframe(); diff --git a/vid-automation/src/main/java/vid/automation/test/test/ViewEditServiceInstanceTest.java b/vid-automation/src/main/java/vid/automation/test/test/ViewEditServiceInstanceTest.java index a24ecb735..cbc28d0b0 100644 --- a/vid-automation/src/main/java/vid/automation/test/test/ViewEditServiceInstanceTest.java +++ b/vid-automation/src/main/java/vid/automation/test/test/ViewEditServiceInstanceTest.java @@ -1,42 +1,45 @@ package vid.automation.test.test; +import static org.apache.logging.log4j.core.util.Assert.isNonEmpty; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.testng.AssertJUnit.assertEquals; +import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND; + import com.google.common.collect.ImmutableMap; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.hamcrest.MatcherAssert; import org.junit.Assert; import org.junit.Before; -import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetNetworkCollectionDetails; import org.onap.sdc.ci.tests.utilities.GeneralUIUtils; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetNetworkCollectionDetails; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.Constants; -import vid.automation.test.infra.*; +import vid.automation.test.infra.Click; +import vid.automation.test.infra.Exists; +import vid.automation.test.infra.FeatureTogglingTest; +import vid.automation.test.infra.Features; +import vid.automation.test.infra.Get; +import vid.automation.test.infra.Wait; import vid.automation.test.model.User; import vid.automation.test.sections.VidBasePage; import vid.automation.test.sections.ViewEditPage; import vid.automation.test.services.BulkRegistration; import vid.automation.test.services.SimulatorApi; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.apache.logging.log4j.core.util.Assert.isNonEmpty; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.collection.IsEmptyCollection.empty; -import static org.testng.AssertJUnit.assertEquals; -import static vid.automation.test.infra.Features.FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE; -import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND; - public class ViewEditServiceInstanceTest extends VidBaseTestCase { private ViewEditPage viewEditPage = new ViewEditPage(); @@ -115,7 +118,6 @@ public class ViewEditServiceInstanceTest extends VidBaseTestCase { deleteInstance(Constants.ViewEdit.DELETE_VF_MODULE_BUTTON_TEST_ID + "aa", Constants.ViewEdit.VF_MODULE_DELETED_SUCCESSFULLY_TEXT); } - @FeatureTogglingTest(value = FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE) @Test public void softDeleteAndResumeVfModuleInstance_deleteDialogAppears_msoResponseIsOk() { SimulatorApi.clearAll(); diff --git a/vid-automation/src/main/java/vid/automation/test/utils/CookieAndJsonHttpHeadersInterceptor.java b/vid-automation/src/main/java/vid/automation/test/utils/CookieAndJsonHttpHeadersInterceptor.java index c98b2428a..0117a8a99 100644 --- a/vid-automation/src/main/java/vid/automation/test/utils/CookieAndJsonHttpHeadersInterceptor.java +++ b/vid-automation/src/main/java/vid/automation/test/utils/CookieAndJsonHttpHeadersInterceptor.java @@ -1,19 +1,23 @@ package vid.automation.test.utils; +import java.io.IOException; +import java.net.URI; +import java.util.Collections; +import java.util.List; import org.junit.Assert; import org.onap.sdc.ci.tests.datatypes.UserCredentials; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.support.HttpRequestWrapper; import org.springframework.web.client.RestTemplate; -import java.io.IOException; -import java.net.URI; -import java.util.Collections; -import java.util.List; - public class CookieAndJsonHttpHeadersInterceptor implements ClientHttpRequestInterceptor { private final HttpHeaders cookieAndJsonHttpHeaders; @@ -33,7 +37,7 @@ public class CookieAndJsonHttpHeadersInterceptor implements ClientHttpRequestInt protected HttpHeaders getCookieAndJsonHttpHeaders(URI uri, UserCredentials userCredentials) { HttpHeaders loginRequestHeaders = new HttpHeaders(); loginRequestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - RestTemplate restTemplate = new RestTemplate(); + RestTemplate restTemplate = InsecureHttpsClient.newRestTemplate(); ResponseEntity<String> loginRes = restTemplate.postForEntity(uri.toASCIIString() + "/login_external.htm", new HttpEntity<>("loginId=" + userCredentials.getUserId() + "&password=" + userCredentials.getPassword(), loginRequestHeaders), String.class); Assert.assertEquals("Login failed - wrong http status with user:" + userCredentials.getUserId() + " password:" + userCredentials.getPassword(), HttpStatus.FOUND, loginRes.getStatusCode()); Assert.assertNull("Failed to login with user:" + userCredentials.getUserId() + " password:" + userCredentials.getPassword(), loginRes.getBody()); diff --git a/vid-automation/src/main/java/vid/automation/test/utils/InsecureHttpsClient.java b/vid-automation/src/main/java/vid/automation/test/utils/InsecureHttpsClient.java new file mode 100644 index 000000000..6106ae4a2 --- /dev/null +++ b/vid-automation/src/main/java/vid/automation/test/utils/InsecureHttpsClient.java @@ -0,0 +1,26 @@ +package vid.automation.test.utils; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +public class InsecureHttpsClient { + + public static RestTemplate newRestTemplate() { + CloseableHttpClient insecureTLSHttpClient + = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build(); + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(insecureTLSHttpClient); + return new RestTemplate(factory); + } + + public static Client newJaxrsClient() { + return ClientBuilder.newBuilder() + .hostnameVerifier(NoopHostnameVerifier.INSTANCE) + .build(); + } + +} diff --git a/vid-automation/src/main/resources/NewServiceInstanceTest/createNewServiceInstance_macro_validPopupDataAndUI__dynamicFieldsEcompNamingFalse.json b/vid-automation/src/main/resources/NewServiceInstanceTest/createNewServiceInstance_macro_validPopupDataAndUI__dynamicFieldsEcompNamingFalse.json index 25725db8e..d8aebc746 100644 --- a/vid-automation/src/main/resources/NewServiceInstanceTest/createNewServiceInstance_macro_validPopupDataAndUI__dynamicFieldsEcompNamingFalse.json +++ b/vid-automation/src/main/resources/NewServiceInstanceTest/createNewServiceInstance_macro_validPopupDataAndUI__dynamicFieldsEcompNamingFalse.json @@ -4,17 +4,13 @@ "flags": { "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, "FLAG_SHOW_ASSIGNMENTS": true, - "FLAG_DEFAULT_VNF": true, "FLAG_A_LA_CARTE_AUDIT_INFO": true, "FLAG_SHOW_VERIFY_SERVICE": true, "FLAG_ASYNC_ALACARTE_VFMODULE": false, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_ASYNC_ALACARTE_VNF": true, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, "FLAG_SUPPLEMENTARY_FILE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_5G_IN_NEW_INSTANTIATION_UI": true, "FLAG_RESTRICTED_SELECT": false, @@ -3249,4 +3245,4 @@ }, "type": "[LCP_REGIONS_AND_TENANTS] Update" } -}
\ No newline at end of file +} diff --git a/vid-automation/src/main/resources/registration_to_simulator/sanity/get_csar_zip_file.json b/vid-automation/src/main/resources/registration_to_simulator/sanity/get_csar_zip_file.json deleted file mode 100644 index 7b39f77e6..000000000 --- a/vid-automation/src/main/resources/registration_to_simulator/sanity/get_csar_zip_file.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "simulatorRequest": { - "method": "GET", - "path": "/vidSimulator/getSomeFile" -} , - "simulatorResponse": { - "responseCode": 200, - "file": "csar15782222_invariantUUIDMacro.zip" - } -}
\ No newline at end of file diff --git a/vid-automation/src/main/resources/registration_to_simulator/sanity/get_sdc_catalog_services_4d71990b.json b/vid-automation/src/main/resources/registration_to_simulator/sanity/get_sdc_catalog_services_4d71990b.json index 56bce65c0..03b6eb71d 100644 --- a/vid-automation/src/main/resources/registration_to_simulator/sanity/get_sdc_catalog_services_4d71990b.json +++ b/vid-automation/src/main/resources/registration_to_simulator/sanity/get_sdc_catalog_services_4d71990b.json @@ -6,7 +6,7 @@ }, "simulatorResponse": { "responseCode": 200, - "file": "csar15782222_invariantUUIDMacro.zip" + "file": "csar15782222_instantiationTypeMacro_invariantUUIDAlacarte.zip" } }, { @@ -24,7 +24,7 @@ "invariantUUID": "d27e42cf-087e-4d31-88ac-6c4b7585f800", "name": "vidmacrofalsenaming", "version": "1.0", - "toscaModelURL": "./csar15782222_invariantUUIDMacro.zip", + "toscaModelURL": "./csar15782222_instantiationTypeMacro_invariantUUIDAlacarte.zip", "category": "Network Connectivityv", "lifecycleState": "CERTIFIED", "lastUpdaterUserId": "rg276b", @@ -35,4 +35,4 @@ } } } -]
\ No newline at end of file +] diff --git a/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java index 25b40ed6b..ff30c9ce5 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java @@ -1,6 +1,8 @@ package org.onap.vid.api; import static java.util.Collections.emptyMap; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.MatcherAssert.assertThat; @@ -8,6 +10,7 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.matchesPattern; +import static org.hamcrest.Matchers.not; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset.DEFAULT_INSTANCE_ID; import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOBaseCreateInstancePost.DEFAULT_REQUEST_ID; @@ -24,6 +27,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Stream; import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset; import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId; @@ -49,6 +53,9 @@ import org.onap.vid.model.asyncInstantiation.JobAuditStatus.SourceStatus; import org.onap.vid.model.asyncInstantiation.ServiceInfo; import org.onap.vid.more.LoggerFormatTest; import org.onap.vid.more.LoggerFormatTest.LogName; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -121,6 +128,50 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { } @Test + public void deployTwoServicesGetServicesFilterByModelId() { + List<String> uuids = new LinkedList<>(); + try { + //given + final ImmutableMap<PresetMSOServiceInstanceGen2WithNames.Keys, String> names = ImmutableMap + .of(SERVICE_NAME, "calazixide85"); + + String SERVICE_MODEL_UUID = "e3c34d88-a216-4f1d-a782-9af9f9588705"; + + uuids = Stream.of( + createBulkOfInstances(false, 1, names, CREATE_BULK_OF_ALACARTE_REQUEST).get(0), + createBulkOfInstances(false, 1, names, CREATE_BULK_OF_ALACARTE_REQUEST).get(0), + createBulkOfInstances(false, 1, names, CREATE_BULK_OF_MACRO_REQUEST).get(0) + ).collect(toList()); + + //when + ResponseEntity<List<ServiceInfo>> response = restTemplate.exchange( + getServiceInfoUrl() + "?serviceModelId=" + SERVICE_MODEL_UUID, + HttpMethod.GET, + null, + new ParameterizedTypeReference<List<ServiceInfo>>() { + }); + + //then + final List<ServiceInfo> body = response.getBody(); + + //assert that service info list contains only services with desired modelId + assertThat(body.stream().map(x -> x.serviceModelId).collect(toSet()), + contains(SERVICE_MODEL_UUID)); + //assert that service info list contains the 2 first jobs + assertThat(body.stream().map(x -> x.jobId).collect(toList()), + hasItems(uuids.get(0), uuids.get(1))); + //assert that service info list doesn't contains last jobs + assertThat(body.stream().map(x -> x.jobId).collect(toList()), + not(hasItems(uuids.get(2)))); + } + finally { + //clear jobs to not disturb next tests + uuids.forEach(uuid->new AsyncJobsService().muteAsyncJobById(uuid)); + } + } + + + @Test public void deleteServiceWithTwoVnfGroups_andRetry() { String parentServiceInstanceId = "service-instance-id"; String firstVnfGroupToDeleteInstanceId = "VNF_GROUP1_INSTANCE_ID"; @@ -408,12 +459,29 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { } } + + @Test + public void deployServiceAfterDragAndDropVFModule__verifyOrderMsoCalls() { + final ImmutableMap<PresetMSOServiceInstanceGen2WithNames.Keys, String> names = ImmutableMap + .of(SERVICE_NAME, "serviceInstanceName"); + String vnfRequestId = UUID.randomUUID().toString(); + registerPresetsForRetryTest("none", names, vnfRequestId, false); + + final List<String> uuids = createBulkOfInstances(false, 1, names, + CREATE_BULK_OF_ALACARTE_NO_TESTAPI_REQUEST_CYPRESS); + + final String jobId = uuids.get(0); + + assertServiceInfoSpecific2(jobId, JobStatus.COMPLETED, names.get(SERVICE_NAME)); + assertMSOcalledWithOrder(); + } + @Test public void verifyMetricsLogInAsyncInstantiation() { final String UUID_REGEX = "[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}"; - final String msoURL = "/mso/serviceInstantiation/v"; + final String msoURL = "/mso"; deploy1ServiceFromCypress__verifyStatusAndMsoCalls_andRetry("none", emptyMap(), emptyMap(), true); List<String> logLines = LoggerFormatTest.getLogLinesAsList(LogName.metrics2019, 200, 1, restTemplate, uri); @@ -525,6 +593,24 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { )); } + + private void assertMSOcalledWithOrder() { + + List<RecordedRequests> requests = retrieveRecordedRequests(); + + String path = "/mso/serviceInstantiation/v7/serviceInstances/.*/vnfs/.*/vfModules"; + List<String> msoVFModulesRequests = + requests.stream().filter(x -> x.path.matches(path)).map(x -> x.body).collect(toList()); + + assertThat("request for vfNodule send with position order", + msoVFModulesRequests, + contains( + containsString("2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0"), + containsString("2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2"), + containsString("2017488PasqualeVpe..PASQUALE_vRE_BV..module-1") + )); + } + private ImmutableList<JobAuditStatus> vidAuditStatusesCompleted(String jobId) { return ImmutableList.of( vidAuditStatus(jobId, "PENDING", false), diff --git a/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementApiTest.java index 7490c0610..6625d2a41 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementApiTest.java @@ -1,50 +1,75 @@ package org.onap.vid.api; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.onap.vid.api.TestUtils.getNestedPropertyInMap; +import static org.testng.AssertJUnit.assertEquals; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.onap.simulator.presetGenerator.presets.aaf.AAFGetBasicAuthPreset; +import org.onap.simulator.presetGenerator.presets.aaf.AAFGetUrlServicePreset; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; import org.onap.simulator.presetGenerator.presets.mso.changeManagement.PresetMsoChangeManagementBase; import org.onap.simulator.presetGenerator.presets.mso.changeManagement.PresetMsoVnfInPlaceSoftwareUpdate; import org.onap.simulator.presetGenerator.presets.mso.changeManagement.PresetMsoVnfReplace; import org.onap.simulator.presetGenerator.presets.mso.changeManagement.PresetMsoVnfUpdate; -import org.onap.simulator.presetGenerator.presets.aaf.*; -import org.onap.vid.model.mso.*; -import org.onap.vid.model.workflow.*; +import org.onap.vid.model.mso.ChangeManagementRequest; +import org.onap.vid.model.mso.ChangeManagementRequestDetails; +import org.onap.vid.model.mso.CloudConfiguration; +import org.onap.vid.model.mso.MsoExceptionResponse; +import org.onap.vid.model.mso.MsoResponseWrapper2; +import org.onap.vid.model.mso.RelatedInstance; +import org.onap.vid.model.mso.RelatedInstanceList; +import org.onap.vid.model.mso.RequestInfo; +import org.onap.vid.model.mso.RequestParameters; +import org.onap.vid.model.workflow.GetVnfWorkflowRelationRequest; +import org.onap.vid.model.workflow.GetWorkflowsResponse; +import org.onap.vid.model.workflow.VnfDetails; +import org.onap.vid.model.workflow.VnfDetailsWithWorkflows; +import org.onap.vid.model.workflow.VnfWorkflowRelationAllResponse; +import org.onap.vid.model.workflow.VnfWorkflowRelationRequest; +import org.onap.vid.model.workflow.VnfWorkflowRelationResponse; +import org.onap.vid.model.workflow.WorkflowsDetail; +import org.onap.vid.more.LoggerFormatTest; import org.springframework.http.HttpStatus; import org.springframework.util.StopWatch; +import org.springframework.web.client.RestTemplate; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.services.SimulatorApi; import vid.automation.test.services.SimulatorApi.RegistrationStrategy; +import vid.automation.test.utils.InsecureHttpsClient; import vid.automation.test.utils.ReadFile; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.onap.vid.api.TestUtils.getNestedPropertyInMap; -import static org.testng.AssertJUnit.assertEquals; - //This is integration test that require running tomcat public class ChangeManagementApiTest extends BaseApiTest { @@ -470,6 +495,14 @@ public class ChangeManagementApiTest extends BaseApiTest { Response response = callChangeManagementUpdate(vnfIds, changeManagementRequest); MsoResponseWrapper2 body = response.readEntity(MsoResponseWrapper2.class); assertForHappyPath(vnfIds, body, requestType); + RestTemplate manualRestTemplate = InsecureHttpsClient.newRestTemplate(); + super.loginWithChosenRESTClient(getUserCredentials(), manualRestTemplate); + SimulatorApi.registerExpectationFromPreset( new PresetAAIGetSubscribersGet(), RegistrationStrategy.APPEND); + LoggerFormatTest + .verifyExistenceOfIncomingReqsInAuditLogs(manualRestTemplate, uri, + response.getHeaders().get("X-ECOMP-RequestID-echo").get(0).toString(), + "/vid/change-management/workflow/VidVnf"); + } private ChangeManagementRequest createChangeManagementRequest(VnfIds vnfDetails, String requestType) { diff --git a/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementUserApiLoggingTest.java b/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementUserApiLoggingTest.java index dd58e8198..ac8584406 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementUserApiLoggingTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/ChangeManagementUserApiLoggingTest.java @@ -41,6 +41,7 @@ public class ChangeManagementUserApiLoggingTest extends BaseApiTest { String requestId = responseEntity.getHeaders().getFirst("X-ECOMP-RequestID-echo"); LoggerFormatTest.assertHeadersAndMetricLogs(restTemplate, uri, requestId, "/mso/orchestrationRequests/", 2); + LoggerFormatTest.verifyExistenceOfIncomingReqsInAuditLogs(restTemplate, uri, requestId, CHANGE_MANAGEMENT + MSO); } @Test diff --git a/vid-automation/src/test/java/org/onap/vid/api/InstantiationTemplatesApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/InstantiationTemplatesApiTest.java new file mode 100644 index 000000000..f6fbd268d --- /dev/null +++ b/vid-automation/src/test/java/org/onap/vid/api/InstantiationTemplatesApiTest.java @@ -0,0 +1,138 @@ +package org.onap.vid.api; + +import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.greaterThan; +import static org.onap.vid.api.TestUtils.convertRequest; +import static vid.automation.test.services.SimulatorApi.registerExpectationFromPreset; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.IOException; +import java.util.Map.Entry; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.onap.sdc.ci.tests.datatypes.UserCredentials; +import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; +import org.onap.vid.model.mso.MsoResponseWrapper2; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; +import vid.automation.test.Constants; +import vid.automation.test.model.User; +import vid.automation.test.services.AsyncJobsService; +import vid.automation.test.services.SimulatorApi.RegistrationStrategy; + +public class InstantiationTemplatesApiTest extends AsyncInstantiationBase { + + /* + Testing the Template Topology API should be very thin, given the following + assumptions: + + - Template topology API is relying on Retry's logic. + + - The templates themselves are an actual representation of the initial + state in VID's backend. This is all the knowledge that used to create + a service in the first time. So if API is fed with same state, it already + should be able to reiterate another instance. + + + The tests below will verify that: + + - A request resulting from Cypress test on "instantiation-templates.e2e.ts" + is accepted by API endpoint + + - A valid "regular" (not from template) request, yields a template that a + Cypress is able to deploy. + + These two tests are, technically, cyclic. + + Currently the only test below is shortcutting the both tests, by checking + that feeding a Cypress input yields a Template that is the same. This is + not perfect, but currently what we have. + + */ + + @Override + public UserCredentials getUserCredentials() { + User user = usersService.getUser(Constants.Users.EMANUEL_EMANUEL); + return new UserCredentials(user.credentials.userId, user.credentials.password, Constants.Users.EMANUEL_EMANUEL, "", ""); + } + + @AfterMethod + protected void dropAllFromNameCounter() { + AsyncJobsService asyncJobsService = new AsyncJobsService(); + asyncJobsService.muteAllAsyncJobs(); + asyncJobsService.dropAllFromNameCounter(); + } + + protected String templateTopologyUri(String jobId) { + return uri.toASCIIString() + "/asyncInstantiation/templateTopology/" + jobId; + } + + @Test + public void templateTopology_givenDeployFromCypressE2E_getTemplateTopologyDataIsEquivalent() throws IOException { + templateTopology_givenDeploy_templateTopologyIsEquivalent(objectMapper.readValue( + convertRequest(objectMapper, "asyncInstantiation/templates__instance_template.json"), + JsonNode.class)); + } + + public void templateTopology_givenDeploy_templateTopologyIsEquivalent(JsonNode body) { + registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), RegistrationStrategy.CLEAR_THEN_SET); + + String uuid1 = postAsyncInstanceRequest(body); + JsonNode templateTopology1 = restTemplate.getForObject(templateTopologyUri(uuid1), JsonNode.class); + + assertThat(cleanupTemplate(templateTopology1), jsonEquals(cleanupTemplate(body))); + } + + private JsonNode cleanupTemplate(JsonNode templateTopology) { + return Stream.of(templateTopology) + .map(this::removeTrackById) + .map(this::removeNullValues) + .findAny().get(); + } + + private JsonNode removeTrackById(JsonNode node) { + return removeAny(node, it -> it.getKey().equals("trackById")); + } + + private JsonNode removeNullValues(JsonNode node) { + return removeAny(node, it -> it.getValue().isNull()); + } + + private JsonNode removeAny(JsonNode node, Predicate<Entry<String, JsonNode>> entryPredicate) { + if (node.isObject()) { + ((ObjectNode) node).remove( + Streams.fromIterator(node.fields()) + .filter(entryPredicate) + .map(Entry::getKey) + .collect(Collectors.toList()) + ); + + for (JsonNode child : node) { + removeAny(child, entryPredicate); + } + } + + return node; + } + + private <T> String postAsyncInstanceRequest(T body) { + String[] jobsUuids = (String[]) restTemplate.exchange( + getCreateBulkUri(), + HttpMethod.POST, + new HttpEntity<>(body), + new ParameterizedTypeReference<MsoResponseWrapper2<String[]>>() { + }) + .getBody().getEntity(); + + assertThat(jobsUuids, arrayWithSize(greaterThan(0))); + return jobsUuids[0]; + } + +} diff --git a/vid-automation/src/test/java/org/onap/vid/api/ProbeApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/ProbeApiTest.java index 5ed302468..d3c72dab6 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/ProbeApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/ProbeApiTest.java @@ -1,22 +1,34 @@ package org.onap.vid.api; +import static org.hamcrest.CoreMatchers.anyOf; +import static org.hamcrest.CoreMatchers.both; +import static org.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.testng.Assert.assertEquals; +import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET; + import com.google.common.collect.ImmutableList; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; -import org.junit.Assert; import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGetInvalidResponse; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestsManyStatusesGet; import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestsManyStatusesInvalidResponseGet; +import org.onap.simulator.presetGenerator.presets.scheduler.PresetGetSchedulerChangeManagementInvalidResponse; +import org.onap.simulator.presetGenerator.presets.scheduler.PresetGetSchedulerChangeManagements; import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceToscaModelGet; import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceToscaModelGetEmptyResult; import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceToscaModelGetInvalidResponse; import org.onap.vid.model.probe.ExternalComponentStatus; import org.onap.vid.model.probe.HttpRequestMetadata; -import org.onap.simulator.presetGenerator.presets.scheduler.PresetGetSchedulerChangeManagementInvalidResponse; -import org.onap.simulator.presetGenerator.presets.scheduler.PresetGetSchedulerChangeManagements; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; @@ -25,19 +37,12 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.services.SimulatorApi; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.List; - -import static org.hamcrest.CoreMatchers.*; -import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET; - public class ProbeApiTest extends BaseApiTest { private static final String MSO_QUERY_PARAMS = "filter=requestExecutionDate:EQUALS:01-01-2100"; private static final String AAI_QUERY_PARMAS = "business/customers?subscriber-type=INFRA&depth=0"; private static final String SDC_PATH_PARAMS = "46401eec-35bd-4e96-ad0d-0356ff6b8c8d/toscaModel"; - private static final String SCHEDULER_PATH = "http://localhost:1080/scheduler/v1/ChangeManagement/schedules/scheduleDetails/"; + private static final String SCHEDULER_PATH = "/scheduler/v1/ChangeManagement/schedules/scheduleDetails/"; @BeforeClass @@ -203,7 +208,7 @@ public class ProbeApiTest extends BaseApiTest { new ParameterizedTypeReference<List<ExternalComponentStatus>>() { }); List<ExternalComponentStatus> probeResults = response.getBody(); - Assert.assertEquals(5, probeResults.size()); + assertEquals(5, probeResults.size()); assertResultAsExpected(ExternalComponentStatus.Component.AAI, probeResults, expectedStatuses); assertResultAsExpected(ExternalComponentStatus.Component.SDC, probeResults, expectedStatuses); assertResultAsExpected(ExternalComponentStatus.Component.MSO, probeResults, expectedStatuses); @@ -216,16 +221,16 @@ public class ProbeApiTest extends BaseApiTest { ExternalComponentStatus componentStatus = probeResults.stream().filter(x -> x.getComponent() == component) .findFirst().orElseThrow(() -> new AssertionError(component.name()+" result not found in response")); - Assert.assertThat("wrong metadata for " + component, requestMetadataReflected(componentStatus.getMetadata()), + assertThat("wrong metadata for " + component, requestMetadataReflected(componentStatus.getMetadata()), is(requestMetadataReflected(expectedStatus.getMetadata()))); - Assert.assertThat("wrong url for " + component, componentStatus.getMetadata().getUrl(), + assertThat("wrong url for " + component, componentStatus.getMetadata().getUrl(), both(endsWith(expectedStatus.getMetadata().getUrl())).and(startsWith("http"))); - Assert.assertThat("wrong description for " + component, componentStatus.getMetadata().getDescription(), + assertThat("wrong description for " + component, componentStatus.getMetadata().getDescription(), anyOf(equalTo(expectedStatus.getMetadata().getDescription()), startsWith(expectedStatus.getMetadata().getDescription()))); - Assert.assertThat("wrong status for " + component, componentStatus.isAvailable(), is(expectedStatus.isAvailable())); + assertThat("wrong status for " + component, componentStatus.isAvailable(), is(expectedStatus.isAvailable())); } //serialize fields except of fields we cannot know ahead of time diff --git a/vid-automation/src/test/java/org/onap/vid/api/SdcApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/SdcApiTest.java index 858b2f8ef..ba70ca94a 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/SdcApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/SdcApiTest.java @@ -21,8 +21,10 @@ package org.onap.vid.api; import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals; import static net.javacrumbs.jsonunit.JsonMatchers.jsonStringEquals; import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; @@ -129,7 +131,16 @@ public class SdcApiTest extends BaseApiTest { ResponseEntity<String> response = restTemplate.getForEntity(buildUri(SDC_GET_SERVICE_MODEL + MACRO_INSTANTIATION_TYPE_UUID), String.class); assertEquals(response.getStatusCode(), HttpStatus.OK); String emptyInstantiationTypeExpectedResponse = loadResourceAsString(EMPTY_INSTANTIATION_TYPE_EXPECTED_RESPONSE); - assertThat("The response is in the format of JSON", response.getBody(), is(jsonStringEquals(turnOffInstantiationUI(emptyInstantiationTypeExpectedResponse)))); + + final String body = response.getBody(); + + assertThat(body, jsonEquals(emptyInstantiationTypeExpectedResponse) + .when(IGNORING_ARRAY_ORDER) + .whenIgnoringPaths("service.vidNotions.instantiationUI", "service.vidNotions.instantiationType")); + + assertThat(body, jsonPartEquals("service.vidNotions.instantiationType", + Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND.isActive() + ? "ALaCarte" : "ClientConfig")); } @Test @@ -149,7 +160,9 @@ public class SdcApiTest extends BaseApiTest { ResponseEntity<String> response = restTemplate.getForEntity(buildUri(SDC_GET_SERVICE_MODEL + MIN_MAX_INITIAL_UUID), String.class); assertEquals(response.getStatusCode(), HttpStatus.OK); String minMaxInitialExpectedResponse = loadResourceAsString("sdcApiTest/minMaxInitialExpectedResponse.json"); - assertThat("The response is in the format of JSON", response.getBody(), is(jsonStringEquals(turnOffInstantiationUI(minMaxInitialExpectedResponse)))); + assertThat(response.getBody(), jsonEquals(minMaxInitialExpectedResponse) + .when(IGNORING_ARRAY_ORDER) + .whenIgnoringPaths("service.vidNotions.instantiationUI", "service.vidNotions.instantiationType", "service.vidNotions.viewEditUI")); } @Test @@ -163,12 +176,18 @@ public class SdcApiTest extends BaseApiTest { @Test @FeatureTogglingTest(Features.FLAG_1902_VNF_GROUPING) - public void getServiceModelWithServiceRoleGrouping(){ + public void getServiceModelWithServiceRoleGrouping() throws Exception { registerToSimulatorWithPresets(GROUPING_SERVICE_ROLE_UUID, GROUPING_SERVICE_ROLE_INVARIANT_UUID, GROUPING_SERVICE_ROLE_FILE_PATH); ResponseEntity<String> response = restTemplate.getForEntity(buildUri(SDC_GET_SERVICE_MODEL + GROUPING_SERVICE_ROLE_UUID), String.class); assertEquals(response.getStatusCode(), HttpStatus.OK); String groupingServiceRoleExpectedResponse = loadResourceAsString(GROUPING_SERVICE_ROLE_EXPECTED_RESPONSE); - assertThat("The response is in the format of JSON", response.getBody(), is(jsonStringEquals(groupingServiceRoleExpectedResponse))); + assertThat(response.getBody(), jsonEquals(groupingServiceRoleExpectedResponse) + .when(IGNORING_ARRAY_ORDER) + .whenIgnoringPaths("service.vidNotions.instantiationUI")); + + //assert that instantiationUI is not legacy + JsonNode instantiationUI = objectMapper.readValue(response.getBody(), JsonNode.class).get("service").get("vidNotions").get("instantiationUI"); + assertThat(instantiationUI.asText(), not(equalTo("legacy"))); } private void registerToSimulatorWithPresets(String uuid, String invariantUuid, String pathPath){ @@ -178,15 +197,6 @@ public class SdcApiTest extends BaseApiTest { registerExpectationFromPresets(presets, CLEAR_THEN_SET); } - private String turnOffInstantiationUI(String expectedJson) { - if (!Features.FLAG_5G_IN_NEW_INSTANTIATION_UI.isActive()) { - // replaces the instantiationUI field-value with "legacy", whatever it was - return expectedJson.replaceFirst("(\"instantiationUI\": *\")[^\"]*(\",)", "$1legacy$2"); - } else { - return expectedJson; - } - } - @Test public void withModelFromE2eWithToscaParserButNewFlow_requestModels_expectVnfRelatedVfModulesNotNull() { diff --git a/vid-automation/src/test/java/org/onap/vid/api/ServiceTreeApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/ServiceTreeApiTest.java index f8bdc97e2..5d07a4ee8 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/ServiceTreeApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/ServiceTreeApiTest.java @@ -39,6 +39,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.testng.util.RetryAnalyzerCount; import vid.automation.test.services.SimulatorApi; +import vid.automation.test.services.SimulatorApi.RegistrationStrategy; public class ServiceTreeApiTest extends BaseApiTest { @@ -179,7 +180,12 @@ public class ServiceTreeApiTest extends BaseApiTest { .replace("VNF4_INSTANCE_TYPE", vnfPreset4.getInstanceType()); assertJsonEquals(response, expected); + + SimulatorApi.registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), RegistrationStrategy.APPEND); LoggerFormatTest.assertHeadersAndMetricLogs(restTemplate, uri, echoedRequestId(responseEntity), "/network/generic-vnfs/generic-vnf/", 5); + // org.onap.vid.aai.AaiClient.getCloudRegionAndTenantByVnfId for presets PresetAAIGetCloudRegionFromVnf is + // PUTing to AAI, so path is just /aai/v../query + LoggerFormatTest.assertHeadersAndMetricLogs(restTemplate, uri, echoedRequestId(responseEntity), "/query", 4); } @Test diff --git a/vid-automation/src/test/java/org/onap/vid/api/VersionControllerApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/VersionControllerApiTest.java index 4dc799193..0574cec17 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/VersionControllerApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/VersionControllerApiTest.java @@ -1,19 +1,18 @@ package org.onap.vid.api; +import java.util.HashMap; import org.junit.Assert; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; import org.testng.annotations.Test; - -import java.util.HashMap; +import vid.automation.test.utils.InsecureHttpsClient; public class VersionControllerApiTest extends BaseApiTest { @Test public void probeRequest_returnsResponseAsExpected() { // without log-in - ResponseEntity<HashMap<String, String>> response = new RestTemplate().exchange( + ResponseEntity<HashMap<String, String>> response = InsecureHttpsClient.newRestTemplate().exchange( uri + "/version", org.springframework.http.HttpMethod.GET, null, diff --git a/vid-automation/src/test/java/org/onap/vid/more/LoggerFormatTest.java b/vid-automation/src/test/java/org/onap/vid/more/LoggerFormatTest.java index 7a4eedfa9..b65e797b8 100644 --- a/vid-automation/src/test/java/org/onap/vid/more/LoggerFormatTest.java +++ b/vid-automation/src/test/java/org/onap/vid/more/LoggerFormatTest.java @@ -9,12 +9,17 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInRelativeOrder; +import static org.hamcrest.Matchers.either; +import static org.hamcrest.Matchers.emptyOrNullString; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.matchesPattern; import static vid.automation.test.services.SimulatorApi.retrieveRecordedRequests; import com.fasterxml.jackson.databind.JsonNode; + +import java.lang.reflect.Method; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; @@ -26,10 +31,12 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet; import org.onap.vid.api.BaseApiTest; import org.springframework.web.client.RestTemplate; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import vid.automation.test.services.SimulatorApi; import vid.automation.test.services.SimulatorApi.RecordedRequests; @@ -38,9 +45,10 @@ public class LoggerFormatTest extends BaseApiTest { private final static String logChecker = System.getProperty("EELF_LOG_CHECKER", "http://my-logchecker:8888/validate"); private final Logger logger = LogManager.getLogger(LoggerFormatTest.class); + private final int PRIORITY_LAST = 999; public enum LogName { - audit2019, error, metrics2019 + audit2019, error, metrics2019, debug } @BeforeClass @@ -53,33 +61,51 @@ public class LoggerFormatTest extends BaseApiTest { SimulatorApi.registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET); } - @Test - public void validateAudit2019LogsFormat() { - validateLogsFormat(LogName.audit2019, "audit-ELS-2019.11"); + @DataProvider + public static Object[][] logsAndFormats(Method test) { + return new Object[][]{ + {LogName.debug, "debug", 0.65 }, + {LogName.metrics2019, "metric-ELS-2019.11", 0.95}, + {LogName.audit2019, "audit-ELS-2019.11", 0.95} + }; } - @Test(enabled = false) // no total-score is returned for error-log - public void validateErrorLogsFormat() { - validateLogsFormat(LogName.error); - } - @Test - public void validateMetrics2019LogsFormat() { - validateLogsFormat(LogName.metrics2019, "metric-ELS-2019.11"); + @Test(dataProvider = "logsAndFormats", priority = PRIORITY_LAST) + public void validateLogsAndFormat(LogName logName, String logCheckerFormat, Double expectedRank){ + String logLines = validateLogsFormat(logName, logCheckerFormat, expectedRank); + + if (logName == LogName.audit2019) + { + moreValidationsForAuditFormat(logLines); + } } - private void validateLogsFormat(LogName logName) { - validateLogsFormat(logName, logName.name()); + //more validations for log format that logcheck doesn't verify + private void moreValidationsForAuditFormat (String logLines){ + splitLogLines(logLines).forEach(line -> { + String[] records = line.split("\\|"); + assertThat("server name shall be empty", records[5], emptyOrNullString()); + + //authenticated request shall logs with userId. + final String serviceName = records[6]; + if (StringUtils.containsAny(serviceName, "aai", "mso")) { + assertThat("Partner name shall be userId", records[7], matchesPattern("^[A-Za-z0-9]{4,15}$")); + } + + assertThat("Severity shall be empty", records[13], emptyOrNullString()); + assertThat("marker", records[21], either(is("ENTRY")).or(is("EXIT"))); + }); } - private void validateLogsFormat(LogName logName, String logType) { - validateLogsFormat(logName, logType, 0.95); + private String validateLogsFormat (LogName logName, String logType){ + return validateLogsFormat(logName, logType, 0.95); } - private void validateLogsFormat(LogName logName, String logType, double score) { + private String validateLogsFormat (LogName logName, String logType,double score){ String logLines = getLogLines(logName); - logger.info("logLines are: "+logLines); + logger.info("logLines are: " + logLines); JsonNode response = getCheckerResults(logType, logLines); logger.info("Response is:" + response.toString()); @@ -87,29 +113,29 @@ public class LoggerFormatTest extends BaseApiTest { int valid_records = response.path("summary").path("valid_records").asInt(); assertThat(total_records, greaterThan(30)); //make sure we have at least 30 total records - assertThat((double)valid_records/total_records, is(greaterThanOrEqualTo(score))); + assertThat((double) valid_records / total_records, is(greaterThanOrEqualTo(score))); + + return logLines; } - private String getLogLines(LogName logname) { + private String getLogLines (LogName logname){ return getLogLines(logname, 5000, 30, restTemplate, uri); } - public static String getLogLines(LogName logname, int maxRows, int minRows, RestTemplate restTemplate, URI uri) { + public static String getLogLines (LogName logname,int maxRows, int minRows, RestTemplate restTemplate, URI uri){ String logLines = restTemplate.getForObject(uri + "/logger/" + logname.name() + "?limit={maxRows}", String.class, maxRows); assertThat("expecting at least " + minRows + " rows in " + logname.name(), - StringUtils.countMatches(logLines, '\n') + 1, - is(greaterThanOrEqualTo(minRows))); + StringUtils.countMatches(logLines, '\n') + 1, + is(greaterThanOrEqualTo(minRows))); return logLines; } /** * @return Chronological-ordered list of recent log-lines */ - public static List<String> getLogLinesAsList(LogName logname, int maxRows, int minRows, RestTemplate restTemplate, URI uri) { + public static List<String> getLogLinesAsList (LogName logname,int maxRows, int minRows, RestTemplate restTemplate, URI uri){ String logLines = LoggerFormatTest.getLogLines(logname, maxRows, minRows, restTemplate, uri); - - // Split - List<String> lines = new ArrayList<>(Arrays.asList(logLines.split("(\\r?\\n)"))); + List<String> lines = splitLogLines(logLines); // Reverse reverse(lines); @@ -117,11 +143,16 @@ public class LoggerFormatTest extends BaseApiTest { return lines; } + @NotNull + private static List<String> splitLogLines (String logLines){ + return new ArrayList<>(Arrays.asList(logLines.split("(\\r?\\n)"))); + } + /** * @return Chronological-ordered list of recent log-lines of a given requestId */ - public static List<String> getRequestLogLines(String requestId, LogName logname, RestTemplate restTemplate, URI uri) { + public static List<String> getRequestLogLines (String requestId, LogName logname, RestTemplate restTemplate, URI uri){ List<String> lines = getLogLinesAsList(logname, 30, 1, restTemplate, uri); @@ -131,35 +162,38 @@ public class LoggerFormatTest extends BaseApiTest { return lines; } - public static void verifyExistenceOfIncomingReqsInAuditLogs(RestTemplate restTemplate, URI uri, String requestId, - String path){ + public static void verifyExistenceOfIncomingReqsInAuditLogs (RestTemplate restTemplate, URI uri, String requestId, String path){ List<String> logLines = getRequestLogLines(requestId, LogName.audit2019, restTemplate, uri); String requestIdPrefix = "RequestID="; - assertThat("request id must be found in exactly two rows - entry & exit message in audit log, and include the req path", - logLines, - containsInRelativeOrder( - allOf( - containsString(requestIdPrefix+requestId), - containsString("ENTRY"), - containsString(path)), - allOf( - containsString(requestIdPrefix+requestId), - containsString("EXIT"), - containsString(path)) - )); - } - - public static void assertHeadersAndMetricLogs(RestTemplate restTemplate, URI uri, String requestId, String path, int requestsSize) { + assertThat("\nENTRY & EXIT logs are expected to include RequestId: " + requestId + + " \nAnd request path: " + + path + + "\nin exactly two rows - inside the audit log matching lines:\n" + + String.join("\n", logLines) + "\n", + logLines, + contains( + allOf( + containsString(requestIdPrefix + requestId), + containsString("ENTRY"), + containsString(path)), + allOf( + containsString(requestIdPrefix + requestId), + containsString("EXIT"), + containsString(path)) + )); + } + + public static void assertHeadersAndMetricLogs (RestTemplate restTemplate, URI uri, String requestId, String path, int requestsSize){ List<String> logLines = - getRequestLogLines(requestId, LogName.metrics2019, restTemplate, uri); + getRequestLogLines(requestId, LogName.metrics2019, restTemplate, uri); List<RecordedRequests> requests = retrieveRecordedRequests(); List<RecordedRequests> underTestRequests = - requests.stream().filter(x->x.path.contains(path)).collect(toList()); + requests.stream().filter(x -> x.path.contains(path)).collect(toList()); assertThat(underTestRequests, hasSize(requestsSize)); - underTestRequests.forEach(request-> { + underTestRequests.forEach(request -> { assertThat("X-ONAP-RequestID", request.headers.get("X-ONAP-RequestID"), contains(requestId)); assertThat("X-ECOMP-RequestID", request.headers.get("X-ECOMP-RequestID"), contains(requestId)); assertThat("X-ONAP-PartnerName", request.headers.get("X-ONAP-PartnerName"), contains("VID.VID")); @@ -167,7 +201,7 @@ public class LoggerFormatTest extends BaseApiTest { List<String> allInvocationIds = new LinkedList<>(); - underTestRequests.forEach(request->{ + underTestRequests.forEach(request -> { List<String> invocationIds = request.headers.get("X-InvocationID"); assertThat(invocationIds, hasSize(1)); @@ -180,25 +214,25 @@ public class LoggerFormatTest extends BaseApiTest { //make sure no InvocationId is repeated twice assertThat("expect all InvocationIds to be unique", - allInvocationIds, containsInAnyOrder(new HashSet<>(allInvocationIds).toArray())); + allInvocationIds, containsInAnyOrder(new HashSet<>(allInvocationIds).toArray())); } - public static void assertIdsInMetricsLog(List<String> logLines, String requestId, String invocationId) { + public static void assertIdsInMetricsLog (List < String > logLines, String requestId, String invocationId){ assertThat("request id and invocation id must be found in exactly two rows in: \n" + String.join("\n", logLines), - logLines, - containsInRelativeOrder( - allOf( - containsString("RequestID="+requestId), - containsString("InvocationID="+ invocationId), - containsString("Invoke")), - allOf( - containsString("RequestID="+requestId), - containsString("InvocationID="+ invocationId), - containsString("InvokeReturn")) - )); - } - - private JsonNode getCheckerResults(String logtype, String logLines) { + logLines, + containsInRelativeOrder( + allOf( + containsString("RequestID=" + requestId), + containsString("InvocationID=" + invocationId), + containsString("Invoke")), + allOf( + containsString("RequestID=" + requestId), + containsString("InvocationID=" + invocationId), + containsString("InvokeReturn")) + )); + } + + private JsonNode getCheckerResults (String logtype, String logLines){ Map<String, String> params = new HashMap<>(); params.put("format", "raw"); params.put("type", logtype); diff --git a/vid-automation/src/test/java/org/onap/vid/more/RequestIdFilterInstalled.java b/vid-automation/src/test/java/org/onap/vid/more/RequestIdFilterInstalled.java index 93ab14036..d4a1ce3f8 100644 --- a/vid-automation/src/test/java/org/onap/vid/more/RequestIdFilterInstalled.java +++ b/vid-automation/src/test/java/org/onap/vid/more/RequestIdFilterInstalled.java @@ -136,10 +136,14 @@ public class RequestIdFilterInstalled extends BaseApiTest { @Test public void healthcheck_doGET_RequestIdReceived() { + String path = "/healthCheck"; final Pair<HttpEntity, String> responseAndUuid = makeRequest( - HttpMethod.GET, "/healthCheck", null + HttpMethod.GET, path, null ); assertThatUuidInResponseAndUuidIsInARecentLog(LogName.audit2019, responseAndUuid); + LoggerFormatTest + .verifyExistenceOfIncomingReqsInAuditLogs(restTemplate, uri, + responseAndUuid.getKey().getHeaders().get("X-ECOMP-RequestID-echo").get(0).toString(), path); } private void assertThatUuidInResponseAndUuidIsInARecentLog(LogName logName, Pair<HttpEntity, String> responseAndUuid) { diff --git a/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte-no-testapi.json b/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte-no-testapi.json index a6c4dc16f..1c22fb894 100644 --- a/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte-no-testapi.json +++ b/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte-no-testapi.json @@ -13,6 +13,7 @@ "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": { "instanceName": "mimazepubi", "lcpCloudRegionId": "hvf6", + "position": "2", "tenantId": "624eb554b0d147c19ff8885341760481", "rollbackOnFailure": "false", "sdncPreLoad": false, @@ -37,6 +38,7 @@ "instanceName": "puwesovabe", "volumeGroupName": "puwesovabe_vol", "lcpCloudRegionId": "AAIAIC25", + "position": "3", "legacyRegion": "my region", "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", "rollbackOnFailure": "true", @@ -68,6 +70,7 @@ "instanceName": "bnmgtrx", "volumeGroupName": "", "lcpCloudRegionId": "hvf6", + "position": "1", "tenantId": "624eb554b0d147c19ff8885341760481", "rollbackOnFailure": "false", "sdncPreLoad": false, @@ -98,7 +101,7 @@ "lcpCloudRegionId": "AAIAIC25", "legacyRegion": "just another region", "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", - "platformName": "xxx1", + "platformName": "xxx1,platform", "lineOfBusiness": "zzz1", "instanceParams": [ {} diff --git a/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte.json b/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte.json index cc1d5b566..7924340c0 100644 --- a/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte.json +++ b/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte.json @@ -98,7 +98,7 @@ "lcpCloudRegionId": "AAIAIC25", "legacyRegion": "just another region", "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", - "platformName": "xxx1", + "platformName": "xxx1,platform", "lineOfBusiness": "zzz1", "instanceParams": [ {} diff --git a/vid-automation/src/test/resources/asyncInstantiation/ServiceTreeForRetry_serviceInstance.json b/vid-automation/src/test/resources/asyncInstantiation/ServiceTreeForRetry_serviceInstance.json index 5139aa0c0..d5b282e89 100644 --- a/vid-automation/src/test/resources/asyncInstantiation/ServiceTreeForRetry_serviceInstance.json +++ b/vid-automation/src/test/resources/asyncInstantiation/ServiceTreeForRetry_serviceInstance.json @@ -55,7 +55,7 @@ "instanceParams": [], "pause": false, "bulkSize": 1, - "rollbackOnFailure": false, + "rollbackOnFailure": "false", "isALaCarte": true, "testApi": "VNF_API", "instanceId": "INSTANCE_ID", diff --git a/vid-automation/src/test/resources/asyncInstantiation/ServiceWithFailedServiceInstance.json b/vid-automation/src/test/resources/asyncInstantiation/ServiceWithFailedServiceInstance.json index 849cb7e43..28761f393 100644 --- a/vid-automation/src/test/resources/asyncInstantiation/ServiceWithFailedServiceInstance.json +++ b/vid-automation/src/test/resources/asyncInstantiation/ServiceWithFailedServiceInstance.json @@ -27,7 +27,7 @@ "pause": false, "productFamilyId": "ddf9cc0f-6331-4d35-bed0-a37f2d5e9cb3", "projectName": "zasaki", - "rollbackOnFailure": false, + "rollbackOnFailure": "false", "statusMessage": "The service instantiation is failed.", "subscriberName": "SILVIA ROBBINS", "subscriptionServiceType": "TYLER SILVIA", diff --git a/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json b/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json new file mode 100644 index 000000000..8a6401083 --- /dev/null +++ b/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json @@ -0,0 +1,130 @@ +{ + "action": "Create", + "instanceName": "vProbe_NC_Service_DG_new_SI", + "productFamilyId": null, + "lcpCloudRegionId": null, + "tenantId": null, + "modelInfo": { + "modelInvariantId": "90a32d31-8a01-4de2-a91f-7e2414d6f5aa", + "modelVersionId": "6cfeeb18-c2b0-49df-987a-da47493c8e38", + "modelName": "vProbe_NC_Service", + "modelType": "service", + "modelVersion": "1.0" + }, + "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89", + "subscriptionServiceType": "TYLER SILVIA", + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "owningEntityName": "WayneHolland", + "tenantName": null, + "aicZoneId": null, + "aicZoneName": null, + "projectName": "WATKINS", + "subscriberName": "SILVIA ROBBINS", + "rollbackOnFailure": "true", + "isALaCarte": true, + "testApi": "GR_API", + "trackById": "36601560-f8e3-4020-bdef-3e4709c51e84", + "existingVNFCounterMap": { + "024a417d-ca46-40bf-95ce-809c6a269011": 1 + }, + "existingVRFCounterMap": {}, + "existingVnfGroupCounterMap": {}, + "existingNetworksCounterMap": {}, + "vnfs": { + "vProbe_NC_VNF 0": { + "modelInfo": { + "modelCustomizationName": "vProbe_NC_VNF 0", + "modelCustomizationId": "024a417d-ca46-40bf-95ce-809c6a269011", + "modelInvariantId": "a6a96924-b9c5-4c85-ae18-cbfca848095e", + "modelVersionId": "21ae311e-432f-4c54-b855-446d0b8ded72", + "modelName": "vProbe_NC_VNF", + "modelType": "vnf", + "modelVersion": "1.0" + }, + "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", + "instanceName": "hvf6arlba007", + "action": "Create", + "platformName": "xxx1", + "lcpCloudRegionId": "hvf6", + "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77", + "instanceParams": [ + {} + ], + "rollbackOnFailure": true, + "instanceId": null, + "vfModules": { + "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0": { + "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0ahubg": { + "modelInfo": { + "modelCustomizationName": "VprobeNcVnf..FE_base_module..module-0", + "modelCustomizationId": "4d0818cf-eaa9-4a3f-89c2-639953089e14", + "modelInvariantId": "29b6fa3c-aeb3-4103-b3f7-6f98e097b005", + "modelVersionId": "c5b26cc1-a66f-4b69-aa23-6abc7c647c88", + "modelName": "VprobeNcVnf..FE_base_module..module-0", + "modelType": "vfModule", + "modelVersion": "1" + }, + "instanceName": "hvf6arlba007_lba_Base_01", + "action": "Create", + "lcpCloudRegionId": "hvf6", + "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77", + "instanceParams": [ + {} + ], + "rollbackOnFailure": true, + "trackById": "ea2879a6-10bc-4697-90d7-7bc3e71da0fd", + "isFailed": false + } + }, + "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1": { + "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1yprvi": { + "modelInfo": { + "modelCustomizationName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "modelCustomizationId": "9b99d340-a80b-45ef-9ff1-993fa3e4c001", + "modelInvariantId": "1bcc4824-6c1a-4b51-af7c-076b7fc14d05", + "modelVersionId": "c09e4530-8fd8-418f-9483-2f57ce927b05", + "modelName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "modelType": "vfModule", + "modelVersion": "1" + }, + "instanceName": "hvf6arlba007_lba_dj_01", + "action": "Create", + "lcpCloudRegionId": "hvf6", + "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77", + "instanceParams": [ + {} + ], + "rollbackOnFailure": true, + "trackById": "b134410e-3bc0-478e-883e-1b6bdf8a28df", + "isFailed": false, + "volumeGroupInstanceName": "hvf6arlba007_lba_dj_01_vol", + "usePreload": true + } + } + }, + "trackById": "1d2848a0-3573-4d29-b3dd-60bb263260ea", + "isFailed": false, + "statusMessage": null, + "position": null, + "lineOfBusiness": "zzz1" + } + }, + "networks": {}, + "vrfs": {}, + "vnfGroups": {}, + "instanceParams": [ + {} + ], + "pause": false, + "bulkSize": 1, + "instanceId": null, + "isFailed": false, + "statusMessage": null, + "vidNotions": { + "instantiationUI": "anyAlacarteWhichNotExcluded", + "modelCategory": "5G Fabric Configuration", + "viewEditUI": "legacy", + "instantiationType": "ALaCarte" + }, + "position": null +} diff --git a/vid-automation/src/test/resources/features.properties b/vid-automation/src/test/resources/features.properties index 1324403c6..a1a6cf733 100644 --- a/vid-automation/src/test/resources/features.properties +++ b/vid-automation/src/test/resources/features.properties @@ -1,12 +1,8 @@ -CREATE_INSTANCE_TEST = false -EMPTY_DRAWING_BOARD_TEST = false FLAG_ADD_MSO_TESTAPI_FIELD = true FLAG_NETWORK_TO_ASYNC_INSTANTIATION = false FLAG_SERVICE_MODEL_CACHE = true FLAG_SHOW_ASSIGNMENTS = true FLAG_SHOW_VERIFY_SERVICE = true -FLAG_DEFAULT_VNF = true -FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD = true FLAG_RESTRICTED_SELECT = false FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS = true FLAG_A_LA_CARTE_AUDIT_INFO=true @@ -19,7 +15,6 @@ FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI=false FLAG_ENABLE_WEBPACK_MODERN_UI = false FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST=true FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY=true -FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE = true FLAG_1810_AAI_LOCAL_CACHE = true FLAG_1902_NEW_VIEW_EDIT= false FLAG_EXP_USE_DEFAULT_HOST_NAME_VERIFIER = false @@ -37,3 +32,5 @@ FLAG_FLASH_REDUCED_RESPONSE_CHANGEMG = true FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE = false FLAG_SHOW_ORCHESTRATION_TYPE = false FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE = false +FLAG_A_LA_CARTE_PLATFORM_MULTI_SELECT = false + diff --git a/vid-ext-services-simulator/src/main/java/org/onap/simulator/controller/SimulatorController.java b/vid-ext-services-simulator/src/main/java/org/onap/simulator/controller/SimulatorController.java index b6cc6759f..296d9fcbf 100644 --- a/vid-ext-services-simulator/src/main/java/org/onap/simulator/controller/SimulatorController.java +++ b/vid-ext-services-simulator/src/main/java/org/onap/simulator/controller/SimulatorController.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Scanner; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.PostConstruct; @@ -253,7 +254,7 @@ public class SimulatorController { String userName = reqUri.substring(reqUri.lastIndexOf('/') + 1); TypedQuery<User> userQuery = entityManager.createQuery("select u from fn_user u where u.loginId = :userName", User.class); userQuery.setParameter("userName", userName); - User user = userQuery.getSingleResult(); + User user = doWithSingleRetry(userQuery::getSingleResult); Gson g = new Gson(); String jsonString = g.toJson(user); @@ -269,7 +270,7 @@ public class SimulatorController { return new ResponseEntity<>("Centralized Role Access is disabled", HttpStatus.SERVICE_UNAVAILABLE); } TypedQuery<Function> userQuery = entityManager.createQuery("select f from fn_function f", Function.class); - List<Function> functions = userQuery.getResultList(); + List<Function> functions = doWithSingleRetry(userQuery::getResultList); Gson g = new Gson(); String jsonString = g.toJson(functions); @@ -341,6 +342,16 @@ public class SimulatorController { return responseEntity; } + private <T> T doWithSingleRetry(Supplier<T> supplier) { + try { + return supplier.get(); + } catch (Exception e) { + logger.error("exception was thrown; will retry the same action one more time", e); + // here exceptions will be thrown + return supplier.get(); + } + } + private void register(SimulatorRequestResponseExpectation expectationModel) throws VidSimulatorException{ //Setting request according to what is passed HttpRequest request = HttpRequest.request(); diff --git a/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_instantiationTypeMacroWithCR.zip b/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_instantiationTypeMacroWithCR.zip Binary files differdeleted file mode 100644 index a189f206b..000000000 --- a/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_instantiationTypeMacroWithCR.zip +++ /dev/null diff --git a/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_instantiationTypeMacro_invariantUUIDAlacarte_withoutNetworks.zip b/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_instantiationTypeMacro_invariantUUIDAlacarte_withoutNetworks.zip Binary files differindex 1f073b472..b3ba46098 100644 --- a/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_instantiationTypeMacro_invariantUUIDAlacarte_withoutNetworks.zip +++ b/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_instantiationTypeMacro_invariantUUIDAlacarte_withoutNetworks.zip diff --git a/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_invariantUUIDMacro.zip b/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_invariantUUIDMacro.zip Binary files differindex c76b42601..fe9a7dd83 100644 --- a/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_invariantUUIDMacro.zip +++ b/vid-ext-services-simulator/src/main/resources/download_files/csar15782222_invariantUUIDMacro.zip diff --git a/vid-ext-services-simulator/src/main/resources/download_files/service-VflorenceRvpmsFeAic3011217Svc-csar.csar.zip b/vid-ext-services-simulator/src/main/resources/download_files/service-VflorenceRvpmsFeAic3011217Svc-csar.csar.zip Binary files differindex 9853ac801..cd578ab85 100644 --- a/vid-ext-services-simulator/src/main/resources/download_files/service-VflorenceRvpmsFeAic3011217Svc-csar.csar.zip +++ b/vid-ext-services-simulator/src/main/resources/download_files/service-VflorenceRvpmsFeAic3011217Svc-csar.csar.zip diff --git a/vid-ext-services-simulator/src/main/resources/download_files/service-Vocg1804Svc.zip b/vid-ext-services-simulator/src/main/resources/download_files/service-Vocg1804Svc.zip Binary files differnew file mode 100644 index 000000000..05e0a2974 --- /dev/null +++ b/vid-ext-services-simulator/src/main/resources/download_files/service-Vocg1804Svc.zip diff --git a/vid-ext-services-simulator/src/main/resources/download_files/serviceCreationTest04743c62-ab58-41a0-bc53-1052ef1c094a.zip b/vid-ext-services-simulator/src/main/resources/download_files/serviceCreationTest04743c62-ab58-41a0-bc53-1052ef1c094a.zip Binary files differnew file mode 100644 index 000000000..c93a1cd88 --- /dev/null +++ b/vid-ext-services-simulator/src/main/resources/download_files/serviceCreationTest04743c62-ab58-41a0-bc53-1052ef1c094a.zip diff --git a/vid-webpack-master/.npmrc b/vid-webpack-master/.npmrc new file mode 100644 index 000000000..d883e4fa1 --- /dev/null +++ b/vid-webpack-master/.npmrc @@ -0,0 +1 @@ +progress=false diff --git a/vid-webpack-master/cypress.json b/vid-webpack-master/cypress.json index 7a6bc73fd..80fc773eb 100644 --- a/vid-webpack-master/cypress.json +++ b/vid-webpack-master/cypress.json @@ -9,6 +9,7 @@ "video": false, "viewportWidth": 1920, "viewportHeight": 1080, + "baseUrl": "http://localhost:8080/vid", "reporterOptions": { "mochaFile": "cypress/reports/TEST-cypress-[hash].xml", "toConsole": true, diff --git a/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts index 57c673262..fa628d4b5 100644 --- a/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts @@ -2,7 +2,6 @@ /// <reference types="Cypress" /> import {JsonBuilder} from '../../support/jsonBuilders/jsonBuilder'; import {ServiceModel} from '../../support/jsonBuilders/models/service.model'; -import * as _ from 'lodash'; describe('A la carte', function () { describe('check service name', () => { @@ -14,15 +13,15 @@ describe('A la carte', function () { const CONFIRM_BUTTON: string = 'confirmButton'; beforeEach(() => { - cy.clearSessionStorage(); - cy.setReduxState(); - cy.preventErrorsOnLoading(); - cy.initAAIMock(); - cy.initVidMock(); - cy.mockLatestVersionForService(SERVICE_ID, SERVICE_INVARIANT_ID); - cy.initAlaCarteService(); - cy.initZones(); - cy.login(); + cy.clearSessionStorage(); + cy.setReduxState(); + cy.preventErrorsOnLoading(); + cy.initAAIMock(); + cy.initVidMock(); + cy.mockLatestVersionForService(SERVICE_ID, SERVICE_INVARIANT_ID); + cy.initAlaCarteService(); + cy.initZones(); + cy.login(); }); afterEach(() => { @@ -30,8 +29,7 @@ describe('A la carte', function () { }); - - it(`service name should be mandatory : serviceEcompNaming = true`, ()=> { + it(`service name should be mandatory : serviceEcompNaming = true`, () => { cy.readFile('cypress/support/jsonBuilders/mocks/jsons/basicService.json').then((res) => { jsonBuilderAAIService.basicJson(res, Cypress.config('baseUrl') + '/rest/models/services/' + SERVICE_ID, @@ -43,13 +41,13 @@ describe('A la carte', function () { }); }); - it(`Service a-la-carte`, ()=> { + it(`Service a-la-carte`, () => { - const subscriptionServiceType : string = "TYLER SILVIA"; - const owningEntityName : string = "WayneHolland"; - const rollbackOnFailure : string = "true"; - const projectName : string = "WATKINS"; - const instanceName : string = "serviceInstanceName"; + const subscriptionServiceType: string = "TYLER SILVIA"; + const owningEntityName: string = "WayneHolland"; + const rollbackOnFailure: string = "true"; + const projectName: string = "WATKINS"; + const instanceName: string = "serviceInstanceName"; cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((res) => { cy.setTestApiParamToGR(); @@ -91,8 +89,20 @@ describe('A la carte', function () { }); }); + it(`VNF a-la-carte`, () => { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json').then((res) => { + res['FLAG_2002_VNF_PLATFORM_MULTI_SELECT'] = true; + cy.server() + .route({ + method: 'GET', + delay: 0, + status: 200, + url: Cypress.config('baseUrl') + "/flags**", + response: res + }).as('initFlags with multi select'); + }); + - it(`VNF a-la-carte`, ()=> { cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((res) => { cy.setTestApiParamToGR(); res.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].service.vidNotions.instantiationType = 'ALaCarte'; @@ -119,31 +129,42 @@ describe('A la carte', function () { cy.get('#quantity-select').should('have.attr', 'disabled'); cy.getElementByDataTestsId('form-set').click({force: true}).then(() => { cy.getElementByDataTestsId('node-2017-488_PASQUALE-vPE 0-add-btn').click({force: true}).then(() => { + cy.selectDropdownOptionByText('productFamily', 'Emanuel'); cy.selectDropdownOptionByText('lcpRegion', 'AAIAIC25'); cy.typeToInput("lcpRegionText", "just another region"); cy.selectDropdownOptionByText('tenant', 'USP-SIP-IC-24335-T-01'); cy.selectDropdownOptionByText('lineOfBusiness', 'zzz1'); - cy.selectDropdownOptionByText('platform', 'xxx1'); + + cy.selectPlatformValue('xxx1'); + cy.getElementByDataTestsId('form-set').click({force: true}).then(() => { - cy.getReduxState().then((state) => { - - const vnf = state.service.serviceInstance['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs['2017-488_PASQUALE-vPE 0']; - cy.readFile('../vid-automation/src/test/resources/a-la-carte/redux-a-la-carte.json').then((file) => { - file.vnfs['2017-488_PASQUALE-vPE 0'].trackById = vnf.trackById; - file.vnfs['2017-488_PASQUALE-vPE 0'].vfModules = {}; - file.vnfs['2017-488_PASQUALE-vPE 0'].upgradedVFMSonsCounter = 0; - cy.deepCompare(vnf, file.vnfs['2017-488_PASQUALE-vPE 0']) + + const vnfMenuBtnDataTestId = 'node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0-menu-btn'; + + cy.getElementByDataTestsId(vnfMenuBtnDataTestId).click({force: true}).then(() => { + cy.getElementByDataTestsId('context-menu-edit').click({force: true}); + cy.selectPlatformValue('platform'); + cy.getElementByDataTestsId('form-set').click({force: true}).then(() => { + cy.getReduxState().then((state) => { + + const vnf = state.service.serviceInstance['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs['2017-488_PASQUALE-vPE 0']; + cy.readFile('../vid-automation/src/test/resources/a-la-carte/redux-a-la-carte.json').then((file) => { + file.vnfs['2017-488_PASQUALE-vPE 0'].trackById = vnf.trackById; + file.vnfs['2017-488_PASQUALE-vPE 0'].vfModules = {}; + file.vnfs['2017-488_PASQUALE-vPE 0'].upgradedVFMSonsCounter = 0; + cy.deepCompare(vnf, file.vnfs['2017-488_PASQUALE-vPE 0']) + }); + }); }); }); }); - }); }); }); }); - it(`Network a-la-carte`, ()=> { + it(`Network a-la-carte`, () => { cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((res) => { cy.setTestApiParamToGR(); res.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].service.vidNotions.instantiationType = 'ALaCarte'; @@ -173,6 +194,7 @@ describe('A la carte', function () { cy.setReduxState(<any>res); cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); cy.getElementByDataTestsId("node-ExtVL 0-add-btn").click({force: true}); + cy.selectDropdownOptionByText("platform", "xxx1"); cy.selectDropdownOptionByText("lcpRegion", "AAIAIC25"); cy.selectDropdownOptionByText("tenant", "USP-SIP-IC-24335-T-01"); @@ -193,7 +215,7 @@ describe('A la carte', function () { }); }); - it(`VFModule a-la-carte`, ()=> { + it(`VFModule a-la-carte`, () => { var timeBomb = new Date('12/09/2018'); if (new Date() < timeBomb) { return; @@ -210,7 +232,7 @@ describe('A la carte', function () { cy.selectDropdownOptionByText('lcpRegion', 'hvf6'); cy.selectDropdownOptionByText('tenant', 'AIN Web Tool-15-D-STTest2'); cy.selectDropdownOptionByText('lineOfBusiness', 'zzz1'); - cy.selectDropdownOptionByText('platform', 'xxx1'); + cy.selectPlatformValue('xxx1'); cy.getElementByDataTestsId('form-set').click({force: true}).then(() => { const vnfName = '2017-488_PASQUALE-vPE 0'; let vfModulesNames: Array<string> = [ @@ -219,11 +241,11 @@ describe('A la carte', function () { '2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2', ]; - addVfModule(vnfName, vfModulesNames[0], 'mimazepubi', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, false) + cy.addALaCarteVfModule(vnfName, vfModulesNames[0], 'mimazepubi', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, false) .then(() => { - addVfModule(vnfName, vfModulesNames[1], 'puwesovabe', 'AAIAIC25', 'my region', 'USP-SIP-IC-24335-T-01', true, true, false) + cy.addALaCarteVfModule(vnfName, vfModulesNames[1], 'puwesovabe', 'AAIAIC25', 'my region', 'USP-SIP-IC-24335-T-01', true, true, false) .then(() => { - addVfModule(vnfName, vfModulesNames[2], 'bnmgtrx', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, true) + cy.addALaCarteVfModule(vnfName, vfModulesNames[2], 'bnmgtrx', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, true) .then(() => { cy.getReduxState().then((state) => { const vfModules = state.service.serviceInstance['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs[vnfName].vfModules; @@ -261,28 +283,7 @@ describe('A la carte', function () { .get('.error').contains(INSTANCE_NAME_NOT_MANDATORY_MESSAGE); } - function addVfModule (vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, legacyRegion: string, tenant: string, rollback: boolean, sdncPreLoad: boolean, deleteVgName: boolean): Chainable<any> { - return cy.getElementByDataTestsId('node-' + vnfName).click({force: true}).then(() => { - cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}).then(() => { - cy.getElementByDataTestsId('instanceName').clear().type(instanceName, {force: true}).then(() => { - if (deleteVgName) { - cy.getElementByDataTestsId('volumeGroupName').clear(); - } - }).then(() => { - cy.selectDropdownOptionByText('lcpRegion', lcpRegion); - if (!_.isEmpty(legacyRegion)) { - cy.typeToInput("lcpRegionText", legacyRegion); - } - cy.selectDropdownOptionByText('tenant', tenant); - cy.selectDropdownOptionByText('rollback', String(rollback)); - if (sdncPreLoad) { - cy.getElementByDataTestsId('sdncPreLoad').check(); - } - cy.getElementByDataTestsId('form-set').click({force: true}); - }); - }); - }); - } + }); diff --git a/vid-webpack-master/cypress/integration/iFrames/changeManagement.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/changeManagement.e2e.ts index a48ed4a9f..3c2c9d80c 100644 --- a/vid-webpack-master/cypress/integration/iFrames/changeManagement.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/changeManagement.e2e.ts @@ -23,7 +23,7 @@ describe('Change management AKA VNF changes', function () { "aai-sub-details") }); - cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.json').then(() => { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json').then(() => { cy.server() .route({ method: 'GET', diff --git a/vid-webpack-master/cypress/integration/iFrames/collectionResource.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/collectionResource.e2e.ts index a9649fa99..55c43d01b 100644 --- a/vid-webpack-master/cypress/integration/iFrames/collectionResource.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/collectionResource.e2e.ts @@ -1586,14 +1586,11 @@ describe('Drawing board : Collection resource', function () { "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true, "FLAG_SHOW_VERIFY_SERVICE": true, "FLAG_1902_NEW_VIEW_EDIT": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_1906_INSTANTIATION_API_USER_VALIDATION": true, "FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL": false, "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, - "FLAG_DEFAULT_VNF": true, - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true, "FLAG_ASYNC_ALACARTE_VFMODULE": true, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_ASYNC_ALACARTE_VNF": true, @@ -1602,8 +1599,6 @@ describe('Drawing board : Collection resource', function () { "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_1902_RETRY_JOB": true, "FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, "FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH": true, "FLAG_VF_MODULE_RESUME_STATUS_CREATE": true, "FLAG_SUPPLEMENTARY_FILE": true, diff --git a/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts index e379f7835..133dbe72a 100644 --- a/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts @@ -17,6 +17,22 @@ describe('Drawing board', function () { cy.screenshot(); }); + function addSameVnfMultipleTimes() { + cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); + const vnfNodeName = 'node-2017-488_PASQUALE-vPE 0'; + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).get('i').should('have.class', 'fa-plus-circle'); + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).click({force: true}); + cy.fillVnfPopup(true).then(() => { + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).click({force: true}); + cy.fillVnfPopup().then(() => { + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).click({force: true}); + cy.fillVnfPopup().then(() => { + cy.drawingBoardNumberOfExistingElementsShouldContains(3); + }); + }); + }); + } + describe('duplicate', () => { it('delete vf module reduce the number of vf modules ', function () { @@ -25,7 +41,7 @@ describe('Drawing board', function () { cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').get('i').should('have.class', 'fa-plus-circle'); cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup().then(() => { + cy.fillVnfPopup(true).then(() => { cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); cy.fillVnfPopup().then(() => { cy.drawingBoardNumberOfExistingElementsShouldContains(2); @@ -40,18 +56,7 @@ describe('Drawing board', function () { it('create new vf module update the number of vf modules ', () => { cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((res) => { cy.setReduxState(<any>res); - cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').get('i').should('have.class', 'fa-plus-circle'); - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup().then(() => { - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup().then(() => { - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup().then(() => { - cy.drawingBoardNumberOfExistingElementsShouldContains(3); - }); - }); - }); + addSameVnfMultipleTimes(); }); }); @@ -61,7 +66,7 @@ describe('Drawing board', function () { cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').get('i').should('have.class', 'fa-plus-circle') .drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup().then(() => { + cy.fillVnfPopup(true).then(() => { cy.drawingBoardTreeOpenContextMenuByElementDataTestId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0') .drawingBoardTreeClickOnContextMenuOptionByName('Duplicate') .get('.quantity-select option').should('have.length', 9) @@ -238,6 +243,32 @@ describe('Drawing board', function () { }); + describe('default max instances value', () => { + + it('when there is no maxCountInstances for vfModule, it can be added unlimited times', () => { + let reduxState = getReduxWithVNFS(false); + (<any> reduxState.global.flags)['FLAG_2002_UNLIMITED_MAX'] = true; + cy.setReduxState(<any>reduxState); + cy.openIframe('app/ui/#/servicePlanning?serviceModelId=6e59c5de-f052-46fa-aa7e-2fca9d674c44'); + const vfModuleName = 'vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2'; + const vnfName = "VF_vGeraldine 0"; + cy.addMacroVfModule(vnfName, vfModuleName, 'module-1'); + cy.addMacroVfModule(vnfName, vfModuleName, 'module-2'); + cy.addMacroVfModule(vnfName, vfModuleName, 'module-3'); + cy.getElementByDataTestsId('node-d6557200-ecf2-4641-8094-5393ae3aae60-VF_vGeraldine 0').click(); + cy.getElementByDataTestsId('node-41708296-e443-4c71-953f-d9a010f059e1-vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2').should('have.length', 3); + }); + + it('when there is no max_instances for VNF, it can be added multiple times ', () => { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((reduxState) => { + reduxState.global['flags'] = { 'FLAG_2002_UNLIMITED_MAX' : true }; + delete reduxState.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs['2017-488_PASQUALE-vPE 0'].properties.max_instances; + cy.setReduxState(<any>reduxState); + addSameVnfMultipleTimes(); + }); + }); + }); + describe('multiple tests', () => { it('remove vfModule with missing data should update deploy button status', () => { let res = getReduxWithVFModuleMissingData(); @@ -325,7 +356,7 @@ describe('Drawing board', function () { cy.selectDropdownOptionByText('lcpRegion', 'hvf6'); cy.selectDropdownOptionByText('tenant', 'AIN Web Tool-15-D-testalexandria'); cy.selectDropdownOptionByText('lineOfBusiness', 'ONAP'); - cy.selectDropdownOptionByText('platform', 'platform'); + cy.selectPlatformValue('platform'); cy.genericFormSubmitForm(); cy.getElementByDataTestsId('node-afacccf6-397d-45d6-b5ae-94c39734b168-2017-388_PASQUALE-vPE 0').contains('<Automatically Assigned>'); @@ -345,8 +376,9 @@ describe('Drawing board', function () { cy.selectDropdownOptionByText('productFamily', 'ERICA'); cy.selectDropdownOptionByText('lcpRegion', 'hvf6'); cy.selectDropdownOptionByText('tenant', 'AIN Web Tool-15-D-testalexandria'); - cy.selectDropdownOptionByText('lineOfBusiness', 'ONAP'); - cy.selectDropdownOptionByText('platform', 'platform'); + cy.selectDropdownOptionByText('lineOfBusiness', 'ONAP') + cy.selectPlatformValue('platform'); + cy.genericFormSubmitForm(); cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').contains(vnfModelName); @@ -577,14 +609,13 @@ describe('Drawing board', function () { "flags": { "FLAG_SHOW_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "FLAG_1906_COMPONENT_INFO" : false + "FLAG_1906_COMPONENT_INFO" : false, + "FLAG_2002_VNF_PLATFORM_MULTI_SELECT" : false, + "FLAG_2002_UNLIMITED_MAX" : true }, "type": "[FLAGS] Update" }, @@ -2211,9 +2242,6 @@ describe('Drawing board', function () { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -3864,9 +3892,6 @@ describe('Drawing board', function () { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -5603,7 +5628,6 @@ describe('Drawing board', function () { "name": null, "type": "UPDATE_DRAWING_BOARD_STATUS", "flags": { - "CREATE_INSTANCE_TEST": false, "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, @@ -5611,7 +5635,6 @@ describe('Drawing board', function () { "FLAG_SHOW_ASSIGNMENTS": true, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_DEFAULT_VNF": true, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, "FLAG_A_LA_CARTE_AUDIT_INFO": true, "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true, "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true, @@ -6293,7 +6316,7 @@ describe('Drawing board', function () { } } - function getReduxWithVNFS(isEcompGeneratedNaming: boolean) { + function getReduxWithVNFS(isEcompGeneratedNaming: boolean){ return { "global": { "name": null, @@ -6303,9 +6326,6 @@ describe('Drawing board', function () { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_SUPPLEMENTARY_FILE": true }, diff --git a/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts new file mode 100644 index 000000000..8f76908b9 --- /dev/null +++ b/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts @@ -0,0 +1,138 @@ +import ObjectLike = Cypress.ObjectLike; + +describe('Drawing Board: Instantiation Templates', function () { + + describe('Instantiation templates ', () => { + + beforeEach(() => { + cy.clearSessionStorage(); + cy.setTestApiParamToVNF(); + cy.initAAIMock(); + cy.initVidMock(); + cy.initDrawingBoardUserPermission(); + cy.login(); + + mockAsyncBulkResponse(); + }); + + afterEach(() => { + cy.screenshot(); + }); + + describe('Load Page and Deploy', () => { + + it(`Given a stored template - when click "deploy" - then a coherent request should be sent upon deploy`, function () { + + loadDrawingBoardWithRecreateMode(); + + // Then... + cy.getElementByDataTestsId("node-vProbe_NC_VNF 0").should('be.visible'); + assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd(); + }); + + it('View a template’s details as expected', ()=> { + + loadDrawingBoardWithRecreateMode(); + + // Then... + cy.drawingBoardTreeOpenContextMenuByElementDataTestId("node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0") + .drawingBoardTreeClickOnContextMenuOptionByName('Edit') + .getElementByDataTestsId("instanceName").should('have.value', 'hvf6arlba007') + .getElementByDataTestsId("productFamily").should('contain', 'Emanuel') + .getElementByDataTestsId("tenant").should('contain', 'DN5242-Nov21-T1') + .getElementByDataTestsId("lcpRegion").should('contain', 'hvf6') + .getElementByDataTestsId("lineOfBusiness").should('contain', 'zzz1') + .getElementByDataTestsId("rollback").should('contain', 'Rollback') + + + .getElementByDataTestsId("cancelButton").click(); + + cy.drawingBoardTreeOpenContextMenuByElementDataTestId("node-c5b26cc1-a66f-4b69-aa23-6abc7c647c88-vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0") + .drawingBoardTreeClickOnContextMenuOptionByName('Edit') + .getElementByDataTestsId("instanceName").should('have.value', 'hvf6arlba007_lba_Base_01') + .getElementByDataTestsId("lcpRegion").should('contain', 'hvf6') + .getElementByDataTestsId("tenant").should('contain', 'DN5242-Nov21-T1') + .getElementByDataTestsId("rollback").should('contain', 'Rollback') + + .getElementByDataTestsId("cancelButton").click(); + + cy.drawingBoardTreeOpenContextMenuByElementDataTestId("node-c09e4530-8fd8-418f-9483-2f57ce927b05-vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1") + .drawingBoardTreeClickOnContextMenuOptionByName('Edit') + .getElementByDataTestsId("lcpRegion").should('contain', 'hvf6') + .getElementByDataTestsId("tenant").should('contain', 'DN5242-Nov21-T1') + .getElementByDataTestsId("rollback").should('contain', 'Rollback') + .getElementByDataTestsId("cancelButton").click(); + + + + assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd(); + }); + + it(`Edit the service`, function () { + + loadDrawingBoardWithRecreateMode(); + + cy.openServiceContextMenu() + .getElementByDataTestsId("context-menu-header-edit-item").click({force : true}) + }); + }); + }); + + }); + +function loadDrawingBoardWithRecreateMode() { + const serviceModelId = '6cfeeb18-c2b0-49df-987a-da47493c8e38'; + const templateUuid = "46390edd-7100-46b2-9f18-419bd24fb60b"; + + const drawingBoardAction = `RECREATE`; + const templateTopologyEndpoint = "templateTopology"; + cy.route(`**/rest/models/services/${serviceModelId}`, + 'fixture:../support/jsonBuilders/mocks/jsons/instantiationTemplates/templates__service_model.json') + .as('serviceModel'); + + cy.route(`**/asyncInstantiation/${templateTopologyEndpoint}/${templateUuid}`, + 'fixture:../../../vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json') + .as('templateTopology'); + + // When... + + cy.openIframe(`app/ui/#/servicePlanning/${drawingBoardAction}` + + `?jobId=${templateUuid}` + + `&serviceModelId=${serviceModelId}`); + + cy.wait('@serviceModel'); + cy.wait('@templateTopology'); +} + +function assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd() { + cy.getDrawingBoardDeployBtn().click(); + cy.wait('@expectedPostAsyncInstantiation').then(xhr => { + cy.readFile('../vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json').then((expectedResult) => { + convertRollbackOnFailureValueFromStringToBoolean(expectedResult); + + let xhrBodyWithoutIsDirtyField = removeIsDirtyFieldFromXhrRequestBody(xhr); + cy.deepCompare(xhrBodyWithoutIsDirtyField, expectedResult); + }); + }); +} + + //We use this function because the deployService() on drawing-board-header.component class + // changes rollbackOnFailure value from string type to boolean. + function convertRollbackOnFailureValueFromStringToBoolean(expectedResult: any) { + expectedResult.rollbackOnFailure = Boolean(expectedResult.rollbackOnFailure); + } + +function removeIsDirtyFieldFromXhrRequestBody(xhr : any) { + let xhrTempBody = JSON.parse(JSON.stringify(xhr.request.body)); + delete xhrTempBody.isDirty; + return xhrTempBody; +} + + function mockAsyncBulkResponse() { + cy.server().route({ + url: Cypress.config('baseUrl') + '/asyncInstantiation/bulk', + method: 'POST', + status: 200, + response: "[]", + }).as("expectedPostAsyncInstantiation"); + } diff --git a/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts new file mode 100644 index 000000000..b862e568d --- /dev/null +++ b/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts @@ -0,0 +1,110 @@ +///<reference path="../../../node_modules/cypress/types/index.d.ts"/> +describe('Template', () => { + + beforeEach(() => { + cy.clearSessionStorage(); + cy.setReduxState(); + cy.preventErrorsOnLoading(); + cy.initAAIMock(); + cy.initVidMock(); + cy.login(); + }); + + afterEach(() => { + cy.screenshot(); + }); + + it('when open service popup should show template button', function () { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json').then((flags) => { + cy.server() + .route({ + method: 'GET', + delay: 0, + status: 200, + url: Cypress.config('baseUrl') + "/flags**", + response: { + "FLAG_VF_MODULE_RESUME_STATUS_CREATE": false, + "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP": true + } + }).as('initFlags'); + }); + + const asyncInstantiation = [ + { + "id": 8, + "created": 1525075968000, + "modified": 1525075971000, + "action": "INSTANTIATE", + "createdId": null, + "modifiedId": null, + "rowNum": null, + "auditUserId": null, + "auditTrail": null, + "jobId": "5c2cd8e5-27d0-42e3-85a1-85db5eaba459", + "templateId": "d42ba7c8-9e19-4e34-ae2c-d8af3f24498e", + "userId": "16807000", + "aLaCarte": false, + "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d9c", + "jobStatus": "FAILED", + "statusModifiedDate": 1525075968000, + "hidden": false, + "pause": false, + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "owningEntityName": "WayneHolland", + "project": "WATKINS", + "aicZoneId": "NFT1", + "aicZoneName": "NFTJSSSS-NFT1", + "tenantId": "bae71557c5bb4d5aac6743a4e5f1d054", + "tenantName": "AIN Web Tool-15-D-testalexandria", + "regionId": "hvf6", + "regionName": null, + "serviceType": "TYLER SILVIA", + "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89", + "serviceInstanceId": null, + "serviceInstanceName": "nWUfl instance name_002", + "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", + "serviceModelName": "action-data", + "serviceModelVersion": "1.0", + "createdBulkDate": 1525075968000, + "isRetryEnabled": true + } + ]; + + cy.route(Cypress.config('baseUrl') + "/asyncInstantiation**", asyncInstantiation); + + cy.openIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true'); + cy.getElementByDataTestsId('templateButton').contains('Template') + .getElementByDataTestsId('templateButton').click({force: true}) // Open template Modal + .getElementByDataTestsId('template-modal-title').contains('Templates') // Check Modal header + .getElementByDataTestsId('description-part-1').contains('The following list presents previous instantiations done for this model in this version.') + .getElementByDataTestsId('description-part-2').contains('You may use one of them as a baseline for your instantiation or start from scratch.') + .getElementByDataTestsId('description-part-3').contains('Once you selecting one allows you to change the data before start instantiating.') + + + //check table headers + cy.get(`#header-userId`).contains('User ID'); + cy.get(`#header-createDate`).contains('Date'); + cy.get(`#header-instanceName`).contains('Instance Name'); + cy.get(`#header-instantiationStatus`).contains('Instantiation Status'); + cy.get(`#header-region`).contains('Region'); + cy.get(`#header-tenant`).contains('Tenant'); + cy.get(`#header-aicZone`).contains('AIC Zone'); + + // check table body row + cy.getElementByDataTestsId(`userId-${asyncInstantiation[0].jobId}`).contains('16807000'); + cy.getElementByDataTestsId(`createDate-${asyncInstantiation[0].jobId}`).contains('2018-04-30 11:12:48'); + cy.getElementByDataTestsId(`instanceName-${asyncInstantiation[0].jobId}`).contains('nWUfl instance name_002'); + cy.getElementByDataTestsId(`instantiationStatus-${asyncInstantiation[0].jobId}`).contains('FAILED'); + cy.getElementByDataTestsId(`region-${asyncInstantiation[0].jobId}`).contains('hvf6 (WAYNEHOLLAND)'); + cy.getElementByDataTestsId(`tenant-${asyncInstantiation[0].jobId}`).contains('AIN Web Tool-15-D-testalexandria'); + cy.getElementByDataTestsId(`aicZone-${asyncInstantiation[0].jobId}`).contains('NFTJSSSS-NFT1'); + + + //check load button is disabled + cy.getElementByDataTestsId('LoadTemplateButton').should('be.disabled') + cy.getElementByDataTestsId('row-5c2cd8e5-27d0-42e3-85a1-85db5eaba459').click(); + cy.getElementByDataTestsId('LoadTemplateButton').should('not.be.disabled') + + }); +}); + diff --git a/vid-webpack-master/cypress/integration/iFrames/instantiationStatus.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/instantiationStatus.e2e.ts index 3b657343f..c510391cb 100644 --- a/vid-webpack-master/cypress/integration/iFrames/instantiationStatus.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/instantiationStatus.e2e.ts @@ -7,6 +7,7 @@ import {AsyncInstantiationModel} from '../../support/jsonBuilders/models/asyncIn describe('Instantiation status', function () { var jsonBuilderInstantiationBuilder : JsonBuilder<AsyncInstantiationModel> = new JsonBuilder<AsyncInstantiationModel>(); var asyncRes: Array<any>; + const contextMenuCreateAnotherOne = 'context-menu-recreate'; beforeEach(() => { cy.clearSessionStorage(); @@ -58,34 +59,77 @@ describe('Instantiation status', function () { } }); - it('should enable correct menu items', function () { - cy.openIframe('app/ui/#/instantiationStatus'); - - // Instantiate action with Job status FAILED - isRetry = true - cy.get( '#5c2cd8e5-27d0-42e3-85a1-85db5eaba459').find('.menu-div').click(); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-retry']`).should('not.exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-remove']`).should('exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-open']`).should('exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-hide']`).should('not.exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-audit-info']`).should('not.exist'); - - // Instantiate action with Job status FAILED - isRetry = false - cy.get( '#e1db03c3-6274-4ff7-84cf-7bd3a3946de7').find('.menu-div').click(); - cy.get('.dropdown-menu').find(`[data-tests-id='context-menu-retry']`).should('not.be.visible'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-open']`).should('exist'); - - //Delete action with Job status IN_PROGRESS - cy.get( '#850dc7d2-5240-437f-9bcd-b1ed7dc339c2').find('.menu-div').click(); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-remove']`).should('exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-open']`).should('exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-hide']`).should('exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-audit-info']`).should('not.exist'); - //Update action with Job status COMPLETED - cy.get( '#850dc7d2-5240-437f-9bcd-b1ed7dc339c1').find('.menu-div').click(); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-remove']`).should('exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-open']`).should('not.exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-hide']`).should('not.exist'); - cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='context-menu-audit-info']`).should('not.exist'); + it('should filter rows by filter text', function () { + cy.openIframe('app/ui/#/instantiationStatus'); + cy.getElementByDataTestsId("instantiation-status-filter").type("ComplexService"); + cy.get('table#instantiation-status tbody tr').should('have.length', 2); + }); + + it('should filter rows by url filter text', function () { + cy.openIframe('app/ui/#/instantiationStatus?filterText=ComplexService'); + cy.getElementByDataTestsId("instantiation-status-filter").should('have.value','ComplexService'); + cy.get('table#instantiation-status tbody tr').should('have.length', 2); + }); + + function getDisabledDropDownItemByDataTestId(testId:String) { + return cy.get('.dropdown-menu').find('.disabled').find(`[data-tests-id='${testId}']`); + } + + function clickOnTitleAndThenOnMenuWithJobId(jobId: string) { + cy.getElementByDataTestsId("instantiation-status-title").click(); + cy.get('#' + jobId).find('.menu-div').click(); + } + + it('should disabled correct menu items', function () { + + cy.openIframe('app/ui/#/instantiationStatus'); + + // Instantiate action with Job status FAILED - isRetry = true + + clickOnTitleAndThenOnMenuWithJobId('5c2cd8e5-27d0-42e3-85a1-85db5eaba459'); + getDisabledDropDownItemByDataTestId('context-menu-retry').should('not.exist'); + getDisabledDropDownItemByDataTestId('context-menu-remove').should('exist'); + getDisabledDropDownItemByDataTestId('context-menu-open').should('exist'); + getDisabledDropDownItemByDataTestId('context-menu-hide').should('not.exist'); + getDisabledDropDownItemByDataTestId('context-menu-audit-info').should('not.exist'); + getDisabledDropDownItemByDataTestId(contextMenuCreateAnotherOne).should('not.exist'); + + // Instantiate action with Job status FAILED - isRetry = false + clickOnTitleAndThenOnMenuWithJobId('e1db03c3-6274-4ff7-84cf-7bd3a3946de7'); + getDisabledDropDownItemByDataTestId('context-menu-retry').should('not.be.visible'); + getDisabledDropDownItemByDataTestId('context-menu-open').should('exist'); + getDisabledDropDownItemByDataTestId(contextMenuCreateAnotherOne).should('not.exist'); + + //Delete action with Job status IN_PROGRESS + clickOnTitleAndThenOnMenuWithJobId('850dc7d2-5240-437f-9bcd-b1ed7dc339c2'); + getDisabledDropDownItemByDataTestId('context-menu-remove').should('exist'); + getDisabledDropDownItemByDataTestId('context-menu-open').should('exist'); + getDisabledDropDownItemByDataTestId('context-menu-hide').should('exist'); + getDisabledDropDownItemByDataTestId('context-menu-audit-info').should('not.exist'); + getDisabledDropDownItemByDataTestId(contextMenuCreateAnotherOne).should('exist'); + + //Update action with Job status COMPLETED + clickOnTitleAndThenOnMenuWithJobId('850dc7d2-5240-437f-9bcd-b1ed7dc339c1'); + getDisabledDropDownItemByDataTestId('context-menu-remove').should('exist'); + getDisabledDropDownItemByDataTestId('context-menu-open').should('not.exist'); + getDisabledDropDownItemByDataTestId('context-menu-hide').should('not.exist'); + getDisabledDropDownItemByDataTestId('context-menu-audit-info').should('not.exist'); + getDisabledDropDownItemByDataTestId(contextMenuCreateAnotherOne).should('exist'); + }); + + it('clicking on create another one item, go to expected url', function () { + //see cypress/support/jsonBuilders/mocks/jsons/asyncInstantiation.json id:8 + const jobId = '5c2cd8e5-27d0-42e3-85a1-85db5eaba459'; + const serviceModelId = 'e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0'; + const vidBaseUrl = `http://localhost:8080/vid/serviceModels.htm`; + + cy.openIframe('app/ui/#/instantiationStatus'); + + clickOnTitleAndThenOnMenuWithJobId(jobId); + cy.get('.dropdown-menu').getElementByDataTestsId(contextMenuCreateAnotherOne).click(); + cy.location().should((loc) => { + expect(loc.toString()).to.eq(`${vidBaseUrl}#/servicePlanning/RECREATE?serviceModelId=${serviceModelId}&jobId=${jobId}`); + }); }); }); diff --git a/vid-webpack-master/cypress/integration/iFrames/network.popup.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/network.popup.e2e.ts index 8768e34b5..2baab721c 100644 --- a/vid-webpack-master/cypress/integration/iFrames/network.popup.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/network.popup.e2e.ts @@ -213,10 +213,7 @@ describe('Network popup', function () { "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_ADVANCED_PORTS_FILTER": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, "FLAG_REGION_ID_FROM_REMOTE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" diff --git a/vid-webpack-master/cypress/integration/iFrames/pnf.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/pnf.e2e.ts index 0e106188a..7257cbb76 100644 --- a/vid-webpack-master/cypress/integration/iFrames/pnf.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/pnf.e2e.ts @@ -1447,14 +1447,11 @@ function initDrawingBoardWithFourPnf(serviceModelId: string, pnfName: string) { "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true, "FLAG_SHOW_VERIFY_SERVICE": true, "FLAG_1902_NEW_VIEW_EDIT": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_1906_INSTANTIATION_API_USER_VALIDATION": true, "FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL": false, "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, - "FLAG_DEFAULT_VNF": true, - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true, "FLAG_ASYNC_ALACARTE_VFMODULE": true, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_ASYNC_ALACARTE_VNF": true, @@ -1463,8 +1460,6 @@ function initDrawingBoardWithFourPnf(serviceModelId: string, pnfName: string) { "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_1902_RETRY_JOB": true, "FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, "FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH": true, "FLAG_VF_MODULE_RESUME_STATUS_CREATE": true, "FLAG_SUPPLEMENTARY_FILE": true, diff --git a/vid-webpack-master/cypress/integration/iFrames/resume.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/resume.e2e.ts index 5857e1ac0..ab13f92fe 100644 --- a/vid-webpack-master/cypress/integration/iFrames/resume.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/resume.e2e.ts @@ -67,38 +67,13 @@ describe('Resume tests', function () { cy.screenshot(); }); - it(`Resume Defect 710619 - with flag FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE is ON`, function () { + it(`Resume Defect 710619`, function () { cy.visit('/serviceModels.htm#/instantiate?subscriberId=e433710f-9217-458d-a79d-1c7aff376d89&subscriberName=SILVIA ROBBINS&serviceType=TYLER%20SILVIA&serviceInstanceId=dedd680f-f3bd-46d8-97c7-b6fc28db9317&aaiModelVersionId=4b60252a-bf6c-40df-9db5-98b4c363fdf4&isPermitted=true').then(()=>{ cy.wait('@service-complexService'); checkResumeAndPopup("dpa2bccfx5992v_base_module","vfModuleTreeNode-assigned"); }); }); - it(`Resume Defect 710619 - with flag FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE is OFF`, function () { - - cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.json').then((res) => { - cy.server() - .route({ - method: 'GET', - delay : 0, - status : 200, - url : Cypress.config('baseUrl') + "/flags**", - response : { - "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST" : true, - "FLAG_ADD_MSO_TESTAPI_FIELD": true, - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": false - } - }).as('initFlags'); - }); - - cy.visit('/serviceModels.htm#/instantiate?subscriberId=e433710f-9217-458d-a79d-1c7aff376d89&subscriberName=SILVIA ROBBINS&serviceType=TYLER%20SILVIA&serviceInstanceId=dedd680f-f3bd-46d8-97c7-b6fc28db9317&aaiModelVersionId=4b60252a-bf6c-40df-9db5-98b4c363fdf4&isPermitted=true'); - cy.wait('@service-complexService'); - - checkResumeAndPopup("dpa2bccfx5992v_base_module","vfModuleTreeNode-assigned"); - - }); - - function checkResumeAndPopup(vfModuleName:string, vfModuleClassName:string) { cy.get('div').find('.' + vfModuleClassName) .getElementByDataTestsId('resumeVFModuleButton-' + vfModuleName).click().then(()=> { diff --git a/vid-webpack-master/cypress/integration/iFrames/service.popup.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/service.popup.e2e.ts index d1d41d0d9..7d1a1829d 100644 --- a/vid-webpack-master/cypress/integration/iFrames/service.popup.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/service.popup.e2e.ts @@ -82,6 +82,14 @@ describe('Service popup', function () { cy.get('form-general-error').contains('Page contains errors. Please see details next to the relevant fields.'); }); }); + + it('when open service popup should show showPrevious button', () => { + cy.openIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true'); + cy.getElementByDataTestsId('ShowPreviousInstancesButton').contains('Previous Instantiation').click(); + + }) + + }); }); diff --git a/vid-webpack-master/cypress/integration/iFrames/softDeleteAndResume.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/softDeleteAndResume.e2e.ts index fccdd53c6..f390488a6 100644 --- a/vid-webpack-master/cypress/integration/iFrames/softDeleteAndResume.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/softDeleteAndResume.e2e.ts @@ -75,7 +75,7 @@ describe('Soft delete tests', function () { it(`Resume button display in orch status - pendingactivation, assigned - feature FLAG_VF_MODULE_RESUME_STATUS_CREATE - is OFF`, function () { - cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.json').then(() => { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json').then(() => { cy.server() .route({ method: 'GET', @@ -83,7 +83,6 @@ describe('Soft delete tests', function () { status : 200, url : Cypress.config('baseUrl') + "/flags**", response : { - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true, "FLAG_VF_MODULE_RESUME_STATUS_CREATE": false } }).as('initFlags'); diff --git a/vid-webpack-master/cypress/integration/iFrames/viewEditUpgradeVfModule.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/viewEditUpgradeVfModule.e2e.ts index f111189fc..9f2499f3c 100644 --- a/vid-webpack-master/cypress/integration/iFrames/viewEditUpgradeVfModule.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/viewEditUpgradeVfModule.e2e.ts @@ -105,13 +105,17 @@ describe('View Edit Page: Upgrade VFModule', function () { initServicePlanning("EDIT", '../vid-automation/src/test/resources/viewEdit/ServiceTreeWithMultipleChildren_serviceInstance_withUpdatedLatestVersion.json'); upgradeTheVFM(); + assertVfModuleActionInRedux("None_Upgrade"); undoUpgradeForVFM(); + assertVfModuleActionInRedux("None"); upgradeTheVFM(); cy.getDrawingBoardDeployBtn().click(); cy.wait('@expectedPostAsyncInstantiation').then(xhr => { - expect(Object(xhr.request.body).action).to.equal("None_Upgrade"); - expect(Object(xhr.request.body).vnfs['VNF2_INSTANCE_ID'].action).to.equal("None_Upgrade"); - expect(Object(xhr.request.body).vnfs['VNF2_INSTANCE_ID'].vfModules['dc229cd8-c132-4455-8517-5c1787c18b14']['3ef042c4-259f-45e0-9aba-0989bd8d1cc5'].action).to.equal("None_Upgrade"); + const requestBody = Object(xhr.request.body); + const vfModuleRequest = requestBody.vnfs['VNF2_INSTANCE_ID'].vfModules['vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1']['2c1ca484-cbc2-408b-ab86-25a2c15ce280']; + expect(requestBody.action).to.equal("None_Upgrade"); + expect(requestBody.vnfs['VNF2_INSTANCE_ID'].action).to.equal("None_Upgrade"); + expect(vfModuleRequest.action).to.equal("None_Upgrade"); }); }); @@ -206,16 +210,23 @@ describe('View Edit Page: Upgrade VFModule', function () { method: 'GET', status: 200, response: {}, - }).as("expectLatestServiceModelUpgradeVersion") + }).as("expectLatestServiceModelUpgradeVersion"); } - function upgradeTheVFM(treeNodeId = 'node-undefined-dc229cd8-c132-4455-8517-5c1787c18b14'): Chainable<any> { - return cy.getElementByDataTestsId(`${treeNodeId}-menu-btn`).click() + function upgradeTheVFM(treeNodeId = 'node-522159d5-d6e0-4c2a-aa44-5a542a12a830-vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1') { + cy.getElementByDataTestsId(`${treeNodeId}-menu-btn`).click() .drawingBoardTreeClickOnContextMenuOptionByName("Upgrade"); + // The following is needed when enabling FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS + + cy.getElementByDataTestsId('retainAssignments').click(); + cy.getElementByDataTestsId('retainVolumeGroups').click(); + cy.getElementByDataTestsId('sdncPreLoad').click(); + cy.screenshot(); + cy.getElementByDataTestsId('form-set').click(); } function undoUpgradeForVFM() { - cy.getElementByDataTestsId('node-undefined-dc229cd8-c132-4455-8517-5c1787c18b14-menu-btn').click() + cy.getElementByDataTestsId('node-522159d5-d6e0-4c2a-aa44-5a542a12a830-vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1-menu-btn').click() .drawingBoardTreeClickOnContextMenuOptionByName("Undo Upgrade"); } @@ -223,4 +234,13 @@ describe('View Edit Page: Upgrade VFModule', function () { serviceModel.service.uuid = "6e59c5de-f052-46fa-aa7e-2fca9d674c44"; return serviceModel; } + + function assertVfModuleActionInRedux(expectedState:string) { + cy.getReduxState().then((state) => { + const vfModule = state.service.serviceInstance['6e59c5de-f052-46fa-aa7e-2fca9d674c44'] + .vnfs["VNF2_INSTANCE_ID"] + .vfModules["vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1"]["2c1ca484-cbc2-408b-ab86-25a2c15ce280"]; + expect(vfModule.action).to.equal(expectedState) + }); + } }); diff --git a/vid-webpack-master/cypress/integration/iFrames/viewOnlyDrawingBoard.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/viewOnlyDrawingBoard.e2e.ts index 688d42e94..59e15d325 100644 --- a/vid-webpack-master/cypress/integration/iFrames/viewOnlyDrawingBoard.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/viewOnlyDrawingBoard.e2e.ts @@ -331,7 +331,7 @@ describe('View only drawing board', function () { ['Model version', '2.0'], ['Model customization ID', '91415b44-753d-494c-926a-456a9172bbb9'], ['Min instances', '0'], - ['Max instances', '1'] + ['Max instances', 'Unlimited (default)'] ]; const extraLabelsAndValuesForInstance = [['Instance type', 'VNF2_INSTANCE_TYPE'],['In maintenance','true'], ['Instance ID', 'VNF2_INSTANCE_ID']]; testComponentInfoByType('node-VF_vGeraldine 0', labelsAndValuesForModel,'VNF INFO', diff --git a/vid-webpack-master/cypress/integration/iFrames/vnf.popup.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/vnf.popup.e2e.ts index a014400d4..41ab83399 100644 --- a/vid-webpack-master/cypress/integration/iFrames/vnf.popup.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/vnf.popup.e2e.ts @@ -66,7 +66,7 @@ describe('Vnf popup', function () { cy.getElementByDataTestsId('model-item-label-vnf-min').contains('Minimum to instantiate'); cy.getElementByDataTestsId('model-item-value-vnf-min').contains('0'); cy.getElementByDataTestsId('model-item-label-vnf-max').contains('Maximum to instantiate'); - cy.getElementByDataTestsId('model-item-value-vnf-max').contains('1'); + cy.getElementByDataTestsId('model-item-value-vnf-max').contains('Unlimited (default)'); }) }); @@ -81,7 +81,7 @@ describe('Vnf popup', function () { cy.selectDropdownOptionByText('lcpRegion', 'hvf6'); cy.selectDropdownOptionByText('tenant', 'AIN Web Tool-15-D-STTest2'); cy.selectDropdownOptionByText('lineOfBusiness', 'zzz1'); - cy.selectDropdownOptionByText('platform', 'xxx1'); + cy.selectPlatformValue('xxx1'); }) }); @@ -96,9 +96,6 @@ describe('Vnf popup', function () { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" diff --git a/vid-webpack-master/cypress/integration/iFrames/vnf.update.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/vnf.update.e2e.ts index a314424f3..d5b851ddc 100644 --- a/vid-webpack-master/cypress/integration/iFrames/vnf.update.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/vnf.update.e2e.ts @@ -52,10 +52,12 @@ describe('Delete vnf instance', function () { res.instanceId = "f8791436-8d55-4fde-b4d5-72dd2cf13cfb"; const vnf = res.vnfs['2017-488_PASQUALE-vPE 0']; + vnf.instanceId = "VNF_INSTANCE_ID"; vnf.vfModules['2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0']['2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0uvfot'].instanceId = "VF_MODULE_BASE_INSTANCE_ID"; vnf.vfModules['2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1']['2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1fshmc'].instanceId = "VF_MODULE_INSTANCE_ID"; + jsonBuilderAndMock.basicJson( res, Cypress.config('baseUrl') + "/aai_get_service_instance_topology/e433710f-9217-458d-a79d-1c7aff376d89/TYLER SILVIA/f8791436-8d55-4fde-b4d5-72dd2cf13cfb", @@ -69,7 +71,7 @@ describe('Delete vnf instance', function () { // add a vnf on update mode cy.drawingBoardPressAddButtonByElementName('node-2017-388_PASQUALE-vPE 0').click({force: true}); cy.selectDropdownOptionByText('rollback', 'Rollback'); - cy.fillVnfPopup(); + cy.fillVnfPopup(true); // delete VNF cy.drawingBoardTreeOpenContextMenuByElementDataTestId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0', 0) @@ -83,6 +85,7 @@ describe('Delete vnf instance', function () { cy.wait('@expectedPostAsyncInstantiation').then(xhr => { cy.readFile('../vid-automation/src/test/resources/asyncInstantiation/vidRequestDelete1Create1Vnf.json').then((expectedResult) => { expectedResult.vnfs["2017-388_PASQUALE-vPE 0_1"].trackById = vnf.trackById; + expectedResult.vnfs["2017-388_PASQUALE-vPE 0_1"].platformName = 'platform,xxx1'; cy.deepCompare(expectedResult, xhr.request.body); }); }); diff --git a/vid-webpack-master/cypress/support/elements/element.input.actions.ts b/vid-webpack-master/cypress/support/elements/element.input.actions.ts index 4e6b5e879..b52a35ede 100644 --- a/vid-webpack-master/cypress/support/elements/element.input.actions.ts +++ b/vid-webpack-master/cypress/support/elements/element.input.actions.ts @@ -42,7 +42,7 @@ function focusInput(id : string) : void { test if input with id contains some text ****************************************/ function shouldInputContainsText(id : string, text : string) : void { - cy.getElementByDataTestsId(id).contains('text') + cy.getElementByDataTestsId(id).contains(text) } Cypress.Commands.add('typeToInput', typeToInput); diff --git a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/asyncInstantiation.json b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/asyncInstantiation.json index 01eda9551..2a8c7e882 100644 --- a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/asyncInstantiation.json +++ b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/asyncInstantiation.json @@ -230,59 +230,21 @@ "isRetryEnabled": false }, { - "id": 3, - "created": 1524991828000, - "modified": 1524991830000, - "action": "INSTANTIATE", - "createdId": null, - "modifiedId": null, - "rowNum": null, - "auditUserId": null, - "auditTrail": null, - "jobId": "725ef127-4ee5-4665-bdf1-55ee342b362f", - "templateId": "6bd53c0d-8742-43f6-9ed2-efbb87062779", - "userId": "16807000", - "aLaCarte": true, - "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d96", - "jobStatus": "FAILED", - "statusModifiedDate": 1524991828000, - "hidden": false, - "pause": false, - "owningEntityId": "aaa1", - "owningEntityName": "aaa1", - "project": "WATKINS", - "aicZoneId": "NFT1", - "aicZoneName": "NFTJSSSS-NFT1", - "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", - "tenantName": "USP-SIP-IC-24335-T-01", - "regionId": "AAIAIC25", - "regionName": null, - "serviceType": "TYLER SILVIA", - "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89", - "serviceInstanceId": null, - "serviceInstanceName": null, - "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", - "serviceModelName": "ComplexService", - "serviceModelVersion": "1.0", - "createdBulkDate": 1524991828000, - "isRetryEnabled": false - }, - { - "id": 2, + "id": 9, "created": 1524663233000, "modified": 1524663236000, - "action": "INSTANTIATE", + "action": "DELETE", "createdId": null, "modifiedId": null, "rowNum": null, "auditUserId": null, "auditTrail": null, - "jobId": "b1ff271b-829a-43f9-a2e3-23987a34f261", + "jobId": "850dc7d2-5240-437f-9bcd-b1ed7dc339c2", "templateId": "262fccc5-cae9-4258-b522-540c4010e0a9", "userId": "16807000", "aLaCarte": true, - "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d98", - "jobStatus": "FAILED", + "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d45", + "jobStatus": "IN_PROGRESS", "statusModifiedDate": 1524663233000, "hidden": false, "pause": false, @@ -298,29 +260,29 @@ "serviceType": "TYLER SILVIA", "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89", "serviceInstanceId": null, - "serviceInstanceName": "sPenLiZXXpqzsVck instance name_02", + "serviceInstanceName": "sPenLiZXXpqzsVck instance name_01", "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", "serviceModelName": "action-data", "serviceModelVersion": "1.0", "createdBulkDate": 1524663233000, - "isRetryEnabled": true + "isRetryEnabled": false }, { - "id": 1, + "id": 10, "created": 1524663233000, "modified": 1524663236000, - "action": "INSTANTIATE", + "action": "UPDATE", "createdId": null, "modifiedId": null, "rowNum": null, "auditUserId": null, "auditTrail": null, - "jobId": "850dc7d2-5240-437f-9bcd-b1ed7dc339ca", + "jobId": "850dc7d2-5240-437f-9bcd-b1ed7dc339c1", "templateId": "262fccc5-cae9-4258-b522-540c4010e0a9", "userId": "16807000", "aLaCarte": true, "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d45", - "jobStatus": "IN_PROGRESS", + "jobStatus": "COMPLETED", "statusModifiedDate": 1524663233000, "hidden": false, "pause": false, @@ -340,82 +302,6 @@ "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", "serviceModelName": "action-data", "serviceModelVersion": "1.0", - "createdBulkDate": 1524663233000, - "isRetryEnabled": false - }, - { - "id": 9, - "created": 1524663233000, - "modified": 1524663236000, - "action": "DELETE", - "createdId": null, - "modifiedId": null, - "rowNum": null, - "auditUserId": null, - "auditTrail": null, - "jobId": "850dc7d2-5240-437f-9bcd-b1ed7dc339c2", - "templateId": "262fccc5-cae9-4258-b522-540c4010e0a9", - "userId": "16807000", - "aLaCarte": true, - "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d45", - "jobStatus": "IN_PROGRESS", - "statusModifiedDate": 1524663233000, - "hidden": false, - "pause": false, - "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", - "owningEntityName": "WayneHolland", - "project": "WATKINS", - "aicZoneId": "NFT1", - "aicZoneName": "NFTJSSSS-NFT1", - "tenantId": "bae71557c5bb4d5aac6743a4e5f1d054", - "tenantName": "AIN Web Tool-15-D-testalexandria", - "regionId": "hvf6", - "regionName": null, - "serviceType": "TYLER SILVIA", - "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89", - "serviceInstanceId": null, - "serviceInstanceName": "sPenLiZXXpqzsVck instance name_01", - "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", - "serviceModelName": "action-data", - "serviceModelVersion": "1.0", - "createdBulkDate": 1524663233000, - "isRetryEnabled": false -}, - { - "id": 10, - "created": 1524663233000, - "modified": 1524663236000, - "action": "UPDATE", - "createdId": null, - "modifiedId": null, - "rowNum": null, - "auditUserId": null, - "auditTrail": null, - "jobId": "850dc7d2-5240-437f-9bcd-b1ed7dc339c1", - "templateId": "262fccc5-cae9-4258-b522-540c4010e0a9", - "userId": "16807000", - "aLaCarte": true, - "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d45", - "jobStatus": "COMPLETED", - "statusModifiedDate": 1524663233000, - "hidden": false, - "pause": false, - "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", - "owningEntityName": "WayneHolland", - "project": "WATKINS", - "aicZoneId": "NFT1", - "aicZoneName": "NFTJSSSS-NFT1", - "tenantId": "bae71557c5bb4d5aac6743a4e5f1d054", - "tenantName": "AIN Web Tool-15-D-testalexandria", - "regionId": "hvf6", - "regionName": null, - "serviceType": "TYLER SILVIA", - "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89", - "serviceInstanceId": null, - "serviceInstanceName": "sPenLiZXXpqzsVck instance name_01", - "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", - "serviceModelName": "action-data", - "serviceModelVersion": "1.0", - "createdBulkDate": 1524663233000 -} + "createdBulkDate": 1524663233000 + } ] diff --git a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.json b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json index dc14736cf..531bad3b4 100644 --- a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.json +++ b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json @@ -1,24 +1,27 @@ { - "CREATE_INSTANCE_TEST": false, "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_SERVICE_MODEL_CACHE": false, "FLAG_SHOW_ASSIGNMENTS": true, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, - "FLAG_DEFAULT_VNF" : true, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD" : true, "FLAG_A_LA_CARTE_AUDIT_INFO": true, "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true, "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true, - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true, "FLAG_1902_NEW_VIEW_EDIT": true, - "FLAG_VF_MODULE_RESUME_STATUS_CREATE" : true, + "FLAG_VF_MODULE_RESUME_STATUS_CREATE": true, "FLAG_1906_COMPONENT_INFO": true, "FLAG_1908_RESUME_MACRO_SERVICE": true, "FLAG_ENABLE_WEBPACK_MODERN_UI": true, "FLAG_FLASH_REPLACE_VF_MODULE": true, "FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT": true, "FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE": false, - "FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE": false + "FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE": false, + "FLAG_2002_VNF_PLATFORM_MULTI_SELECT" : true, + "FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS": true, + "FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER": true, + "FLAG_2004_INSTANTIATION_STATUS_FILTER": true, + "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP" : false, + "FLAG_2002_UNLIMITED_MAX" : true, + "FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE": true } diff --git a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/instantiationTemplates/templates__service_model.json b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/instantiationTemplates/templates__service_model.json new file mode 100644 index 000000000..96c29a0b2 --- /dev/null +++ b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/instantiationTemplates/templates__service_model.json @@ -0,0 +1,199 @@ +{ + "service": { + "uuid": "6cfeeb18-c2b0-49df-987a-da47493c8e38", + "invariantUuid": "90a32d31-8a01-4de2-a91f-7e2414d6f5aa", + "name": "vProbe_NC_Service", + "version": "1.0", + "toscaModelURL": null, + "category": "Emanuel", + "serviceType": "INFRASTRUCTURE", + "serviceRole": "VNF", + "description": "vProbe_NC_Service", + "serviceEcompNaming": "false", + "instantiationType": "A-La-Carte", + "inputs": {}, + "vidNotions": { + "instantiationUI": "anyAlacarteWhichNotExcluded", + "modelCategory": "5G Fabric Configuration", + "viewEditUI": "legacy", + "instantiationType": "ALaCarte" + } + }, + "vnfs": { + "vProbe_NC_VNF 0": { + "uuid": "21ae311e-432f-4c54-b855-446d0b8ded72", + "invariantUuid": "a6a96924-b9c5-4c85-ae18-cbfca848095e", + "description": "vProbe", + "name": "vProbe_NC_VNF", + "version": "1.0", + "customizationUuid": "024a417d-ca46-40bf-95ce-809c6a269011", + "inputs": {}, + "commands": {}, + "properties": { + "nf_naming": "{naming_policy=SDNC_Policy.Config_MS_VNFVMVNFCNamingPolicyEmanuel, ecomp_generated_naming=true}", + "multi_stage_design": "false", + "nf_function": "VPMS-UP-VLBA", + "nf_naming_code": "RLBA", + "availability_zone_max_count": "1", + "ecomp_generated_naming": "true", + "security_group_name": "rlba01-sec_grp", + "version_number": "11.04.02.000.02", + "vlbagent_version_name": "vProbe.r.107056", + "nf_type": "PROBE", + "vlbagent_eph_flavor_name": "p1.c16r80d80e2000.n0i2", + "vlbagent_eph_volume_size_1": "5.0", + "vlbagent_eph_volume_size_0": "5.0", + "ntp_timezone": "UTC", + "nf_role": "VLBA-FE", + "vlbagent_eph_image_name": "PROBE_VPROBE_11.3.7.02_NC.qcow2", + "vlbagent_eph_volume_type_0": "rbd1", + "vlbagent_eph_volume_name_0": "log", + "vlbagent_eph_volume_type_1": "rbd1", + "vlbagent_eph_volume_name_1": "config" + }, + "type": "VF", + "modelCustomizationName": "vProbe_NC_VNF 0", + "vfModules": { + "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0": { + "uuid": "c5b26cc1-a66f-4b69-aa23-6abc7c647c88", + "invariantUuid": "29b6fa3c-aeb3-4103-b3f7-6f98e097b005", + "customizationUuid": "4d0818cf-eaa9-4a3f-89c2-639953089e14", + "description": null, + "name": "VprobeNcVnf..FE_base_module..module-0", + "version": "1", + "modelCustomizationName": "VprobeNcVnf..FE_base_module..module-0", + "properties": { + "minCountInstances": 1, + "maxCountInstances": 1, + "initialCount": 1, + "vfModuleLabel": "FE_base_module", + "baseModule": true + }, + "inputs": {}, + "volumeGroupAllowed": false + }, + "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1": { + "uuid": "c09e4530-8fd8-418f-9483-2f57ce927b05", + "invariantUuid": "1bcc4824-6c1a-4b51-af7c-076b7fc14d05", + "customizationUuid": "9b99d340-a80b-45ef-9ff1-993fa3e4c001", + "description": null, + "name": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "version": "1", + "modelCustomizationName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "properties": { + "minCountInstances": 0, + "maxCountInstances": null, + "initialCount": 0, + "vfModuleLabel": "FE_Add_On_Module_vlbagent_eph", + "baseModule": false + }, + "inputs": {}, + "volumeGroupAllowed": true + } + }, + "volumeGroups": { + "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1": { + "uuid": "c09e4530-8fd8-418f-9483-2f57ce927b05", + "invariantUuid": "1bcc4824-6c1a-4b51-af7c-076b7fc14d05", + "customizationUuid": "9b99d340-a80b-45ef-9ff1-993fa3e4c001", + "description": null, + "name": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "version": "1", + "modelCustomizationName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "properties": { + "minCountInstances": 0, + "maxCountInstances": null, + "initialCount": 0, + "vfModuleLabel": "FE_Add_On_Module_vlbagent_eph", + "baseModule": false + }, + "inputs": {} + } + }, + "vfcInstanceGroups": {} + } + }, + "networks": {}, + "collectionResources": {}, + "configurations": {}, + "fabricConfigurations": { + "Fabric Configuration 0": { + "uuid": "fa069a04-cb85-4915-8ca0-df372dde6a3c", + "invariantUuid": "58fa0e1f-f8db-4dce-8972-b8ee630288cf", + "description": "A fabric Configuration object", + "name": "Fabric Configuration", + "version": "9.0", + "customizationUuid": "a41997f7-e019-47b2-a6b4-cd20154cfe46", + "inputs": {}, + "commands": {}, + "properties": { + "role": "Fabric Config", + "function": "Network Cloud", + "ecomp_generated_naming": "false", + "type": "5G" + }, + "type": "Configuration" + } + }, + "serviceProxies": {}, + "vfModules": { + "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0": { + "uuid": "c5b26cc1-a66f-4b69-aa23-6abc7c647c88", + "invariantUuid": "29b6fa3c-aeb3-4103-b3f7-6f98e097b005", + "customizationUuid": "4d0818cf-eaa9-4a3f-89c2-639953089e14", + "description": null, + "name": "VprobeNcVnf..FE_base_module..module-0", + "version": "1", + "modelCustomizationName": "VprobeNcVnf..FE_base_module..module-0", + "properties": { + "minCountInstances": 1, + "maxCountInstances": 1, + "initialCount": 1, + "vfModuleLabel": "FE_base_module", + "baseModule": true + }, + "inputs": {}, + "volumeGroupAllowed": false + }, + "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1": { + "uuid": "c09e4530-8fd8-418f-9483-2f57ce927b05", + "invariantUuid": "1bcc4824-6c1a-4b51-af7c-076b7fc14d05", + "customizationUuid": "9b99d340-a80b-45ef-9ff1-993fa3e4c001", + "description": null, + "name": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "version": "1", + "modelCustomizationName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "properties": { + "minCountInstances": 0, + "maxCountInstances": null, + "initialCount": 0, + "vfModuleLabel": "FE_Add_On_Module_vlbagent_eph", + "baseModule": false + }, + "inputs": {}, + "volumeGroupAllowed": true + } + }, + "volumeGroups": { + "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1": { + "uuid": "c09e4530-8fd8-418f-9483-2f57ce927b05", + "invariantUuid": "1bcc4824-6c1a-4b51-af7c-076b7fc14d05", + "customizationUuid": "9b99d340-a80b-45ef-9ff1-993fa3e4c001", + "description": null, + "name": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "version": "1", + "modelCustomizationName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1", + "properties": { + "minCountInstances": 0, + "maxCountInstances": null, + "initialCount": 0, + "vfModuleLabel": "FE_Add_On_Module_vlbagent_eph", + "baseModule": false + }, + "inputs": {} + } + }, + "pnfs": {}, + "vnfGroups": {}, + "vrfs": {} +} diff --git a/vid-webpack-master/cypress/support/jsonBuilders/mocks/vid.mock.ts b/vid-webpack-master/cypress/support/jsonBuilders/mocks/vid.mock.ts index 6fff0bc2d..2569556e2 100644 --- a/vid-webpack-master/cypress/support/jsonBuilders/mocks/vid.mock.ts +++ b/vid-webpack-master/cypress/support/jsonBuilders/mocks/vid.mock.ts @@ -43,7 +43,7 @@ function initCategoryParameter(response? : JSON) : void { } function initFlags(response? : JSON, delay?: number, status?: number) : void { - cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.json').then((res) => { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json').then((res) => { cy.server() .route({ method: 'GET', diff --git a/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts b/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts index d2977832d..b87e773f9 100644 --- a/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts +++ b/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts @@ -1,10 +1,12 @@ declare namespace Cypress { interface Chainable { - fillVFModulePopup: typeof FillVFModulePopup + fillVFModulePopup: typeof fillVFModulePopup; + addALaCarteVfModule: typeof addALaCarteVfModule; + addMacroVfModule: typeof addMacroVfModule; } } -function FillVFModulePopup(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, tenant: string, rollback: boolean, sdncPreLoad: boolean): Chainable<any> { +function fillVFModulePopup(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, tenant: string, rollback: boolean, sdncPreLoad: boolean): Chainable<any> { cy.getElementByDataTestsId('node-' + vnfName).click({force: true}); cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}); cy.getElementByDataTestsId('instanceName').last().type(instanceName, {force: true}); @@ -21,4 +23,40 @@ function FillVFModulePopup(vnfName: string, vfModuleName: string, instanceName: } -Cypress.Commands.add('fillVFModulePopup', FillVFModulePopup); +function addMacroVfModule(vnfName: string, vfModuleName: string, instanceName: string): Chainable<any> { + return cy.getElementByDataTestsId('node-' + vnfName).click({force: true}).then(() => { + cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}).then(() => { + cy.getElementByDataTestsId('instanceName').clear().type(instanceName, {force: true}).then(() => { + cy.getElementByDataTestsId('form-set').click({force: true}); + }) + }) + }); +} + +function addALaCarteVfModule(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, legacyRegion: string, + tenant: string, rollback: boolean, sdncPreLoad: boolean, deleteVgName: boolean): Chainable<any> { + return cy.getElementByDataTestsId('node-' + vnfName).click({force: true}).then(() => { + cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}).then(() => { + cy.getElementByDataTestsId('instanceName').clear().type(instanceName, {force: true}).then(() => { + if (deleteVgName) { + cy.getElementByDataTestsId('volumeGroupName').clear(); + } + }).then(() => { + cy.selectDropdownOptionByText('lcpRegion', lcpRegion); + if (legacyRegion) { + cy.typeToInput("lcpRegionText", legacyRegion); + } + cy.selectDropdownOptionByText('tenant', tenant); + cy.selectDropdownOptionByText('rollback', String(rollback)); + if (sdncPreLoad) { + cy.getElementByDataTestsId('sdncPreLoad').check(); + } + cy.getElementByDataTestsId('form-set').click({force: true}); + }); + }); + }); +} + +Cypress.Commands.add('fillVFModulePopup', fillVFModulePopup); +Cypress.Commands.add('addALaCarteVfModule', addALaCarteVfModule); +Cypress.Commands.add('addMacroVfModule', addMacroVfModule); diff --git a/vid-webpack-master/cypress/support/steps/fill.vnf.popup.step.ts b/vid-webpack-master/cypress/support/steps/fill.vnf.popup.step.ts index a5319b80f..3e91f7719 100644 --- a/vid-webpack-master/cypress/support/steps/fill.vnf.popup.step.ts +++ b/vid-webpack-master/cypress/support/steps/fill.vnf.popup.step.ts @@ -7,12 +7,14 @@ declare namespace Cypress { duplicateVnf: typeof DuplicateVnf, } } -function FillVnfPopup(): Chainable<any> { +function FillVnfPopup(changePlatformValue?: boolean): Chainable<any> { cy.selectDropdownOptionByText('productFamily', 'Emanuel'); cy.selectDropdownOptionByText('lcpRegion', 'hvf6'); cy.selectDropdownOptionByText('tenant', 'AIN Web Tool-15-D-STTest2'); cy.selectDropdownOptionByText('lineOfBusiness', 'zzz1'); - cy.selectDropdownOptionByText('platform', 'xxx1'); + if(changePlatformValue === true){ + cy.selectPlatformValue('xxx1') + } return cy.getElementByDataTestsId('form-set').click({force : true}).then((done)=>{ return done; }); diff --git a/vid-webpack-master/cypress/support/steps/genericForm/genericFormAction.steps.ts b/vid-webpack-master/cypress/support/steps/genericForm/genericFormAction.steps.ts index 9786369cf..00a945711 100644 --- a/vid-webpack-master/cypress/support/steps/genericForm/genericFormAction.steps.ts +++ b/vid-webpack-master/cypress/support/steps/genericForm/genericFormAction.steps.ts @@ -1,12 +1,22 @@ declare namespace Cypress { interface Chainable { genericFormSubmitForm: typeof genericFormSubmitForm + selectPlatformValue: typeof selectPlatformValue } } -function genericFormSubmitForm() : Chainable<any> { - return cy.getElementByDataTestsId('form-set').click({force: true}); + +function selectPlatformValue(selectOption: string) { + cy.getElementByDataTestsId("multi-selectPlatform").get('.c-btn').click({force: true}); + cy.getElementByDataTestsId(`multi-selectPlatform-${selectOption}`).click(); + cy.getElementByDataTestsId("multi-selectPlatform").get('.c-btn').click({force: true}); +} + + +function genericFormSubmitForm(): Chainable<any> { + return cy.getElementByDataTestsId('form-set').click({force: true}); } Cypress.Commands.add('genericFormSubmitForm', genericFormSubmitForm); +Cypress.Commands.add('selectPlatformValue', selectPlatformValue); diff --git a/vid-webpack-master/cypress/support/steps/login.step.ts b/vid-webpack-master/cypress/support/steps/login.step.ts index a7ed0752e..99c80bcb7 100644 --- a/vid-webpack-master/cypress/support/steps/login.step.ts +++ b/vid-webpack-master/cypress/support/steps/login.step.ts @@ -34,8 +34,8 @@ function login(): void { } } -function openIframe(iframeUrl : string): void { - cy.visit(iframeUrl); +function openIframe(iframeUrl : string): Chainable<Window> { + return cy.visit(iframeUrl); } Cypress.Commands.add('login', login); diff --git a/vid-webpack-master/package.cypress.json b/vid-webpack-master/package.cypress.json index 096e61565..da6aa602f 100644 --- a/vid-webpack-master/package.cypress.json +++ b/vid-webpack-master/package.cypress.json @@ -4,16 +4,16 @@ "license": "Apache-2.0", "scripts": { "cypress:open": "cypress open", - "cypress": "cypress open --config baseUrl=http://localhost:8080/vid ", + "cypress": "cypress open", "cypress:run": "cypress run", - "cypress:headless": "cypress run --config baseUrl=http://localhost:8080/vid " + "cypress:headless": "cypress run" }, "private": true, "dependencies": {}, "devDependencies": { "@bahmutov/add-typescript-to-cypress": "2.0.0", "@types/lodash": "4.14.121", - "cypress": "^3.1.0", + "cypress": "3.6.1", "typescript": "3.1.6", "rxjs": "^6.3.3", "rxjs-compat": "^6.3.3" diff --git a/vid-webpack-master/package.json b/vid-webpack-master/package.json index 617a4516c..f2f913612 100644 --- a/vid-webpack-master/package.json +++ b/vid-webpack-master/package.json @@ -19,9 +19,9 @@ "e2e": "ng e2e", "build-watch": "ng build --watch", "cypress:open": "cypress open", - "cypress": "cypress open --config watchForFileChanges=false,baseUrl=http://localhost:8080/vid", + "cypress": "cypress open", "cypress:run": "cypress run", - "cypress:headless": "cypress run --config baseUrl=http://localhost:8080/vid", + "cypress:headless": "cypress run", "format": "prettier", "format:fix": "pretty-quick --staged", "lint": "ng lint" @@ -56,6 +56,7 @@ "install": "0.12.2", "jest-image-snapshot": "2.8.1", "jest-preset-angular": "6.0.2", + "moment": "^2.24.0", "ng-multiselect-dropdown": "0.1.3", "ng2-bootstrap-modal": "1.0.1", "ngx-bootstrap": "^2.0.2", @@ -87,7 +88,7 @@ "angular2-template-loader": "0.6.2", "babel-jest": "24.1.0", "codelyzer": "4.5.0", - "cypress": "^3.1.5", + "cypress": "3.6.1", "hammerjs": "2.0.8", "husky": "^1.3.1", "istanbul-reports": "2.1.1", diff --git a/vid-webpack-master/pom.xml b/vid-webpack-master/pom.xml index 59aa42d68..2fe0a6eaf 100644 --- a/vid-webpack-master/pom.xml +++ b/vid-webpack-master/pom.xml @@ -139,16 +139,6 @@ </execution> <execution> - <id>npm set no-progress</id> - <goals> - <goal>npm</goal> - </goals> - <configuration> - <arguments>set progress=false</arguments> - </configuration> - </execution> - - <execution> <id>npm install</id> <goals> <goal>npm</goal> diff --git a/vid-webpack-master/src/app/app.routing.ts b/vid-webpack-master/src/app/app.routing.ts index 779d17e3c..eaf4e9ca4 100644 --- a/vid-webpack-master/src/app/app.routing.ts +++ b/vid-webpack-master/src/app/app.routing.ts @@ -6,12 +6,20 @@ import {SupportComponent} from "./support/support.component"; import {HealthStatusRoutes} from "./healthStatus/health-status.routing"; import {VlanTaggingRoutes} from "./vlanTagging/vlan-tagging.routing"; import {InstantiationStatusRoutes} from "./instantiationStatus/InstantiationStatus.routing"; +import {InstantiationTemplatesModalComponent} from "./shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component"; const routes: Routes = [ ...DrawingBoardRoutes, ...HealthStatusRoutes, ...VlanTaggingRoutes, ...InstantiationStatusRoutes, { + path: 'instantiationTemplatesPopup', + component: InstantiationTemplatesModalComponent, + resolve: { + flags: FlagsResolve + } + }, + { path: 'servicePopup', component: GenericFormPopupComponent, resolve: { diff --git a/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts b/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts index 0c1fa700c..aebbdee5a 100644 --- a/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts +++ b/vid-webpack-master/src/app/drawingBoard/drawingBoard.routing.ts @@ -4,6 +4,7 @@ import {FlagsResolve} from "../shared/resolvers/flag/flag.resolver"; import {ViewEditResolver} from "../shared/resolvers/viewEdit/viewEdit.resolver"; import {DrawingBoardGuard} from "./guards/servicePlanningGuard/drawingBoardGuard"; import {RetryResolver} from "../shared/resolvers/retry/retry.resolver"; +import {RecreateResolver} from "../shared/resolvers/recreate/recreate.resolver"; export const DrawingBoardRoutes: Route[] = [ { @@ -27,6 +28,14 @@ export const DrawingBoardRoutes: Route[] = [ } }, { + path: 'RECREATE', + component: ServicePlanningComponent, + resolve: { + flags: FlagsResolve, + viewEditResolver: RecreateResolver + } + }, + { path: 'RETRY_EDIT', component: ServicePlanningComponent, resolve: { diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts index 145ee19da..fb1172945 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts @@ -28,6 +28,7 @@ import {DrawingBoardTreeComponent} from "../drawing-board-tree/drawing-board-tre import {ComponentInfoModel} from "../component-info/component-info-model"; import {ComponentInfoService} from "../component-info/component-info.service"; import {FeatureFlagsService, Features} from "../../../shared/services/featureFlag/feature-flags.service"; +import {Utils} from "../../../shared/utils/utils"; @Component({ @@ -93,6 +94,7 @@ export class AvailableModelsTreeComponent { service = {name: ''}; options: ITreeOptions = { + allowDrop:false, nodeHeight: 36, dropSlotHeight: 0, nodeClass: (node: ITreeNode) => { @@ -145,10 +147,10 @@ export class AvailableModelsTreeComponent { this.isNewObject = isNewObject; let data = node.data; let dynamicInputs = data.dynamicInputs; - let isAlaCarte: boolean = this.serviceHierarchy.service.vidNotions.instantiationType == 'ALaCarte'; + let isAlaCarte: boolean = Utils.isALaCarte(this.serviceHierarchy.service.vidNotions.instantiationType); let isEcompGeneratedNaming: boolean = data.isEcompGeneratedNaming; let type: string = data.type; - if (!this.store.getState().global.flags['FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD'] || node.data.type === ServiceNodeTypes.VF || + if (node.data.type === ServiceNodeTypes.VF || this._availableModelsTreeService.shouldOpenDialog(type, dynamicInputs, isEcompGeneratedNaming)) { this._iframeService.addClassOpenModal(this.parentElementClassName); node.data.onAddClick(node, serviceId); diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts index 7923313bf..8228f9531 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts @@ -180,7 +180,7 @@ export class DrawingBoardHeader { } } - extractOwningEntityNameAccordingtoId(id:String): string { + extractOwningEntityNameAccordingToId(id:String): string { let owningEntityName; _.forEach(this.store.getState().service.categoryParameters.owningEntityList,(owningEntity: OwningEntity) => { if (owningEntity.id === id) { @@ -190,12 +190,20 @@ export class DrawingBoardHeader { return owningEntityName; } + private extractSubscriberNameByGlobalSubscriberId(globalSubscriberId: string) { + return this.store.getState().service.subscribers.find(sub => sub.id === globalSubscriberId).name; + } + extractServiceFields(): any { let instanceFields : ServiceInstance; instanceFields = this.store.getState().service.serviceInstance[this.serviceModelId]; if (instanceFields.action === ServiceInstanceActions.Create) { - instanceFields.subscriberName = this.store.getState().service.subscribers.find(sub => sub.id === instanceFields.globalSubscriberId).name; - instanceFields.owningEntityName = this.extractOwningEntityNameAccordingtoId(instanceFields.owningEntityId); + if(_.isNil(instanceFields.subscriberName)) { + instanceFields.subscriberName = this.extractSubscriberNameByGlobalSubscriberId(instanceFields.globalSubscriberId); + } + if (_.isNil(instanceFields.owningEntityName)) { + instanceFields.owningEntityName = this.extractOwningEntityNameAccordingToId(instanceFields.owningEntityId); + } } return _.omit(instanceFields,['optionalGroupMembersMap', 'upgradedVFMSonsCounter', 'isUpgraded', 'latestAvailableVersion']); } diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts index 1b71d9098..634fa6271 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts @@ -96,7 +96,7 @@ export class DrawingBoardHeaderService{ showEditService(mode: DrawingBoardModes, serviceModelId: string): boolean{ const serviceInstance = this.store.getState().service.serviceInstance; - return mode === DrawingBoardModes.CREATE || ((mode === DrawingBoardModes.RETRY_EDIT || mode === DrawingBoardModes.EDIT)&& + return mode === DrawingBoardModes.CREATE || ((mode === DrawingBoardModes.RETRY_EDIT || mode === DrawingBoardModes.EDIT || mode === DrawingBoardModes.RECREATE )&& !_.isNil(serviceInstance) && !_.isNil(serviceInstance[serviceModelId])&& serviceInstance[serviceModelId].action === ServiceInstanceActions.Create); } diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts index 01ae898f5..425568b68 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.spec.ts @@ -5,14 +5,15 @@ import {DragAndDropService} from "./dragAndDrop.service"; import {AppState} from "../../../../shared/store/reducers"; class MockAppStore<T> { - dispatch(){ + dispatch() { } + getState() { return { global: { flags: { - "FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE" : true + "FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE": true } }, service: { @@ -53,6 +54,7 @@ describe('Drag and drop service', () => { let service: DragAndDropService; let httpMock: HttpTestingController; let store: NgRedux<AppState>; + let nodes; beforeAll(done => (async () => { TestBed.configureTestingModule({ @@ -67,158 +69,142 @@ describe('Drag and drop service', () => { service = injector.get(DragAndDropService); httpMock = injector.get(HttpTestingController); store = injector.get(NgRedux); + + })().then(done).catch(done.fail)); + beforeEach(() => { + nodes = [ + { + "trackById": "ckfqe3sb3y8", + "componentInfoType": "VNF", + "parentType": "", + "type": "VF", + "typeName": "VNF", + "instanceName": "2017-488_PASQUALE-vPE", + "id": "04686zg11ur2", + "children": [ + { + "id": "1150884479608", + "action": "Create", + "instanceName": "puwesovabe", + "name": "puwesovabe", + "type": "VFmodule", + "trackById": "d5if1906rqa", + "parentType": "VNF", + "position": 1, + "componentInfoType": "VFModule", + "errors": {}, + "updatePoistionFunction": () => { + }, + }, + { + "id": "4637423092446", + "action": "Create", + "instanceName": "bnmgtrx", + "name": "bnmgtrx", + "type": "VFmodule", + "trackById": "9ei9adlh27e", + "parentType": "VNF", + "position": 2, + "componentInfoType": "VFModule", + "updatePoistionFunction": () => { + } + } + ], + "errors": {}, + } + ]; + }) + test('drag should execute array_move when the nodes parent are same', () => { - test('drag should move element position', () => { - let nodes = [{ - "modelCustomizationId": "91415b44-753d-494c-926a-456a9172bbb9", - "modelId": "d6557200-ecf2-4641-8094-5393ae3aae60", - "modelUniqueId": "91415b44-753d-494c-926a-456a9172bbb9", - "missingData": false, - "id": "tjjongy92jn", - "action": "Create", - "inMaint": false, - "name": "yoav2_001", - "modelName": "VF_vGeraldine 0", - "type": "VF", - "isEcompGeneratedNaming": true, - "networkStoreKey": "VF_vGeraldine 0:0001", - "vnfStoreKey": "VF_vGeraldine 0:0001", - "typeName": "VNF", - "menuActions": {"edit": {}, "showAuditInfo": {}, "duplicate": {}, "remove": {}, "delete": {}, "undoDelete": {}}, - "isFailed": false, - "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, { - "key": "Orch Status:", - "testId": "orchStatus" - }], - "trackById": "di9khuolht", - "parentType": "", - "position": 0, - "children": [{ - "modelCustomizationId": "f8c040f1-7e51-4a11-aca8-acf256cfd861", - "modelId": "a27f5cfc-7f12-4f99-af08-0af9c3885c87", - "modelUniqueId": "f8c040f1-7e51-4a11-aca8-acf256cfd861", - "missingData": false, - "id": 6654971919519, - "action": "Create", - "name": "VFModule1", - "modelName": "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0", - "type": "VFmodule", - "isEcompGeneratedNaming": true, - "dynamicInputs": [], - "dynamicModelName": "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0bykqx", - "typeName": "M", - "menuActions": {"edit": {}, "showAuditInfo": {}, "remove": {}, "delete": {}, "undoDelete": {}}, - "isFailed": false, - "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, { - "key": "Orch Status:", - "testId": "orchStatus" - }], - "trackById": "5pfyfah820h", - "parentType": "VNF", - "position": 0, - "errors": {} - }, { - "modelCustomizationId": "6add59e0-7fe1-4bc4-af48-f8812422ae7c", - "modelId": "41708296-e443-4c71-953f-d9a010f059e1", - "modelUniqueId": "6add59e0-7fe1-4bc4-af48-f8812422ae7c", - "missingData": false, - "id": 987761655742, - "action": "Create", - "name": "VNFModule3", - "modelName": "vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2", - "type": "VFmodule", - "isEcompGeneratedNaming": true, - "dynamicInputs": [], - "dynamicModelName": "vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2fjrrc", - "typeName": "M", - "menuActions": {"edit": {}, "showAuditInfo": {}, "remove": {}, "delete": {}, "undoDelete": {}}, - "isFailed": false, - "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, { - "key": "Orch Status:", - "testId": "orchStatus" - }], - "trackById": "i3dllio31bb", - "parentType": "VNF", - "position": 1, - "errors": {} - }, { - "modelCustomizationId": "55b1be94-671a-403e-a26c-667e9c47d091", - "modelId": "522159d5-d6e0-4c2a-aa44-5a542a12a830", - "modelUniqueId": "55b1be94-671a-403e-a26c-667e9c47d091", - "missingData": false, - "id": 873798901625, - "action": "Create", - "name": "VFModule2", - "modelName": "vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1", - "type": "VFmodule", - "isEcompGeneratedNaming": true, - "dynamicInputs": [], - "dynamicModelName": "vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1djjni", - "typeName": "M", - "menuActions": {"edit": {}, "showAuditInfo": {}, "remove": {}, "delete": {}, "undoDelete": {}}, - "isFailed": false, - "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, { - "key": "Orch Status:", - "testId": "orchStatus" - }], - "trackById": "w7bvw1nh47s", - "parentType": "VNF", - "position": 2, - "errors": {} - }], - "errors": {} - }, { - "modelCustomizationId": "91415b44-753d-494c-926a-456a9172bbb9", - "modelId": "d6557200-ecf2-4641-8094-5393ae3aae60", - "modelUniqueId": "91415b44-753d-494c-926a-456a9172bbb9", - "missingData": false, - "id": "dywch8hkomi", - "action": "Create", - "inMaint": false, - "name": "yoav2", - "modelName": "VF_vGeraldine 0", - "type": "VF", - "isEcompGeneratedNaming": true, - "networkStoreKey": "VF_vGeraldine 0", - "vnfStoreKey": "VF_vGeraldine 0", - "typeName": "VNF", - "menuActions": {"edit": {}, "showAuditInfo": {}, "duplicate": {}, "remove": {}, "delete": {}, "undoDelete": {}}, - "isFailed": false, - "statusProperties": [{"key": "Prov Status:", "testId": "provStatus"}, { - "key": "Orch Status:", - "testId": "orchStatus" - }], - "trackById": "fjczf1urdqo", - "parentType": "", - "position": 1, - "children": [], - "errors": {} - }]; let from = { + id: "04686zg11ur2", + index: 0, data: { - type: 'VF', - index: 1 + instanceName: 'puwesovabe', + }, + parent: { + data: { + type: 'VF', + index: 0, + trackById: 'ckfqe3sb3y8', + vnfStoreKey: '2017-488_PASQUALE-vPE 0', + } } }; let to = { parent: { + id: "4637423092446", + index: 1, data: { - type: 'VF', - index: 0 + instanceName: 'bnmgtrx', + }, + parent: { + data: { + type: 'VF', + trackById: 'ckfqe3sb3y8', + vnfStoreKey: '2017-488_PASQUALE-vPE 0', + } } } }; - jest.spyOn(service, 'array_move'); - service.drag(store, "serviceInstanceId", nodes, {from, to}); + jest.spyOn(service, 'array_move'); + service.drop(store, "serviceInstanceId", nodes, {from, to}); expect(service.array_move).toHaveBeenCalled(); }); + test('drag shouldnt execute array_move when the nodes parent are different', () => { + + let from = { + id: 1150884479608, + index: 0, + data: { + instanceName: '2017-488_PASQUALE-vPE', + }, + parent: {} + }; + + let to = { + parent: { + id: 4637423092446, + index: 1, + data: { + instanceName: 'bnmgtrx', + }, + parent: { + data: { + type: 'VF', + trackById: '1111', + vnfStoreKey: '2017-488_PASQUALE-vPE 0', + } + } + } + }; + + + jest.spyOn(service, 'array_move'); + + service.drop(store, "serviceInstanceId", nodes, {from, to}); + + jest.clearAllMocks(); + + expect(service.array_move).not.toHaveBeenCalled(); + + }); + + test('drop should change nodes index and position', () => { + + let arr: Array<any> = service.array_move(nodes[0].children, 0, 1, "serviceInstanceId", '') + + expect(arr[0]).toMatchObject({instanceName: "bnmgtrx", position: 1}); + expect(arr[1]).toMatchObject({instanceName: "puwesovabe", position: 2}); + + }); }); diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts index 15da89ad3..96e50178b 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts @@ -8,11 +8,29 @@ import * as _ from 'lodash'; @Injectable() export class DragAndDropService { - constructor(private store: NgRedux<AppState>){} + constructor(private store: NgRedux<AppState>) { + } - isAllow(): boolean { + isFlagOn(): boolean { return FeatureFlagsService.getFlagState(Features.FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE, this.store); } + + + /*********************************************************************************************** + if the falg is ON and nodes have same parent + ***********************************************************************************************/ + isAllowDrop(from: any, to: any): boolean { + return this.isFlagOn() && this.isSameParent(from, to); + } + + private isSameParent(from: any, to: any): boolean { + try { + return from.parent.data.trackById === to.parent.parent.data.trackById; + } catch (e) { //parent not found + return false; + } + } + /******************************************************************** * manage drawing-board drag and drop operation * @param nodes - array with elements data. @@ -22,57 +40,67 @@ export class DragAndDropService { * @param to - element to information ************************************************************/ - drag(store, instanceId : string , nodes, {from, to}) :void{ - if (!store.getState().global.flags["FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE"]) return; + drop(store, instanceId: string, nodes, {from, to}): void { + + if (!this.isFlagOn()) return; - let firstLevelNames : DragAndDropModel[] = [ + if (this.isAllowDrop(from, to)) { + let vfModules = nodes.find((parent) => { + return parent.trackById === to.parent.parent.data.trackById; + }).children; + this.array_move(vfModules, from.index, to.parent.index, instanceId, to.parent.parent.data.vnfStoreKey); + } + + /* let firstLevelNames : DragAndDropModel[] = [ new DragAndDropModel('VF',true), new DragAndDropModel('VL',true), new DragAndDropModel('VFmodule',false) - ]; - - const fromObject = _.find(firstLevelNames, ['type', from.data.type]); - const toObject = _.find(firstLevelNames, ['type', to.parent.data.type]); - - /*********************************************************************************************** - if the type are the same and there in same level + same parent -> then change element position - ***********************************************************************************************/ - if(fromObject.isFirstLevel === toObject.isFirstLevel){ // moving element in the same level and in the first level - if(fromObject.isFirstLevel){ - this.array_move(nodes, from.index , to.parent.index, instanceId); - } else if(fromObject.isFirstLevel === toObject.isFirstLevel){ - /* check if they have the same parent */ - if(from.parent.data.trackById === to.parent.parent.data.trackById){ - let vfModules = nodes.find((parents)=> { - return parents.trackById === to.parent.parent.data.trackById; - }).children; - this.array_move(vfModules, from.index , to.parent.index, instanceId, to.parent.parent.data.vnfStoreKey); + ]; + + const fromObject = _.find(firstLevelNames, ['type', from.data.type]); + const toObject = _.find(firstLevelNames, ['type', to.parent.data.type]); + + /!*********************************************************************************************** + if the type are the same and there in same level + same parent -> then change element position + ***********************************************************************************************!/ + if(fromObject.isFirstLevel === toObject.isFirstLevel){ // moving element in the same level and in the first level + if(fromObject.isFirstLevel){ + this.array_move(nodes, from.index , to.parent.index, instanceId); + } else if(fromObject.isFirstLevel === toObject.isFirstLevel){ + /!* check if they have the same parent *!/ + if(from.parent.data.trackById === to.parent.parent.data.trackById){ + let vfModules = nodes.find((parents)=> { + return parents.trackById === to.parent.parent.data.trackById; + }).children; + this.array_move(vfModules, from.index , to.parent.index, instanceId, to.parent.parent.data.vnfStoreKey); + } } - } - } + }*/ } - /******************************************************************** + /******************************************************************** * move element inside array with elements position * @param arr - array with elements data. * @param originalPosition - element original position * @param destPosition - element dest position * @param destPinstanceIdosition - instance id ******************************************************************/ - array_move(arr, originalPosition, destPosition, instanceId : string, parentStoreKey?) { - if (destPosition >= arr.length) { - let k = destPosition - arr.length + 1; - while (k--) { - arr.push(undefined); - } - } - arr.splice(destPosition, 0, arr.splice(originalPosition, 1)[0]); + array_move(arr, originalPosition, destPosition, instanceId: string, parentStoreKey?): Array<any> { + + let moved_node = arr[originalPosition] + + arr.splice(originalPosition, 1); + + arr.splice(destPosition, 0, moved_node); + arr.forEach((item, index) => { - if(item.position !== index){ - item.position = index; + if (item.position !== index + 1) { + item.position = index + 1; item.updatePoistionFunction(this, item, instanceId, parentStoreKey); } }); + + return arr; }; } diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts index 0e2d8e276..f3542573d 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts @@ -127,11 +127,11 @@ export class DrawingBoardTreeComponent implements OnInit, AfterViewInit { nodes = []; serviceModelId: string; options = { - allowDrag: this._dragAndDropService.isAllow(), + allowDrag: this._dragAndDropService.isFlagOn(), actionMapping: { mouse: { drop: (tree:TreeModel, node:TreeNode, $event:any, {from, to}) => { - this._dragAndDropService.drag(this.store, this.serviceModelId, this.nodes, {from, to}); + this._dragAndDropService.drop(this.store, this.serviceModelId, this.nodes, {from, to}); } } }, diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts index 452666f91..78e2b629e 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board.modes.ts @@ -4,5 +4,6 @@ export enum DrawingBoardModes { VIEW = 'VIEW', EDIT = 'EDIT', OLD_VIEW_EDIT = 'OLD_VIEW_EDIT', - CREATE = 'CREATE' + CREATE = 'CREATE', + RECREATE = 'RECREATE' } diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts index 3483885b5..50bfa936e 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts @@ -3,9 +3,10 @@ import {LogService} from '../../../shared/utils/log/log.service'; import {NgRedux} from '@angular-redux/store'; import {ITreeNode} from "angular-tree-component/dist/defs/api"; import {SdcUiServices} from "onap-ui-angular"; -import {IModalConfig} from "onap-ui-angular/dist/components/common"; +import {IModalConfig} from 'onap-ui-angular/dist/components/common'; import {AppState} from "../../../shared/store/reducers"; import {getTestBed, TestBed} from "@angular/core/testing"; +import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service"; class MockAppStore<T> { getState(){ @@ -52,15 +53,23 @@ class MockAppStore<T> { class MockModalService<T> {} +class MockFeatureFlagsService extends FeatureFlagsService{ + getAllFlags(): { [p: string]: boolean } { + return {}; + } +} + describe('Drawing board tree service', () => { let injector; let service: DuplicateService; let store : NgRedux<AppState>; + let featureFlagsService : FeatureFlagsService; beforeAll(done => (async () => { TestBed.configureTestingModule({ providers : [ DuplicateService, LogService, + {provide: FeatureFlagsService, useClass: MockFeatureFlagsService}, {provide: NgRedux, useClass: MockAppStore}, {provide: SdcUiServices.ModalService, useClass: MockModalService} ] @@ -70,6 +79,7 @@ describe('Drawing board tree service', () => { injector = getTestBed(); service = injector.get(DuplicateService); store = injector.get(NgRedux); + featureFlagsService = injector.get(FeatureFlagsService); })().then(done).catch(done.fail)); @@ -418,6 +428,11 @@ describe('Drawing board tree service', () => { } } + }, + global : { + flags : { + + } } } } diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts index 5fb5f0b15..847790de9 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts @@ -11,15 +11,18 @@ import {TypeNodeInformation} from "../typeNodeInformation.model"; import {SdcUiCommon, SdcUiServices} from "onap-ui-angular"; import {changeInstanceCounter, duplicateBulkInstances} from "../../../shared/storeUtil/utils/general/general.actions"; import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config"; +import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service"; +import {Utils} from "../../../shared/utils/utils"; @Injectable() export class DuplicateService { - constructor(private _logService : LogService, private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) { + constructor(private _logService: LogService, private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) { this.modalService = modalService; } - numberOfDuplicates:number; + numberOfDuplicates: number; + setNumberOfDuplicates(numberOfDuplicates: number) { this.numberOfDuplicates = numberOfDuplicates; } @@ -30,10 +33,9 @@ export class DuplicateService { storeKey: string = null; padding = '0000'; modalService: SdcUiServices.ModalService; - store : NgRedux<AppState>; - existingNames : {[key: string] : any}; - currentNode : ITreeNode = null; - + store: NgRedux<AppState>; + existingNames: { [key: string]: any }; + currentNode: ITreeNode = null; canDuplicate(node: ITreeNode): boolean { @@ -41,25 +43,31 @@ export class DuplicateService { return node.data.type === 'VF' || node.data.type === 'VL'; } - isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId : string): boolean { - if(!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])){ - if(this.hasMissingData(node)) return false; - const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node); - const max : number = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties['max_instances'] || 1; + isEnabled(node: ITreeNode, store: NgRedux<AppState>, serviceId: string): boolean { + if (!_.isNil(node) && !_.isNil(node.data.menuActions['duplicate'])) { + if (this.hasMissingData(node)) return false; + const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node); + const flags = FeatureFlagsService.getAllFlags(store); + const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][node.data.modelUniqueId]; + const maxInstances = Utils.getMaxFirstLevel(store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][node.data.modelName].properties, flags); + if (_.isNil(maxInstances)) { + return true; + } else { + return maxInstances - currentExisting > 0; + } - return max - currentExisting > 0; - }else { + } else { return false; } } - hasMissingData(node : ITreeNode): boolean { - if(!_.isNil(node)){ - if(node.data.missingData) return true; - if(!_.isNil(node.data.children)){ - for(let child of node.data.children) { - if(child.missingData){ + hasMissingData(node: ITreeNode): boolean { + if (!_.isNil(node)) { + if (node.data.missingData) return true; + if (!_.isNil(node.data.children)) { + for (let child of node.data.children) { + if (child.missingData) { return true; } } @@ -69,16 +77,22 @@ export class DuplicateService { return false; } - getRemainsInstance(modelId : string, modelName : string, serviceId : string, store: NgRedux<AppState>, node : ITreeNode) : number { - const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node); - const properties = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties; - const currentExisting : number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId]; - return (!_.isNil(properties) && !_.isNil(properties['max_instances'])) ? properties['max_instances'] - currentExisting : null; + getRemainsInstance(modelId: string, modelName: string, serviceId: string, store: NgRedux<AppState>, node: ITreeNode): number { + const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node); + const properties = store.getState().service.serviceHierarchy[serviceId][typeNodeInformation.hierarchyName][modelName].properties; + const currentExisting: number = store.getState().service.serviceInstance[serviceId][typeNodeInformation.existingMappingCounterName][modelId]; + + const flags = FeatureFlagsService.getAllFlags(store); + const maxInstances = Utils.getMaxFirstLevel(properties, flags); + if (_.isNil(maxInstances)) { + return 10; + } else { + return maxInstances - currentExisting; + } } - - openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey : string, numberOfDuplicate: number, _store : NgRedux<AppState>, node: ITreeNode): IModalConfig { + openDuplicateModal(currentServiceId: string, currentUuid: string, currentId: string, storeKey: string, numberOfDuplicate: number, _store: NgRedux<AppState>, node: ITreeNode): IModalConfig { this.currentInstanceId = currentId; this.currentServiceId = currentServiceId; this.maxNumberOfDuplicate = this.getRemainsInstance(currentUuid, currentId, currentServiceId, _store, node); @@ -87,7 +101,7 @@ export class DuplicateService { this.currentNode = node; - return { + return { size: SdcUiCommon.ModalSize.medium, title: 'Duplicate Node', type: SdcUiCommon.ModalType.custom, @@ -98,12 +112,12 @@ export class DuplicateService { }; } - duplicate(node : ITreeNode): void { - const typeNodeInformation : TypeNodeInformation = new TypeNodeInformation(node); + duplicate(node: ITreeNode): void { + const typeNodeInformation: TypeNodeInformation = new TypeNodeInformation(node); this.existingNames = this.store.getState().service.serviceInstance[this.currentServiceId].existingNames; - const toClone = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey]; + const toClone = this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName][this.storeKey]; let newObjects = {}; - for(let i = 0; i < this.numberOfDuplicates; i++) { + for (let i = 0; i < this.numberOfDuplicates; i++) { const uniqueStoreKey = this.generateUniqueStoreKey(this.currentServiceId, this.currentInstanceId, this.store.getState().service.serviceInstance[this.currentServiceId][typeNodeInformation.hierarchyName], newObjects); const clone = this.cloneVnf(toClone, this.currentInstanceId); newObjects[uniqueStoreKey] = clone; @@ -114,12 +128,12 @@ export class DuplicateService { } - cloneVnf(vnf : VnfInstance, originalName: string): VnfInstance { - let newUniqueVnf : VnfInstance = _.cloneDeep(vnf); + cloneVnf(vnf: VnfInstance, originalName: string): VnfInstance { + let newUniqueVnf: VnfInstance = _.cloneDeep(vnf); newUniqueVnf.originalName = originalName; newUniqueVnf.trackById = DefaultDataGeneratorService.createRandomTrackById(); - if (!_.isNil(vnf.instanceName)){ + if (!_.isNil(vnf.instanceName)) { newUniqueVnf.instanceName = this.ensureUniqueNameOrGenerateOne(vnf.instanceName); } @@ -127,10 +141,10 @@ export class DuplicateService { const vfModuleModel: VfModuleMap = vnf.vfModules[vf_module_model_name]; for (let vfModule in vfModuleModel) { newUniqueVnf.vfModules[vf_module_model_name][vfModule].trackById = DefaultDataGeneratorService.createRandomTrackById(); - if (!_.isNil(vfModuleModel[vfModule].instanceName)){ + if (!_.isNil(vfModuleModel[vfModule].instanceName)) { newUniqueVnf.vfModules[vf_module_model_name][vfModule].instanceName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].instanceName); } - if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)){ + if (!_.isNil(vfModuleModel[vfModule].volumeGroupName)) { newUniqueVnf.vfModules[vf_module_model_name][vfModule].volumeGroupName = this.ensureUniqueNameOrGenerateOne(vfModuleModel[vfModule].volumeGroupName); } } @@ -138,7 +152,7 @@ export class DuplicateService { return newUniqueVnf; } - ensureUniqueNameOrGenerateOne(instanceName){ + ensureUniqueNameOrGenerateOne(instanceName) { let uniqueInstanceName = instanceName; if (this.isAlreadyExists(instanceName, this.existingNames)) { uniqueInstanceName = this.generateNextUniqueName(instanceName, this.existingNames); @@ -148,33 +162,33 @@ export class DuplicateService { } - isAlreadyExists(name : string, existingNames : {[key: string] : any}){ + isAlreadyExists(name: string, existingNames: { [key: string]: any }) { return _.has(existingNames, name.toLowerCase()); } - generateNextUniqueName(name : string, existingNames : {[key: string] : any}) :string{ + generateNextUniqueName(name: string, existingNames: { [key: string]: any }): string { let suffix = "000"; let counter = 1; - if (name.match(/^.*_[\d]{3}$/)){ + if (name.match(/^.*_[\d]{3}$/)) { name = name.substring(0, name.length - 4); } - while(true){ - let paddingNumber : string = this.getNumberAsPaddingString(counter, suffix); + while (true) { + let paddingNumber: string = this.getNumberAsPaddingString(counter, suffix); let candidateUniqueName = name + '_' + paddingNumber; - if(!this.isAlreadyExists(candidateUniqueName, existingNames)){ + if (!this.isAlreadyExists(candidateUniqueName, existingNames)) { return candidateUniqueName; } counter++; } } - generateUniqueStoreKey(serviceId : string, objectName : string, existing : any, newObjects: any) : string { + generateUniqueStoreKey(serviceId: string, objectName: string, existing: any, newObjects: any): string { let counter = 1; - while(true){ - let paddingNumber : string = this.getNumberAsPaddingString(counter, this.padding); + while (true) { + let paddingNumber: string = this.getNumberAsPaddingString(counter, this.padding); const name = objectName + ':' + paddingNumber; - if(_.isNil(existing[name]) && _.isNil(newObjects[name])){ + if (_.isNil(existing[name]) && _.isNil(newObjects[name])) { return name; } counter++; diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts index 10c13661f..089f812a7 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts @@ -12,6 +12,7 @@ import {DrawingBoardModes} from "../../../drawing-board.modes"; import {IframeService} from "../../../../../shared/utils/iframe.service"; import {DuplicateService} from "../../../duplicate/duplicate.service"; import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component"; +import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service"; class MockAppStore<T> { getState() { @@ -19,27 +20,27 @@ class MockAppStore<T> { global: { 'drawingBoardStatus': DrawingBoardModes.CREATE }, - service : { - serviceHierarchy : { - 'servicedId' : { - 'networks' : { - 'networkName' : { - 'properties' : { - 'max_instances' : 1 + service: { + serviceHierarchy: { + 'servicedId': { + 'networks': { + 'networkName': { + 'properties': { + 'max_instances': 1 } } } } }, - serviceInstance : { - 'servicedId' : { - 'existingNetworksCounterMap' : { - 'networkId' : 1 + serviceInstance: { + 'servicedId': { + 'existingNetworksCounterMap': { + 'networkId': 1 }, - 'networks' : { - 'networkName' :{ + 'networks': { + 'networkName': { 'action': 'Create', - 'originalName' : 'networkName' + 'originalName': 'networkName' } } } @@ -48,15 +49,24 @@ class MockAppStore<T> { } } } + +class MockFeatureFlagsService extends FeatureFlagsService { + getAllFlags(): { [p: string]: boolean } { + return {}; + } +} + + describe('Network Model Info', () => { let injector; - let _dynamicInputsService : DynamicInputsService; - let _sharedTreeService : SharedTreeService; + let _dynamicInputsService: DynamicInputsService; + let _sharedTreeService: SharedTreeService; let networkModel: NetworkModelInfo; - let _dialogService : DialogService; - let _networkPopupService : NetworkPopupService; - let _duplicateService : DuplicateService; - let _iframeService : IframeService; + let _dialogService: DialogService; + let _networkPopupService: NetworkPopupService; + let _duplicateService: DuplicateService; + let _iframeService: IframeService; + let _featureFlagsService: FeatureFlagsService; beforeAll(done => (async () => { TestBed.configureTestingModule({ @@ -69,13 +79,16 @@ describe('Network Model Info', () => { IframeService, DuplicateService, {provide: NgRedux, useClass: MockAppStore}, + {provide: FeatureFlagsService, useClass: MockFeatureFlagsService}, MockNgRedux] }); await TestBed.compileComponents(); injector = getTestBed(); _sharedTreeService = injector.get(SharedTreeService); - networkModel = new NetworkModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _networkPopupService, _duplicateService, null, _iframeService, MockNgRedux.getInstance()); + _featureFlagsService = injector.get(FeatureFlagsService); + + networkModel = new NetworkModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _networkPopupService, _duplicateService, null, _iframeService, _featureFlagsService, MockNgRedux.getInstance()); })().then(done).catch(done.fail)); test('NetworkModelInfo should be defined', () => { @@ -137,39 +150,37 @@ describe('Network Model Info', () => { expect(model.type).toEqual('VL'); }); - test('showNodeIcons should return false if reachLimit of max', ()=>{ - let serviceId : string = 'servicedId'; + test('showNodeIcons should return false if reachLimit of max', () => { + let serviceId: string = 'servicedId'; let node = { - data : { - id : 'networkId', - name : 'networkName', - modelCustomizationId : 'modelCustomizationId' + data: { + id: 'networkId', + name: 'networkName', + modelCustomizationId: 'modelCustomizationId' } }; jest.spyOn(_sharedTreeService, 'getExistingInstancesWithDeleteMode').mockReturnValue(0); jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({ - global : {}, - service : { - serviceHierarchy : { - 'servicedId' : { - 'networks' : { - 'networkName' : { - 'properties' : { - 'max_instances' : 1 + global: {}, + service: { + serviceHierarchy: { + 'servicedId': { + 'networks': { + 'networkName': { + 'properties': { + 'max_instances': 1 } } } } }, - serviceInstance : { - 'servicedId' : { - 'existingNetworksCounterMap' : { - 'modelCustomizationId' : 1 + serviceInstance: { + 'servicedId': { + 'existingNetworksCounterMap': { + 'modelCustomizationId': 1 }, - 'networks' : { - 'networkName' :{ - - } + 'networks': { + 'networkName': {} } } } @@ -177,41 +188,39 @@ describe('Network Model Info', () => { }); let result = networkModel.showNodeIcons(<any>node, serviceId); - expect(result).toEqual(new AvailableNodeIcons(true , false)); + expect(result).toEqual(new AvailableNodeIcons(true, false)); }); - test('showNodeIcons should return true if not reachLimit of max', ()=>{ - let serviceId : string = 'servicedId'; + test('showNodeIcons should return true if not reachLimit of max', () => { + let serviceId: string = 'servicedId'; let node = { - data : { - id : 'networkId', - name : 'networkName' + data: { + id: 'networkId', + name: 'networkName' } }; jest.spyOn(_sharedTreeService, 'getExistingInstancesWithDeleteMode').mockReturnValue(0); jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({ - global : {}, - service : { - serviceHierarchy : { - 'servicedId' : { - 'networks' : { - 'networkName' : { - 'properties' : { - 'max_instances' : 2 + global: {}, + service: { + serviceHierarchy: { + 'servicedId': { + 'networks': { + 'networkName': { + 'properties': { + 'max_instances': 2 } } } } }, - serviceInstance : { - 'servicedId' : { - 'existingNetworksCounterMap' : { - 'networkId' : 1 + serviceInstance: { + 'servicedId': { + 'existingNetworksCounterMap': { + 'networkId': 1 }, - 'networks' : { - 'networkName' :{ - - } + 'networks': { + 'networkName': {} } } } @@ -219,34 +228,34 @@ describe('Network Model Info', () => { }); let result = networkModel.showNodeIcons(<any>node, serviceId); - expect(result).toEqual(new AvailableNodeIcons(true , false)); + expect(result).toEqual(new AvailableNodeIcons(true, false)); }); - test('getNodeCount should return number of nodes', ()=>{ - let serviceId : string = 'servicedId'; + test('getNodeCount should return number of nodes', () => { + let serviceId: string = 'servicedId'; jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({ - global : {}, - service : { - serviceHierarchy : { - 'servicedId' : { - 'networks' : { - 'networkName' : { - 'properties' : { - 'max_instances' : 1 + global: {}, + service: { + serviceHierarchy: { + 'servicedId': { + 'networks': { + 'networkName': { + 'properties': { + 'max_instances': 1 } } } } }, - serviceInstance : { - 'servicedId' : { - 'existingNetworksCounterMap' : { - 'modelCustomizationId' : 1 + serviceInstance: { + 'servicedId': { + 'existingNetworksCounterMap': { + 'modelCustomizationId': 1 }, - 'networks' : { - 'networkName' :{ + 'networks': { + 'networkName': { 'action': 'Create', - 'originalName' : 'networkName' + 'originalName': 'networkName' } } } @@ -255,24 +264,24 @@ describe('Network Model Info', () => { }); let node = { - data : { - id : 'networkId', - name : 'networkName', + data: { + id: 'networkId', + name: 'networkName', action: 'Create', - modelCustomizationId : "modelCustomizationId", + modelCustomizationId: "modelCustomizationId", modelUniqueId: "modelCustomizationId" } }; - let result = networkModel.getNodeCount(<any>node , serviceId); + let result = networkModel.getNodeCount(<any>node, serviceId); expect(result).toEqual(1); node.data.modelCustomizationId = 'networkId_notExist'; node.data.modelUniqueId = 'networkId_notExist'; - result = networkModel.getNodeCount(<any>node , serviceId); + result = networkModel.getNodeCount(<any>node, serviceId); expect(result).toEqual(0); }); - test('getMenuAction: showAuditInfoNetwork', ()=>{ + test('getMenuAction: showAuditInfoNetwork', () => { jest.spyOn(MockNgRedux.getInstance(), 'getState').mockReturnValue({ global: { @@ -281,7 +290,7 @@ describe('Network Model Info', () => { }); jest.spyOn(_sharedTreeService, 'isRetryMode').mockReturnValue(true); let node = { - data : { + data: { "modelId": "6b528779-44a3-4472-bdff-9cd15ec93450", "action": "Create", "isFailed": true, @@ -300,7 +309,7 @@ describe('Network Model Info', () => { test('Info for network should be correct', () => { const model = getNetworkModel(); const instance = getNetworkInstance(); - let actualNetworkInfo = networkModel.getInfo(model,instance); + let actualNetworkInfo = networkModel.getInfo(model, instance); let expectedNetworkInfo = [ ModelInformationItem.createInstance('Network role', "network role 1, network role 2"), ModelInformationItem.createInstance("Route target id", null), @@ -309,26 +318,27 @@ describe('Network Model Info', () => { expect(actualNetworkInfo).toEqual(expectedNetworkInfo); }); - function getNetworkModel(){ + function getNetworkModel() { return { - "customizationUuid":"94fdd893-4a36-4d70-b16a-ec29c54c184f", - "name":"ExtVL", - "version":"37.0", - "description":"ECOMP generic virtual link (network) base type for all other service-level and global networks", - "uuid":"ddc3f20c-08b5-40fd-af72-c6d14636b986", - "invariantUuid":"379f816b-a7aa-422f-be30-17114ff50b7c", - "max":1, - "min":0, - "isEcompGeneratedNaming":false, - "type":"VL", - "modelCustomizationName":"ExtVL 0", - "roles":["network role 1"," network role 2"], - "properties":{ - "network_role":"network role 1, network role 2", + "customizationUuid": "94fdd893-4a36-4d70-b16a-ec29c54c184f", + "name": "ExtVL", + "version": "37.0", + "description": "ECOMP generic virtual link (network) base type for all other service-level and global networks", + "uuid": "ddc3f20c-08b5-40fd-af72-c6d14636b986", + "invariantUuid": "379f816b-a7aa-422f-be30-17114ff50b7c", + "max": 1, + "min": 0, + "isEcompGeneratedNaming": false, + "type": "VL", + "modelCustomizationName": "ExtVL 0", + "roles": ["network role 1", " network role 2"], + "properties": { + "network_role": "network role 1, network role 2", "network_assignments": "{is_external_network=false, ipv4_subnet_default_assignment={min_subnets_count=1}, ecomp_generated_network_assignment=false, ipv6_subnet_default_assignment={min_subnets_count=1}}", - "exVL_naming":"{ecomp_generated_naming=true}","network_flows":"{is_network_policy=false, is_bound_to_vpn=false}", - "network_homing":"{ecomp_selected_instance_node_target=false}" + "exVL_naming": "{ecomp_generated_naming=true}", + "network_flows": "{is_network_policy=false, is_bound_to_vpn=false}", + "network_homing": "{ecomp_selected_instance_node_target=false}" } }; @@ -370,9 +380,7 @@ describe('Network Model Info', () => { } - - - function getServiceHierarchy(){ + function getServiceHierarchy() { return { "service": { "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450", diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts index 3ed40cd5f..3ba4a2c4b 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts @@ -30,6 +30,7 @@ import { import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config"; import {ComponentInfoType} from "../../../component-info/component-info-model"; import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component"; +import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service"; export class NetworkModelInfo implements ILevelNodeInfo { constructor(private _dynamicInputsService: DynamicInputsService, @@ -39,6 +40,7 @@ export class NetworkModelInfo implements ILevelNodeInfo { private _duplicateService: DuplicateService, private modalService: SdcUiServices.ModalService, private _iframeService: IframeService, + private _featureFlagsService: FeatureFlagsService, private _store: NgRedux<AppState>) { } @@ -70,7 +72,7 @@ export class NetworkModelInfo implements ILevelNodeInfo { ************************************************************/ getModel = (networkModelId: string, instance: NetworkInstance, serviceHierarchy): NetworkModel => { const originalModelName = instance.originalName ? instance.originalName : networkModelId; - return new NetworkModel(serviceHierarchy[this.name][originalModelName]); + return new NetworkModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags()); }; @@ -164,8 +166,8 @@ export class NetworkModelInfo implements ILevelNodeInfo { counter -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'networks'); const properties = this._store.getState().service.serviceHierarchy[serviceModelId].networks[node.data.name].properties; - const maxInstances: number = !_.isNil(properties) ? (properties.max_instances || 1) : 1; - const isReachedLimit = !(maxInstances > counter); + const flags = FeatureFlagsService.getAllFlags(this._store); + const isReachedLimit: boolean = this._sharedTreeService.isReachedToMaxInstances(properties, counter, flags); const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !isReachedLimit; return new AvailableNodeIcons(showAddIcon, isReachedLimit) diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts index 840f31dcf..a44c21bf0 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts @@ -13,6 +13,7 @@ import {VnfPopupService} from "../../../../../shared/components/genericFormPopup import {DuplicateService} from "../../../duplicate/duplicate.service"; import {IframeService} from "../../../../../shared/utils/iframe.service"; import {RelatedVnfMemberInfoModel} from "./relatedVnfMember.info.model"; +import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; class MockAppStore<T> { @@ -38,6 +39,7 @@ describe('Related Vnf member Model Info', () => { DynamicInputsService, DialogService, VfModulePopuopService, + VfModuleUpgradePopupService, VnfPopupService, DefaultDataGeneratorService, SharedTreeService, diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts index b596d0b48..276c0aeb2 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts @@ -16,6 +16,9 @@ import {ModelInformationItem} from "../../../../../shared/components/model-infor import {AaiService} from "../../../../../shared/services/aaiService/aai.service"; import {HttpClient, HttpHandler} from "@angular/common/http"; import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service"; +import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; +import {instance, mock, when} from "ts-mockito"; +import each from "jest-each"; class MockAppStore<T> { getState() { @@ -27,6 +30,12 @@ class MockAppStore<T> { } } +class MockFeatureFlagsService extends FeatureFlagsService{ + getAllFlags(): { [p: string]: boolean } { + return {}; + } +} + describe('VFModule Model Info', () => { let injector; let _dynamicInputsService : DynamicInputsService; @@ -34,8 +43,12 @@ describe('VFModule Model Info', () => { let vfModuleModel: VFModuleModelInfo; let _dialogService : DialogService; let _vfModulePopupService : VfModulePopuopService; + let _vfModuleUpgradePopupService : VfModuleUpgradePopupService; let _iframeService : IframeService; let _componentInfoService : ComponentInfoService; + let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService); + let mockFeatureFlagsServiceInstance: FeatureFlagsService = instance(mockFeatureFlagsService); + beforeAll(done => (async () => { TestBed.configureTestingModule({ @@ -44,6 +57,7 @@ describe('VFModule Model Info', () => { DynamicInputsService, DialogService, VfModulePopuopService, + VfModuleUpgradePopupService, SharedTreeService, IframeService, {provide: NgRedux, useClass: MockAppStore}, @@ -51,7 +65,7 @@ describe('VFModule Model Info', () => { AaiService, HttpClient, HttpHandler, - FeatureFlagsService, + {provide: FeatureFlagsService, useValue: mockFeatureFlagsServiceInstance}, ComponentInfoService ] }); @@ -59,8 +73,9 @@ describe('VFModule Model Info', () => { injector = getTestBed(); _sharedTreeService = injector.get(SharedTreeService); - _componentInfoService = injector.get(ComponentInfoService) - vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _iframeService, MockNgRedux.getInstance(),_componentInfoService); + _componentInfoService = injector.get(ComponentInfoService); + vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, + _iframeService, mockFeatureFlagsServiceInstance, MockNgRedux.getInstance(),_componentInfoService); })().then(done).catch(done.fail)); @@ -468,6 +483,33 @@ describe('VFModule Model Info', () => { expect(actualVNFInfo).toEqual(expectedVNFInfo); }); + each([ + ["maxCountInstances 3, currentNodeCount 1, flag on",{maxCountInstances:3}, 1, {FLAG_2002_UNLIMITED_MAX: true}, false], + ["maxCountInstances 3, currentNodeCount 3, flag on",{maxCountInstances:3}, 3, {FLAG_2002_UNLIMITED_MAX: true}, true], + ["no maxCountInstances, currentNodeCount 0, flag off",{}, 0, {FLAG_2002_UNLIMITED_MAX: false}, false], + ["no maxCountInstances, currentNodeCount 1, flag off",{}, 1, {FLAG_2002_UNLIMITED_MAX: false}, true], + ["no maxCountInstances, currentNodeCount 1, no flags",{}, 1, null, true], + ["no maxCountInstances, currentNodeCount 0, flag on",{}, 0, {FLAG_2002_UNLIMITED_MAX: true}, false], + ["no maxCountInstances, currentNodeCount 1, flag on",{}, 1, {FLAG_2002_UNLIMITED_MAX: true}, false], + ["no maxCountInstances, currentNodeCount 1000, flag on",{}, 1000, {FLAG_2002_UNLIMITED_MAX: true}, false], + ]).test('isVFModuleReachedLimit: %s', (desc, properties, currentNodeCount, flags, expected) => { + + const node = { data: { + name : 'vfModuleName' + }}; + + const serviceHierarchy = { + servicedId :{ + vfModules : { + vfModuleName : { + properties + }}}}; + + when(mockFeatureFlagsService.getAllFlags()).thenReturn(flags); + + expect(vfModuleModel.isVFModuleReachedLimit(node, serviceHierarchy, 'servicedId', currentNodeCount)).toEqual(expected); + }); + function getVFModule(){ return { "uuid":"522159d5-d6e0-4c2a-aa44-5a542a12a830", diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts index 47a6dcb50..1ce452793 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts @@ -8,10 +8,7 @@ import {VfModuleInstance} from "../../../../../shared/models/vfModuleInstance"; import {VfModule} from "../../../../../shared/models/vfModule"; import {NgRedux} from "@angular-redux/store"; import {ITreeNode} from "angular-tree-component/dist/defs/api"; -import { - GenericFormPopupComponent, - PopupType -} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component"; +import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component"; import {DialogService} from "ng2-bootstrap-modal"; import {VfModulePopuopService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service"; import {AppState} from "../../../../../shared/store/reducers"; @@ -19,24 +16,22 @@ import {MessageBoxData} from "../../../../../shared/components/messageBox/messag import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service"; import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service"; import {IframeService} from "../../../../../shared/utils/iframe.service"; -import { - deleteActionVfModuleInstance, - removeVfModuleInstance, - undoDeleteVfModuleInstance, - undoUgradeVFModule, - updateVFModulePosition, - upgradeVFModule -} from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions"; +import {deleteActionVfModuleInstance, deleteVFModuleField, removeVfModuleInstance, undoDeleteVfModuleInstance, undoUgradeVFModule, updateVFModulePosition, upgradeVFModule} from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions"; import {ComponentInfoService} from "../../../component-info/component-info.service"; import {ComponentInfoType} from "../../../component-info/component-info-model"; import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component"; +import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; +import {FeatureFlagsService, Features} from "../../../../../shared/services/featureFlag/feature-flags.service"; +import {Utils} from "../../../../../shared/utils/utils"; export class VFModuleModelInfo implements ILevelNodeInfo { constructor(private _dynamicInputsService: DynamicInputsService, private _sharedTreeService: SharedTreeService, private _dialogService: DialogService, private _vfModulePopupService: VfModulePopuopService, + private _vfModuleUpgradePopupService: VfModuleUpgradePopupService, private _iframeService: IframeService, + private _featureFlagsService: FeatureFlagsService, private _store: NgRedux<AppState>, private _componentInfoService: ComponentInfoService) { } @@ -93,7 +88,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo { newVfModule.typeName = this.typeName; newVfModule.menuActions = this.getMenuAction(<any>newVfModule, currentModel.uuid); newVfModule.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed; - newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage: ""; + newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : ""; newVfModule = this._sharedTreeService.addingStatusProperty(newVfModule); return newVfModule; @@ -247,7 +242,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo { if (!_.isNil(this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF]) && node.parent.data.name === this._store.getState().service.serviceInstance[serviceModelId].vnfs[selectedVNF].originalName) { const existingVFModules = this.getCountVFModuleOfSelectedVNF(node, selectedVNF, serviceModelId); const reachedLimit = this.isVFModuleReachedLimit(node, this._store.getState().service.serviceHierarchy, serviceModelId, existingVFModules); - const showAddIcon = this._sharedTreeService.shouldShowAddIcon()&& !reachedLimit; + const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !reachedLimit; return new AvailableNodeIcons(showAddIcon, reachedLimit); } return new AvailableNodeIcons(false, false); @@ -297,13 +292,16 @@ export class VFModuleModelInfo implements ILevelNodeInfo { } isVFModuleReachedLimit(node: any, serviceHierarchy: any, serviceModelId: string, currentNodeCount: number): boolean { - let maxNodes: number = 1; + const flags = this._featureFlagsService.getAllFlags(); let vnfModules = serviceHierarchy[serviceModelId].vfModules; - if (vnfModules[node.data.name]) { - maxNodes = vnfModules[node.data.name].properties.maxCountInstances || 1; + const maxInstances = vnfModules[node.data.name] + ? Utils.getMaxVfModule(vnfModules[node.data.name].properties, flags) + : null; + if (_.isNil(maxInstances)) { + return false; } - return !(maxNodes > currentNodeCount); + return !(maxInstances > currentNodeCount); } getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } { @@ -351,15 +349,15 @@ export class VFModuleModelInfo implements ILevelNodeInfo { }, undoDelete: { method: (node, serviceModelId) => { - this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId)) + this._store.dispatch(undoDeleteVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId)); + this._store.dispatch(deleteVFModuleField(node.data.modelName, node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments')); }, visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node), enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId) }, - upgrade : { - method : (node, serviceModelId) => { - this._sharedTreeService.upgradeBottomUp(node, serviceModelId); - this._store.dispatch(upgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName)); + upgrade: { + method: (node, serviceModelId) => { + this.upgradeVFM(serviceModelId, node); }, visible: (node,serviceModelId) => { return this._sharedTreeService.shouldShowUpgrade(node, serviceModelId); @@ -371,7 +369,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo { undoUpgrade: { method: (node, serviceModelId) => { this._sharedTreeService.undoUpgradeBottomUp(node, serviceModelId); - this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName)); + this._store.dispatch(undoUgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId, node.data.dynamicModelName)); }, visible: (node) => { return this._sharedTreeService.shouldShowUndoUpgrade(node); @@ -383,7 +381,31 @@ export class VFModuleModelInfo implements ILevelNodeInfo { }; } - updatePosition(that , node, instanceId, parentStoreKey): void { + private upgradeVFM(serviceModelId, node) { + if (FeatureFlagsService.getFlagState(Features.FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, this._store)) { + this._iframeService.addClassOpenModal('content'); + this._dialogService.addDialog(GenericFormPopupComponent, { + type: PopupType.VF_MODULE_UPGRADE, + uuidData: <any>{ + serviceId: serviceModelId, + modelName: node.data.modelName, + vFModuleStoreKey: node.data.dynamicModelName, + vnfStoreKey: node.parent.data.vnfStoreKey, + modelId: node.data.modelId, + type: node.data.type, + popupService: this._vfModuleUpgradePopupService, + vfModule : _.cloneDeep(node) + }, + node, + isUpdateMode: false + }); + }else { + this._sharedTreeService.upgradeBottomUp(node, serviceModelId); + this._store.dispatch(upgradeVFModule(node.data.modelName, node.parent.data.vnfStoreKey, serviceModelId ,node.data.dynamicModelName)); + } + } + + updatePosition(that, node, instanceId, parentStoreKey): void { that.store.dispatch(updateVFModulePosition(node, instanceId, parentStoreKey)); } @@ -395,12 +417,12 @@ export class VFModuleModelInfo implements ILevelNodeInfo { getInfo(model, instance): ModelInformationItem[] { const modelInformation = !_.isEmpty(model) && !_.isEmpty(model.properties) ? [ ModelInformationItem.createInstance("Base module", model.properties.baseModule), - ModelInformationItem.createInstance("Min instances", !_.isNull(model.properties.minCountInstances)? String(model.properties.minCountInstances): null), - ModelInformationItem.createInstance("Max instances", !_.isNull(model.properties.maxCountInstances)? String(model.properties.maxCountInstances): null), - ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.properties.initialCount)? String(model.properties.initialCount): null) + ModelInformationItem.createInstance("Min instances", !_.isNull(model.properties.minCountInstances) ? String(model.properties.minCountInstances) : null), + ModelInformationItem.createInstance("Max instances", !_.isNull(model.properties.maxCountInstances) ? String(model.properties.maxCountInstances) : null), + ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.properties.initialCount) ? String(model.properties.initialCount) : null) ] : []; - const instanceInfo = []; + const instanceInfo = []; const result = [modelInformation, instanceInfo]; return _.uniq(_.flatten(result)); } diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts index de8962787..3ac6076dc 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts @@ -22,6 +22,13 @@ import {ComponentInfoService} from "../../../component-info/component-info.servi import {AaiService} from "../../../../../shared/services/aaiService/aai.service"; import {HttpClient, HttpHandler} from "@angular/common/http"; import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service"; +import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; + +class MockFeatureFlagsService extends FeatureFlagsService{ + getAllFlags(): { [p: string]: boolean } { + return {}; + } +} describe('Vnf Model Info', () => { let injector; @@ -32,10 +39,12 @@ describe('Vnf Model Info', () => { let _defaultDataGeneratorService : DefaultDataGeneratorService; let _dialogService : DialogService; let _vfModulePopupService : VfModulePopuopService; + let _vfModuleUpgradePopupService : VfModuleUpgradePopupService; let _vnfPopupService : VnfPopupService; let _duplicateService : DuplicateService; let _iframeService : IframeService; let _componentInfoService : ComponentInfoService; + let _featureFlagsService : FeatureFlagsService; let _store : NgRedux<AppState>; let vnfModel: VnfModelInfo; @@ -47,6 +56,7 @@ describe('Vnf Model Info', () => { DynamicInputsService, DialogService, VfModulePopuopService, + VfModuleUpgradePopupService, VnfPopupService, DefaultDataGeneratorService, SharedTreeService, @@ -54,7 +64,7 @@ describe('Vnf Model Info', () => { AaiService, HttpClient, HttpHandler, - FeatureFlagsService, + {provide: FeatureFlagsService, useClass: MockFeatureFlagsService}, ComponentInfoService, IframeService] }).compileComponents(); @@ -62,7 +72,7 @@ describe('Vnf Model Info', () => { injector = getTestBed(); _sharedTreeService = injector.get(SharedTreeService); _store = injector.get(NgRedux); - _componentInfoService = injector.get(ComponentInfoService); + _featureFlagsService = injector.get(FeatureFlagsService); vnfModel = new VnfModelInfo( _dynamicInputsService, @@ -71,10 +81,12 @@ describe('Vnf Model Info', () => { _dialogService, _vnfPopupService, _vfModulePopupService, + _vfModuleUpgradePopupService, _duplicateService, null, _iframeService, _componentInfoService, + _featureFlagsService, _store); @@ -456,6 +468,12 @@ describe('Vnf Model Info', () => { expect(actualVNFInfo).toEqual(expectedVNFInfo); }); + test('When there is no max Max instances text is: Unlimited (default)', () => { + let actualVNFInfo = vnfModel.getInfo({just:"not empty"},null); + const maxInstancesItem = actualVNFInfo.find((item)=> item.label == 'Max instances'); + expect(maxInstancesItem.values[0]).toEqual('Unlimited (default)'); + }); + function getVNFModel(){ return { "name":"VF_vGeraldine", diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts index ebcba162e..ff86925f1 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts @@ -9,10 +9,7 @@ import {SharedTreeService} from "../../shared.tree.service"; import {NgRedux} from "@angular-redux/store"; import {AppState} from "../../../../../shared/store/reducers"; import {DefaultDataGeneratorService} from "../../../../../shared/services/defaultDataServiceGenerator/default.data.generator.service"; -import { - GenericFormPopupComponent, - PopupType -} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component"; +import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component"; import {DialogService} from 'ng2-bootstrap-modal'; import {VnfPopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service"; import {VfModulePopuopService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service"; @@ -26,18 +23,15 @@ import {changeInstanceCounter, removeInstance} from "../../../../../shared/store import {MessageBoxData} from "../../../../../shared/components/messageBox/messageBox.data"; import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service"; import {ServiceInstanceActions} from "../../../../../shared/models/serviceInstanceActions"; -import { - deleteActionVnfInstance, - undoDeleteActionVnfInstance, - undoUpgradeVnf, - updateVnfPosition, - upgradeVnf -} from "../../../../../shared/storeUtil/utils/vnf/vnf.actions"; +import {deleteActionVnfInstance, undoDeleteActionVnfInstance, undoUpgradeVnf, updateVnfPosition, upgradeVnf} from "../../../../../shared/storeUtil/utils/vnf/vnf.actions"; import * as _ from 'lodash'; import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config"; import {ComponentInfoType} from "../../../component-info/component-info-model"; import {ComponentInfoService} from "../../../component-info/component-info.service"; import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component"; +import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; +import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service"; +import {Constants} from "../../../../../shared/utils/constants"; export class VnfModelInfo implements ILevelNodeInfo { constructor(private _dynamicInputsService: DynamicInputsService, @@ -46,10 +40,12 @@ export class VnfModelInfo implements ILevelNodeInfo { private _dialogService: DialogService, private _vnfPopupService: VnfPopupService, private _vfModulePopupService: VfModulePopuopService, + private _vfModuleUpgradePopupService: VfModuleUpgradePopupService, private _duplicateService: DuplicateService, private modalService: SdcUiServices.ModalService, private _iframeService: IframeService, private _componentInfoService: ComponentInfoService, + private _featureFlagsService: FeatureFlagsService, private _store: NgRedux<AppState>) { } @@ -85,7 +81,7 @@ export class VnfModelInfo implements ILevelNodeInfo { ************************************************************/ getModel = (vnfModelId: string, instance: VnfInstance, serviceHierarchy): VNFModel => { const originalModelName = instance.originalName ? instance.originalName : vnfModelId; - return new VNFModel(serviceHierarchy[this.name][originalModelName]); + return new VNFModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags()); }; @@ -102,7 +98,7 @@ export class VnfModelInfo implements ILevelNodeInfo { node.typeName = this.typeName; node.menuActions = this.getMenuAction(<any>node, model.uuid); node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed; - node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage: ""; + node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : ""; node = this._sharedTreeService.addingStatusProperty(node); return node; }; @@ -111,7 +107,7 @@ export class VnfModelInfo implements ILevelNodeInfo { * return next level object (VFModule) ************************************************************/ getNextLevelObject = (): VFModuleModelInfo => { - return new VFModuleModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vfModulePopupService, this._iframeService, this._store, this._componentInfoService); + return new VFModuleModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vfModulePopupService, this._vfModuleUpgradePopupService, this._iframeService, this._featureFlagsService, this._store, this._componentInfoService); }; /*********************************************************** @@ -179,8 +175,8 @@ export class VnfModelInfo implements ILevelNodeInfo { counter -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'vnfs'); const properties = this._store.getState().service.serviceHierarchy[serviceModelId].vnfs[node.data.name].properties; - const maxInstances: number = !_.isNil(properties) ? (properties.max_instances || 1) : 1; - const isReachedLimit = !(maxInstances > counter); + const flags = FeatureFlagsService.getAllFlags(this._store); + const isReachedLimit: boolean = this._sharedTreeService.isReachedToMaxInstances(properties, counter, flags); const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !isReachedLimit; return new AvailableNodeIcons(showAddIcon, isReachedLimit) } @@ -209,9 +205,9 @@ export class VnfModelInfo implements ILevelNodeInfo { }, showAuditInfo: { method: (node, serviceModelId) => { - const instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.data.vnfStoreKey]; - this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VNF', this); - }, + const instance = this._store.getState().service.serviceInstance[serviceModelId].vnfs[node.data.vnfStoreKey]; + this._sharedTreeService.openAuditInfoModal(node, serviceModelId, instance, 'VNF', this); + }, visible: (node) => this._sharedTreeService.shouldShowAuditInfo(node), enable: (node) => this._sharedTreeService.shouldShowAuditInfo(node) }, @@ -322,8 +318,9 @@ export class VnfModelInfo implements ILevelNodeInfo { getInfo(model, instance): ModelInformationItem[] { const modelInformation = !_.isEmpty(model) ? [ - ModelInformationItem.createInstance("Min instances", !_.isNull(model.min)? String(model.min): null), - ModelInformationItem.createInstance("Max instances", !_.isNull(model.max)? String(model.max): null) + ModelInformationItem.createInstance("Min instances", !_.isNil(model.min) ? String(model.min) : null), + ModelInformationItem.createInstance("Max instances", !_.isNil(model.max) ? String(model.max) : + Constants.ModelInfo.UNLIMITED_DEFAULT) ] : []; const instanceInfo = !_.isEmpty(instance) ? [ diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts index 4c779a313..3dbc60adb 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts @@ -26,12 +26,14 @@ import { undoDeleteActionVrfInstance } from "../../../../../shared/storeUtil/utils/vrf/vrf.actions"; import * as _ from "lodash"; +import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service"; export class VrfModelInfo implements ILevelNodeInfo { constructor(private _store: NgRedux<AppState>, private _sharedTreeService: SharedTreeService, private _dialogService: DialogService, private _iframeService: IframeService, + private _featureFlagsService : FeatureFlagsService, private _networkStepService: NetworkStepService, private _vpnStepService: VpnStepService) { } @@ -70,7 +72,7 @@ export class VrfModelInfo implements ILevelNodeInfo { return new VpnModelInfo(this._store, this._sharedTreeService); } else { if (nextLevelType === 'networks') { - return new NetworkModelInfo(null, this._sharedTreeService, null, null, null, null, null, this._store); + return new NetworkModelInfo(null, this._sharedTreeService, null, null, null, null, null,this._featureFlagsService, this._store); } } }; diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts index c7c8d07a0..6ad640317 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service.spec.ts @@ -84,7 +84,6 @@ describe('Network step service', () => { "genericModalCriteria": {"roles": ["-- select an option --", "network role 1", "network role 2", "network role 3", "network role 4", "network role 5"]}, "name": null, "flags": { - "CREATE_INSTANCE_TEST": false, "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, "FLAG_ENABLE_WEBPACK_MODERN_UI": true, @@ -95,12 +94,9 @@ describe('Network step service', () => { "FLAG_SHOW_ASSIGNMENTS": true, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_DUPLICATE_VNF": true, - "FLAG_DEFAULT_VNF": true, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, "FLAG_A_LA_CARTE_AUDIT_INFO": true, "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true, "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true, - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true, "FLAG_1902_NEW_VIEW_EDIT": true, "FLAG_VF_MODULE_RESUME_STATUS_CREATE": true, "FLAG_1906_COMPONENT_INFO": true diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts index 7ab2f5b5b..9add349db 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts @@ -32,6 +32,7 @@ import {ErrorMsgService} from "../../../../shared/components/error-msg/error-msg import {ComponentInfoService} from "../../component-info/component-info.service"; import {NetworkStepService} from "../models/vrf/vrfModal/networkStep/network.step.service"; import {VpnStepService} from "../models/vrf/vrfModal/vpnStep/vpn.step.service"; +import {VfModuleUpgradePopupService} from "../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; class MockAppStore<T> { getState() { @@ -73,6 +74,7 @@ describe('Model Tree Generator service', () => { NetworkPopupService, NetworkControlGenerator, VfModulePopuopService, + VfModuleUpgradePopupService, VfModuleControlGenerator, VnfGroupControlGenerator, DialogService, diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts index 7246adc27..e5559ee15 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts @@ -35,6 +35,7 @@ import {ComponentInfoService} from "../../component-info/component-info.service" import {IModelTreeNodeModel} from "../../../objectsToTree/objectToModelTree/modelTreeNode.model"; import {VpnStepService} from "../models/vrf/vrfModal/vpnStep/vpn.step.service"; import {NetworkStepService} from "../models/vrf/vrfModal/networkStep/network.step.service"; +import {VfModuleUpgradePopupService} from "../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; class MockAppStore<T> { getState() { @@ -98,6 +99,7 @@ describe('Model Tree Generator service', () => { NetworkPopupService, NetworkControlGenerator, VfModulePopuopService, + VfModuleUpgradePopupService, VfModuleControlGenerator, VnfGroupControlGenerator, DialogService, diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts index c101f44e9..75ae1e149 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts @@ -3,11 +3,13 @@ import {ILevelNodeInfo} from "../models/basic.model.info"; import {ObjectToTreeService} from "../objectToTree.service"; import * as _ from "lodash"; import {IModelTreeNodeModel} from "../../../objectsToTree/objectToModelTree/modelTreeNode.model"; +import {FeatureFlagsService} from "../../../../shared/services/featureFlag/feature-flags.service"; @Injectable() export class ObjectToModelTreeService { numberOfPlusButton: number; - constructor(private _objectToTreeService: ObjectToTreeService) { + + constructor(private _objectToTreeService: ObjectToTreeService, private _featureFlagsService: FeatureFlagsService) { } /*********************************************************** @@ -18,9 +20,10 @@ export class ObjectToModelTreeService { let _this = this; const firstLevelOptions: ILevelNodeInfo[] = _this._objectToTreeService.getFirstLevelOptions(); let nodes = []; + let flags = this._featureFlagsService.getAllFlags(); for (let option of firstLevelOptions) { _.forOwn(serviceModel[option.name], function (item, key) { - nodes.push(_this.addFirstLevelModel(serviceModel.service.uuid, key, item, item.type, serviceModel, option)); + nodes.push(_this.addFirstLevelModel(serviceModel.service.uuid, key, item, item.type, serviceModel, option, flags)); }); } @@ -30,10 +33,10 @@ export class ObjectToModelTreeService { return nodes; } - calculateNumberOfNodesWithPlusIcon(serviceModel, nodes) : void { - this.numberOfPlusButton = nodes.reduce((sum, node)=>{ - let showNodeIconResult = node.showNodeIcons({data : node}, serviceModel.service.uuid); - return (!_.isNil(showNodeIconResult) && showNodeIconResult.addIcon && !showNodeIconResult.vIcon) ? sum + 1 : sum; + calculateNumberOfNodesWithPlusIcon(serviceModel, nodes): void { + this.numberOfPlusButton = nodes.reduce((sum, node) => { + let showNodeIconResult = node.showNodeIcons({data: node}, serviceModel.service.uuid); + return (!_.isNil(showNodeIconResult) && showNodeIconResult.addIcon && !showNodeIconResult.vIcon) ? sum + 1 : sum; }, 0); } @@ -47,9 +50,9 @@ export class ObjectToModelTreeService { * @param parentModel - current parent Model object * @param levelNodeInfo - current level node information ************************************************************/ - private addFirstLevelModel(serviceId: string, name, currentModel, type, parentModel, levelNodeInfo: ILevelNodeInfo) { - let node = ObjectToModelTreeService.convertItemToTreeNode(serviceId, name, currentModel, type, null, levelNodeInfo); - node.children = this.addNextLevelNodes(serviceId, currentModel, parentModel, levelNodeInfo, node); + private addFirstLevelModel(serviceId: string, name, currentModel, type, parentModel, levelNodeInfo: ILevelNodeInfo, flags?: { [key: string]: boolean }) { + let node = ObjectToModelTreeService.convertItemToTreeNode(serviceId, name, currentModel, type, null, levelNodeInfo, flags); + node.children = this.addNextLevelNodes(serviceId, currentModel, parentModel, levelNodeInfo, node, flags); return node; } @@ -61,13 +64,13 @@ export class ObjectToModelTreeService { * @param levelNodeInfo - current level node information * @param parentNode - parent node. ************************************************************/ - addNextLevelNodes(serviceId: string, currentModel, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode): any[] { + addNextLevelNodes(serviceId: string, currentModel, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode, flags?: { [key: string]: boolean }): any[] { if (!_.isNil(levelNodeInfo.childNames) && levelNodeInfo.childNames.length > 0) { levelNodeInfo.childNames.forEach(function (childName) { if (!_.isNil(currentModel[childName])) { let nextLevelNodeInfo = levelNodeInfo.getNextLevelObject.apply(this, [childName]); parentNode.children = Object.keys(currentModel[childName]).map((key) => - ObjectToModelTreeService.convertItemToTreeNode(serviceId, key, currentModel[childName][key], childName, currentModel, nextLevelNodeInfo)); + ObjectToModelTreeService.convertItemToTreeNode(serviceId, key, currentModel[childName][key], childName, currentModel, nextLevelNodeInfo, flags)); } }) } @@ -84,17 +87,18 @@ export class ObjectToModelTreeService { * @param parentModel - current parent model * @param levelNodeInfo - current levelNodeInfo object ************************************************************/ - static convertItemToTreeNode(serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo) { - let node : IModelTreeNodeModel = { + static convertItemToTreeNode(serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo, flags?: { [key: string]: boolean }) { + const type: string = levelNodeInfo.getType(); + let node: IModelTreeNodeModel = { id: currentModel.customizationUuid || currentModel.uuid, - modelCustomizationId : currentModel.customizationUuid, - modelVersionId: currentModel.uuid, - modelUniqueId : currentModel.customizationUuid || currentModel.uuid, + modelCustomizationId: currentModel.customizationUuid, + modelVersionId: currentModel.uuid, + modelUniqueId: currentModel.customizationUuid || currentModel.uuid, name: name, tooltip: levelNodeInfo.getTooltip(), - type: levelNodeInfo.getType(), + type, count: currentModel.count || 0, - max: currentModel.max || 1, + max: ObjectToModelTreeService.getMax(currentModel, type, flags), children: [], disabled: false, dynamicInputs: levelNodeInfo.updateDynamicInputsDataFromModel(currentModel), @@ -105,15 +109,24 @@ export class ObjectToModelTreeService { return node; } + static getMax(currentModel, type, flags: { [key: string]: boolean }) { + if (flags && !!flags['FLAG_2002_UNLIMITED_MAX'] && (type === 'VF' || type === 'Network' || type === 'VFmodule')) { + return !_.isNil(currentModel.max) ? currentModel.max : null; + } else { + return currentModel.max || 1 + } + } - static addExtraFunctionality(node, serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo){ + + static addExtraFunctionality(node, serviceId: string, name: string, currentModel: any, valueType: string, parentModel: string, levelNodeInfo: ILevelNodeInfo) { node.onAddClick = (node, serviceId) => levelNodeInfo.onClickAdd(node, serviceId); node.getNodeCount = (node, serviceId) => levelNodeInfo.getNodeCount(node, serviceId); node.getMenuAction = (node, serviceId) => levelNodeInfo.getMenuAction(node, serviceId); node.showNodeIcons = (node, serviceId) => levelNodeInfo.showNodeIcons(node, serviceId); node.typeName = levelNodeInfo.typeName; node.getModel = levelNodeInfo.getModel.bind(levelNodeInfo); - node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : ()=>{}; + node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : () => { + }; node.componentInfoType = levelNodeInfo.componentInfoType; return node; } diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts index 0072196f2..1e6825130 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts @@ -24,6 +24,8 @@ import {AaiService} from "../../../shared/services/aaiService/aai.service"; import {VrfModelInfo} from "./models/vrf/vrf.model.info"; import {NetworkStepService} from "./models/vrf/vrfModal/networkStep/network.step.service"; import {VpnStepService} from "./models/vrf/vrfModal/vpnStep/vpn.step.service"; +import { VfModuleUpgradePopupService } from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; +import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service"; @Injectable() export class ObjectToTreeService { @@ -34,6 +36,7 @@ export class ObjectToTreeService { private _vnfPopupService : VnfPopupService, private _networkPopupService : NetworkPopupService, private _vfModulePopupService : VfModulePopuopService, + private _vfModuleUpgradePopupService : VfModuleUpgradePopupService, private _vnfGroupPopupService : VnfGroupPopupService, private _duplicateService : DuplicateService, private _modalService: SdcUiServices.ModalService, @@ -42,6 +45,7 @@ export class ObjectToTreeService { private _networkStepService : NetworkStepService, private _vpnStepService : VpnStepService, private _aaiService : AaiService, + private _featureFlagsService: FeatureFlagsService, private _store : NgRedux<AppState>) { } @@ -52,10 +56,10 @@ export class ObjectToTreeService { * return all first optional first level of the model tree ************************************************************/ getFirstLevelOptions(): ILevelNodeInfo[] { - return [new VnfModelInfo(this._dynamicInputsService, this._sharedTreeService, this._defaultDataGeneratorService, this._dialogService, this._vnfPopupService, this._vfModulePopupService, this._duplicateService, this._modalService, this._iframeService, this._componentInfoService, this._store) - , new NetworkModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._networkPopupService, this._duplicateService, this._modalService, this._iframeService, this._store), + return [new VnfModelInfo(this._dynamicInputsService, this._sharedTreeService, this._defaultDataGeneratorService, this._dialogService, this._vnfPopupService, this._vfModulePopupService, this._vfModuleUpgradePopupService,this._duplicateService, this._modalService, this._iframeService, this._componentInfoService, this._featureFlagsService, this._store) + , new NetworkModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._networkPopupService, this._duplicateService, this._modalService, this._iframeService, this._featureFlagsService, this._store), new PnfModelInfo(), - new VrfModelInfo(this._store, this._sharedTreeService, this._dialogService, this._iframeService, this._networkStepService, this._vpnStepService), + new VrfModelInfo(this._store, this._sharedTreeService, this._dialogService, this._iframeService, this._featureFlagsService, this._networkStepService, this._vpnStepService), new CollectionResourceModelInfo(this._store, this._sharedTreeService), new ConfigurationModelInfo(this._dynamicInputsService, this._sharedTreeService), new VnfGroupingModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._vnfGroupPopupService, this._iframeService, this._aaiService, this._store)]; diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts index 89e20a2d6..b330b72dc 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts @@ -40,6 +40,7 @@ import {ComponentInfoModel, ComponentInfoType} from "../component-info/component import {ModelInformationItem} from "../../../shared/components/model-information/model-information.component"; import {VpnStepService} from "./models/vrf/vrfModal/vpnStep/vpn.step.service"; import {NetworkStepService} from "./models/vrf/vrfModal/networkStep/network.step.service"; +import {VfModuleUpgradePopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; class MockAppStore<T> { getState() { @@ -96,6 +97,7 @@ describe('Shared Tree Service', () => { NetworkPopupService, NetworkControlGenerator, VfModulePopuopService, + VfModuleUpgradePopupService, VfModuleControlGenerator, VnfGroupControlGenerator, DialogService, @@ -162,7 +164,7 @@ describe('Shared Tree Service', () => { jest.spyOn(AuditInfoModalComponent.openInstanceAuditInfoModal, 'next'); let modelInfoServiceMock: ILevelNodeInfo = new VnfModelInfo(null, null, - null, null, null, null, + null, null, null, null, null, null, null, null, null,null); const modelMock = {"a": "a"}; const instanceMock = {"instance": "instance", "trackById": "123456789"}; @@ -465,19 +467,15 @@ function getStore() { "global": { "name": null, "flags": { - "CREATE_INSTANCE_TEST": false, "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_SHOW_ASSIGNMENTS": true, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, - "FLAG_DEFAULT_VNF": true, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, "FLAG_A_LA_CARTE_AUDIT_INFO": true, "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true, "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true, - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true, "FLAG_1902_NEW_VIEW_EDIT": true, "FLAG_1810_IDENTIFY_SERVICE_FOR_NEW_UI": false, "FLAG_1902_VNF_GROUPING": true, diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts index c56cc4999..b8eddbbf7 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts @@ -13,6 +13,7 @@ import {ModelInformationItem} from "../../../shared/components/model-information import {undoUpgradeService, upgradeService} from "../../../shared/storeUtil/utils/service/service.actions"; import {VNFMethods} from "../../../shared/storeUtil/utils/vnf/vnf.actions"; import {FeatureFlagsService, Features} from "../../../shared/services/featureFlag/feature-flags.service"; +import {Utils} from "../../../shared/utils/utils"; @Injectable() export class SharedTreeService { @@ -239,6 +240,16 @@ export class SharedTreeService { const mode = this._store.getState().global.drawingBoardStatus; return mode === DrawingBoardModes.EDIT || mode=== DrawingBoardModes.CREATE; } + + + isReachedToMaxInstances(properties, counter, flags): boolean{ + let maxInstances = Utils.getMaxFirstLevel(properties, flags); + if(_.isNil(maxInstances)){ + return false; + }else { + return !(maxInstances > counter); + } + } /************************************************ return number of instances with action Delete @type: vnfs networks, vngGroups (not vfModule) diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html index 212981aaf..16b8c0132 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html @@ -16,6 +16,13 @@ <span class="icon-refresh"></span> </div> </div> + <div class="instantiationStatusFilter" *ngIf=isInstantiationStatusFilterFlagOn()> + <input + [attr.data-tests-id]="'instantiation-status-filter'" + class="form-control input-text" + [placeholder]="'filter'" + [(ngModel)]="filterText"> + </div> </div> </div> </div> @@ -41,51 +48,51 @@ </tr> </thead> <tbody > - <tr *ngFor="let data of serviceInfoData; trackBy: trackByFn; let i = index" [ngClass]="{'odd' : data.serviceIndex%2 == 1}" [id]="data.jobId"> - <td class="smallTd" id="userId"><custom-ellipsis [id]="data.userId" [value]="data.userId"></custom-ellipsis></td> - <td class="smallTd" id="action"><custom-ellipsis [id]="data.action" [value]="data.action | capitalizeAndFormat"></custom-ellipsis></td> - <td class="normal" id="serviceModelName"><custom-ellipsis [id]="data.serviceModelName" [value]="data.serviceModelName"></custom-ellipsis></td> - <td class="normal" id="serviceInstanceName"><custom-ellipsis [id]="data.serviceInstanceName" [value]="data.serviceInstanceName"></custom-ellipsis></td> - <td class="smallTd" id="serviceModelVersion"><custom-ellipsis [id]="data.serviceModelVersion" [value]="data.serviceModelVersion"></custom-ellipsis></td> - <td class="normal" id="subscriberName"><custom-ellipsis [id]="data.subscriberName" [value]="data.subscriberName"></custom-ellipsis></td> - <td class="mediumTd" id="serviceType"><custom-ellipsis [id]="data.serviceType" [value]="data.serviceType"></custom-ellipsis></td> - <td class="normal" id="regionId"><custom-ellipsis [id]="data.regionId" [value]="data.regionId"></custom-ellipsis></td> - <td class="mediumTd" id="tenantName"><custom-ellipsis [id]="data.tenantName" [value]="data.tenantName"></custom-ellipsis></td> - <td class="mediumTd" id="aicZoneName"><custom-ellipsis [id]="data.aicZoneName" [value]="data.aicZoneName"></custom-ellipsis></td> - <td class="mediumTd" id="project"><custom-ellipsis [id]="data.project" [value]="data.project"></custom-ellipsis></td> - <td class="mediumTd" id="owningEntityName"><custom-ellipsis [id]="data.owningEntityName" [value]="data.owningEntityName"></custom-ellipsis></td> - <td class="smallTd" id="pause"><custom-ellipsis [id]="data.pause" [value]="data.pause"></custom-ellipsis></td> - <td class="mediumTd" id="created"><custom-ellipsis [id]="data.created" [value]="data.created | date:'MMM. dd, yyyy HH:mm'"></custom-ellipsis></td> - <td class="last" id="jobStatus" [ngClass]="data.jobStatus"> - <custom-popover [value]="data.serviceStatus.tooltip" [popoverType]="data?.serviceStatus?.color" style="float: left;"> - <svg-icon - id="jobStatusIcon-{{i}}" - (click)="auditInfo(data)" - [mode]="data.serviceStatus.color" - [size]="'large'" - [name]="data.serviceStatus.iconClassName"> - </svg-icon> + <tr *ngFor="let data of serviceInfoData | searchFilter: filterText ; trackBy: trackByFn; let i = index" [ngClass]="{'odd' : data.serviceIndex%2 == 1}" [id]="data.jobId"> + <td class="smallTd" id="userId"><custom-ellipsis [id]="data.userId" [value]="data.userId"></custom-ellipsis></td> + <td class="smallTd" id="action"><custom-ellipsis [id]="data.action" [value]="data.action | capitalizeAndFormat"></custom-ellipsis></td> + <td class="normal" id="serviceModelName"><custom-ellipsis [id]="data.serviceModelName" [value]="data.serviceModelName"></custom-ellipsis></td> + <td class="normal" id="serviceInstanceName"><custom-ellipsis [id]="data.serviceInstanceName" [value]="data.serviceInstanceName"></custom-ellipsis></td> + <td class="smallTd" id="serviceModelVersion"><custom-ellipsis [id]="data.serviceModelVersion" [value]="data.serviceModelVersion"></custom-ellipsis></td> + <td class="normal" id="subscriberName"><custom-ellipsis [id]="data.subscriberName" [value]="data.subscriberName"></custom-ellipsis></td> + <td class="mediumTd" id="serviceType"><custom-ellipsis [id]="data.serviceType" [value]="data.serviceType"></custom-ellipsis></td> + <td class="normal" id="regionId"><custom-ellipsis [id]="data.regionId" [value]="data.regionId"></custom-ellipsis></td> + <td class="mediumTd" id="tenantName"><custom-ellipsis [id]="data.tenantName" [value]="data.tenantName"></custom-ellipsis></td> + <td class="mediumTd" id="aicZoneName"><custom-ellipsis [id]="data.aicZoneName" [value]="data.aicZoneName"></custom-ellipsis></td> + <td class="mediumTd" id="project"><custom-ellipsis [id]="data.project" [value]="data.project"></custom-ellipsis></td> + <td class="mediumTd" id="owningEntityName"><custom-ellipsis [id]="data.owningEntityName" [value]="data.owningEntityName"></custom-ellipsis></td> + <td class="smallTd" id="pause"><custom-ellipsis [id]="data.pause" [value]="data.pause"></custom-ellipsis></td> + <td class="mediumTd" id="created"><custom-ellipsis [id]="data.created" [value]="data.created | date:'MMM. dd, yyyy HH:mm'"></custom-ellipsis></td> + <td class="last" id="jobStatus" [ngClass]="data.jobStatus"> + <custom-popover [value]="data.serviceStatus.tooltip" [popoverType]="data?.serviceStatus?.color" style="float: left;"> + <svg-icon + id="jobStatusIcon-{{i}}" + (click)="auditInfo(data)" + [mode]="data.serviceStatus.color" + [size]="'large'" + [name]="data.serviceStatus.iconClassName"> + </svg-icon> - </custom-popover> - <div class="menu-div" (click)="onContextMenu($event, data)"> - <span class="icon-menu"></span> - <context-menu> - <ng-template *ngFor="let action of contextMenuActions" contextMenuItem let-item - [visible]="action.visible" - [enabled]="action.enabled" - (execute)="action.click($event.item)"> - <div [attr.data-tests-id]="action.dataTestId" - [tooltip]="action?.tooltip" - [tooltipDisabled]="!action.tooltip"> + </custom-popover> + <div class="menu-div" (click)="onContextMenu($event, data)" [attr.data-tests-id]="'menu-'+data.jobId"> + <span class="icon-menu"></span> + <context-menu> + <ng-template *ngFor="let action of contextMenuActions" contextMenuItem let-item + [visible]="action.visible" + [enabled]="action.enabled" + (execute)="action.click($event.item)"> + <div [attr.data-tests-id]="action.dataTestId" + [tooltip]="action?.tooltip" + [tooltipDisabled]="!action.tooltip"> <span class="context-menu-icon"> <i class="fa {{action.className}}" aria-hidden="true"></i> </span> - {{action.name}} - </div> - </ng-template> - </context-menu> - </div> - </td> + {{action.name}} + </div> + </ng-template> + </context-menu> + </div> + </td> </tr> </tbody> </table> diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss index 65c2400a3..352a7db10 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.scss @@ -275,3 +275,9 @@ div.dataTables_wrapper { margin-top: 0px; height: 0; } + +.instantiationStatusFilter { + position: absolute; + right: 20px; + width: 22%; +} diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts index 27d3f419b..eedd46dd3 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts @@ -1,49 +1,29 @@ import {getTestBed, TestBed} from '@angular/core/testing'; -import { - COMPLETED_WITH_ERRORS, - INPROGRESS, - InstantiationStatusComponentService, - PAUSE, - PENDING, - ServiceStatus, - STOPPED, - SUCCESS_CIRCLE, - UNKNOWN, - X_O -} from './instantiationStatus.component.service'; +import {COMPLETED_WITH_ERRORS, INPROGRESS, InstantiationStatusComponentService, PAUSE, PENDING, ServiceStatus, STOPPED, SUCCESS_CIRCLE, UNKNOWN, X_O} from './instantiationStatus.component.service'; import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model'; import {AaiService} from "../shared/services/aaiService/aai.service"; import {MsoService} from "../shared/services/msoService/mso.service"; import {NgRedux} from "@angular-redux/store"; import {HttpClientTestingModule} from "@angular/common/http/testing"; -import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags.service"; +import {FeatureFlagsService, Features} from "../shared/services/featureFlag/feature-flags.service"; import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes"; import {RouterTestingModule} from "@angular/router/testing"; import {of} from "rxjs"; import {UrlTree} from "@angular/router"; +import each from "jest-each"; +import {ServiceAction} from "../shared/models/serviceInstanceActions"; +import {instance, mock, when} from "ts-mockito"; class MockAppStore<T> { - - getState() { - return { - global: { - flags: { - 'FLAG_1902_NEW_VIEW_EDIT': true, - - } - } - } - } - - dispatch() { - - } + dispatch() {} } + describe('Instantiation Status Service', () => { let injector; let aaiService: AaiService; let msoService: MsoService; let service: InstantiationStatusComponentService; + let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService); beforeAll(done => (async () => { @@ -57,7 +37,9 @@ describe('Instantiation Status Service', () => { AaiService, MsoService, FeatureFlagsService, - {provide: NgRedux, useClass: MockAppStore}] + {provide: NgRedux, useClass: MockAppStore}, + {provide: FeatureFlagsService, useValue: instance(mockFeatureFlagsService)} + ] }); await TestBed.compileComponents(); @@ -101,33 +83,48 @@ describe('Instantiation Status Service', () => { }); }); - test('click on "Open" button should open new view edit' , ()=>{ - const item = { - serviceModelId : 'serviceModelId', - serviceInstanceId : 'serviceInstanceId', - serviceType : 'serviceType', - subscriberId : 'subscriberId' - }; - let params:UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.VIEW); - expect(params.toString().startsWith('/servicePlanning/VIEW')).toBeTruthy(); - expect(params.queryParams).toEqual( - { - serviceModelId: item.serviceModelId, - serviceInstanceId: item.serviceInstanceId, - serviceType : item.serviceType, - subscriberId : item.subscriberId - }); - }); + describe('navigations tests:', () => { - test('build the View Edit url' , ()=>{ const item = { - serviceModelId : '28aeb8f6-5620-4148-8bfb-a5fb406f0309', + serviceModelId: '28aeb8f6-5620-4148-8bfb-a5fb406f0309', + serviceInstanceId: 'myInstanceId', + serviceType: 'myService', + subscriberId: 'mySubscriber', + jobId: 'aJobId' }; - let serviceModelUrl: string = '/servicePlanning/EDIT?serviceModelId=28aeb8f6-5620-4148-8bfb-a5fb406f0309'; - let suffix:string = '../../serviceModels.htm#'; - let tree:UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.EDIT); - let result = service.getViewEditUrl(tree); - expect (suffix + serviceModelUrl).toEqual(result); + + test('click on "Open" button should open new view edit', () => { + let params: UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.VIEW); + expect(params.toString().startsWith('/servicePlanning/VIEW')).toBeTruthy(); + expect(params.queryParams).toEqual( + { + serviceModelId: item.serviceModelId, + serviceInstanceId: item.serviceInstanceId, + serviceType: item.serviceType, + subscriberId: item.subscriberId, + jobId: item.jobId + }); + }); + + test('build the View Edit url', () => { + + let serviceModelUrl: string = '/servicePlanning/EDIT?serviceModelId=28aeb8f6-5620-4148-8bfb-a5fb406f0309' + + '&serviceInstanceId=myInstanceId&serviceType=myService&subscriberId=mySubscriber&jobId=aJobId'; + let prefix: string = '../../serviceModels.htm#'; + let tree: UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.EDIT); + let result = service.getViewEditUrl(tree); + expect(result).toEqual(prefix + serviceModelUrl); + }); + + test('recreate url shall contains mode RECREATE and only jobId and serviceModelId', () =>{ + let params: UrlTree = service.getNewViewEditUrlTree(<any>item, DrawingBoardModes.RECREATE); + expect(params.toString().startsWith('/servicePlanning/RECREATE')).toBeTruthy(); + expect(params.queryParams).toEqual( + { + serviceModelId: item.serviceModelId, + jobId: item.jobId + }); + }); }); for (let [status, tooltip] of Object.entries({ @@ -154,6 +151,27 @@ describe('Instantiation Status Service', () => { expect(statusResult.iconClassName).toEqual(UNKNOWN); }); + + each([ + [true, ServiceAction.INSTANTIATE], + [false, ServiceAction.UPDATE], + [false, ServiceAction.DELETE], + ]). + test('isRecreateEnabled: should be %s if action is %s', (expected:boolean, action:ServiceAction) => { + let serviceInfoModel = new ServiceInfoModel(); + serviceInfoModel.action = action; + expect(service.isRecreateEnabled(serviceInfoModel)).toBe(expected); + }); + + each([ + [true, true], + [false, false], + ]). + test('isRecreateVisible: should be %s if flag is %s', (expected:boolean, flag:boolean) => { + when(mockFeatureFlagsService.getFlagState(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)).thenReturn(flag); + expect(service.isRecreateVisible()).toEqual(expected); + }); + test('getStatusTooltip should return correct icon per job status', () => { let result : ServiceStatus = service.getStatus('pending'); expect(result.iconClassName).toEqual(PENDING); diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts index ffc2e681a..4bfedd913 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts @@ -12,6 +12,7 @@ import {updateDrawingBoardStatus} from "../shared/storeUtil/utils/global/global. import {Router, UrlTree} from "@angular/router"; import {of} from "rxjs"; import {MsoService} from "../shared/services/msoService/mso.service"; +import {ServiceAction} from "../shared/models/serviceInstanceActions"; export let PENDING : string = "pending"; export let INPROGRESS : string = "in_progress"; @@ -28,7 +29,8 @@ export class InstantiationStatusComponentService { constructor( private _aaiService: AaiService, private _msoService: MsoService, private _router : Router, - private _store: NgRedux<AppState>) { + private _store: NgRedux<AppState>, + private _featureFlagsService:FeatureFlagsService) { } generateServiceInfoDataMapping(arr: ServiceInfoModel[]) : { [serviceInstanceId: string]: ServiceInfoModel[]}{ @@ -69,7 +71,7 @@ export class InstantiationStatusComponentService { } open(item: ServiceInfoModel): void { - if (FeatureFlagsService.getFlagState(Features.FLAG_1902_VNF_GROUPING, this._store)) { + if (this._featureFlagsService.getFlagState(Features.FLAG_1902_VNF_GROUPING)) { this._aaiService.getServiceModelById(item['serviceModelId']).subscribe((result)=>{ const serviceModel = new ServiceModel(result); @@ -91,7 +93,7 @@ export class InstantiationStatusComponentService { } navigateToNewViewOnlyOrOldEditView(item: ServiceInfoModel) { - if (FeatureFlagsService.getFlagState(Features.FLAG_1902_NEW_VIEW_EDIT, this._store)) { + if (this._featureFlagsService.getFlagState(Features.FLAG_1902_NEW_VIEW_EDIT)) { this.navigateToNewViewEdit(item, DrawingBoardModes.VIEW); } else { @@ -122,19 +124,31 @@ export class InstantiationStatusComponentService { ['/servicePlanning/' + mode], { queryParams: - { - serviceModelId: item.serviceModelId, - serviceInstanceId: item.serviceInstanceId, - serviceType : item.serviceType, - subscriberId : item.subscriberId, - jobId: item.jobId - } + mode==DrawingBoardModes.RECREATE ? + this.getRecreateQueryParams(item) : + this.getDefaultViewEditQueryParams(item) }); } + private getDefaultViewEditQueryParams(item: ServiceInfoModel) { + return { + serviceModelId: item.serviceModelId, + serviceInstanceId: item.serviceInstanceId, + serviceType: item.serviceType, + subscriberId: item.subscriberId, + jobId: item.jobId + }; + } + + private getRecreateQueryParams(item: ServiceInfoModel) { + return { + serviceModelId: item.serviceModelId, + jobId: item.jobId + }; + } + getViewEditUrl(viewEditUrlTree:UrlTree): string { return '../../serviceModels.htm#' + viewEditUrlTree.toString(); - } getStatus(status : string) : ServiceStatus { @@ -162,6 +176,18 @@ export class InstantiationStatusComponentService { retry(item: ServiceInfoModel): void { this.navigateToNewViewEdit(item, DrawingBoardModes.RETRY_EDIT); } + + recreate(item: ServiceInfoModel): void { + this.navigateToNewViewEdit(item, DrawingBoardModes.RECREATE); + } + + isRecreateEnabled(item: ServiceInfoModel): boolean { + return item.action === ServiceAction.INSTANTIATE; + } + + isRecreateVisible(): boolean { + return this._featureFlagsService.getFlagState(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE); + } } diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts index 53dfcc1f2..e6ccdda8e 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts @@ -17,7 +17,10 @@ import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags. import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions"; import each from 'jest-each'; import {ServiceInfoModel} from "../shared/server/serviceInfo/serviceInfo.model"; -import { TooltipModule } from 'ngx-tooltip'; +import {TooltipModule} from 'ngx-tooltip'; +import {SearchFilterPipe} from "../shared/pipes/searchFilter/search-filter.pipe"; +import {ActivatedRoute} from "@angular/router"; +import {FormsModule} from "@angular/forms"; class MockAppStore<T> { @@ -36,10 +39,21 @@ class MockAppStore<T> { } } +class ActivatedRouteMock<T>{ + queryParams() { + return {} + }; + + snapshot = { + queryParams : {} + } +} + describe('Instantiation Status Component', () => { let component: InstantiationStatusComponent; let fixture: ComponentFixture<InstantiationStatusComponent>; -let item = new ServiceInfoModel(); + let item = new ServiceInfoModel(); + beforeAll(done => (async () => { TestBed.configureTestingModule({ @@ -48,7 +62,8 @@ let item = new ServiceInfoModel(); ContextMenuModule, ScrollToModule.forRoot(), RouterTestingModule, - TooltipModule + TooltipModule, + FormsModule, ], providers: [ ServiceInfoService, @@ -59,9 +74,10 @@ let item = new ServiceInfoModel(); FeatureFlagsService, ConfigurationService, LogService, + {provide: ActivatedRoute, useClass: ActivatedRouteMock}, {provide: NgRedux, useClass: MockAppStore} ], - declarations: [InstantiationStatusComponent, CapitalizeAndFormatPipe], + declarations: [InstantiationStatusComponent, CapitalizeAndFormatPipe, SearchFilterPipe], schemas: [ CUSTOM_ELEMENTS_SCHEMA ] }); await TestBed.compileComponents(); diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts index f3f651960..58227c9eb 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts @@ -1,4 +1,4 @@ -import {Component, ViewChild} from '@angular/core'; +import {Component, OnInit, ViewChild} from '@angular/core'; import {ServiceInfoService} from '../shared/server/serviceInfo/serviceInfo.service'; import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model'; import {InstantiationStatusComponentService} from './instantiationStatus.component.service'; @@ -11,7 +11,8 @@ import {LogService} from '../shared/utils/log/log.service'; import {AppState} from "../shared/store/reducers"; import {NgRedux} from '@angular-redux/store'; import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions"; -import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes"; +import {ActivatedRoute} from "@angular/router"; +import {FeatureFlagsService, Features} from "../shared/services/featureFlag/feature-flags.service"; export interface MenuAction{ name: string; @@ -28,7 +29,7 @@ export interface MenuAction{ templateUrl : './instantiationStatus.component.html', styleUrls : ['./instantiationStatus.component.scss'] }) -export class InstantiationStatusComponent { +export class InstantiationStatusComponent implements OnInit { TIMER_TIME_IN_SECONDS : number = 0; timer = null; @@ -58,6 +59,14 @@ export class InstantiationStatusComponent { visible: () => true, }, { + name: "Recreate", + dataTestId: "context-menu-recreate", + className: "fa-clone", + click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.recreate(item), + enabled: (item: ServiceInfoModel) => this.instantiationStatusComponentService.isRecreateEnabled(item), + visible: () => this.instantiationStatusComponentService.isRecreateVisible(), + }, + { name: "Audit info", dataTestId: "context-menu-audit-info", className: "fa-info-circle", @@ -85,12 +94,14 @@ export class InstantiationStatusComponent { ]; flags: any; + filterText: string; constructor(private _serviceInfoService: ServiceInfoService, private _instantiationStatusComponentService : InstantiationStatusComponentService, private _contextMenuService: ContextMenuService, private _configurationService : ConfigurationService, private _scrollToService: ScrollToService, private _logService : LogService, + private route: ActivatedRoute, private _store: NgRedux<AppState>) { this.instantiationStatusComponentService = _instantiationStatusComponentService; this.configurationService = this._configurationService; @@ -101,6 +112,11 @@ export class InstantiationStatusComponent { }); } + ngOnInit() { + let filterTextParam = this.route.snapshot.queryParams["filterText"]; + this.filterText = filterTextParam ? filterTextParam : "" ; + } + activateInterval() { if (this.TIMER_TIME_IN_SECONDS > 0) { this.timer = setInterval(() => { @@ -115,7 +131,7 @@ export class InstantiationStatusComponent { refreshData(): void { this.dataIsReady = false; - this._serviceInfoService.getServicesJobInfo(true, this.lastUpdatedDate === null) + this._serviceInfoService.getServicesJobInfo(this.lastUpdatedDate === null) .subscribe((res: ServiceInfoModel[]) => { this._instantiationStatusComponentService.convertObjectToArray(res).subscribe((res) => { this._logService.info('refresh instantiation status table', res); @@ -144,7 +160,7 @@ export class InstantiationStatusComponent { this.refreshData(); }); } - + retryItem(item: ServiceInfoModel) : void { if (item.isRetryEnabled) { this._instantiationStatusComponentService.retry(item); @@ -230,4 +246,8 @@ export class InstantiationStatusComponent { }, 0) } } + + isInstantiationStatusFilterFlagOn() { + return FeatureFlagsService.getFlagState(Features.FLAG_2004_INSTANTIATION_STATUS_FILTER, this._store); + } } diff --git a/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts index 07f4d481b..a7b8ac744 100644 --- a/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts +++ b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts @@ -3,18 +3,20 @@ import {HighlightPipe} from "../../pipes/highlight/highlight-filter.pipe"; import * as _ from 'lodash'; @Component({ - selector : 'custom-ellipsis', + selector: 'custom-ellipsis', template: ` <span - sdc-tooltip - class="ellipsis" - id="{{id}}" - [innerHtml]="displayValue | safe : 'html'" - [ngClass]="{'breakWord' : breakWord == true}" - [tooltip-text]="value"> + sdc-tooltip + class="ellipsis" + [attr.data-tests-id]="dataTestId" + id="{{id}}" + [innerHtml]="displayValue | safe : 'html'" + [ngStyle]="{'white-space' : showDots ? 'nowrap' : 'initial'}" + [ngClass]="{'breakWord' : breakWord == true}" + [tooltip-text]="value"> </span>`, - styles : [ - ` + styles: [ + ` .ellipsis { white-space: nowrap; overflow: hidden; @@ -23,30 +25,33 @@ import * as _ from 'lodash'; width: 99%; text-align: left; } - + .breakWord { word-wrap: break-word; white-space: normal; } ` ], - providers : [HighlightPipe] + providers: [HighlightPipe] }) -export class EllipsisComponent implements OnChanges{ - @Input() value : string; - @Input() id : string; - @Input() hightlight : string; - @Input() breakWord : boolean = false; +export class EllipsisComponent implements OnChanges { + @Input() value: string; + @Input() id: string; + @Input() hightlight: string; + @Input() breakWord: boolean = false; + @Input() dataTestId: string; + @Input() showDots: boolean = false; + + displayValue: string; - displayValue : string; - constructor(private _highlightPipe : HighlightPipe){ + constructor(private _highlightPipe: HighlightPipe) { this.displayValue = this.value; } ngOnChanges(changes: SimpleChanges): void { this.displayValue = this.value; - if(!_.isNil(this.hightlight)){ - this.displayValue = this._highlightPipe.transform(this.value ,this.hightlight ? this.hightlight : ''); + if (!_.isNil(this.hightlight)) { + this.displayValue = this._highlightPipe.transform(this.value, this.hightlight ? this.hightlight : ''); } } } diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html index f7c4894b2..f205259e4 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html @@ -1,16 +1,26 @@ -<div> - <div class="details-item" *ngIf="data != null && form != null"> - <label [ngClass]="{'required': data.isRequired()}" - for="{{data?.dataTestId}}">{{data?.displayName}}:</label> - <angular2-multiselect id="{{data?.dataTestId}}" - [attr.data-tests-id]="data?.dataTestId" - [formControl]="form.controls[data.controlName]" - [(ngModel)]="data.selectedItems" - [data]="data?.options$" - [settings]="data?.settings" - title="{{data.tooltip}}" - [ngClass]="{'error-style' : form?.controls[data?.controlName]?.touched && form?.controls[data?.controlName]?.errors}"> - </angular2-multiselect> - </div> -</div> +<div class="details-item" *ngIf="data != null && form != null"> + <label [ngClass]="{'required': data.isRequired()}" + for="{{data?.dataTestId}}-select">{{data?.displayName}}:</label> + + <angular2-multiselect + [attr.data-tests-id]="data?.dataTestId" + [data]="options" + [(ngModel)]="selectedItems" + [settings]="dropdownSettings" + (onSelect)="onItemSelect($event)" + (onDeSelect)="OnItemDeSelect($event)" + (onSelectAll)="onSelectAll($event)" + (onDeSelectAll)="onDeSelectAll($event)">> + <c-item> + <ng-template let-item="item"> + <label + [attr.data-tests-id]="data.dataTestId + '-' + item?.itemName" + style="color: #333;min-width: 150px;">{{item?.itemName}}</label> + </ng-template> + </c-item> + </angular2-multiselect> + + <form-control-error *ngIf="data?.hasEmptyOptions && data?.isRequired()" + [message]="'No results for this request. Please change criteria.'"></form-control-error> +</div> diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts deleted file mode 100644 index 81c8d4679..000000000 --- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core' -import {CommonModule} from "@angular/common"; -import {FormBuilder, FormControl, ReactiveFormsModule, Validators} from "@angular/forms"; -import { - ValidatorModel, - ValidatorOptions -} from "../../../../models/formControlModels/formControl.model"; -import {FormControlMessageErrorComponent} from "../../errorMessage/formControlMessageError.component"; -import {BrowserModule} from "@angular/platform-browser"; -import {MultiselectFormControlComponent} from "./multiselect.formControl.component"; -import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; -import { of } from "rxjs"; -describe('Dropdown Form Control Component', () => { - let component: MultiselectFormControlComponent; - let fixture: ComponentFixture<MultiselectFormControlComponent>; - let fb: FormBuilder; - - beforeAll(done => (async () => { - TestBed.configureTestingModule({ - imports: [CommonModule, BrowserModule, ReactiveFormsModule], - providers: [FormBuilder], - declarations: [MultiselectFormControlComponent, FormControlMessageErrorComponent], - schemas: [CUSTOM_ELEMENTS_SCHEMA] - }); - await TestBed.compileComponents(); - - fixture = TestBed.createComponent(MultiselectFormControlComponent); - component = fixture.componentInstance; - fb = TestBed.get(FormBuilder); - - })().then(done).catch(done.fail)); - - test('component should initialize basic parameters', () => { - component.data = new MultiselectFormControl({ - displayName: "display Name", - validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], - dataTestId: "data-test-id", - placeHolder: "place holder", - controlName: 'testDropdown', - options: of([ - 'option1', - 'option2', - 'option3', - 'onBlur' - ]) - }); - - component.data.hasErrors = function () { - return this.formGroup.controls[this.controlName].touched && this.formGroup.controls[this.controlName].errors ? ['error-style'] : []; - }; - - component.data.onBlur = function () { - component.form.controls['testDropdown'].setValue('onBlur'); - }; - - component.form = fb.group({ - 'testDropdown': new FormControl({ - value: component.data.value, - disabled: false - }, Validators.compose(component.data.validations.map(item => item.validator))) - }); - - component.form.controls['testDropdown'].setValue(''); - expect(component.form.controls['testDropdown'].errors.required).toBeTruthy(); - component.form.controls['testDropdown'].setValue('option2'); - expect(component.form.controls['testDropdown'].errors).toBeFalsy(); - component.data.onBlur(); - expect(component.form.controls['testDropdown'].value).toEqual('onBlur'); - expect(component.form.controls['testDropdown'].errors).toBeFalsy(); - } - ) -}); - diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts index 4b98c7e26..26a55e9d2 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts @@ -1,6 +1,8 @@ import {Component, Input, OnChanges, SimpleChanges} from "@angular/core"; import {FormGroup} from "@angular/forms"; import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; +import {MultiselectFormControlService} from "./multiselect.formControl.service"; +import {MultiSelectItem} from "./multiselect.model"; @Component({ selector: 'multiselect-form-control', @@ -8,13 +10,54 @@ import {MultiselectFormControl} from "../../../../models/formControlModels/multi }) export class MultiselectFormControlComponent implements OnChanges{ @Input() data: MultiselectFormControl = null; + @Input() multiselectOptions: [] = null; + @Input() selectedItems = []; @Input() form: FormGroup = null; - ngOnChanges(changes: SimpleChanges): void { + + multiselectFormControlService : MultiselectFormControlService; + constructor(private _multiselectFormControlService : MultiselectFormControlService){ + this.multiselectFormControlService = _multiselectFormControlService; + } + + dropdownSettings = { + singleSelection : false, + limitSelection : 1000 + }; + + options : MultiSelectItem[]; + + + + async ngOnChanges(changes: SimpleChanges) { + if(this.data.options$){ + this._multiselectFormControlService.convertOriginalItems(this.data).then((options)=>{ + this.options = options; + this._multiselectFormControlService.convertSelectedItems(this.data).then((res)=> { + this.selectedItems = res; + this.form.controls[this.data.controlName].setValue(this.selectedItems); + }) + }); + } if (changes["data"] !== undefined && changes["data"].currentValue !== changes["data"].previousValue && changes["data"].firstChange) { - if(this.data.onInit){ + if (this.data.onInit) { + this.dropdownSettings.limitSelection = this.data.limitSelection; this.data.onInit(this.data, this.form); } } } + + onItemSelect(item:any){ + this.data.onChange(this.selectedItems ,this.form); + } + OnItemDeSelect(item:any){ + this.data.onChange(this.selectedItems ,this.form); + } + onSelectAll(items: any){ + this.data.onChange(this.selectedItems ,this.form); + } + onDeSelectAll(items: any){ + this.data.onChange(this.selectedItems ,this.form); + } } + diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.spec.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.spec.ts new file mode 100644 index 000000000..3c3c344a3 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.spec.ts @@ -0,0 +1,159 @@ +import {async, getTestBed, TestBed} from '@angular/core/testing'; +import {MultiselectFormControlService} from "./multiselect.formControl.service"; +import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; +import {MultiSelectItem} from "./multiselect.model"; + +describe('Multi Select Form Control Service', () => { + + let injector; + let service: MultiselectFormControlService; + + beforeAll(done => (async () => { + TestBed.configureTestingModule({ + imports: [], + providers: [MultiselectFormControlService] + }); + await TestBed.compileComponents(); + injector = getTestBed(); + service = injector.get(MultiselectFormControlService); + })().then(done).catch(done.fail)); + + + const options = [ + { + id: 'A', + name: 'a' + }, + { + id: 'B', + name: 'b', + keepMe: -42 + }, + { + id: 'C', + name: 'c' + } + ], + selectedFieldName = 'name', + ngValue = 'id'; + + + test('convertOriginalItems should convert options array to <MultiSelectItem> list', async(() => { + let control: MultiselectFormControl = <any>{ + ngValue, + selectedFieldName, + options$: options + }; + + service.convertOriginalItems(control).then((result: MultiSelectItem[]) => { + expect(result).toEqual([ + {"id": 1, "itemId": 'A', "itemName": 'a'}, + {"id": 2, "itemId": 'B', "itemName": 'b'}, + {"id": 3, "itemId": 'C', "itemName": 'c'} + ]); + }); + })); + + test('convertOriginalItems should return empty list when options list is empty', async(() => { + let control: MultiselectFormControl = <any>{ + ngValue, + selectedFieldName, + options$: [] + }; + + service.convertOriginalItems(control).then((result) => { + expect(result).toEqual([]); + }); + })); + + test('convertOptionsToHashMap - should convert any object to hash map with ngValue', async(() => { + + let control: MultiselectFormControl = <any>{ + ngValue, + selectedFieldName, + options$: options + }; + + let map = service.convertOptionsToHashMap(control); + + expect(Object.keys(map)).toHaveLength(3); + expect(map).toEqual({ + 'A': { + id: 'A', + name: 'a', + index: 1 + }, + 'B': { + id: 'B', + name: 'b', + keepMe: -42, + index: 2 + }, + 'C': { + id: 'C', + name: 'c', + index: 3 + } + + }) + })); + + test('convertOptionsToHashMap - should convert any object to hash map with ngValue: empty options', async(() => { + let control: MultiselectFormControl = <any>{ + ngValue, + selectedFieldName, + options$: [] + }; + + let map = service.convertOptionsToHashMap(control); + + expect(Object.keys(map)).toHaveLength(0) + })); + + test('convertSelectedItems - should convert select item to multi select list', async(() => { + let control: MultiselectFormControl = <any>{ + ngValue, + selectedFieldName, + options$: options, + value: ['A', 'C'] + }; + + service.convertSelectedItems(control).then((selectedOptions) => { + expect(selectedOptions).toHaveLength(2); + expect(selectedOptions[0].itemName).toEqual('a'); + expect(selectedOptions[1].itemName).toEqual('c'); + }) + })); + + test('convertSelectedItems - should convert select item to multi select list with special convert function', async(() => { + let control: MultiselectFormControl = <any>{ + ngValue, + selectedFieldName, + options$: options, + value: 'A,C', + convertOriginalDataToArray: (value) => { + return value.split(','); + } + }; + + service.convertSelectedItems(control).then((selectedOptions) => { + expect(selectedOptions).toHaveLength(2); + expect(selectedOptions[0].itemName).toEqual('a'); + expect(selectedOptions[1].itemName).toEqual('c'); + }) + })); + + + test('convertSelectedItems - should return empty list iof value is empty list', async(() => { + let control: MultiselectFormControl = <any>{ + ngValue, + selectedFieldName, + options$: options, + value: [] + }; + + service.convertSelectedItems(control).then((selectedOptions) => { + expect(selectedOptions).toHaveLength(0); + }) + })); +}); diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts new file mode 100644 index 000000000..0b50f4d28 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts @@ -0,0 +1,50 @@ +import {Injectable} from "@angular/core"; +import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; +import {MultiSelectItem} from "./multiselect.model"; +import * as _ from "lodash"; + + +@Injectable() +export class MultiselectFormControlService { + + convertOriginalItems = (control : MultiselectFormControl) : Promise<MultiSelectItem[]> => { + return new Promise<MultiSelectItem[]>((resolve) =>{ + let result: MultiSelectItem[] = []; + if(control.options$) { + let index: number = 1; + control.options$.map((originalItems: any) => { + result.push(new MultiSelectItem(index, originalItems[control.ngValue], originalItems[control.selectedFieldName])); + index++; + }); + } + resolve(result); + }) + }; + + + convertOptionsToHashMap = (config : MultiselectFormControl) => { + let index = 1; + return _.reduce(config.options$ , (obj, param: any ) => { + param.index = index; + index++; + obj[param[config.ngValue]] = param; + return obj; + }, {}); + }; + + convertSelectedItems(control : MultiselectFormControl) : Promise<MultiSelectItem[]>{ + return new Promise<MultiSelectItem[]>((resolve) =>{ + let result: MultiSelectItem[] = []; + const hashMap = this.convertOptionsToHashMap(control); + + if(control.options$ && control.value) { + const convertArray = control.convertOriginalDataToArray ? control.convertOriginalDataToArray(control.value) : control.value; + convertArray.map((itemId) => { + const uniqueIdentifier = itemId.trim(); + result.push(new MultiSelectItem(hashMap[uniqueIdentifier].index, hashMap[uniqueIdentifier][control.ngValue], hashMap[uniqueIdentifier][control.selectedFieldName])); + }); + } + resolve(result); + }); + } +} diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts new file mode 100644 index 000000000..a495211d4 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts @@ -0,0 +1,11 @@ +export class MultiSelectItem { + id : number; + itemId : number; + itemName : string; + + constructor(genericId: number, itemId : number, itemName : string){ + this.id = genericId; + this.itemId = itemId; + this.itemName = itemName; + } +} diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts index fc2eed4ae..077d849e6 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.spec.ts @@ -5,6 +5,7 @@ import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.s import {BasicControlGenerator} from "./basic.control.generator"; import {NgRedux} from '@angular-redux/store'; import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; +import {FileFormControl} from "../../../models/formControlModels/fileFormControl.model"; class MockAppStore<T> {} @@ -44,5 +45,41 @@ describe('Basic Control Generator', () => { const legacyRegionControl: FormControlModel = service.getLegacyRegion(instance); expect(legacyRegionControl.isVisible).toBeFalsy(); }); + + test('sdn-preload checkbox is visible', () => { + const instance = {}; + const sdncPreload: FormControlModel = service.getSDNCControl(instance); + expect (sdncPreload.displayName).toEqual('SDN-C pre-load'); + expect (sdncPreload.value).toBeFalsy(); + }); + + test('given instance, get supp file from getSupplementaryFile ', () => { + const instance = {}; + const suppFileForInstance: FileFormControl = service.getSupplementaryFile(instance); + expect(suppFileForInstance.isVisible).toBeTruthy(); + expect(suppFileForInstance.hiddenFile.length).toBeGreaterThanOrEqual(1); + expect(suppFileForInstance.hiddenFile[0].validations[0].validatorName).toEqual("isFileTooBig"); + }); + + test('concatSupplementaryFile add SupplementaryFile control and hidden file', () => { + + //given + const instance = {}; + const controls = [service.getLegacyRegion(instance)]; + expect(controls).toHaveLength(1); + + //when + const result = service.concatSupplementaryFile(controls, instance); + + //then + expect(controls).toHaveLength(1); //original controls remain the same + + expect(result.map((control) => {return control.controlName})).toEqual([ + "legacyRegion", + "supplementaryFile", + "supplementaryFile_hidden", + "supplementaryFile_hidden_content" + ]); + }); }); diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts index cbbff3c39..7ab64753a 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/basic.control.generator.ts @@ -1,12 +1,7 @@ import {Injectable} from "@angular/core"; import {DropdownFormControl} from "../../../models/formControlModels/dropdownFormControl.model"; import {FormGroup} from "@angular/forms"; -import { - CustomValidatorOptions, - FormControlModel, - ValidatorModel, - ValidatorOptions -} from "../../../models/formControlModels/formControl.model"; +import {CustomValidatorOptions, FormControlModel, ValidatorModel, ValidatorOptions} from "../../../models/formControlModels/formControl.model"; import {InputFormControl} from "../../../models/formControlModels/inputFormControl.model"; import {AppState} from "../../../store/reducers"; import {NgRedux} from "@angular-redux/store"; @@ -21,7 +16,11 @@ import {FormGeneralErrorsService} from "../../formGeneralErrors/formGeneralError import {Observable, of} from "rxjs"; import {NodeModel} from "../../../models/nodeModel"; import {Constants} from "../../../utils/constants"; +import {FileUnit} from "../../formControls/component/file/fileUnit.enum"; +import {CheckboxFormControl} from "../../../models/formControlModels/checkboxFormControl.model"; +export const SUPPLEMENTARY_FILE = 'supplementaryFile'; +export const SDN_C_PRE_LOAD = 'sdncPreLoad'; @Injectable() export class BasicControlGenerator { @@ -237,4 +236,71 @@ export class BasicControlGenerator { return initialInstanceName; } + concatSupplementaryFile(originalArray: FormControlModel[], vfModuleInstance): FormControlModel[] { + let suppFileInput: FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance)); + return originalArray.concat([suppFileInput], suppFileInput.hiddenFile); + } + + getSDNCControl = (instance: any): FormControlModel => { + return new CheckboxFormControl({ + controlName: SDN_C_PRE_LOAD, + displayName: 'SDN-C pre-load', + dataTestId: 'sdncPreLoad', + value: instance ? instance.sdncPreLoad : false, + validations: [new ValidatorModel(ValidatorOptions.required, 'is required')] + }) + }; + + getSupplementaryFile(instance: any): FileFormControl { + return new FileFormControl({ + controlName: SUPPLEMENTARY_FILE, + displayName: 'Supplementary Data File (JSON format)', + dataTestId: 'SupplementaryFile', + placeHolder: 'Choose file', + selectedFile: !_.isNil(instance) ? instance.supplementaryFileName: null, + isVisible: true, + acceptedExtentions: "application/json", + hiddenFile : [new InputFormControl({ + controlName: SUPPLEMENTARY_FILE + "_hidden", + isVisible: false, + validations: [new ValidatorModel(CustomValidatorOptions.isFileTooBig, "File size exceeds 5MB.", [FileUnit.MB, 5])] + }), + new InputFormControl({ + controlName: SUPPLEMENTARY_FILE + "_hidden_content", + isVisible: false, + validations: [new ValidatorModel(CustomValidatorOptions.isValidJson, + "File is invalid, please make sure a legal JSON file is uploaded using name:value pairs.",[]), + new ValidatorModel(CustomValidatorOptions.isStringContainTags, + "File is invalid, please remove tags <>.",[])], + value: !_.isNil(instance) ? (instance.supplementaryFile_hidden_content): null, + }) + ], + onDelete : this.getOnDeleteForSupplementaryFile(), + onChange : this.getOnChangeForSupplementaryFile() + }) + }; + + private getOnDeleteForSupplementaryFile() { + return (form: FormGroup) => { + form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null); + form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null); + }; + } + + private getOnChangeForSupplementaryFile() { + return (files: FileList, form: FormGroup) => { + if (files.length > 0) { + const file = files.item(0); + let reader = new FileReader(); + reader.onload = function (event) { + form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(reader.result); + form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(file); + }; + reader.readAsText(file); + } else { + form.controls[SUPPLEMENTARY_FILE + "_hidden"].setValue(null); + form.controls[SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null); + } + }; + } } diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts index 5b64aea9b..0bb278a8e 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/networkGenerator/network.control.generator.spec.ts @@ -7,11 +7,7 @@ import {GenericFormService} from "../../generic-form.service"; import {FormBuilder} from "@angular/forms"; import {LogService} from "../../../../utils/log/log.service"; import {FormControlNames, NetworkControlGenerator} from "./network.control.generator"; -import { - FormControlModel, - ValidatorModel, - ValidatorOptions -} from "../../../../models/formControlModels/formControl.model"; +import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; class MockAppStore<T> { @@ -25,9 +21,6 @@ class MockAppStore<T> { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts index a6a29d1df..6bcec09c4 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/service.control.generator.spec.ts @@ -25,9 +25,6 @@ class MockAppStore<T> { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts index 351f8393c..deb1a784a 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts @@ -1,18 +1,16 @@ import {getTestBed, TestBed} from '@angular/core/testing'; import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; import {NgRedux} from '@angular-redux/store'; -import {BasicControlGenerator} from "../basic.control.generator"; +import {BasicControlGenerator, SDN_C_PRE_LOAD} from "../basic.control.generator"; import {AaiService} from "../../../../services/aaiService/aai.service"; import {GenericFormService} from "../../generic-form.service"; import {FormBuilder} from "@angular/forms"; import {LogService} from "../../../../utils/log/log.service"; -import { - FormControlModel, - ValidatorModel, - ValidatorOptions -} from "../../../../models/formControlModels/formControl.model"; +import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model"; import {FormControlNames, VfModuleControlGenerator} from "./vfModule.control.generator"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; +import {VfModuleInstance} from "../../../../models/vfModuleInstance"; +import {VfModule} from "../../../../models/vfModule"; class MockAppStore<T> { getState() { @@ -25,9 +23,6 @@ class MockAppStore<T> { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -978,6 +973,46 @@ describe('VFModule Control Generator', () => { } }); + + const cases = [ + [true, true, true, null, true, true], + [true, true, false, null, true, false], //Scenario to check that UI field doesn't appear. + [false, true, false, "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0_vol", true, true], + [false, true, true, "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0_vol", true, true], + [false, false, true, null, false, false], + ]; + + test.each(cases)('Given Ecomp Gen Name: %p and VG Name %p , ' + + 'is A La Carte %p - expect the name value for VG to be %p , ' + + 'VG Name should be defined: %p , and should the field be visible: %p', + (ecomGenName, vGName, isALaCarte, expectedName, shouldWeVerifyDefinitionOfField, isVisible) => { + const moduleName = "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0"; + service.vfModuleModel = new VfModule(); + service.vfModuleModel.name = moduleName; + service.vfModuleModel.volumeGroupAllowed = vGName; + let vnf : Object = {isEcompGeneratedNaming: ecomGenName}; + const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44"; + const vnfStoreKey: string = 'VF_vGeraldine 0'; + const uuidData: Object = { + modelName : moduleName, + vFModuleStoreKey : "vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0vmvzo", + }; + const vfModuleModel :VfModuleInstance = service.getVfModuleInstance(serviceId, vnfStoreKey, uuidData,true); + let existingMatchingFieldInForm = buildVfModuleFormControlModel(vfModuleModel ,serviceId, vnf, isALaCarte); + if (shouldWeVerifyDefinitionOfField) { + expect(existingMatchingFieldInForm).toBeDefined(); + expect(existingMatchingFieldInForm.value).toEqual(expectedName); + expect(existingMatchingFieldInForm.isVisible).toEqual(isVisible); + } else { + expect(existingMatchingFieldInForm).toBeUndefined(); + } + }); + + let buildVfModuleFormControlModel = function(vfModuleModel :any, serviceId: string, vnf, isALaCarte) :FormControlModel { + let controls: FormControlModel[] = service.pushInstanceAndVGToForm([], vfModuleModel, serviceId, vnf, isALaCarte); + return controls.find(ctrl => ctrl.controlName === FormControlNames.VOLUME_GROUP_NAME); + }; + test('getMacroFormControls check for mandatory controls', () => { const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44"; const vnfStoreKey: string = 'VF_vGeraldine 0'; @@ -1022,7 +1057,7 @@ describe('VFModule Control Generator', () => { FormControlNames.LEGACY_REGION, FormControlNames.TENANT_ID, FormControlNames.ROLLBACK_ON_FAILURE, - FormControlNames.SDN_C_PRE_LOAD + SDN_C_PRE_LOAD, ]; expect(controls.length).toEqual(7); @@ -1057,7 +1092,7 @@ describe('VFModule Control Generator', () => { FormControlNames.TENANT_ID, // TENANT_ID must be after LEGACY_REGION FormControlNames.LEGACY_REGION, FormControlNames.ROLLBACK_ON_FAILURE, - FormControlNames.SDN_C_PRE_LOAD + SDN_C_PRE_LOAD, ]; for(let i = 0 ; i < orderedControls.length ; i++) { @@ -1114,7 +1149,7 @@ describe('VFModule Control Generator', () => { FormControlNames.LEGACY_REGION, FormControlNames.TENANT_ID, FormControlNames.ROLLBACK_ON_FAILURE, - FormControlNames.SDN_C_PRE_LOAD + SDN_C_PRE_LOAD, ]; for(let i = 0 ; i < orderedControls.length ; i++) { diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts index 3012c139c..8919c0419 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts @@ -37,8 +37,6 @@ export enum FormControlNames { LEGACY_REGION = 'legacyRegion', TENANT_ID = 'tenantId', ROLLBACK_ON_FAILURE = 'rollbackOnFailure', - SDN_C_PRE_LOAD = 'sdncPreLoad', - SUPPLEMENTARY_FILE = 'supplementaryFile' } @@ -46,7 +44,6 @@ export enum FormControlNames { export class VfModuleControlGenerator { aaiService: AaiService; vfModuleModel: VfModule; - vfModuleName : string; isUpdateMode : boolean; constructor(private genericFormService: GenericFormService, @@ -63,7 +60,6 @@ export class VfModuleControlGenerator { const vfModulesKeys = Object.keys(vfModules); for(let key of vfModulesKeys){ if(vfModules[key].uuid === vfModuleUuid){ - this.vfModuleName = key; return; } } @@ -105,15 +101,18 @@ export class VfModuleControlGenerator { let result: FormControlModel[] = []; if (!_.isNil(vfModuleModel)) { - result.push(this.getInstanceName(vfModuleInstance, serviceId, vnfModel.isEcompGeneratedNaming)); - if (this.vfModuleModel.volumeGroupAllowed) { - result.push(this.getVolumeGroupName(vfModuleInstance, serviceId, vnfStoreKey, vfModuleInstance && vfModuleInstance.volumeGroupName, vnfModel.isEcompGeneratedNaming)); - } + result = this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, false); } if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) { - let suppFileInput:FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance)); - result.push(suppFileInput); - result = result.concat(suppFileInput.hiddenFile); + result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance); + } + return result; + } + + pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean) :FormControlModel[]{ + result.push(this.getInstanceName(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming)); + if (this.vfModuleModel.volumeGroupAllowed) { + result.push(this.getVolumeGroupData(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming, isALaCarte)); } return result; } @@ -133,23 +132,16 @@ export class VfModuleControlGenerator { const vfModuleInstance = this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode); let result: FormControlModel[] = []; - result.push(this.getInstanceName(vfModuleInstance, serviceId, vnfModel.isEcompGeneratedNaming)); - - if (this.vfModuleModel.volumeGroupAllowed) { - result.push(this.getVolumeGroupName(vfModuleInstance, serviceId, vnfStoreKey, this.vfModuleName, vnfModel.isEcompGeneratedNaming)); - } + this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, true); result.push(this.getLcpRegionControl(serviceId, vfModuleInstance, result)); result.push(this._basicControlGenerator.getLegacyRegion(vfModuleInstance)); result.push(this.getTenantControl(serviceId, vfModuleInstance, result)); result.push(this.getRollbackOnFailureControl(vfModuleInstance, result)); - result.push(this.getSDNCControl(vfModuleInstance, result)); + result.push(this._basicControlGenerator.getSDNCControl(vfModuleInstance)); if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) { - let suppFileInput:FileFormControl = <FileFormControl>(this.getSupplementaryFile(vfModuleInstance)); - result.push(suppFileInput); - result = result.concat(suppFileInput.hiddenFile); + result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance); } return result; - } getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel { @@ -163,7 +155,7 @@ export class VfModuleControlGenerator { return formControlModel; } - getDefaultVolumeGroupName(instance: any, vfModuleName: string, isEcompGeneratedNaming: boolean): string { + getDefaultVolumeGroupName(instance: any, isEcompGeneratedNaming: boolean): string { if ((!_.isNil(instance) && instance.volumeGroupName)) { return instance.volumeGroupName; } @@ -173,7 +165,7 @@ export class VfModuleControlGenerator { return this._basicControlGenerator.getDefaultInstanceName(instance, this.vfModuleModel) + "_vol"; } - getVolumeGroupName(instance: any, serviceId: string, vnfStoreKey: string, vfModuleName: string, isEcompGeneratedNaming: boolean): FormControlModel { + getVolumeGroupData(instance: any, serviceId: string, isEcompGeneratedNaming: boolean, isALaCarte: boolean): FormControlModel { let validations: ValidatorModel[] = [ new ValidatorModel(ValidatorOptions.pattern, 'Instance name may include only alphanumeric characters and underscore.', BasicControlGenerator.INSTANCE_NAME_REG_EX), new ValidatorModel(CustomValidatorOptions.uniqueInstanceNameValidator, 'Volume Group instance name is already in use, please pick another name', [this.store, serviceId, instance && instance.volumeGroupName]) @@ -190,8 +182,8 @@ export class VfModuleControlGenerator { validations: validations, tooltip : 'When filled, VID will create a Volume Group by this name and associate with this module.\n' + 'When empty, the module is created without a Volume Group.', - isVisible: true, - value: this.getDefaultVolumeGroupName(instance, vfModuleName, isEcompGeneratedNaming), + isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming,isALaCarte), + value: this.getDefaultVolumeGroupName(instance, isEcompGeneratedNaming), onKeypress: (event) => { const pattern:RegExp = BasicControlGenerator.INSTANCE_NAME_REG_EX; if (pattern) { @@ -204,51 +196,13 @@ export class VfModuleControlGenerator { }); } - getSupplementaryFile(instance: any): FormControlModel { - return new FileFormControl({ - controlName: FormControlNames.SUPPLEMENTARY_FILE, - displayName: 'Supplementary Data File (JSON format)', - dataTestId: 'SupplementaryFile', - placeHolder: 'Choose file', - selectedFile: !_.isNil(instance) ? instance.supplementaryFileName: null, - isVisible: true, - acceptedExtentions: "application/json", - hiddenFile : [new InputFormControl({ - controlName: FormControlNames.SUPPLEMENTARY_FILE + "_hidden", - isVisible: false, - validations: [new ValidatorModel(CustomValidatorOptions.isFileTooBig, "File size exceeds 5MB.", [FileUnit.MB, 5])] - }), - new InputFormControl({ - controlName: FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content", - isVisible: false, - validations: [new ValidatorModel(CustomValidatorOptions.isValidJson, - "File is invalid, please make sure a legal JSON file is uploaded using name:value pairs.",[]), - new ValidatorModel(CustomValidatorOptions.isStringContainTags, - "File is invalid, please remove tags <>.",[])], - value: !_.isNil(instance) ? (instance.supplementaryFile_hidden_content): null, - }) - ], - onDelete : (form : FormGroup) => { - form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(null); - form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null); - }, - onChange : (files: FileList, form : FormGroup) => { - if (files.length > 0) { - const file = files.item(0); - let reader = new FileReader(); - reader.onload = function(event) { - form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(reader.result); - form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(file); - }; - reader.readAsText(file); - } - else { - form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden"].setValue(null); - form.controls[FormControlNames.SUPPLEMENTARY_FILE + "_hidden_content"].setValue(null); - } - } - }) - }; + private shouldVGNameBeVisible(isEcompGeneratedNaming: boolean, isALaCarte: boolean) { + if((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte){ + return true; + } + return false; + + } getTenantControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => { const service = this.store.getState().service.serviceInstance[serviceId]; @@ -316,17 +270,6 @@ export class VfModuleControlGenerator { }) }; - getSDNCControl = (instance: any, controls: FormControlModel[]): CheckboxFormControl => { - return new CheckboxFormControl({ - type: FormControlType.CHECKBOX, - controlName: 'sdncPreLoad', - displayName: 'SDN-C pre-load', - dataTestId: 'sdncPreLoad', - value: instance ? instance.sdncPreLoad : false, - validations: [new ValidatorModel(ValidatorOptions.required, 'is required')] - }) - }; - getRollbackOnFailureControl = (instance: any, controls: FormControlModel[]): DropdownFormControl => { return new DropdownFormControl({ type: FormControlType.DROPDOWN, diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts index 66afac9ad..28d49d51b 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts @@ -6,16 +6,13 @@ import {BasicControlGenerator} from "../basic.control.generator"; import {AaiService} from "../../../../services/aaiService/aai.service"; import {GenericFormService} from "../../generic-form.service"; import {FormBuilder} from "@angular/forms"; -import { - FormControlModel, - ValidatorModel, - ValidatorOptions -} from "../../../../models/formControlModels/formControl.model"; +import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model"; import {LogService} from "../../../../utils/log/log.service"; import {VnfControlGenerator} from "./vnf.control.generator"; import {Observable} from "rxjs"; import {SelectOption} from "../../../../models/selectOption"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; +import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum"; class MockAppStore<T> { getState(){ @@ -28,9 +25,6 @@ class MockAppStore<T> { "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -941,6 +935,18 @@ describe('VNF Control Generator', () => { })().then(done).catch(done.fail)); + test('should generate platform multi select control', ()=>{ + const control = service.getPlatformMultiselectControl(null, [],false); + expect(control.type).toEqual(FormControlType.MULTI_SELECT); + expect(control.controlName).toEqual('platformName'); + expect(control.displayName).toEqual('Platform'); + expect(control.dataTestId).toEqual('multi-selectPlatform'); + expect(control.selectedFieldName).toEqual('name'); + expect(control.value).toEqual(''); + expect(control.onChange).toBeDefined(); + expect(control.convertOriginalDataToArray).toBeDefined(); + }); + test('getMacroFormControls check for mandatory controls', () => { const serviceId : string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44"; const vnfName : string = "VF_vGeraldine 0"; diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts index 7760ba8ad..ff0a525b5 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts @@ -15,11 +15,12 @@ import {AppState} from "../../../../store/reducers"; import {FormGroup} from "@angular/forms"; import {DropdownFormControl} from "../../../../models/formControlModels/dropdownFormControl.model"; import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum"; -import {InputFormControl} from "../../../../models/formControlModels/inputFormControl.model"; import {Observable, of} from "rxjs"; import {SelectOption} from "../../../../models/selectOption"; import * as _ from 'lodash'; import {Constants} from "../../../../utils/constants"; +import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; +import {MultiSelectItem} from "../../../formControls/component/multiselect/multiselect.model"; export enum FormControlNames { INSTANCE_NAME = 'instanceName', @@ -76,6 +77,7 @@ export class VnfControlGenerator { const vnfInstance = this.getVnfInstance(serviceId, vnfStoreKey); const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfName]); let result: FormControlModel[] = []; + const flags = this.store.getState().global.flags; if (!_.isNil(vnfModel)) { result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming)); @@ -83,7 +85,7 @@ export class VnfControlGenerator { result.push(this.getLcpRegionControl(serviceId, vnfInstance, result)); result.push(this._basicControlGenerator.getLegacyRegion(vnfInstance)); result.push(this.getTenantControl(serviceId, vnfInstance, result)); - result.push(this.getPlatformControl(vnfInstance, result)); + result.push(this.getPlatformMultiselectControl(vnfInstance, result, flags['FLAG_2002_VNF_PLATFORM_MULTI_SELECT'])); result.push(this.getLineOfBusinessControl(vnfInstance, result)); } return result; @@ -101,12 +103,13 @@ export class VnfControlGenerator { const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfName]); if (!_.isNil(vnfModel)) { + const flags = this.store.getState().global.flags; result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming)); result.push(this._basicControlGenerator.getProductFamilyControl(vnfInstance, result, false)); result.push(this.getLcpRegionControl(serviceId, vnfInstance, result)); result.push(this._basicControlGenerator.getLegacyRegion(vnfInstance)); result.push(this.getTenantControl(serviceId, vnfInstance, result)); - result.push(this.getPlatformControl(vnfInstance, result)); + result.push(this.getPlatformMultiselectControl(vnfInstance, result, flags['FLAG_2002_VNF_PLATFORM_MULTI_SELECT'])); result.push(this.getLineOfBusinessControl(vnfInstance, result)); result.push(this.getRollbackOnFailureControl(vnfInstance, result)); } @@ -139,20 +142,34 @@ export class VnfControlGenerator { }) }; - getPlatformControl = (instance: any, controls: FormControlModel[]): DropdownFormControl => { - return new DropdownFormControl({ - type: FormControlType.DROPDOWN, + + + getPlatformMultiselectControl = (instance: any, controls: FormControlModel[], isMultiSelected: boolean) : MultiselectFormControl => { + return new MultiselectFormControl({ + type: FormControlType.MULTI_SELECT , controlName: 'platformName', displayName: 'Platform', - dataTestId: 'platform', + dataTestId: 'multi-selectPlatform', + selectedFieldName : 'name' , + ngValue : 'name', placeHolder: 'Select Platform', isDisabled: false, name: "platform", - value: instance ? instance.platformName : null, + value: instance ? instance.platformName : '', + limitSelection : isMultiSelected ? 1000 : 1, validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], onInitSelectedField: ['platformList'], - onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters) - }) + onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters), + onChange : (param: MultiSelectItem[], form: FormGroup) => { + form.controls['platformName'].setValue(param.map((multiSelectItem: MultiSelectItem)=>{ + return multiSelectItem.itemName + }).join(',')); + }, + convertOriginalDataToArray : (value?: string) => { + if(_.isNil(value)) return []; + return value.split(','); + } + }); }; getTenantControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => { diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts index 71d661191..81cfd9614 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator.spec.ts @@ -6,11 +6,7 @@ import {BasicControlGenerator} from "../basic.control.generator"; import {AaiService} from "../../../../services/aaiService/aai.service"; import {GenericFormService} from "../../generic-form.service"; import {FormBuilder} from "@angular/forms"; -import { - FormControlModel, - ValidatorModel, - ValidatorOptions -} from "../../../../models/formControlModels/formControl.model"; +import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model"; import {LogService} from "../../../../utils/log/log.service"; import {VnfGroupControlGenerator} from "./vnfGroup.control.generator"; import {Observable} from "rxjs"; @@ -25,19 +21,14 @@ class MockAppStore<T> { "type": "UPDATE_DRAWING_BOARD_STATUS", "drawingBoardStatus": "CREATE", "flags": { - "CREATE_INSTANCE_TEST": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_NETWORK_TO_ASYNC_INSTANTIATION": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true, "FLAG_SERVICE_MODEL_CACHE": false, "FLAG_SHOW_ASSIGNMENTS": true, "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, - "FLAG_DEFAULT_VNF": true, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": true, "FLAG_A_LA_CARTE_AUDIT_INFO": true, "FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST": true, "FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS": true, - "FLAG_1810_CR_SOFT_DELETE_ALACARTE_VF_MODULE": true, "FLAG_1902_NEW_VIEW_EDIT": true } }, diff --git a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html index d4c5118b3..edf86823c 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html +++ b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html @@ -6,6 +6,11 @@ <checkbox-form-control *ngSwitchCase="'CHECKBOX'" [data]="formControl" [form]="dynamicFormGroup" ></checkbox-form-control> <dropdown-form-control *ngSwitchCase="'DROPDOWN'" [data]="formControl" [form]="dynamicFormGroup" ></dropdown-form-control> <file-form-control *ngSwitchCase="'FILE'" [data]="formControl" [form]="dynamicFormGroup"></file-form-control> + <multiselect-form-control *ngSwitchCase="'MULTI_SELECT'" + [data]="formControl" + [form]="dynamicFormGroup" + [multiselectOptions]="formControl?.options$" + [selectedItems]="formControl.value"></multiselect-form-control> </div> <div *ngIf="dynamicFormGroup != null && formControl != null && dynamicFormGroup.controls[formControl.controlName]?.errors"> <div *ngFor="let validatorModel of formControl?.validations"> diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html index 57064f658..f9a11eab1 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html @@ -3,14 +3,13 @@ <div class="modal-header"> <button type="button" class="close" - (click)="formPopupDetails?.onCancel(formPopupDetails.that,dynamicForm)" >× + (click)="formPopupDetails?.onCancel(formPopupDetails.that,dynamicForm)">× </button> <span [attr.data-tests-id]="'create-modal-title'" class="modal-title">{{formPopupDetails?.title}} </span> </div> <div class="modal-body popup-content"> - <div class="header-left"> <div>MODEL: <span>"{{formPopupDetails?.leftSubTitle}}"</span></div> </div> @@ -36,12 +35,14 @@ <model-information [modelInformationItems]="formPopupDetails?.modelInformationItems"></model-information> </div> - <div class="instance-form"> + <div class="instance-form"> <div style="position: relative;height: 100%;overflow: auto;"> - <label id="notification-area" *ngIf="shouldShowNotification() == true" style="color: #959595;font-size: 12px;left: 30px;margin-left: 30px;">Data entered will apply to all service instances</label> - <generic-form [formControls]="formPopupDetails?.formControlList" - [dynamicInputs]="formPopupDetails?.dynamicInputsControlList" - (onFormChanged)="dynamicForm = $event" ></generic-form> + <label id="notification-area" *ngIf="shouldShowNotification() == true" + style="color: #959595;font-size: 12px;left: 30px;margin-left: 30px;">Data entered will apply to all + service instances</label> + <generic-form [formControls]="formPopupDetails?.formControlList" + [dynamicInputs]="formPopupDetails?.dynamicInputsControlList" + (onFormChanged)="dynamicForm = $event"></generic-form> </div> </div> @@ -54,6 +55,19 @@ </div> <div class="col-md-6" style="padding: 15px;padding-right: 35px;"> <button + *ngIf="showTemplateBtn" + [attr.data-tests-id]="'templateButton'" + type="button" class="btn btn-success submit" + (click)="openTemplateModal()" + ><span>Template</span></button> + <button + *ngIf="isShowPreviousInstantiationBtn" + [attr.data-tests-id]="'ShowPreviousInstancesButton'" + type="button" class="btn btn-success submit" + (click)="formPopupDetails.onOtherAction(formPopupDetails.that, dynamicForm)"> + <span>Previous Instantiation</span> + </button> + <button [attr.data-tests-id]="'cancelButton'" type="button" class="btn btn-default cancel" (click)="formPopupDetails.onCancel(formPopupDetails.that, dynamicForm)"><span>Cancel</span></button> diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss index 5057b44a5..18416dae6 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss @@ -134,7 +134,7 @@ $grid-border: 1px #d2d2d2 solid; } .submit { - width: 120px; + min-width: 120px; height: 36px; background: #009fdb; border-radius: 2px; diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts index 8a95d108f..3939e44ff 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts @@ -13,55 +13,62 @@ import {AaiService} from "../../services/aaiService/aai.service"; import {GenericFormPopupService} from "./generic-form-popup.service"; import {FormControlModel} from "../../models/formControlModels/formControl.model"; import {FormGeneralErrorsService} from "../formGeneralErrors/formGeneralErrors.service"; +import {FeatureFlagsService, Features} from "../../services/featureFlag/feature-flags.service"; +import {InstantiationTemplatesModalComponent} from "./instantiationTemplatesModal/instantiation.templates.modal.component"; export interface PopupModel { - type : PopupType; - uuidData : UUIDData; - node : ITreeNode; - isUpdateMode : boolean; + type: PopupType; + uuidData: UUIDData; + node: ITreeNode; + isUpdateMode: boolean; } -export enum PopupType{ +export enum PopupType { SERVICE = 'service', VNF = 'vnf', NETWORK = 'network', VF_MODULE = 'vf_module', + VF_MODULE_UPGRADE = 'vf_module_upgrade', VNF_GROUP = 'vnf_group' } @Component({ - selector : 'generic-form-popup', - templateUrl : 'generic-form-popup.component.html', - styleUrls : ['generic-form-popup.component.scss'] + selector: 'generic-form-popup', + templateUrl: 'generic-form-popup.component.html', + styleUrls: ['generic-form-popup.component.scss'] }) -export class GenericFormPopupComponent extends DialogComponent<PopupModel, boolean> implements OnInit, OnDestroy{ - formPopupDetails : FormPopupDetails = null; - dynamicForm : FormGroup; - type : PopupType; - uuidData : UUIDData; - isUpdateMode : boolean; - node : ITreeNode = null; - hasGeneralApiError : boolean = false; +export class GenericFormPopupComponent extends DialogComponent<PopupModel, boolean> implements OnInit, OnDestroy { + formPopupDetails: FormPopupDetails = null; + dynamicForm: FormGroup; + type: PopupType; + uuidData: UUIDData; + showTemplateBtn: boolean = false; + isShowPreviousInstantiationBtn: boolean = false; + isUpdateMode: boolean; + node: ITreeNode = null; + hasGeneralApiError: boolean = false; parentElementClassName = 'content'; errorMsg = 'Page contains errors. Please see details next to the relevant fields.'; servicesQty = 1; quantityOptions = _.range(1, 51) - constructor(dialogService: DialogService , - private _iframeService : IframeService, + + constructor(dialogService: DialogService, + private _iframeService: IframeService, private _store: NgRedux<AppState>, - private _servicePopupService : ServicePopupService, - private _activatedRoute : ActivatedRoute, - private _aaiService : AaiService, + private _servicePopupService: ServicePopupService, + private _activatedRoute: ActivatedRoute, + private _aaiService: AaiService, + private _dialogService: DialogService, private _route: ActivatedRoute, - private _genericFormPopupService : GenericFormPopupService){ + private _genericFormPopupService: GenericFormPopupService) { super(dialogService); } - closeDialog(that) : void{ + closeDialog(that): void { this._iframeService.removeClassCloseModal(that.parentElementClassName); this.dialogService.removeDialog(this); setTimeout(() => { @@ -69,7 +76,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole }, 15); } - shouldShowNotification() : boolean { + shouldShowNotification(): boolean { return this.formPopupDetails && this.formPopupDetails.UUIDData['bulkSize'] > 1 } @@ -78,38 +85,17 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole .queryParams .subscribe(params => { console.log('changed'); - if(params['serviceModelId'] && params['isCreate']=="true"){ - this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId : string)=>{ - this.uuidData = <any>{ - bulkSize : 1, - isMacro : this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro', - type : PopupType.SERVICE, - serviceId: serviceModelId, - popupService: this._servicePopupService, - }; - - this.uuidData.popupService.closeDialogEvent.subscribe((that)=>{ - this.closeDialog(that); - }); - - this.formPopupDetails = this.uuidData.popupService.getGenericFormPopupDetails( - this.uuidData['serviceId'], - null, - null, - this.node, - this.uuidData, - false - ); - }); + if (params['serviceModelId'] && params['isCreate'] == "true") { + this.onInitForCreateNewServicePopup(); } }); - FormGeneralErrorsService.checkForErrorTrigger.subscribe(()=>{ + FormGeneralErrorsService.checkForErrorTrigger.subscribe(() => { this.hasSomeError(this.formPopupDetails, this.dynamicForm); }); - - if(!_.isNil(this.uuidData)){ - this.uuidData.popupService.closeDialogEvent.subscribe((that)=>{ + + if (!_.isNil(this.uuidData)) { + this.uuidData.popupService.closeDialogEvent.subscribe((that) => { this.closeDialog(that); }); @@ -118,28 +104,62 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole } } - hasSomeError(formPopupDetails : FormPopupDetails, form : FormGroup) : boolean{ - if(_.isNil(formPopupDetails)) return false; + private onInitForCreateNewServicePopup() { + this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId: string) => { + this.uuidData = <any>{ + bulkSize: 1, + isMacro: this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro', + type: PopupType.SERVICE, + serviceId: serviceModelId, + popupService: this._servicePopupService, + }; + this.showTemplateBtn = !!this._store.getState().global.flags["FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"]; + + this.isShowPreviousInstantiationBtn = !!this._store.getState().global.flags["FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER"]; + + this.uuidData.popupService.closeDialogEvent.subscribe((that) => { + this.closeDialog(that); + }); + + this.formPopupDetails = this.uuidData.popupService.getGenericFormPopupDetails( + this.uuidData['serviceId'], + null, + null, + this.node, + this.uuidData, + false + ); + }); + } + + hasSomeError(formPopupDetails: FormPopupDetails, form: FormGroup): boolean { + if (_.isNil(formPopupDetails)) return false; else { - for(let controlName in form.controls){ - if(form.controls[controlName].errors){ + for (let controlName in form.controls) { + if (form.controls[controlName].errors) { let error: string[] = Object.keys(form.controls[controlName].errors); - if(error.length === 1 && error[0] === 'required'){ + if (error.length === 1 && error[0] === 'required') { continue; - }else if(Object.keys(form.controls[controlName].errors).length > 0 ){ + } else if (Object.keys(form.controls[controlName].errors).length > 0) { return true; } } } } - return formPopupDetails.formControlList.filter((item : FormControlModel) => item.type === 'DROPDOWN' && item['hasEmptyOptions'] && item.isRequired()).length > 0 + return formPopupDetails.formControlList.filter((item: FormControlModel) => item.type === 'DROPDOWN' && item['hasEmptyOptions'] && item.isRequired()).length > 0 } + + + openTemplateModal = (): void => { + this._dialogService.addDialog(InstantiationTemplatesModalComponent, {}); + } + } -export class UUIDData extends Object{ - type : string; - popupService : any; +export class UUIDData extends Object { + type: string; + popupService: any; } diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts index fa77bed5f..63c980cd5 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts @@ -20,6 +20,7 @@ import {NetworkControlGenerator} from "../genericForm/formControlsServices/netwo import {VfModulePopuopService} from "./genericFormServices/vfModule/vfModule.popuop.service"; import {VfModuleControlGenerator} from "../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator"; import {FeatureFlagsService} from "../../services/featureFlag/feature-flags.service"; +import {VfModuleUpgradePopupService} from "./genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; class MockAppStore<T>{ getState() { @@ -32,9 +33,6 @@ class MockAppStore<T>{ "FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS": true, "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -970,6 +968,7 @@ describe('Generic Form popup Service', () => { NetworkPopupService, NetworkControlGenerator, VfModulePopuopService, + VfModuleUpgradePopupService, VfModuleControlGenerator, {provide:FeatureFlagsService, useClass: MockFeatureFlagsService}, {provide: ActivatedRoute, useClass: ActivatedRouteMock}, diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts index 54af063d8..a3c83263c 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts @@ -33,10 +33,7 @@ class MockReduxStore<T> { "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_ADVANCED_PORTS_FILTER": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, "FLAG_REGION_ID_FROM_REMOTE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts index 5d4d16567..1d44a9e5e 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts @@ -10,6 +10,7 @@ import * as _ from 'lodash'; import {VfModule} from "../../../models/vfModule"; import {VNFModel} from "../../../models/vnfModel"; import {VnfGroupModel} from "../../../models/vnfGroupModel"; +import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service"; @Injectable() export class BasicPopupService { @@ -29,17 +30,18 @@ export class BasicPopupService { } getModelFromResponse(result: any, modelType: string, modelName: string) { + let flags = FeatureFlagsService.getAllFlags(this._store); let rawModel = result[modelType][modelName]; if (!rawModel) return; switch (modelType){ case 'vnfs' : { - return new VNFModel(rawModel); + return new VNFModel(rawModel, flags); } case 'vfModules' : { - return new VfModule(rawModel); + return new VfModule(rawModel, flags); } case 'networks' : { - return new NetworkModel(rawModel); + return new NetworkModel(rawModel, flags); } case 'vnfGroups' : { return new VnfGroupModel(rawModel); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts index eb094abfb..67c371212 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts @@ -30,10 +30,7 @@ class MockReduxStore<T> { "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_ADVANCED_PORTS_FILTER": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, "FLAG_REGION_ID_FROM_REMOTE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts index 5b5acd33b..ebea695f7 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts @@ -31,10 +31,7 @@ class MockReduxStore<T> { "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_ADVANCED_PORTS_FILTER": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, "FLAG_REGION_ID_FROM_REMOTE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -2143,6 +2140,33 @@ describe('Service popup service', () => { expect(service.closeDialogEvent.next).toHaveBeenCalledWith(that); }); + test('showPreviousInstantiations should trigger postMessage', () => { + let that = <any>{ + parentElementClassName: 'content', + _iframeService: iframeService, + resetPopupData : () =>{ }, + serviceModel:{ + uuid:'1111' + } + + }; + + let expectedMessage= { + eventId: 'showPreviousInstantiations', + data: { + serviceModelId: that.serviceModel.uuid + } + }; + + jest.spyOn(window.parent, 'postMessage'); + + service.showPreviousInstantiations(that, fb.group({})); + + expect( window.parent.postMessage).toHaveBeenCalledWith(expectedMessage,"*") + + }); + + test('getDynamicInputs should return list of controls' ,() => { const result: FormControlModel[] = service.getDynamicInputs('6b528779-44a3-4472-bdff-9cd15ec93450'); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts index 7694e6314..3e7e8c1e5 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts @@ -20,6 +20,7 @@ import {ModelInfo} from "../../../../models/modelInfo"; import {FormControlModel} from "../../../../models/formControlModels/formControl.model"; import {createServiceInstance, updateServiceInstance} from "../../../../storeUtil/utils/service/service.actions"; import * as _ from 'lodash'; +import {Utils} from "../../../../utils/utils"; @Injectable() export class ServicePopupService implements GenericPopupInterface { @@ -58,7 +59,12 @@ export class ServicePopupService implements GenericPopupInterface { this.getDynamicInputs(serviceId), this.modelInformations, (that, form: FormGroup) => {that.onSubmit(that, form);}, - (that: any, form: FormGroup) => {that.onCancel(that, form); } + (that: any, form: FormGroup) => { + that.onCancel(that, form); + }, + (that: any, form: FormGroup) => { + that.showPreviousInstantiations(that, form); + } ); } @@ -122,13 +128,24 @@ export class ServicePopupService implements GenericPopupInterface { onSubmit(that, form: FormGroup, ...args): void { form = that.updateExtraValues(that, form); that.storeServiceInstance(form.value, args[0], [], new ModelInfo(that.serviceModel), that.serviceModel); - window.parent.postMessage( { - eventId: 'submitIframe', + const eventId = 'submitIframe'; + this.postMessageToWindowParent(eventId, that.serviceModel.uuid); + this.onCancel(that, form); + } + + showPreviousInstantiations(that, form: FormGroup,): void { + const eventId = 'showPreviousInstantiations'; + this.postMessageToWindowParent(eventId, that.serviceModel.uuid); + this.onCancel(that, form); + } + + private postMessageToWindowParent(eventId: string, serviceModelId:string) { + window.parent.postMessage({ + eventId: eventId, data: { - serviceModelId: that.serviceModel.uuid + serviceModelId } }, "*"); - this.onCancel(that, form); } updateExtraValues = (that, form) : any => { @@ -163,13 +180,13 @@ export class ServicePopupService implements GenericPopupInterface { this._store.dispatch(updateServiceInstance(formValues, serviceModel.modelVersionId)); } - if (this._store.getState().global.flags['FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD'] && isCreateMode) { + if (isCreateMode) { this._defaultDataGeneratorService.updateReduxOnFirstSet(serviceModel.modelVersionId, formValues); } }; setIsALaCarte = (formValues: any, instantiationType) => { - formValues.isALaCarte = instantiationType === 'ALaCarte'; + formValues.isALaCarte = Utils.isALaCarte(instantiationType); }; setTestApi = (formValues: any) =>{ diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts index 5b27b6e29..6c487102f 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.spec.ts @@ -30,10 +30,7 @@ class MockReduxStore<T> { "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_ADVANCED_PORTS_FILTER": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, "FLAG_REGION_ID_FROM_REMOTE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts index c7a71efc0..20336e5eb 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service.ts @@ -21,8 +21,7 @@ import {FormControlModel} from "../../../../models/formControlModels/formControl import * as _ from 'lodash'; import {createVFModuleInstance, updateVFModuleInstance} from "../../../../storeUtil/utils/vfModule/vfModule.actions"; -@Injectable() -export class VfModulePopuopService implements GenericPopupInterface { +export abstract class VfModulePopupServiceBase { dynamicInputs: any; instance: any; model: any; @@ -31,16 +30,27 @@ export class VfModulePopuopService implements GenericPopupInterface { uuidData: Object; closeDialogEvent: Subject<any> = new Subject<any>(); isUpdateMode: boolean; + storeVFModule = (that, formValues: any): void => { + formValues.modelInfo = new ModelInfo(that.model); + formValues.uuid = formValues.modelInfo.uuid; + formValues.isMissingData = false; + const vnf = that._store.getState().service.serviceInstance[that.uuidData.serviceId].vnfs[that.uuidData.vnfStoreKey]; + if (!that.uuidData.vFModuleStoreKey) { + this._store.dispatch(createVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, 0, that.uuidData.vnfStoreKey)); + } else { + this._store.dispatch(updateVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, that.uuidData.vFModuleStoreKey, that.uuidData.vnfStoreKey)); + } + }; - constructor(private _basicControlGenerator: BasicControlGenerator, - private _vfModuleControlGenerator: VfModuleControlGenerator, - private _iframeService: IframeService, - private _defaultDataGeneratorService: DefaultDataGeneratorService, - private _aaiService: AaiService, - private _basicPopupService : BasicPopupService, - private _store: NgRedux<AppState>) { - + protected constructor( + protected _basicControlGenerator: BasicControlGenerator, + protected _vfModuleControlGenerator: VfModuleControlGenerator, + protected _iframeService: IframeService, + protected _defaultDataGeneratorService: DefaultDataGeneratorService, + protected _aaiService: AaiService, + protected _basicPopupService: BasicPopupService, + protected _store: NgRedux<AppState>) { } getInstance(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string): any { @@ -51,45 +61,6 @@ export class VfModulePopuopService implements GenericPopupInterface { return vfModules[this.uuidData['modelName']][vfModuleStoreKey]; } - getDynamicInputs(UUIDData : Object) : FormControlModel[]{ - let dynamic = this._defaultDataGeneratorService.getArbitraryInputs(this._store.getState().service.serviceHierarchy[UUIDData['serviceId']].vfModules[UUIDData['modelName']].inputs); - return this.getVFModuleDynamicInputs(dynamic, UUIDData); - } - - getVFModuleDynamicInputs(dynamicInputs : any, UUIDData : Object) : FormControlModel[] { - let result : FormControlModel[] = []; - if(dynamicInputs) { - let vfModuleInstance = null; - if (_.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs, UUIDData['vnfStoreKey']) && - _.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules, UUIDData['modelName'])) { - vfModuleInstance = Object.assign({},this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules[UUIDData['modelName']][UUIDData['vfModuleStoreKey']]); - } - result = this._basicControlGenerator.getDynamicInputs(dynamicInputs, vfModuleInstance); - } - return result; - } - - - getGenericFormPopupDetails(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, node: ITreeNode, uuidData: Object, isUpdateMode: boolean): FormPopupDetails { - - this.uuidData = uuidData; - this.instance = this.getInstance(serviceId, vnfStoreKey, vfModuleStoreKey); - this.getModelInformation(serviceId, uuidData['modelName']); - - return new FormPopupDetails(this, - PopupType.VFMODULE, - uuidData, - this.getTitle(isUpdateMode), - this.getSubLeftTitle(), - this.getSubRightTitle(), - this.getControls(serviceId, vnfStoreKey, vfModuleStoreKey, isUpdateMode), - this.getDynamicInputs(uuidData), - this.modelInformations, - (that, form: FormGroup) => {that.onSubmit(that, form);}, - (that: any, form: FormGroup) => {that.onCancel(that, form); } - ); - } - getModelInformation(serviceId: string, modelName: string) { this._aaiService.getServiceModelById(serviceId).subscribe((result: any) => { this.serviceModel = new ServiceModel(result); @@ -116,69 +87,125 @@ export class VfModulePopuopService implements GenericPopupInterface { }); } - getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean) { - if (this._store.getState().service.serviceHierarchy[serviceId].service.vidNotions.instantiationType === 'Macro') { - return this._vfModuleControlGenerator.getMacroFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode); - } else { - return this._vfModuleControlGenerator.getAlaCarteFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode); - } + protected postSubmitIframeMessage(that) { + window.parent.postMessage({ + eventId: 'submitIframe', + data: { + serviceModelId: that.serviceModel.uuid + } + }, "*"); } + onCancel(that, form) { + form.reset(); + that._iframeService.removeClassCloseModal('content'); + this.closeDialogEvent.next(that); + } - onSubmit(that, form: FormGroup) { - form.value['instanceParams'] = form.value['instanceParams'] && [form.value['instanceParams']]; + getSubLeftTitle(): string { + return this.model.name; + } + + getSubRightTitle(): string { + return "Module (Heat stack) Instance Details"; + } + + abstract getTitle(isUpdateMode : boolean) : string; + abstract getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean); + abstract getDynamicInputs(UUIDData : Object) : FormControlModel[]; + + getGenericFormPopupDetails(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, node: ITreeNode, uuidData: Object, isUpdateMode: boolean): FormPopupDetails { + + this.uuidData = uuidData; + this.instance = this.getInstance(serviceId, vnfStoreKey, vfModuleStoreKey); + this.getModelInformation(serviceId, uuidData['modelName']); + + return new FormPopupDetails(this, + PopupType.VFMODULE, + uuidData, + this.getTitle(isUpdateMode), + this.getSubLeftTitle(), + this.getSubRightTitle(), + this.getControls(serviceId, vnfStoreKey, vfModuleStoreKey, isUpdateMode), + this.getDynamicInputs(uuidData), + this.modelInformations, + (that, form: FormGroup) => { + that.onSubmit(that, form); + }, + (that: any, form: FormGroup) => { + that.onCancel(that, form); + } + ); + } + + updateFormValueWithSupplementaryFile(form: FormGroup, that) { if (!_.isNil(form.controls['supplementaryFile_hidden_content']) && form.controls['supplementaryFile_hidden_content'].value) { form.value['supplementaryFileContent'] = JSON.parse(form.controls['supplementaryFile_hidden_content'].value); if (!_.isNil(form.controls['supplementaryFile_hidden'].value)) { form.value['supplementaryFileName'] = form.controls['supplementaryFile_hidden'].value.name; - } - else { + } else { form.value['supplementaryFileName'] = that.instance.supplementaryFileName; } - } - else { + } else { delete form.value['supplementaryFileContent']; delete form.value['supplementaryFileName']; } - that.storeVFModule(that, form.value); - window.parent.postMessage({ - eventId: 'submitIframe', - data: { - serviceModelId: that.serviceModel.uuid - } - }, "*"); - this.onCancel(that, form); } +} +@Injectable() +export class VfModulePopuopService extends VfModulePopupServiceBase implements GenericPopupInterface { + + + constructor(_basicControlGenerator: BasicControlGenerator, + _vfModuleControlGenerator: VfModuleControlGenerator, + _iframeService: IframeService, + _defaultDataGeneratorService: DefaultDataGeneratorService, + _aaiService: AaiService, + _basicPopupService : BasicPopupService, + _store: NgRedux<AppState>) { + super(_basicControlGenerator, _vfModuleControlGenerator, _iframeService, _defaultDataGeneratorService, _aaiService, _basicPopupService, _store); - onCancel(that, form) { - form.reset(); - that._iframeService.removeClassCloseModal('content'); - this.closeDialogEvent.next(that); } - storeVFModule = (that, formValues: any): void => { - formValues.modelInfo = new ModelInfo(that.model); - formValues.uuid = formValues.modelInfo.uuid; - formValues.isMissingData = false; - const vnf = that._store.getState().service.serviceInstance[that.uuidData.serviceId].vnfs[that.uuidData.vnfStoreKey]; + getDynamicInputs(UUIDData : Object) : FormControlModel[]{ + let dynamic = this._defaultDataGeneratorService.getArbitraryInputs(this._store.getState().service.serviceHierarchy[UUIDData['serviceId']].vfModules[UUIDData['modelName']].inputs); + return this.getVFModuleDynamicInputs(dynamic, UUIDData); + } - if (!that.uuidData.vFModuleStoreKey) { - this._store.dispatch(createVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, 0, that.uuidData.vnfStoreKey)); - } else { - this._store.dispatch(updateVFModuleInstance(formValues, that.uuidData.modelName, that.uuidData.serviceId, that.uuidData.vFModuleStoreKey, that.uuidData.vnfStoreKey)); + getVFModuleDynamicInputs(dynamicInputs : any, UUIDData : Object) : FormControlModel[] { + let result : FormControlModel[] = []; + if(dynamicInputs) { + let vfModuleInstance = null; + if (_.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs, UUIDData['vnfStoreKey']) && + _.has(this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules, UUIDData['modelName'])) { + vfModuleInstance = Object.assign({},this._store.getState().service.serviceInstance[UUIDData['serviceId']].vnfs[UUIDData['vnfStoreKey']].vfModules[UUIDData['modelName']][UUIDData['vfModuleStoreKey']]); + } + result = this._basicControlGenerator.getDynamicInputs(dynamicInputs, vfModuleInstance); } - }; + return result; + } - getTitle(isUpdateMode : boolean) : string { - return isUpdateMode ? 'Edit Module (Heat stack)' : 'Set new Module (Heat stack)'; + + getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean) { + if (this._store.getState().service.serviceHierarchy[serviceId].service.vidNotions.instantiationType === 'Macro') { + return this._vfModuleControlGenerator.getMacroFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode); + } else { + return this._vfModuleControlGenerator.getAlaCarteFormControls(serviceId, vnfStoreKey, vfModuleStoreKey, this.uuidData, isUpdateMode); + } } - getSubLeftTitle(): string { - return this.model.name; + + onSubmit(that, form: FormGroup) { + form.value['instanceParams'] = form.value['instanceParams'] && [form.value['instanceParams']]; + this.updateFormValueWithSupplementaryFile(form, that); + that.storeVFModule(that, form.value); + this.postSubmitIframeMessage(that); + this.onCancel(that, form); } - getSubRightTitle(): string { - return "Module (Heat stack) Instance Details"; + getTitle(isUpdateMode : boolean) : string { + return isUpdateMode ? 'Edit Module (Heat stack)' : 'Set new Module (Heat stack)'; } + } diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service.ts new file mode 100644 index 000000000..bbfe8705e --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service.ts @@ -0,0 +1,95 @@ +import {Injectable} from "@angular/core"; +import {ITreeNode} from "angular-tree-component/dist/defs/api"; +import {FormGroup} from "@angular/forms"; +import {VfModulePopupServiceBase} from "../vfModule/vfModule.popuop.service"; +import {upgradeVFModule} from "../../../../storeUtil/utils/vfModule/vfModule.actions"; +import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service"; +import {NgRedux} from "@angular-redux/store"; +import {AppState} from "../../../../store/reducers"; +import {BasicControlGenerator} from "../../../genericForm/formControlsServices/basic.control.generator"; +import {VfModuleControlGenerator} from "../../../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator"; +import {IframeService} from "../../../../utils/iframe.service"; +import {DefaultDataGeneratorService} from "../../../../services/defaultDataServiceGenerator/default.data.generator.service"; +import {AaiService} from "../../../../services/aaiService/aai.service"; +import {BasicPopupService} from "../basic.popup.service"; +import {FormControlModel} from "../../../../models/formControlModels/formControl.model"; +import {CheckboxFormControl} from "../../../../models/formControlModels/checkboxFormControl.model"; +import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum"; +import {mergeObjectByPathAction} from "../../../../storeUtil/utils/general/general.actions"; + +export enum UpgradeFormControlNames { + RETAIN_VOLUME_GROUPS = 'retainVolumeGroups', + RETAIN_ASSIGNMENTS = 'retainAssignments', + SDN_C_PRE_LOAD = 'sdncPreLoad', +} + +@Injectable() +export class VfModuleUpgradePopupService extends VfModulePopupServiceBase { + constructor(protected _basicControlGenerator: BasicControlGenerator, + protected _vfModuleControlGenerator: VfModuleControlGenerator, + protected _iframeService: IframeService, + protected _defaultDataGeneratorService: DefaultDataGeneratorService, + protected _aaiService: AaiService, + protected _basicPopupService: BasicPopupService, + protected _store: NgRedux<AppState>, + private _sharedTreeService: SharedTreeService) { + super(_basicControlGenerator, _vfModuleControlGenerator, _iframeService, _defaultDataGeneratorService, _aaiService, _basicPopupService, _store); + } + + node: ITreeNode; + + getDynamicInputs = () => null; + + getControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, isUpdateMode: boolean): FormControlModel[] { + let result: FormControlModel[] =[ + this.getRetainAssignmentsControl(), + this.getRetainVolumeGroupsControl(), + this._basicControlGenerator.getSDNCControl(null) + ]; + + const vfModuleInstance = this._vfModuleControlGenerator.getVfModuleInstance(serviceId, vnfStoreKey, this.uuidData, isUpdateMode); + result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance); + return result; + }; + + getTitle = (): string => 'Upgrade Module'; + + onSubmit(that, form: FormGroup) { + const node = that.uuidData.vfModule; + const serviceInstanceId: string = that.uuidData.serviceId; + const vnfStoreKey = node.parent.data.vnfStoreKey; + const modelName = node.data.modelName; + const dynamicModelName = node.data.dynamicModelName; + + this.updateFormValueWithSupplementaryFile(form, that); + + this._store.dispatch(upgradeVFModule(modelName, vnfStoreKey, serviceInstanceId, dynamicModelName)); + this._store.dispatch(mergeObjectByPathAction(['serviceInstance', serviceInstanceId, 'vnfs', vnfStoreKey, 'vfModules', modelName, dynamicModelName], form.value)); + this._sharedTreeService.upgradeBottomUp(node, serviceInstanceId); + + this.postSubmitIframeMessage(that); + this.onCancel(that, form); + } + + getRetainVolumeGroupsControl = (): CheckboxFormControl => { + return new CheckboxFormControl({ + type: FormControlType.CHECKBOX, + controlName: UpgradeFormControlNames.RETAIN_VOLUME_GROUPS, + displayName: 'Retain Volume Groups', + dataTestId: UpgradeFormControlNames.RETAIN_VOLUME_GROUPS, + value: true, + validations: [] + }) + }; + + getRetainAssignmentsControl = (): CheckboxFormControl => { + return new CheckboxFormControl({ + type: FormControlType.CHECKBOX, + controlName: UpgradeFormControlNames.RETAIN_ASSIGNMENTS, + displayName: 'Retain Assignments', + dataTestId: UpgradeFormControlNames.RETAIN_ASSIGNMENTS, + value: true, + validations: [] + }) + }; +} diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts new file mode 100644 index 000000000..7c1cc084a --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts @@ -0,0 +1,201 @@ +import {LogService} from "../../../../utils/log/log.service"; +import {NgRedux} from "@angular-redux/store"; +import {BasicControlGenerator, SDN_C_PRE_LOAD, SUPPLEMENTARY_FILE} from "../../../genericForm/formControlsServices/basic.control.generator"; +import {AaiService} from "../../../../services/aaiService/aai.service"; +import {HttpClient} from "@angular/common/http"; +import {GenericFormService} from "../../../genericForm/generic-form.service"; +import {FormBuilder, FormGroup} from "@angular/forms"; +import {IframeService} from "../../../../utils/iframe.service"; +import {DefaultDataGeneratorService} from "../../../../services/defaultDataServiceGenerator/default.data.generator.service"; +import {BasicPopupService} from "../basic.popup.service"; +import {VfModuleControlGenerator} from "../../../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator"; +import {SdcUiServices} from "onap-ui-angular"; +import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; +import {getTestBed, TestBed} from "@angular/core/testing"; +import {UpgradeFormControlNames, VfModuleUpgradePopupService} from "./vfModule.upgrade.popuop.service"; +import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service"; +import {AppState} from "../../../../store/reducers"; +import {instance, mock} from "ts-mockito"; +import {GeneralActions} from "../../../../storeUtil/utils/general/general.actions"; +import {VfModuleActions} from "../../../../storeUtil/utils/vfModule/vfModule.actions"; +import {ServiceActions} from "../../../../storeUtil/utils/service/service.actions"; +import {FormControlModel} from "../../../../models/formControlModels/formControl.model"; + +class MockModalService<T> {} + +class MockAppStore<T> {} + +class MockReduxStore<T> { + getState() { + return { + service: { + serviceInstance : { + serviceId : { + vnfs : { + vnfStoreKey : { + vfModules: { + vfModuleName: { + vfModuleId : { + supplementaryFileName: "myFileName" + }}}}}}}} + }; + } + + dispatch() {} +} + +class MockFeatureFlagsService {} + +describe('VFModule popup service', () => { + let injector; + let service: VfModuleUpgradePopupService; + let genericFormService: GenericFormService; + let defaultDataGeneratorService: DefaultDataGeneratorService; + let fb: FormBuilder; + let iframeService: IframeService; + let store : NgRedux<AppState>; + + beforeAll(done => (async () => { + TestBed.configureTestingModule({ + providers: [ + VfModuleUpgradePopupService, + BasicControlGenerator, + VfModuleControlGenerator, + DefaultDataGeneratorService, + GenericFormService, + FormBuilder, + IframeService, + AaiService, + LogService, + BasicPopupService, + SharedTreeService, + {provide: FeatureFlagsService, useClass: MockFeatureFlagsService}, + {provide: NgRedux, useClass: MockReduxStore}, + {provide: HttpClient, useClass: MockAppStore}, + {provide: SdcUiServices.ModalService, useClass: MockModalService} + ] + }); + await TestBed.compileComponents(); + + injector = getTestBed(); + service = injector.get(VfModuleUpgradePopupService); + genericFormService = injector.get(GenericFormService); + defaultDataGeneratorService = injector.get(DefaultDataGeneratorService); + fb = injector.get(FormBuilder); + iframeService = injector.get(IframeService); + store = injector.get(NgRedux); + service.uuidData = { + modelName: 'vfModuleName', + vFModuleStoreKey: 'vfModuleId' + }; + + })().then(done).catch(done.fail)); + + test('getTitle should return the correct title', () => { + expect(service.getTitle()).toBe("Upgrade Module") + }); + + function findControlByName(controls: FormControlModel[], controlName: string) : FormControlModel { + return controls.find((control) => { + return control.controlName === controlName; + }); + } + + function getControlByNameAndCheckValue(controlName: string, expectedValue: any) { + const controls = service.getControls('serviceId', 'vnfStoreKey', 'vfModuleId', true); + const control = findControlByName(controls, controlName); + expect(control).toBeDefined(); + expect(control.value).toEqual(expectedValue); + } + + test('get controls should return retainAssignments control with true value', ()=> { + getControlByNameAndCheckValue(UpgradeFormControlNames.RETAIN_ASSIGNMENTS, true); + }); + + test('get controls should return retainVolumeGroup control with true value', ()=> { + getControlByNameAndCheckValue(UpgradeFormControlNames.RETAIN_VOLUME_GROUPS, true); + }); + + test('get controls should contain SUPPLEMENTARY_FILE controller', ()=> { + + //when + const controls = service.getControls('serviceId', 'vnfStoreKey', 'vfModuleId', true); + + //then + const control = findControlByName(controls, SUPPLEMENTARY_FILE); + expect(control).toBeDefined(); + expect(control.selectedFile).toBe("myFileName"); + }); + + test('on submit should call merge action of form value to vfModule', () => { + + //given + + const serviceId = "serviceId5"; + const vnfStoreKey = 'vnfStoreKey3'; + const modelName = 'modelA'; + const dynamicModelName = 'dynamicModel'; + const that = { + uuidData : { + vfModule : { + data : { + modelName, + dynamicModelName + }, + parent : { + data: { + vnfStoreKey + }}}, + serviceId + }, + serviceModel: { + uuid : "someUuid" + }, + _iframeService: { + removeClassCloseModal : jest.fn() + } + }; + + let mockFrom: FormGroup = mock(FormGroup); + let form = instance(mockFrom); + form.value = { + a: "value", + b: "another" + }; + form.controls = { + supplementaryFile_hidden_content : { + value: '{"c": "c", "d": 1}' + }, + supplementaryFile_hidden : { + value: { + name: "name" + } + } + }; + + let expectedMergePayload = { + a: "value", + b: "another", + supplementaryFileContent: {c: "c", d: 1}, + supplementaryFileName: "name" + }; + + spyOn(store, 'dispatch'); + + //when + service.onSubmit(that, form); + + //then + expect(store.dispatch).toBeCalledWith( + {type: GeneralActions.MERGE_OBJECT_BY_PATH, path: ['serviceInstance', serviceId, 'vnfs', vnfStoreKey, 'vfModules',modelName, dynamicModelName], payload:expectedMergePayload}); + expect(store.dispatch).toBeCalledWith( + {type: VfModuleActions.UPGRADE_VFMODULE, dynamicModelName: "dynamicModel", modelName: "modelA", serviceId: "serviceId5", vnfStoreKey: "vnfStoreKey3"}); + expect(store.dispatch).toBeCalledWith({type: ServiceActions.UPGRADE_SERVICE_ACTION, serviceUuid: "serviceId5"}); + + }); + + + test( 'get controls should return usePreload with false value', () => { + getControlByNameAndCheckValue(SDN_C_PRE_LOAD, false); + }); +}); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts index 6458e4f97..c4317f241 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.spec.ts @@ -14,6 +14,7 @@ import {VnfControlGenerator} from "../../../genericForm/formControlsServices/vnf import {UUIDData} from "../../generic-form-popup.component"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; import {getTestBed, TestBed} from "@angular/core/testing"; +import {VfModuleUpgradePopupService} from "../vfModuleUpgrade/vfModule.upgrade.popuop.service"; class MockAppStore<T> {} @@ -29,10 +30,7 @@ class MockReduxStore<T> { "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_ADVANCED_PORTS_FILTER": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, "FLAG_REGION_ID_FROM_REMOTE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -2261,6 +2259,7 @@ describe('vnf new popup service', () => { LogService, BasicPopupService, VfModulePopuopService, + VfModuleUpgradePopupService, BasicControlGenerator, VnfControlGenerator, {provide: NgRedux, useClass: MockReduxStore}, @@ -2335,6 +2334,10 @@ describe('vnf new popup service', () => { expect(service.modelInformations[13].values).toEqual(['5']); }); + test('when there is no max instances in model , shell return maximum item with Unlimited text', () =>{ + expect(service.createMaximumToInstantiateModelInformationItem({}).values[0]).toEqual('Unlimited (default)'); + }); + test('getSubLeftTitle new vnf popup should return service model name', () => { service.uuidData = { serviceId: '6e59c5de-f052-46fa-aa7e-2fca9d674c44', diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts index b23f74530..283603275 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service.ts @@ -97,11 +97,21 @@ export class VnfPopupService implements GenericPopupInterface{ new ModelInformationItem("Service type", "serviceType", [this.serviceModel.serviceType]), new ModelInformationItem("Service role", "serviceRole", [this.serviceModel.serviceRole]), new ModelInformationItem("Minimum to instantiate", "vnf-min", [!_.isNil(this.model.min) ? this.model.min.toString() : '0'], "", false), - new ModelInformationItem("Maximum to instantiate", "vnf-max", [!_.isNil(this.model.max) ? this.model.max.toString() : '1'], "", false) + (this.createMaximumToInstantiateModelInformationItem(this.model)) ]; }) } + createMaximumToInstantiateModelInformationItem(model) { + return new ModelInformationItem( + "Maximum to instantiate", + "vnf-max", + [!_.isNil(model.max) ? model.max.toString() : Constants.ModelInfo.UNLIMITED_DEFAULT], + "", + false + ); + } + getSubLeftTitle(): string { return "VNF MODEL: " + this._store.getState().service.serviceHierarchy[this.uuidData['serviceId']].vnfs[this.uuidData['modelName']].name; } diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts index 5397a7233..3a81e5b2b 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service.spec.ts @@ -14,6 +14,7 @@ import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flag import {VnfGroupPopupService} from "./vnfGroup.popup.service"; import {VnfGroupControlGenerator} from "../../../genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator"; import {getTestBed, TestBed} from "@angular/core/testing"; +import {VfModuleUpgradePopupService} from "../vfModuleUpgrade/vfModule.upgrade.popuop.service"; class MockAppStore<T> {} @@ -29,10 +30,7 @@ class MockReduxStore<T> { "FLAG_SHOW_VERIFY_SERVICE": false, "FLAG_SERVICE_MODEL_CACHE": true, "FLAG_ADVANCED_PORTS_FILTER": true, - "CREATE_INSTANCE_TEST": false, - "FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD": false, "FLAG_REGION_ID_FROM_REMOTE": true, - "EMPTY_DRAWING_BOARD_TEST": false, "FLAG_ADD_MSO_TESTAPI_FIELD": true }, "type": "[FLAGS] Update" @@ -2258,6 +2256,7 @@ describe('vnf group new popup service', () => { LogService, BasicPopupService, VfModulePopuopService, + VfModuleUpgradePopupService, BasicControlGenerator, VnfGroupControlGenerator, {provide: NgRedux, useClass: MockReduxStore}, diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html new file mode 100644 index 000000000..19f641a56 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html @@ -0,0 +1,164 @@ +<div id="template-popup" class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" + class="close" + (click)="closeModal()">× + </button> + <span [attr.data-tests-id]="'template-modal-title'" + class="modal-title">Templates + </span> + </div> + <div class="modal-body templateModalBody"> + <div class="row description-section"> + <div class="col-md-6"> + <div [attr.data-tests-id]="'description-part-1'">The following list presents previous instantiations done for + this model in this version. + </div> + <div [attr.data-tests-id]="'description-part-2'">You may use one of them as a baseline for your instantiation + or start from scratch. + </div> + <div [attr.data-tests-id]="'description-part-3'">Once you selecting one allows you to change the data before + start instantiating. + </div> + </div> + <div class="col-md-6"> + <div class="col-md-6"> + </div> + <div class="col-md-6"> + <input + class="filter-input form-control input-text" + placeholder="Filter..." + [(ngModel)]="filterText"> + </div> + </div> + </div> + <div class="row" style="margin-left: 0;margin-right: 0;padding: 20px;"> + <table id="member-table" class="table table-bordered" style="table-layout: fixed"> + <thead class="thead-dark"> + <tr> + <th class="header-title" id="header-userId">User ID</th> + <th class="header-title" id="header-createDate" style="width: 21ch;">Date</th> + <th class="header-title" id="header-instanceName" style="max-width: 50ch;">Instance Name</th> + <th class="header-title" id="header-instantiationStatus" style="width: 30ch;">Instantiation Status</th> + <th class="header-title" id="header-summary">Summary</th> + <th class="header-title" id="header-region">Region</th> + <th class="header-title" id="header-tenant">Tenant</th> + <th class="header-title" id="header-aicZone">AIC Zone</th> + </tr> + </thead> + <tbody> + <tr class="member-table-row" + *ngFor="let item of filterTableData | searchFilter: filterText ;" + (click)="selectedJobId = item.jobId" + [ngClass]="{'selected' : selectedJobId === item.jobId}" + [attr.data-tests-id]="'row-' + item.jobId"> + <td> + <div> + <custom-ellipsis + [dataTestId]="'userId-' + item.jobId" + [id]="item.userId" + [value]="item.userId" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + <td style="width: 21ch;"> + <div> + <custom-ellipsis + [dataTestId]="'createDate-' + item.jobId" + [id]="item.createDate" + [value]="item.createDate" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + <td style="max-width: 50ch;"> + <div> + <custom-ellipsis + [showDots]="true" + [dataTestId]="'instanceName-' + item.jobId" + [id]="item.instanceName" + [value]="item.instanceName" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + <td> + <div> + <custom-ellipsis + [showDots]="true" + [dataTestId]="'instantiationStatus-' + item.jobId" + [id]="item.instantiationStatus" + [value]="item.instantiationStatus" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + <td> + <div> + <custom-ellipsis + [dataTestId]="'summary-' + item.jobId" + [id]="item.summary" + [value]="item.summary" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + <td> + <div> + <custom-ellipsis + [showDots]="true" + [dataTestId]="'region-' + item.jobId" + [id]="item.region" + [value]="item.region" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + <td> + <div> + <custom-ellipsis + [showDots]="true" + [dataTestId]="'tenant-' + item.jobId" + [id]="item.tenant" + [value]="item.tenant" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + <td> + <div> + <custom-ellipsis + [dataTestId]="'aicZone-' + item.jobId" + [id]="item.aicZone" + [value]="item.aicZone" + [breakWord]="true"> + </custom-ellipsis> + </div> + </td> + </tr> + </tbody> + </table> + </div> + + </div> + <div class="modal-footer row" style="padding: 0"> + <div class="col-md-6"> + </div> + <div class="col-md-6" style="padding: 15px;padding-right: 35px;"> + <button + [disabled]="selectedJobId === null" + [attr.data-tests-id]="'LoadTemplateButton'" + type="button" class="btn btn-primary submit" + (click)="loadTemplate()"><span>Load Template</span> + </button> + <button + [attr.data-tests-id]="'startFromScratchButton'" + type="button" class="btn btn-success submit startFromScratchButton" + (click)="closeModal()"><span>Start from Scratch</span> + </button> + </div> + </div> + </div> +</div> diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss new file mode 100644 index 000000000..267d2cee0 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.scss @@ -0,0 +1,196 @@ +$grid-border: 1px #d2d2d2 solid; + +#template-popup { + color: #191919; + + thead { + background: #F8F8F8; + } + .left-panel { + background: #f2f2f2; + border-right: $grid-border; + } + + .header-common { + height: 100%; + align-items: center; + display: flex; + font-family: OpenSans-Semibold; + font-size: 12px; + } + + .header-text { + padding-left: 30px; + @extend .header-common; + } + + .header-left { + grid-area: header-left; + @extend .header-text; + @extend .left-panel; + border-bottom: $grid-border; + + span { + font-family: OpenSans-Regular; + font-size: 14px; + } + ; + } + + .header-right { + grid-area: header-right; + + @extend .header-text; + } + + .quantity-label { + grid-area: quantity-label; + @extend .header-common; + height: 100%; + font-family: OpenSans-Regular; + } + + input[type="number"]:hover::-webkit-inner-spin-button { + height: 20px; + } + + .popup-content { + display: grid; + grid-template-columns: 400px auto 30px 93px; + grid-template-rows: 50px calc(100vh - 180px); + grid-template-areas: "header-left header-right quantity-label quantity" "model-information instance-form instance-form instance-form"; + padding: 0; + } +} + +.modal { + background-color: #191919; + opacity: 0.8; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0; +} + +@media (min-width: 1150px) { + .popup-content { + grid-template-rows: 30px 680px; + } +} + +.modal-content { + border-radius: 0; + box-shadow: none; + border: none; + min-height: calc(100vh); + +} + +.modal-footer { + padding: 0; + position: absolute; + bottom: 0; + width: 100%; + + .cancel { + width: 120px; + height: 36px; + background: #ffffff; + border: 1px solid #009fdb; + border-radius: 2px; + + span { + font-family: OpenSans-Regular; + font-size: 14px; + color: #009fdb; + line-height: 16px; + } + } + + .startFromScratchButton { + width: 150px !important; + } + + .submit { + min-width: 120px; + height: 36px; + background: #009fdb; + border-radius: 2px; + border-color: #009fdb; + + + span { + font-family: OpenSans-Regular; + font-size: 14px; + color: #FFFFFF; + line-height: 16px; + } + } +} + +.modal-header { + background-color: #009fdb; + + padding-bottom: 13px; + padding-top: 13px; + padding-left: 29px; + padding-right: 21px; + + .close { + font-size: 32px; + font-weight: 200; + color: #d8d8d8; + text-shadow: none; + filter: none; + opacity: 1; + } + + .modal-title { + font-family: OpenSans-Regular; + font-size: 24px; + color: #fff; + line-height: 34px; + } +} + +.modal-body { + padding: 0; + height: calc(85vh); + + .description-section { + padding: 20px; + font-size: 20px; + } + + .filter-input { + float: right; + width: 50%; + } + + .details-item { + text-align: right; + } + + + td.loadTemplateButton { + text-align: center; + vertical-align: middle; + } + + td { + text-align: center; + vertical-align: middle; + padding-left: 5px; + padding-right: 5px; + } + + .member-table-row:hover { + background: #80808033 !important; + } + + .member-table-row.selected { + background: #8080808f !important; + } +} diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts new file mode 100644 index 000000000..4d89750f9 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.ts @@ -0,0 +1,57 @@ +import {Component, OnDestroy, OnInit} from "@angular/core"; +import {DialogComponent, DialogService} from "ng2-bootstrap-modal"; +import {IframeService} from "../../../utils/iframe.service"; +import {ActivatedRoute} from "@angular/router"; +import {ServiceInfoService} from "../../../server/serviceInfo/serviceInfo.service"; +import {InstantiationTemplatesModalService} from "./instantiation.templates.modal.service"; +import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model"; + +@Component({ + selector: 'template-modal', + templateUrl: 'instantiation.templates.modal.component.html', + styleUrls: ['instantiation.templates.modal.component.scss'] +}) + +export class InstantiationTemplatesModalComponent extends DialogComponent<string, boolean> implements OnInit, OnDestroy { + + selectedJobId : string = null; + templateModalComponentService: InstantiationTemplatesModalService; + originalTableData: InstantiationTemplatesRowModel[] = []; + filterTableData : InstantiationTemplatesRowModel[] = []; + filterText: string; + + constructor(dialogService: DialogService, + private _iframeService: IframeService, + private _serviceInfoService: ServiceInfoService, + private _templateModalComponentService: InstantiationTemplatesModalService, + private _route: ActivatedRoute) { + super(dialogService); + this.templateModalComponentService = _templateModalComponentService; + } + + ngOnInit(): void { + this.filterText = ''; + this._route + .queryParams + .subscribe(params => { + this._serviceInfoService.getServicesJobInfo(true, params['serviceModelId']).subscribe((jobs) => { + this.originalTableData = this._templateModalComponentService.convertResponseToUI(jobs); + this.filterTableData = this.originalTableData; + }); + }); + } + + loadTemplate = () => { + + }; + + + closeModal(): void { + this._iframeService.removeClassCloseModal('content'); + this.dialogService.removeDialog(this); + setTimeout(() => { + window.parent.postMessage("closeIframe", "*"); + }, 15); + + } +} diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts new file mode 100644 index 000000000..1ff0f61e2 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts @@ -0,0 +1,133 @@ +import {getTestBed, TestBed} from '@angular/core/testing'; +import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; +import {InstantiationTemplatesModalService} from "./instantiation.templates.modal.service"; +import {AaiService} from "../../../services/aaiService/aai.service"; +import {ActivatedRoute} from "@angular/router"; +import {IframeService} from "../../../utils/iframe.service"; +import {NgRedux} from "@angular-redux/store"; +import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service"; +import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model"; + + +class ActivatedRouteMock<T> { + queryParams() { + return { + serviceModelId: '6e59c5de-f052-46fa-aa7e-2fca9d674c44' + } + } +} + +class MockAppStore { + +} + +describe('instantiation templates modal service', () => { + let injector; + let service: InstantiationTemplatesModalService; + let httpMock: HttpTestingController; + let _aaiService: AaiService; + let _activatedRoute: ActivatedRoute; + + beforeAll(done => (async () => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [InstantiationTemplatesModalService, + IframeService, + AaiService, + FeatureFlagsService, + {provide: ActivatedRoute, useClass: ActivatedRouteMock}, + {provide: NgRedux, useClass: MockAppStore} + ] + }); + await TestBed.compileComponents(); + + injector = getTestBed(); + service = injector.get(InstantiationTemplatesModalService); + httpMock = injector.get(HttpTestingController); + _aaiService = injector.get(AaiService); + _activatedRoute = injector.get(ActivatedRoute); + + })().then(done).catch(done.fail)); + + + test('service should be defined', () => { + expect(service).toBeDefined(); + }); + + + test('convertResponseToUI - should return table data', () => { + const jobs = [{ + "id": 5, + "created": 1524995555000, + "modified": 1524995556000, + "action": "INSTANTIATE", + "createdId": null, + "modifiedId": null, + "rowNum": null, + "auditUserId": null, + "auditTrail": null, + "jobId": "9f88fdb5-bb47-4bf3-8c5f-98f1ad0ec87c", + "templateId": "ce4ec177-cfc8-483e-8a2c-b7aea53fd740", + "userId": "16807000", + "msoRequestId": "c0011670-0e1a-4b74-945d-8bf5aede1d91", + "requestId": null, + "jobStatus": "FAILED", + "statusModifiedDate": 1524995555000, + "hidden": false, + "pause": false, + "owningEntityId": "aaa1", + "owningEntityName": "aaa1", + "project": "WATKINS", + "aicZoneId": "BAN1", + "aicZoneName": "VSDKYUTP-BAN1", + "tenantId": "1178612d2b394be4834ad77f567c0af2", + "tenantName": "AIN Web Tool-15-D-SSPtestcustome", + "regionId": "hvf6", + "regionName": null, + "serviceType": "TYLER SILVIA", + "subscriberName": "e433710f-9217-458d-a79d-1c7aff376d89", + "serviceInstanceId": null, + "serviceInstanceName": 'serviceInstanceName', + "serviceModelId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0", + "serviceModelName": "ComplexService", + "serviceModelVersion": "1.0", + "createdBulkDate": 1524995555000, + "isRetryEnabled": false + }]; + const tableRows: InstantiationTemplatesRowModel[] = service.convertResponseToUI(jobs); + expect(tableRows).toHaveLength(1); + expect(tableRows[0].userId).toEqual('16807000'); + expect((new Date(tableRows[0].createDate)).toISOString()).toEqual('2018-04-29T09:52:35.000Z'); + expect(tableRows[0].instanceName).toEqual('serviceInstanceName'); + expect(tableRows[0].instantiationStatus).toEqual('FAILED'); + expect(tableRows[0].region).toEqual('hvf6 (AAA1)'); + expect(tableRows[0].tenant).toEqual('AIN Web Tool-15-D-SSPtestcustome'); + expect(tableRows[0].aicZone).toEqual('VSDKYUTP-BAN1'); + expect(tableRows[0].jobId).toEqual('9f88fdb5-bb47-4bf3-8c5f-98f1ad0ec87c'); + }); + + + test('getCloudOwner should remove "-att" from owningEntityName : "att-owner', () => { + let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({ + owningEntityName: 'att-owner', + regionId: 'regionId' + }); + expect(result.region).toEqual('regionId (OWNER)'); + }); + + test('getCloudOwner should not return owningEntityName if not exist', () => { + let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({owningEntityName: null, regionId: 'regionId'}); + expect(result.region).toEqual('regionId'); + }); + + test('getInstanceName should return instance name id exist if not exist', () => { + let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({serviceInstanceName: 'instanceName'}); + expect(result.instanceName).toEqual('instanceName'); + }); + + test('getInstanceName should return <Automatically generated> if instance name not exist', () => { + let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({}); + expect(result.instanceName).toEqual('<Automatically generated>'); + }); + +}); diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts new file mode 100644 index 000000000..7126da36a --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts @@ -0,0 +1,15 @@ +import {Injectable} from "@angular/core"; +import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.model"; + +@Injectable() +export class InstantiationTemplatesModalService { + convertResponseToUI = (jobsResponse: any[]): InstantiationTemplatesRowModel[] => { + let tableRows: InstantiationTemplatesRowModel[] = []; + + jobsResponse.forEach((job) => { + tableRows.push(new InstantiationTemplatesRowModel(job)); + }); + + return tableRows; + }; +} diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts new file mode 100644 index 000000000..08982cc67 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts @@ -0,0 +1,51 @@ +import * as moment from 'moment'; +import * as _ from 'lodash'; + +export class InstantiationTemplatesRowModel { + readonly jobId: string; + readonly userId ?: string; + readonly createDate ?: string; + readonly instanceName ?: string; + readonly instantiationStatus?: string; + readonly summary?: string; + readonly region?: string; + readonly tenant?: string; + readonly aicZone?: string; + + constructor(data) { + this.jobId = data.jobId; + this.userId = !_.isNil(data.created) ? data.userId : null; + this.createDate = !_.isNil(data.created) ? moment(data.created).format("YYYY-MM-DD HH:mm:ss") : null; + this.instanceName = this.getInstanceName(data.serviceInstanceName); + this.instantiationStatus = !_.isNil(data.jobStatus) ? data.jobStatus : null; + this.summary = null; + this.region = this.getRegion(data.regionId, data.owningEntityName); + this.tenant = !_.isNil(data.tenantName) ? data.tenantName : null; + this.aicZone = !_.isNil(data.aicZoneName) ? data.aicZoneName : null; + + } + + + /************************************************************************************************** + return the LCP region and in brackets the cloud owner removing the “att-“ with capital letters. + **************************************************************************************************/ + getCloudOwner = (owningEntityName: string): string => { + const splitByAtt: string[] = owningEntityName.split('att-'); + let owning: string = splitByAtt[splitByAtt.length - 1]; + return owning.toUpperCase(); + }; + + getRegion = (regionId: string, owningEntityName: string): string => { + const convertOwning = !_.isNil(owningEntityName) ? `(${this.getCloudOwner(owningEntityName)})` : ''; + return `${regionId} ${convertOwning}`.trim(); + }; + + + getInstanceName = (instanceName?: string): string => { + if (_.isNil(instanceName)) { + return '<Automatically generated>'; + } + return instanceName; + } +} + diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts index 8ea3d2d0b..40d74d63f 100644 --- a/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts +++ b/vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts @@ -14,6 +14,8 @@ export class FormPopupDetails { modelInformationItems: ModelInformationItem[]; onSubmit : (that : any, form: FormGroup , ...args) => void; onCancel : (that : any, form: FormGroup) => void; + onOtherAction: (that: any, form: FormGroup) => void; + constructor(that : any, popupTypeName : PopupType , @@ -25,7 +27,8 @@ export class FormPopupDetails { dynamicInputsControlList : FormControlModel[], modelInformationItems : ModelInformationItem[], onSubmit : (that : any, form : FormGroup, ...args) => void, - onCancel : (that : any, form : FormGroup) => void){ + onCancel: (that: any, form: FormGroup) => void, + onOtherAction?: (that: any, form: FormGroup) => void) { this.title = title; this.leftSubTitle = leftSubTitle; this.rightSubTitle = rightSubTitle; @@ -34,6 +37,7 @@ export class FormPopupDetails { this.modelInformationItems = modelInformationItems; this.onSubmit = onSubmit; this.onCancel = onCancel; + this.onOtherAction = onOtherAction; this.popupTypeName = popupTypeName; this.UUIDData = UUIDData; this.that = that; @@ -49,6 +53,7 @@ export enum PopupType { VNF_MACRO ='vnf macro', VNF_A_LA_CARTE = 'vnf a-la-carte', VFMODULE = 'vfModule', + VFMODULE_UPGRADE = 'vfModule_upgrade', NETWORK_MACRO = 'network_macro', VNF_GROUP = 'vnfGroup' } diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts index b13745104..f5db715ba 100644 --- a/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts +++ b/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts @@ -7,10 +7,14 @@ export class MultiselectFormControl extends FormControlModel{ options$ : Observable<any[]>; args : string[]; onInit: (data : MultiselectFormControl, form: FormGroup) => Observable<any>; - selectedItems : string; + selectedItems : any[]; onInitSelectedItems : string[]; + selectedFieldName : string; ngValue : string; settings: {}; + onInitSelectedField?: string[]; + convertOriginalDataToArray? : (values)=> void; + limitSelection?: number; constructor(data) { @@ -18,10 +22,14 @@ export class MultiselectFormControl extends FormControlModel{ this.type = FormControlType.MULTI_SELECT; this.options$ = data.options; this.onInit = data.onInit; - this.selectedItems = data.selectedItems; + this.selectedItems = data.selectedItems || []; this.onInitSelectedItems = data.onInitSelectedItems ? data.onInitSelectedItems : null; this.ngValue = data.selectedField ? data.selectedField : 'id'; + this.selectedFieldName = data.selectedFieldName; this.settings = data.settings || {}; + this.onInitSelectedField = data.onInitSelectedField ? data.onInitSelectedField : null; + this.convertOriginalDataToArray = data.convertOriginalDataToArray ? data.convertOriginalDataToArray : null + this.limitSelection = data.limitSelection ? data.limitSelection : 1000; } } diff --git a/vid-webpack-master/src/app/shared/models/networkModel.ts b/vid-webpack-master/src/app/shared/models/networkModel.ts index 03f118eb7..b4879a59d 100644 --- a/vid-webpack-master/src/app/shared/models/networkModel.ts +++ b/vid-webpack-master/src/app/shared/models/networkModel.ts @@ -2,29 +2,30 @@ import { Level1Model, Level1ModelProperties, Level1ModelResponseInterface } from "./nodeModel"; -import {VfcInstanceGroupMap} from "./vfcInstanceGroupMap"; +import {Utils} from "../utils/utils"; -export interface NetworkProperties extends Level1ModelProperties{ +export interface NetworkProperties extends Level1ModelProperties { ecomp_generated_naming: string; network_role: string; } -export interface NetworkModelResponseInterface extends Level1ModelResponseInterface{ +export interface NetworkModelResponseInterface extends Level1ModelResponseInterface { properties: NetworkProperties; } -export class NetworkModel extends Level1Model{ +export class NetworkModel extends Level1Model { roles: string[] = []; properties: NetworkProperties; - constructor(networkJson?: NetworkModelResponseInterface){ + constructor(networkJson?: NetworkModelResponseInterface, flags?: { [key: string]: boolean }) { super(networkJson); - if(networkJson && networkJson.properties){ + if (networkJson && networkJson.properties) { this.properties = networkJson.properties; // expecting network_role to be a comma-saparated list this.roles = networkJson.properties.network_role ? networkJson.properties.network_role.split(',') : []; + this.max = Utils.getMaxFirstLevel(this.properties, flags); } } diff --git a/vid-webpack-master/src/app/shared/models/vfModule.ts b/vid-webpack-master/src/app/shared/models/vfModule.ts index c75202124..8f92ba428 100644 --- a/vid-webpack-master/src/app/shared/models/vfModule.ts +++ b/vid-webpack-master/src/app/shared/models/vfModule.ts @@ -1,4 +1,5 @@ import {NodeModel, NodeModelResponseInterface} from "./nodeModel"; +import {Utils} from "../utils/utils"; export interface Properties{ @@ -23,7 +24,7 @@ export class VfModule extends NodeModel { modelCustomizationName: string; volumeGroupAllowed : boolean; - constructor(vf?: VFModuleResponseInterface) { + constructor(vf?: VFModuleResponseInterface, flags?: { [key: string]: boolean }) { super(vf); if(vf){ this.customizationUuid = vf.customizationUuid; @@ -32,7 +33,7 @@ export class VfModule extends NodeModel { } if (vf && vf.properties) { this.min = vf.properties.minCountInstances; - this.max = vf.properties.maxCountInstances; + this.max = Utils.getMaxVfModule(vf.properties, flags); this.initial = vf.properties.initialCount; this.rollbackOnFailure = true } diff --git a/vid-webpack-master/src/app/shared/models/vnfModel.ts b/vid-webpack-master/src/app/shared/models/vnfModel.ts index 8389606b6..220dc0fc5 100644 --- a/vid-webpack-master/src/app/shared/models/vnfModel.ts +++ b/vid-webpack-master/src/app/shared/models/vnfModel.ts @@ -3,25 +3,24 @@ import { Level1ModelProperties, Level1ModelResponseInterface } from "./nodeModel"; +import {Utils} from "../utils/utils"; - - -export interface VnfProperties extends Level1ModelProperties{ +export interface VnfProperties extends Level1ModelProperties { ecomp_generated_naming: string; } -export interface VNFModelResponseInterface extends Level1ModelResponseInterface{ +export interface VNFModelResponseInterface extends Level1ModelResponseInterface { properties: VnfProperties; } -export class VNFModel extends Level1Model{ +export class VNFModel extends Level1Model { properties: VnfProperties; - constructor(vnfJson?: VNFModelResponseInterface) { + constructor(vnfJson?: VNFModelResponseInterface, flags?: { [key: string]: boolean }) { super(vnfJson); if (vnfJson) { this.properties = vnfJson.properties; + this.max = Utils.getMaxFirstLevel(this.properties, flags); } } - } diff --git a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts new file mode 100644 index 000000000..2567cbf27 --- /dev/null +++ b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.spec.ts @@ -0,0 +1,17 @@ +import {SearchFilterPipe} from "./search-filter.pipe"; +import * as _ from 'lodash'; + +describe('Search filter pipe', () => { + + const items= [{'id':1, 'name': 'aaa'}, + {'id':12, 'name': 'bbb', 'children':{'first': 155, 'second': 2, 'third': 3}}, + {'id':3, 'name': 'ccc', 'children':{'first': 1, 'BbB': 'BbB', 'third': 3}}, + {'id':4, 'name': 'aad', 'children':{'first': 1, 'second': 2, 'third': 3}}]; + + test('should return items contains substring bb', () => { + let filter = new SearchFilterPipe(); + let res:any[] = filter.transform(items,'bb'); + expect(_.map(res, 'name' )).toEqual(['bbb','ccc']); + }); + +}); diff --git a/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts new file mode 100644 index 000000000..6e5cfc667 --- /dev/null +++ b/vid-webpack-master/src/app/shared/pipes/searchFilter/search-filter.pipe.ts @@ -0,0 +1,43 @@ +import {Pipe, PipeTransform} from '@angular/core'; +import * as _ from 'lodash'; + +@Pipe({ + name: 'searchFilter' +}) +export class SearchFilterPipe implements PipeTransform { + transform(items: Object[], searchText: string): any[] { + if (!items) return []; + if (!searchText) return items; + return items.filter((item: object) => { + + const deepFlatObject = this.flatten(item); + + const values = _.values(deepFlatObject).map((item: string) => { + return item.toString().toLowerCase() + }); + + return _.some(values, _.method('includes', searchText.toLowerCase())); + }); + } + + flatten = object => { + return Object.assign( + {}, + ...(function _flatten(objectBit, path = '') { + //spread the result into our return object + if(objectBit === null) return []; + return [].concat( + //concat everything into one level + + ...Object.keys(objectBit).map( + //iterate over object + key => + typeof objectBit[key] === 'object' //check if there is a nested object + ? _flatten(objectBit[key], `${path}/${key}`) //call itself if there is + : { [`${path}/${key}`]: objectBit[key] } //append object with it’s path as key + ) + ); + })(object) + ); + }; +} diff --git a/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.spec.ts b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.spec.ts new file mode 100644 index 000000000..1a3a1ab3f --- /dev/null +++ b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.spec.ts @@ -0,0 +1,66 @@ +import {RecreateResolver} from "./recreate.resolver"; +import {getTestBed, TestBed} from '@angular/core/testing'; +import {NgRedux} from "@angular-redux/store"; +import {InstantiationTemplatesService} from "../../services/templateService/instantiationTemplates.service"; +import {AaiService} from "../../services/aaiService/aai.service"; +import {mock} from "ts-mockito"; +import {ServiceInstance} from "../../models/serviceInstance"; +import {HttpClientTestingModule} from "@angular/common/http/testing"; +import {FeatureFlagsService} from "../../services/featureFlag/feature-flags.service"; +import {convertToParamMap} from "@angular/router"; +import {of} from 'rxjs/observable/of' + +class MockAppStore<T> { + getState() {} +} + +describe('Recreate resolver', () => { + + let injector; + let recreateResolver: RecreateResolver; + let aaiService: AaiService; + let instantiationTemplatesService: InstantiationTemplatesService; + + beforeAll(done => (async () => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [ + FeatureFlagsService, + InstantiationTemplatesService, + RecreateResolver, + AaiService, + {provide: NgRedux, useClass: MockAppStore}, + ] + }); + await TestBed.compileComponents(); + + injector = getTestBed(); + recreateResolver = injector.get(RecreateResolver); + aaiService = injector.get(AaiService); + instantiationTemplatesService = injector.get(InstantiationTemplatesService); + })().then(done).catch(done.fail)); + + test("when resolve() invoked -> then getServiceModelById and retrieveAndStoreInstantiationTemplateTopology are called", done => { + jest.spyOn(aaiService, 'getServiceModelById') + .mockReturnValue(of({})); + jest.spyOn(instantiationTemplatesService, 'retrieveAndStoreInstantiationTemplateTopology') + .mockReturnValue(of(mock(ServiceInstance))); + + recreateResolver.resolve(<any>{ + queryParamMap: + convertToParamMap({ + serviceModelId: "someServiceModelId", + jobId: "someJobId", + }) + }) + + .subscribe(() => { + expect(aaiService.getServiceModelById) + .toHaveBeenCalledWith("someServiceModelId"); + expect(instantiationTemplatesService.retrieveAndStoreInstantiationTemplateTopology) + .toHaveBeenCalledWith("someJobId", "someServiceModelId"); + done(); + }); + }) + +}); diff --git a/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.ts b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.ts new file mode 100644 index 000000000..b7e952a64 --- /dev/null +++ b/vid-webpack-master/src/app/shared/resolvers/recreate/recreate.resolver.ts @@ -0,0 +1,29 @@ +import {Injectable} from "@angular/core"; +import {NgRedux} from "@angular-redux/store"; + +import {ActivatedRouteSnapshot, Resolve} from "@angular/router"; +import {Observable} from "rxjs"; +import {AppState} from "../../store/reducers"; +import {InstantiationTemplatesService} from "../../services/templateService/instantiationTemplates.service"; +import {forkJoin} from "rxjs/observable/forkJoin"; +import {AaiService} from "../../services/aaiService/aai.service"; +import {ServiceInstance} from "../../models/serviceInstance"; + +@Injectable() +export class RecreateResolver implements Resolve<Observable<[any, ServiceInstance]>> { + constructor(private _templateService: InstantiationTemplatesService, + private _aaiService: AaiService, + private _store: NgRedux<AppState>) { + } + + resolve(route: ActivatedRouteSnapshot): Observable<[any, ServiceInstance]> { + const serviceModelId: string = route.queryParamMap.get("serviceModelId"); + const jobId: string = route.queryParamMap.get("jobId"); + + let serviceModelApi = this._aaiService.getServiceModelById(serviceModelId); + let instantiationTemplateApi = this._templateService.retrieveAndStoreInstantiationTemplateTopology(jobId, serviceModelId); + + return forkJoin([serviceModelApi, instantiationTemplateApi]) + } + +} diff --git a/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts b/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts index 540e02fe6..075e18f25 100644 --- a/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts +++ b/vid-webpack-master/src/app/shared/resolvers/viewEdit/viewEdit.resolver.ts @@ -10,6 +10,7 @@ import {ServiceInstance} from "../../models/serviceInstance"; import * as _ from "lodash"; import {ModelInfo} from "../../models/modelInfo"; import {FeatureFlagsService, Features} from "../../services/featureFlag/feature-flags.service"; +import {Utils} from "../../utils/utils"; @Injectable() export class ViewEditResolver implements Resolve<Observable<boolean>> { @@ -69,7 +70,7 @@ export class ViewEditResolver implements Resolve<Observable<boolean>> { }; setIsALaCarte(service: any, instantiationType) :void{ - service.isALaCarte = instantiationType === 'ALaCarte'; + service.isALaCarte = Utils.isALaCarte(instantiationType); }; } diff --git a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts index 147434b1a..0234ea514 100644 --- a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts +++ b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.spec.ts @@ -37,6 +37,25 @@ describe('Service Info Service', () => { }); }); + describe('#getServicesJobInfo', ()=> { + test('should call without serviceModelId', ()=>{ + let job: ServiceInfoModel = new ServiceInfoModel(); + + service.getServicesJobInfo().subscribe(); + const req = httpMock.expectOne(Constants.Path.SERVICES_JOB_INFO_PATH); + + expect(req.request.method).toBe('GET'); + }); + + test('should call with serviceModelId', ()=>{ + let job: ServiceInfoModel = new ServiceInfoModel(); + + service.getServicesJobInfo(true, "123").subscribe(); + const req = httpMock.expectOne(`${Constants.Path.SERVICES_JOB_INFO_PATH}?${Constants.Path.SERVICE_MODEL_ID}=123`); + expect(req.request.method).toBe('GET'); + }); + }); + describe('#getALaCarteJobAuditStatus Without params', ()=> { test('should return Observable<Object[]>', ()=>{ let job: ServiceInfoModel = new ServiceInfoModel(); diff --git a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts index fe6ebc7ee..388afdba0 100644 --- a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts +++ b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.service.ts @@ -2,8 +2,6 @@ import {Injectable} from '@angular/core'; import {Observable} from 'rxjs'; import {ServiceInfoModel} from './serviceInfo.model'; import {HttpClient, HttpHeaders} from '@angular/common/http'; -import { of } from 'rxjs'; -import { map } from 'rxjs/operators'; import {Constants} from '../../utils/constants'; import {forkJoin} from "rxjs/observable/forkJoin"; import * as _ from 'lodash'; @@ -14,10 +12,11 @@ export class ServiceInfoService { constructor(private _http: HttpClient) { } - getServicesJobInfo(filterByUser : boolean, showSpinner: boolean = true): Observable<ServiceInfoModel[]> { + getServicesJobInfo(showSpinner: boolean = true, serviceModelId: string = null): Observable<ServiceInfoModel[]> { let pathQuery = Constants.Path.SERVICES_JOB_INFO_PATH; let headers = new HttpHeaders({'x-show-spinner': showSpinner.toString()}); - return this._http.get<ServiceInfoModel[]>(pathQuery, { headers: headers }).map(res => res ); + let params = serviceModelId ? {serviceModelId} : {}; + return this._http.get<ServiceInfoModel[]>(pathQuery, { headers: headers, params }); } deleteJob(jobId: string): Observable<any> { diff --git a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts index a34f2fe20..03461eaa1 100644 --- a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts +++ b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.spec.ts @@ -32,6 +32,7 @@ describe('Default Data Generator Service', () => { let result = service.generateVFModule(serviceHierarchy.vnfs[vnfUUID].vfModules[vnfModuleUUID], [], false, true); expect(result.isMissingData).toBeTruthy(); + expect(result.rollbackOnFailure).toBeTruthy(); }); test('generateVFModule should create vf module object', () => { @@ -51,6 +52,7 @@ describe('Default Data Generator Service', () => { expect(result.sdncPreReload).toBeNull(); expect(result.isMissingData).toBeTruthy(); expect(result.instanceParams).toEqual([{}]); + expect(result.rollbackOnFailure).toBeNull(); }); test('generateVNFData should create vnf object', () => { diff --git a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts index b0baa82ec..a3cb475a0 100644 --- a/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts +++ b/vid-webpack-master/src/app/shared/services/defaultDataServiceGenerator/default.data.generator.service.ts @@ -186,7 +186,7 @@ export class DefaultDataGeneratorService { for (let networkUUID in serviceHierarchy.networks) { const isEcompGeneratedNaming = this.getIsEcompGeneratedNaming(serviceHierarchy.networks[networkUUID]); let min_vnf_instances_greater_than_0 = serviceHierarchy.networks[networkUUID].properties['min_instances'] && serviceHierarchy.networks[networkUUID].properties['min_instances'] > 0; - if(this.store.getState().global.flags['FLAG_DEFAULT_VNF'] && min_vnf_instances_greater_than_0) + if(min_vnf_instances_greater_than_0) { this.createNetworkInstanceReduxIfNotExist( serviceId, @@ -203,7 +203,7 @@ export class DefaultDataGeneratorService { for (let vnfGroupUUID in serviceHierarchy.vnfGroups) { const isEcompGeneratedNaming = this.getIsEcompGeneratedNaming(serviceHierarchy.vnfGroups[vnfGroupUUID]); let min_vnf_group_instances_greater_than_0 = serviceHierarchy.vnfGroups[vnfGroupUUID].properties['min_instances'] && serviceHierarchy.vnfGroups[vnfGroupUUID].properties['min_instances'] > 0; - if(this.store.getState().global.flags['FLAG_DEFAULT_VNF'] && min_vnf_group_instances_greater_than_0) + if(min_vnf_group_instances_greater_than_0) { this.createVnfGroupInstanceReduxIfNotExist( serviceId, @@ -244,7 +244,7 @@ export class DefaultDataGeneratorService { } let min_vnf_instances_greater_than_0 = serviceHierarchy.vnfs[vnfUUID].properties['min_instances'] && serviceHierarchy.vnfs[vnfUUID].properties['min_instances'] > 0; - if(this.store.getState().global.flags['FLAG_DEFAULT_VNF'] && min_vnf_instances_greater_than_0) + if(min_vnf_instances_greater_than_0) { this.createVNFInstanceReduxIfNotExist( serviceId, @@ -328,6 +328,7 @@ export class DefaultDataGeneratorService { instanceParams ], 'trackById': DefaultDataGeneratorService.createRandomTrackById(), + 'rollbackOnFailure' : isALaCarte ? true : null, }; } diff --git a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts index d6c37c936..74fcd8f87 100644 --- a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts +++ b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts @@ -8,11 +8,14 @@ export enum Features { FLAG_1902_VNF_GROUPING='FLAG_1902_VNF_GROUPING', FLAG_VF_MODULE_RESUME_STATUS_CREATE = 'FLAG_VF_MODULE_RESUME_STATUS_CREATE', FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE = 'FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE', - FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE = 'FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE', FLAG_1906_COMPONENT_INFO = 'FLAG_1906_COMPONENT_INFO', FLAG_1908_RESUME_MACRO_SERVICE = 'FLAG_1908_RESUME_MACRO_SERVICE', FLAG_FLASH_REPLACE_VF_MODULE ='FLAG_FLASH_REPLACE_VF_MODULE', - FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT ='FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT' + FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT ='FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT', + FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS ='FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS', + FLAG_2004_INSTANTIATION_STATUS_FILTER ='FLAG_2004_INSTANTIATION_STATUS_FILTER', + FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE = 'FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE', + FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER ='FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER', } @Injectable() @@ -24,6 +27,14 @@ export class FeatureFlagsService { return FeatureFlagsService.getFlagState(flag, this.store); } + public getAllFlags(): { [key: string]: boolean}{ + return this.store.getState().global.flags; + } + + public static getAllFlags(store: NgRedux<AppState>): { [key: string]: boolean}{ + return store.getState().global.flags; + } + /*static method for easy refactoring of code, so no injection of FeatureFlagsService is needed*/ public static getFlagState(flag: Features, store: NgRedux<AppState>):boolean { let storeStateGlobalFields = store.getState().global; diff --git a/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.spec.ts b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.spec.ts new file mode 100644 index 000000000..80b113bde --- /dev/null +++ b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.spec.ts @@ -0,0 +1,51 @@ +import {HttpClientTestingModule, HttpTestingController} from "@angular/common/http/testing"; +import {InstantiationTemplatesService} from "./instantiationTemplates.service"; +import {mock} from "ts-mockito"; +import {NgRedux} from "@angular-redux/store"; +import {getTestBed, TestBed} from "@angular/core/testing"; +import {ServiceInstance} from "../../models/serviceInstance"; +import {Constants} from "../../utils/constants"; + +class MockAppStore<T> { + dispatch() {} + getState() {} +} + +describe("TemplateService", ()=>{ + let injector; + let httpMock: HttpTestingController; + let templateService: InstantiationTemplatesService; + + beforeAll( done => (async () => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [ + InstantiationTemplatesService, + {provide: NgRedux, useClass: MockAppStore}, + ] + }); + await TestBed.compileComponents(); + + injector = getTestBed(); + httpMock = injector.get(HttpTestingController); + templateService = injector.get(InstantiationTemplatesService); + })().then(done).catch(done.fail)); + + describe ('#retrieveInstantiationTemplateTopology tests', () => { + test('when called -> retrieve template from backend', done => { + const mockedTemplate = mock(ServiceInstance); + const jobId: string = "some-random-job-id"; + + templateService.retrieveInstantiationTemplateTopology(jobId) + .subscribe((result: ServiceInstance) => { + expect(Object.is(result, mockedTemplate)).toBe(true); + done(); + }); + + httpMock + .expectOne(`${Constants.Path.INSTANTIATION_TEMPLATE_TOPOLOGY}/${jobId}`) + .flush(mockedTemplate); + }) + }) +}); + diff --git a/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.ts b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.ts new file mode 100644 index 000000000..018e0d367 --- /dev/null +++ b/vid-webpack-master/src/app/shared/services/templateService/instantiationTemplates.service.ts @@ -0,0 +1,27 @@ +import {Injectable} from "@angular/core"; +import {HttpClient} from "@angular/common/http"; +import {NgRedux} from "@angular-redux/store"; +import {AppState} from "../../store/reducers"; +import {Observable} from "rxjs"; +import {ServiceInstance} from "../../models/serviceInstance"; +import {Constants} from "../../utils/constants"; +import {createServiceInstance} from "../../storeUtil/utils/service/service.actions"; +import {createServiceInstanceFromTemplate} from "../../storeUtil/utils/useTemplate/useTemplate.action"; + +@Injectable() +export class InstantiationTemplatesService { + constructor(private http: HttpClient, private store: NgRedux<AppState>) { + } + + retrieveInstantiationTemplateTopology(jobId: string): Observable<ServiceInstance> { + let pathQuery: string = `${Constants.Path.INSTANTIATION_TEMPLATE_TOPOLOGY}/${jobId}`; + return this.http.get<ServiceInstance>(pathQuery) + } + + public retrieveAndStoreInstantiationTemplateTopology(jobId: string, serviceModelId: string): Observable<ServiceInstance> { + return this.retrieveInstantiationTemplateTopology(jobId).do((instantiationTemplate: ServiceInstance) => { + this.store.dispatch(createServiceInstanceFromTemplate(instantiationTemplate, serviceModelId)); + }); + }; + +} diff --git a/vid-webpack-master/src/app/shared/shared.module.ts b/vid-webpack-master/src/app/shared/shared.module.ts index 93452256b..273dff472 100644 --- a/vid-webpack-master/src/app/shared/shared.module.ts +++ b/vid-webpack-master/src/app/shared/shared.module.ts @@ -42,6 +42,7 @@ import {NetworkPopupService} from "./components/genericFormPopup/genericFormServ import {NetworkControlGenerator} from "./components/genericForm/formControlsServices/networkGenerator/network.control.generator"; import {BasicPopupService} from "./components/genericFormPopup/genericFormServices/basic.popup.service"; import {VfModulePopuopService} from "./components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service"; +import {VfModuleUpgradePopupService} from "./components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; import {VfModuleControlGenerator} from "./components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator"; import {OrderByPipe} from "./pipes/order/orderBy.pipe"; import {ServicePopupService} from "./components/genericFormPopup/genericFormServices/service/service.popup.service"; @@ -72,6 +73,12 @@ import {ClickOutsideDirective} from "./directives/clickOutside/clickOutside.dire import {DynamicInputsComponent} from "./components/dynamic-inputs/dynamic-inputs.component"; import {DynamicInputLabelPipe} from "./pipes/dynamicInputLabel/dynamic-input-label.pipe"; import {ModelInformationService} from "./components/model-information/model-information.service"; +import {MultiselectFormControlService} from "./components/formControls/component/multiselect/multiselect.formControl.service"; +import {InstantiationTemplatesModalComponent} from "./components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component"; +import {InstantiationTemplatesModalService} from "./components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service"; +import {SearchFilterPipe} from "./pipes/searchFilter/search-filter.pipe"; +import {RecreateResolver} from "./resolvers/recreate/recreate.resolver"; +import {InstantiationTemplatesService} from "./services/templateService/instantiationTemplates.service"; @NgModule({ @@ -112,6 +119,7 @@ import {ModelInformationService} from "./components/model-information/model-info SafePipe, ObjectToArrayPipe, DataFilterPipe, + SearchFilterPipe, InputFormControlComponent, FormControlMessageErrorComponent, GenericFormPopupComponent, @@ -123,7 +131,8 @@ import {ModelInformationService} from "./components/model-information/model-info SvgComponent, ErrorMsgComponent, DynamicInputsComponent, - DynamicInputLabelPipe + DynamicInputLabelPipe, + InstantiationTemplatesModalComponent ], exports: [ PopoverComponent, @@ -143,6 +152,7 @@ import {ModelInformationService} from "./components/model-information/model-info SafePipe, ObjectToArrayPipe, DataFilterPipe, + SearchFilterPipe, InputFormControlComponent, FormControlMessageErrorComponent, GenericFormPopupComponent, @@ -158,7 +168,8 @@ import {ModelInformationService} from "./components/model-information/model-info ], entryComponents : [ GenericFormPopupComponent, - SearchElementsModalComponent + SearchElementsModalComponent, + InstantiationTemplatesModalComponent ], providers: [ ServiceInfoService, @@ -173,6 +184,8 @@ import {ModelInformationService} from "./components/model-information/model-info FlagsResolve, ViewEditResolver, RetryResolver, + RecreateResolver, + InstantiationTemplatesService, ServiceControlGenerator, ServicePopupService, VnfControlGenerator, @@ -181,6 +194,7 @@ import {ModelInformationService} from "./components/model-information/model-info CustomValidators, NetworkPopupService, VfModulePopuopService, + VfModuleUpgradePopupService, NetworkControlGenerator, VnfGroupControlGenerator, VnfGroupPopupService, @@ -193,7 +207,10 @@ import {ModelInformationService} from "./components/model-information/model-info ElementsTableService, ErrorMsgService, DataFilterPipe, + SearchFilterPipe, ModelInformationService, + MultiselectFormControlService, + InstantiationTemplatesModalService ] }) export class SharedModule { diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts index 7a10eba0a..79dd3c717 100644 --- a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.actions.ts @@ -5,6 +5,7 @@ import {ServiceType} from "../../../models/serviceType"; import {ITreeNode} from "angular-tree-component/dist/defs/api"; export enum GeneralActions { + MERGE_OBJECT_BY_PATH = "MERGE_OBJECT_BY_PATH", UPDATE_LCP_REGIONS_AND_TENANTS = "UPDATE_LCP_REGIONS_AND_TENANTS", UPDATE_SUBSCRIBERS = "UPDATE_SUBSCRIBERS", UPDATE_PRODUCT_FAMILIES = "UPDATE_PRODUCT_FAMILIES", @@ -78,6 +79,11 @@ export interface UpdateServiceTypesAction extends Action { subscriberId: string; } +export interface MergeObjectByPathAction extends Action{ + path: String[]; + payload: object; +} + export const updateLcpRegionsAndTenants: ActionCreator<UpdateLcpRegionsAndTenantsAction> = lcpRegionsAndTenants => ({ type: GeneralActions.UPDATE_LCP_REGIONS_AND_TENANTS, lcpRegionsAndTenants: lcpRegionsAndTenants @@ -147,4 +153,10 @@ export const updateServiceTypes: ActionCreator<UpdateServiceTypesAction> = (serv subscriberId: subscriberId }); +export const mergeObjectByPathAction : ActionCreator<MergeObjectByPathAction> = (path, payload) => ({ + type: GeneralActions.MERGE_OBJECT_BY_PATH, + path, + payload +}); + diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts index ed456314e..952a92842 100644 --- a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.spec.ts @@ -1,22 +1,12 @@ import {LcpRegion} from "../../../models/lcpRegion"; import {Tenant} from "../../../models/tenant"; import {generalReducer} from "./general.reducers"; -import { - ChangeInstanceCounterAction, - RemoveInstanceAction, - DuplicateBulkInstancesAction, - GeneralActions, - UpdateAicZonesAction, - UpdateCategoryParametersAction, - UpdateProductFamiliesAction, - UpdateServiceTypesAction, - UpdateSubscribersAction, - UpdateUserIdAction, UpdateNetworkCollectionFunction, -} from "./general.actions"; +import {ChangeInstanceCounterAction, DuplicateBulkInstancesAction, GeneralActions, MergeObjectByPathAction, RemoveInstanceAction, UpdateAicZonesAction, UpdateCategoryParametersAction, UpdateNetworkCollectionFunction, UpdateProductFamiliesAction, UpdateServiceTypesAction, UpdateSubscribersAction, UpdateUserIdAction,} from "./general.actions"; import {SelectOption} from "../../../models/selectOption"; import {ServiceType} from "../../../models/serviceType"; import {ITreeNode} from "angular-tree-component/dist/defs/api"; import {VnfInstance} from "../../../models/vnfInstance"; +import each from "jest-each"; describe('generalReducer', () => { test('#UPDATE_LCP_REGIONS_AND_TENANTS : should update lcp region and tenants', () => { @@ -370,6 +360,45 @@ describe('generalReducer', () => { expect(state).toBeDefined(); expect(state['networkFunctions']).toBeDefined(); }); + + const originalMockObject = { + remain: 'forever', + obsolete: 'toBeChange' + }; + + each([ + [ + ['serviceInstance', 'serviceModelId', 'vnfs'], + { + remain: 'forever', + obsolete: 'newValue', + newField: 'newValue2' + } + ], + [ + ['serviceInstance', 'nowhere', 'somewhere'], + originalMockObject + ], + ]). + test('#MERGE_OBJECT_BY_PATH: should update some object by path %s', (path, expected) => { + let state = generalReducer(<any>{serviceInstance : { + 'serviceModelId' : { + vnfs : originalMockObject, + existingVNFCounterMap : {} + } + }}, + <MergeObjectByPathAction>{ + type: GeneralActions.MERGE_OBJECT_BY_PATH, + path, + payload: { + obsolete: 'newValue', + newField: 'newValue2' + } + }); + + expect(state).toBeDefined(); + expect(state.serviceInstance['serviceModelId'].vnfs).toEqual(expected); + }); }); diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts index 5b265dbfd..f87a97397 100644 --- a/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/general/general.reducers.ts @@ -1,12 +1,5 @@ import {Action} from "redux"; -import { - ChangeInstanceCounterAction, RemoveInstanceAction, DuplicateBulkInstancesAction, - GeneralActions, - UpdateAicZonesAction, UpdateCategoryParametersAction, - UpdateLcpRegionsAndTenantsAction, UpdateNetworkCollectionFunction, - UpdateProductFamiliesAction, UpdateServiceTypesAction, - UpdateSubscribersAction, UpdateUserIdAction -} from "./general.actions"; +import {ChangeInstanceCounterAction, DuplicateBulkInstancesAction, GeneralActions, MergeObjectByPathAction, RemoveInstanceAction, UpdateAicZonesAction, UpdateCategoryParametersAction, UpdateLcpRegionsAndTenantsAction, UpdateNetworkCollectionFunction, UpdateProductFamiliesAction, UpdateServiceTypesAction, UpdateSubscribersAction, UpdateUserIdAction} from "./general.actions"; import {TypeNodeInformation} from "../../../../drawingBoard/service-planning/typeNodeInformation.model"; import * as _ from "lodash"; import {ITreeNode} from "angular-tree-component/dist/defs/api"; @@ -92,6 +85,19 @@ export function generalReducer(state: ServiceState, action: Action) : ServiceSta return newState; } + case GeneralActions.MERGE_OBJECT_BY_PATH : { + const mergeObjectByPathAction = <MergeObjectByPathAction>action; + let newState = _.cloneDeep(state); + let targetObject = _.get(newState, <any>mergeObjectByPathAction.path); + if (targetObject) { + targetObject = _.merge(targetObject, mergeObjectByPathAction.payload); + } + else { + console.error(`Can't find object at ${mergeObjectByPathAction.path.join()}`) + } + return newState; + } + } } diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts index c02049eb9..a135563eb 100644 --- a/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/main.reducer.ts @@ -9,9 +9,11 @@ import {VNFActions} from "./vnf/vnf.actions"; import {vnfReducer} from "./vnf/vnf.reducers"; import {generalReducer} from "./general/general.reducers"; import {serviceReducer} from "./service/service.reducers"; +import {useTemplateReducer} from "./useTemplate/useTemplate.reducer"; import {networkReducer} from "./network/network.reducers"; import {vfModuleReducer} from "./vfModule/vfModule.reducers"; import {ServiceInstance} from "../../models/serviceInstance"; +import {UseTemplateActions} from "./useTemplate/useTemplate.action"; import {SelectOptionInterface} from "../../models/selectOption"; import {ServiceType} from "../../models/serviceType"; import {VnfGroupActions} from "./vnfGroup/vnfGroup.actions"; @@ -72,6 +74,8 @@ export const MainReducer = function (state: ServiceState = initialState, action: return crReducer(state, action); }else if(Object.values(NcfActions).includes(action.type)){ return ncfReducer(state, action); + } else if(Object.values(UseTemplateActions).includes(action.type)) { + return useTemplateReducer(state, action); } else { return Object.assign({}, state); } diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.action.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.action.ts new file mode 100644 index 000000000..2cfd38482 --- /dev/null +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.action.ts @@ -0,0 +1,17 @@ +import {Action, ActionCreator} from "redux"; +import {ServiceInstance} from "../../../models/serviceInstance"; + +export enum UseTemplateActions { + CREATE_SERVICE_INSTANCE_FROM_TEMPLATE = 'CREATE_SERVICE_INSTANCE_FROM_TEMPLATE', +} + +export interface CreateServiceInstanceFromTemplate extends Action { + serviceInstantiationTemplate?: ServiceInstance; + serviceModelId?: string; +} + +export const createServiceInstanceFromTemplate: ActionCreator<CreateServiceInstanceFromTemplate> = (serviceInstantiationTemplate, serviceModelId) => ({ + type: UseTemplateActions.CREATE_SERVICE_INSTANCE_FROM_TEMPLATE, + serviceInstantiationTemplate: serviceInstantiationTemplate, + serviceModelId: serviceModelId +}); diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.spec.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.spec.ts new file mode 100644 index 000000000..e0f46e13a --- /dev/null +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.spec.ts @@ -0,0 +1,18 @@ +import {ServiceInstance} from "../../../models/serviceInstance"; +import {useTemplateReducer} from "./useTemplate.reducer"; +import {CreateServiceInstanceFromTemplate, UseTemplateActions} from "./useTemplate.action"; + +test('#CREATE_SERVICE_INSTANCE_FROM_TEMPLATE should add new service instance from template to redux ', () => { + let serviceFromTemplateInstance: ServiceInstance = <any>{ + instanceName: 'templateInstanceName' + }; + let serviceState = useTemplateReducer(<any>{ + serviceInstance:{}}, + <CreateServiceInstanceFromTemplate> { + type: UseTemplateActions.CREATE_SERVICE_INSTANCE_FROM_TEMPLATE, + serviceModelId: 'serviceModelID', + serviceInstantiationTemplate: serviceFromTemplateInstance, + }) + expect (serviceState).toBeDefined(); + expect (serviceState.serviceInstance['serviceModelID'].instanceName).toEqual('templateInstanceName'); +}); diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.ts new file mode 100644 index 000000000..5a06d6e0a --- /dev/null +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/useTemplate/useTemplate.reducer.ts @@ -0,0 +1,20 @@ +import {ServiceState} from "../main.reducer"; +import {Action} from "redux"; +import { + createServiceInstanceFromTemplate, + CreateServiceInstanceFromTemplate, + UseTemplateActions +} from "./useTemplate.action"; +import * as _ from "lodash"; + +export function useTemplateReducer(state: ServiceState, action: Action) : ServiceState { + switch (action.type) { + case UseTemplateActions.CREATE_SERVICE_INSTANCE_FROM_TEMPLATE : { + const updateServiceInstanceFromTemplateAction = <CreateServiceInstanceFromTemplate>action; + const uuid = updateServiceInstanceFromTemplateAction.serviceModelId; + let newState = _.cloneDeep(state); + newState.serviceInstance[uuid] = updateServiceInstanceFromTemplateAction.serviceInstantiationTemplate; + return newState; + } + } +} diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts index 59e5ee1fa..70c10c429 100644 --- a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.actions.ts @@ -9,6 +9,8 @@ export enum VfModuleActions { UPDATE_VFMODULE_POSITION = "UPDATE_VFMODULE_POSITION", UPGRADE_VFMODULE = "UPGRADE_VFMODULE", UNDO_UPGRADE_VFMODULE_ACTION = "UNDO_UPGRADE_VFMODULE_ACTION", + UPDATE_VFMODULE_FEILD = "UPDATE_VFMODULE_FEILD", + DELETE_VFMODULE_FEILD = "DELETE_VFMODULE_FEILD", } @@ -62,6 +64,23 @@ export interface UndoUpgradeVfModuleInstanceAction extends Action { dynamicModelName: string; } +export interface UpdateVFModuleField extends Action { + modelName : string; + vnfStoreKey : string; + serviceId: string; + dynamicModelName: string; + fieldName: string; + fieldValue : any; +} + +export interface DeleteVFModuleField extends Action { + modelName : string; + vnfStoreKey : string; + serviceId: string; + dynamicModelName: string; + deleteFieldName: string; +} + export interface UndoDeleteActionVfModuleInstanceAction extends Action { dynamicModelName: string; vnfStoreKey : string; @@ -132,3 +151,22 @@ export const undoUgradeVFModule: ActionCreator<UndoUpgradeVfModuleInstanceAction vnfStoreKey, serviceId }); + +export const updateVFModuleField: ActionCreator<UpdateVFModuleField> = (modelName, vnfStoreKey, serviceId, dynamicModelName, fieldName, fieldValue) => ({ + type: VfModuleActions.UPDATE_VFMODULE_FEILD, + dynamicModelName, + modelName, + vnfStoreKey, + serviceId, + fieldName, + fieldValue +}); + +export const deleteVFModuleField: ActionCreator<DeleteVFModuleField> = (modelName, vnfStoreKey, serviceId, dynamicModelName, deleteFieldName) => ({ + type: VfModuleActions.DELETE_VFMODULE_FEILD, + dynamicModelName, + modelName, + vnfStoreKey, + serviceId, + deleteFieldName +}); diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts index ee0edb0a7..7b890b715 100644 --- a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.spec.ts @@ -1,9 +1,9 @@ import { CreateVFModuleInstanceAction, - DeleteActionVfModuleInstanceAction, + DeleteActionVfModuleInstanceAction, DeleteVFModuleField, DeleteVfModuleInstanceAction, UndoDeleteActionVfModuleInstanceAction, - UpdateVFModluePosition, + UpdateVFModluePosition, UpdateVFModuleField, UpgradeVfModuleInstanceAction, VfModuleActions } from "./vfModule.actions"; @@ -14,12 +14,13 @@ import {ServiceInstanceActions} from "../../../models/serviceInstanceActions"; describe('vfModuleReducer', () => { test('#REMOVE_VNF_MODULE_INSTANCE : should delete existing vnf module by dynamicModelName', () => { - let state = vfModuleReducer(<any>{serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vfName' : { - vfModules : { - 'modelName' : { + let state = vfModuleReducer(<any>{ + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vfName': { + vfModules: { + 'modelName': { 'dynamicModelName1': {}, 'dynamicModelName2': {}, } @@ -27,13 +28,14 @@ describe('vfModuleReducer', () => { } } } - }}, + } + }, <DeleteVfModuleInstanceAction>{ type: VfModuleActions.REMOVE_VNF_MODULE_INSTANCE, - modelName : 'modelName', - vfName : 'vfName', - vnfStoreKey : 'vfName', - serviceModelId : 'serviceModelId', + modelName: 'modelName', + vfName: 'vfName', + vnfStoreKey: 'vfName', + serviceModelId: 'serviceModelId', dynamicModelName: 'dynamicModelName1' }); @@ -43,26 +45,27 @@ describe('vfModuleReducer', () => { }); test('#DELETE_LAST_VNF_MODULE_INSTANCE : should delete existing vnf module', () => { - let state = vfModuleReducer(<any>{serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vfName' : { - vfModules : { - 'modelName' : { - 'dynamicModelName': { - } + let state = vfModuleReducer(<any>{ + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vfName': { + vfModules: { + 'modelName': { + 'dynamicModelName': {} } } } } } - }}, + } + }, <DeleteVfModuleInstanceAction>{ type: VfModuleActions.REMOVE_VNF_MODULE_INSTANCE, - modelName : 'modelName', - vfName : 'vfName', - vnfStoreKey : 'vfName', - serviceModelId : 'serviceModelId', + modelName: 'modelName', + vfName: 'vfName', + vnfStoreKey: 'vfName', + serviceModelId: 'serviceModelId', dynamicModelName: 'dynamicModelName' }); @@ -70,28 +73,29 @@ describe('vfModuleReducer', () => { expect(state.serviceInstance['serviceModelId'].vnfs['vfName'].vfModules['modelName']).not.toBeDefined(); }); - test('#CREATE_VF_MODULE: should create new vfModule to existing VNF', ()=>{ - let vfModuleInstance : VfModuleInstance = new VfModuleInstance(); + test('#CREATE_VF_MODULE: should create new vfModule to existing VNF', () => { + let vfModuleInstance: VfModuleInstance = new VfModuleInstance(); vfModuleInstance.instanceName = 'instanceName'; vfModuleInstance.isMissingData = false; vfModuleInstance.volumeGroupName = 'volumeGroupName'; - let vfModule = vfModuleReducer(<any>{serviceInstance : { - 'serviceUuid' : { - vnfs : { - 'vnfStoreKey' : { - 'vfModules' : { - } + let vfModule = vfModuleReducer(<any>{ + serviceInstance: { + 'serviceUuid': { + vnfs: { + 'vnfStoreKey': { + 'vfModules': {} } } } - }}, + } + }, <CreateVFModuleInstanceAction>{ type: VfModuleActions.CREATE_VF_MODULE, - vfId : 'vfId', - vfInstance : new VfModuleInstance(), - vnfStoreKey : 'vnfStoreKey', - serviceUuid : 'serviceUuid', - index : 1 + vfId: 'vfId', + vfInstance: new VfModuleInstance(), + vnfStoreKey: 'vnfStoreKey', + serviceUuid: 'serviceUuid', + index: 1 }).serviceInstance['serviceUuid'].vnfs['vnfStoreKey'].vfModules; let firstVfModuleName = Object.keys(vfModule)[0]; @@ -99,23 +103,64 @@ describe('vfModuleReducer', () => { expect(vfModule[firstVfModuleName].isMissingData).toBeFalsy(); }); - test('#UPDATE_VF_MODULE: should update existing VFModule', ()=>{ - let vfModuleInstance : VfModuleInstance = new VfModuleInstance(); - vfModuleInstance.instanceName = 'instanceName'; - vfModuleInstance.isMissingData = false; - vfModuleInstance.volumeGroupName = 'volumeGroupName'; - let vfModule = vfModuleReducer(<any>{ - serviceHierarchy : { - 'serviceModelId' : {} + test('#UPDATE_VFMODULE_FEILD: should update field with some value', () => { + const newFieldName = 'newFieldName'; + const newFieldValue = 'newFieldValue'; + let oldState = { + serviceHierarchy: { + 'serviceModelId': {} + }, + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vnfStoreKey': { + vfModules: { + 'modelName': { + 'dynamicModelName1': { + isMissingData: true, + action: 'None' + }, + 'dynamicModelName2': {}, + } + } + } + } + } + } + }; + + let newState = vfModuleReducer(<any>oldState, + <UpdateVFModuleField>{ + type: VfModuleActions.UPDATE_VFMODULE_FEILD, + dynamicModelName: 'dynamicModelName1', + vnfStoreKey: 'vnfStoreKey', + serviceId: 'serviceModelId', + modelName: 'modelName', + fieldName: newFieldName, + fieldValue: newFieldValue + }); + + let vfModule = newState.serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; + + expect(vfModule[newFieldName]).toEqual(newFieldValue); + }); + + test('#DELETE_VFMODULE_FEILD: should update field with some value', () => { + const deleteFieldName = 'deleteFieldName'; + let oldState = { + serviceHierarchy: { + 'serviceModelId': {} }, - serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vfName' : { - vfModules : { - 'modelName' : { + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vnfStoreKey': { + vfModules: { + 'modelName': { 'dynamicModelName1': { - isMissingData : true + isMissingData: true, + [deleteFieldName]: true, + action: 'None' }, 'dynamicModelName2': {}, } @@ -123,192 +168,197 @@ describe('vfModuleReducer', () => { } } } - }}, - <CreateVFModuleInstanceAction>{ - type: VfModuleActions.UPDATE_VF_MODULE, - vfId : 'modelName', - vfInstance : new VfModuleInstance(), - vnfStoreKey : 'vfName', - dynamicModelName : 'dynamicModelName1', - serviceUuid : 'serviceModelId', - index : 1 - }).serviceInstance['serviceModelId'].vnfs['vfName'].vfModules; + } + }; + let newState = vfModuleReducer(<any>oldState, + <DeleteVFModuleField>{ + type: VfModuleActions.DELETE_VFMODULE_FEILD, + dynamicModelName: 'dynamicModelName1', + vnfStoreKey: 'vnfStoreKey', + serviceId: 'serviceModelId', + modelName: 'modelName', + deleteFieldName: deleteFieldName, + }); - let firstVfModuleName = Object.keys(vfModule)[0]; - expect(vfModule[firstVfModuleName]).toBeDefined(); - expect(vfModule[firstVfModuleName].isMissingData).toBeFalsy(); - }); + let vfModule = newState.serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; + expect(vfModule[deleteFieldName]).toBeUndefined(); +}); - test('#UPDATE_VFMODULE_POSITION: should update position', ()=>{ - let vfModule = vfModuleReducer(<any>{ - serviceHierarchy : { - 'serviceModelId' : {} - }, - serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vfName' : { - vfModules : { - 'modelName' : { - 'dynamicModelName': { - isMissingData : true - } +test('#UPDATE_VFMODULE_POSITION: should update position', () => { + let vfModule = vfModuleReducer(<any>{ + serviceHierarchy: { + 'serviceModelId': {} + }, + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vfName': { + vfModules: { + 'modelName': { + 'dynamicModelName': { + isMissingData: true } } } } } - }}, - <UpdateVFModluePosition>{ - type: VfModuleActions.UPDATE_VFMODULE_POSITION, - node: { - position : 1, - dynamicModelName : "dynamicModelName", - modelName : "modelName" - }, - instanceId : "serviceModelId", - vnfStoreKey : "vfName" + } + } + }, + <UpdateVFModluePosition>{ + type: VfModuleActions.UPDATE_VFMODULE_POSITION, + node: { + position: 1, + dynamicModelName: "dynamicModelName", + modelName: "modelName" + }, + instanceId: "serviceModelId", + vnfStoreKey: "vfName" - }).serviceInstance['serviceModelId'].vnfs['vfName'].vfModules["modelName"]["dynamicModelName"]; - - expect(vfModule.position).toEqual(1); - }); + }).serviceInstance['serviceModelId'].vnfs['vfName'].vfModules["modelName"]["dynamicModelName"]; + expect(vfModule.position).toEqual(1); +}); - test('#DELETE_ACTION_VF_MODULE_INSTANCE', ()=>{ - let vfModule = vfModuleReducer(<any>{ - serviceHierarchy : { - 'serviceModelId' : {} - }, - serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vnfStoreKey' : { - vfModules : { - 'modelName' : { - 'dynamicModelName1': { - isMissingData : true, - action : 'None' - }, - 'dynamicModelName2': {}, - } +test('#DELETE_ACTION_VF_MODULE_INSTANCE', () => { + let vfModule = vfModuleReducer(<any>{ + serviceHierarchy: { + 'serviceModelId': {} + }, + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vnfStoreKey': { + vfModules: { + 'modelName': { + 'dynamicModelName1': { + isMissingData: true, + action: 'None' + }, + 'dynamicModelName2': {}, } } } } - }}, - <DeleteActionVfModuleInstanceAction>{ - type: VfModuleActions.DELETE_ACTION_VF_MODULE_INSTANCE, - dynamicModelName: 'dynamicModelName1', - vnfStoreKey : 'vnfStoreKey', - serviceId: 'serviceModelId' - }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; + } + } + }, + <DeleteActionVfModuleInstanceAction>{ + type: VfModuleActions.DELETE_ACTION_VF_MODULE_INSTANCE, + dynamicModelName: 'dynamicModelName1', + vnfStoreKey: 'vnfStoreKey', + serviceId: 'serviceModelId' + }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; - console.log(vfModule.action); - expect(vfModule).toBeDefined(); - expect(vfModule.isMissingData).toBeTruthy(); - expect(vfModule.action).toEqual(ServiceInstanceActions.None_Delete); - }); + console.log(vfModule.action); + expect(vfModule).toBeDefined(); + expect(vfModule.isMissingData).toBeTruthy(); + expect(vfModule.action).toEqual(ServiceInstanceActions.None_Delete); +}); - test('#UNDO_DELETE_ACTION_VF_MODULE_INSTANCE', ()=>{ - let vfModule = vfModuleReducer(<any>{ - serviceHierarchy : { - 'serviceModelId' : {} - }, - serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vnfStoreKey' : { - vfModules : { - 'modelName' : { - 'dynamicModelName1': { - isMissingData : true, - action : 'None_Delete' - }, - 'dynamicModelName2': {}, - } +test('#UNDO_DELETE_ACTION_VF_MODULE_INSTANCE', () => { + let vfModule = vfModuleReducer(<any>{ + serviceHierarchy: { + 'serviceModelId': {} + }, + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vnfStoreKey': { + vfModules: { + 'modelName': { + 'dynamicModelName1': { + isMissingData: true, + action: 'None_Delete' + }, + 'dynamicModelName2': {}, } } } } - }}, - <UndoDeleteActionVfModuleInstanceAction>{ - type: VfModuleActions.UNDO_DELETE_ACTION_VF_MODULE_INSTANCE, - dynamicModelName: 'dynamicModelName1', - vnfStoreKey : 'vnfStoreKey', - serviceId: 'serviceModelId' - }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; + } + } + }, + <UndoDeleteActionVfModuleInstanceAction>{ + type: VfModuleActions.UNDO_DELETE_ACTION_VF_MODULE_INSTANCE, + dynamicModelName: 'dynamicModelName1', + vnfStoreKey: 'vnfStoreKey', + serviceId: 'serviceModelId' + }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; - console.log(vfModule.action); - expect(vfModule).toBeDefined(); - expect(vfModule.action).toEqual(ServiceInstanceActions.None); - }); + console.log(vfModule.action); + expect(vfModule).toBeDefined(); + expect(vfModule.action).toEqual(ServiceInstanceActions.None); +}); - test('#UPGRADE_VFMODULE', ()=>{ - let vfModule = vfModuleReducer(<any>{ - serviceHierarchy : { - 'serviceModelId' : {} - }, - serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vnfStoreKey' : { - vfModules : { - 'modelName' : { - 'dynamicModelName1': { - isMissingData : true, - action : 'None' - }, - 'dynamicModelName2': {}, - } +test('#UPGRADE_VFMODULE', () => { + let vfModule = vfModuleReducer(<any>{ + serviceHierarchy: { + 'serviceModelId': {} + }, + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vnfStoreKey': { + vfModules: { + 'modelName': { + 'dynamicModelName1': { + isMissingData: true, + action: 'None' + }, + 'dynamicModelName2': {}, } } } } - }}, - <UpgradeVfModuleInstanceAction>{ - type: VfModuleActions.UPGRADE_VFMODULE, - dynamicModelName: 'dynamicModelName1', - vnfStoreKey : 'vnfStoreKey', - serviceId: 'serviceModelId', - modelName: 'modelName' - }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; + } + } + }, + <UpgradeVfModuleInstanceAction>{ + type: VfModuleActions.UPGRADE_VFMODULE, + dynamicModelName: 'dynamicModelName1', + vnfStoreKey: 'vnfStoreKey', + serviceId: 'serviceModelId', + modelName: 'modelName' + }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; - expect(vfModule.action).toEqual(ServiceInstanceActions.None_Upgrade); - }); + expect(vfModule.action).toEqual(ServiceInstanceActions.None_Upgrade); +}); - test('#UNDO_UPGRADE_VFMODULE', ()=>{ - let vfModule = vfModuleReducer(<any>{ - serviceHierarchy : { - 'serviceModelId' : {} - }, - serviceInstance : { - 'serviceModelId' : { - vnfs : { - 'vnfStoreKey' : { - vfModules : { - 'modelName' : { - 'dynamicModelName1': { - isMissingData : true, - action : 'None_Upgrade' - }, - 'dynamicModelName2': {}, - } +test('#UNDO_UPGRADE_VFMODULE', () => { + let vfModule = vfModuleReducer(<any>{ + serviceHierarchy: { + 'serviceModelId': {} + }, + serviceInstance: { + 'serviceModelId': { + vnfs: { + 'vnfStoreKey': { + vfModules: { + 'modelName': { + 'dynamicModelName1': { + isMissingData: true, + action: 'None_Upgrade' + }, + 'dynamicModelName2': {}, } } } } - }}, - <UpgradeVfModuleInstanceAction>{ - type: VfModuleActions.UNDO_UPGRADE_VFMODULE_ACTION, - dynamicModelName: 'dynamicModelName1', - vnfStoreKey : 'vnfStoreKey', - serviceId: 'serviceModelId', - modelName: 'modelName' - }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; - - expect(vfModule.action).toEqual(ServiceInstanceActions.None); - }); + } + } + }, + <UpgradeVfModuleInstanceAction>{ + type: VfModuleActions.UNDO_UPGRADE_VFMODULE_ACTION, + dynamicModelName: 'dynamicModelName1', + vnfStoreKey: 'vnfStoreKey', + serviceId: 'serviceModelId', + modelName: 'modelName' + }).serviceInstance['serviceModelId'].vnfs['vnfStoreKey'].vfModules['modelName']['dynamicModelName1']; + expect(vfModule.action).toEqual(ServiceInstanceActions.None); }); + +}) +; diff --git a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts index a7aadba41..1bb2b15fd 100644 --- a/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts +++ b/vid-webpack-master/src/app/shared/storeUtil/utils/vfModule/vfModule.reducers.ts @@ -1,10 +1,10 @@ import {Action} from "redux"; import * as _ from "lodash"; import { - CreateVFModuleInstanceAction, DeleteActionVfModuleInstanceAction, - DeleteVfModuleInstanceAction, UndoDeleteActionVfModuleInstanceAction, UpdateVFModluePosition, + CreateVFModuleInstanceAction, DeleteActionVfModuleInstanceAction, DeleteVFModuleField, + DeleteVfModuleInstanceAction, UndoDeleteActionVfModuleInstanceAction, UpdateVFModluePosition, UpdateVFModuleField, UpdateVFModuleInstanceAction, UpgradeVfModuleInstanceAction, - VfModuleActions + VfModuleActions, } from "./vfModule.actions"; import {ServiceInstance} from "../../../models/serviceInstance"; import {VfModuleMap} from "../../../models/vfModulesMap"; @@ -145,6 +145,26 @@ export function vfModuleReducer(state: ServiceState , action: Action) : ServiceS } return clonedState; } + case VfModuleActions.UPDATE_VFMODULE_FEILD : { + let clonedState = _.cloneDeep(state); + let updateFieldAction = <UpdateVFModuleField> action; + + clonedState.serviceInstance[updateFieldAction.serviceId] + .vnfs[updateFieldAction.vnfStoreKey] + .vfModules[updateFieldAction.modelName][updateFieldAction.dynamicModelName][updateFieldAction.fieldName] = updateFieldAction.fieldValue; + + return clonedState; + } + case VfModuleActions.DELETE_VFMODULE_FEILD : { + let clonedState = _.cloneDeep(state); + let deleteAction = <DeleteVFModuleField> action; + + delete clonedState.serviceInstance[deleteAction.serviceId] + .vnfs[deleteAction.vnfStoreKey] + .vfModules[deleteAction.modelName][deleteAction.dynamicModelName][deleteAction.deleteFieldName]; + + return clonedState; + } } } diff --git a/vid-webpack-master/src/app/shared/utils/constants.ts b/vid-webpack-master/src/app/shared/utils/constants.ts index 400a4d8dc..f793e05db 100644 --- a/vid-webpack-master/src/app/shared/utils/constants.ts +++ b/vid-webpack-master/src/app/shared/utils/constants.ts @@ -92,7 +92,9 @@ export module Constants { public static WELCOME_PATH = 'welcome.htm'; public static IS_PERMITTED_SUB_PATH = '&isPermitted='; public static SERVICES_JOB_INFO_PATH = '../../asyncInstantiation'; + public static SERVICE_MODEL_ID = 'serviceModelId'; public static SERVICES_RETRY_TOPOLOGY = '../../asyncInstantiation/bulkForRetry'; + public static INSTANTIATION_TEMPLATE_TOPOLOGY = '../../asyncInstantiation/templateTopology'; public static CONFIGURATION_PATH = '../../get_property/{name}/defaultvalue'; public static SERVICES_JOB_AUDIT_PATH = '/auditStatus'; public static SERVICES_PROBE_PATH = "../../probe"; @@ -295,4 +297,8 @@ export module Constants { export class LegacyRegion { public static MEGA_REGION = ['AAIAIC25']; } + + export class ModelInfo { + public static UNLIMITED_DEFAULT = 'Unlimited (default)'; + } } diff --git a/vid-webpack-master/src/app/shared/utils/util.spec.ts b/vid-webpack-master/src/app/shared/utils/util.spec.ts index 2f9142f9c..ae39238c2 100644 --- a/vid-webpack-master/src/app/shared/utils/util.spec.ts +++ b/vid-webpack-master/src/app/shared/utils/util.spec.ts @@ -1,23 +1,8 @@ import {Utils} from "./utils"; -import {TestBed} from "@angular/core/testing"; +import each from "jest-each"; describe('Util', () => { - let util: Utils; - - beforeAll(done => (async () => { - TestBed.configureTestingModule({ - - }); - await TestBed.compileComponents(); - - util = new Utils(); - - })().then(done).catch(done.fail)); - - test('should be defined', () => { - expect(util).toBeDefined(); - }); test('hasContents should return false if object is undefined or null or empty', () => { expect(Utils.hasContents(undefined)).toBeFalsy(); @@ -28,4 +13,39 @@ describe('Util', () => { test('hasContents should return true if object is not undefined and not null and not empty', () => { expect(Utils.hasContents("someValue")).toBeTruthy(); }); + + const instantiationTypesDataProvider = [ + ['Macro', false ], + ['ALaCarte', true ], + ['ClientConfig', true], + ['dont know', true] + ]; + each(instantiationTypesDataProvider).test('instantiationType %s isALaCarte shall be %s', (instantiationType, expected ) => { + expect(Utils.isALaCarte(instantiationType)).toEqual(expected); + }); + + each([ + ["empty properties, empty flags",{}, {}, 1], + ["null properties, undefined flags",null, undefined, 1], + ["max_instances 3, flag is on", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3], + ["max_instances 3, flag is off", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: false}, 3], + ["null properties, flag is on", null, {FLAG_2002_UNLIMITED_MAX: true}, null], + ["null properties, flag is off", null, {FLAG_2002_UNLIMITED_MAX: false}, 1], + ["undefined properties, flag is off", undefined, {FLAG_2002_UNLIMITED_MAX: false}, 1], + ]).test('getMaxFirstLevel %s', (desc, properties, flags, expected) => { + expect(Utils.getMaxFirstLevel(properties, flags)).toEqual(expected); + }); + + each([ + ["empty properties, empty flags",{}, {}, 1], + ["null properties, undefined flags",null, undefined, 1], + ["wrong field, flag is on", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: true}, null], + ["maxCountInstances 3, flag is on", {maxCountInstances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3], + ["maxCountInstances 3, flag is off", {maxCountInstances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3], + ]).test('getMaxFirstLevel %s', (desc, properties, flags, expected) => { + expect(Utils.getMaxVfModule(properties, flags)).toEqual(expected); + }); + + + }); diff --git a/vid-webpack-master/src/app/shared/utils/utils.ts b/vid-webpack-master/src/app/shared/utils/utils.ts index d63a3c997..3db770738 100644 --- a/vid-webpack-master/src/app/shared/utils/utils.ts +++ b/vid-webpack-master/src/app/shared/utils/utils.ts @@ -2,6 +2,21 @@ import * as _ from 'lodash' export class Utils { + static getMaxFirstLevel(properties, flags: { [key: string]: boolean }) : number | null{ + return this.getMaxInstancesAllowed(properties, 'max_instances', flags) + } + + static getMaxVfModule(properties, flags: { [key: string]: boolean }) : number | null{ + return this.getMaxInstancesAllowed(properties, 'maxCountInstances', flags) + } + + static getMaxInstancesAllowed(properties, filedName: string, flags: { [key: string]: boolean }) : number | null{ + if (!_.isNil(properties) && !_.isNil(properties[filedName])) { + return properties[filedName]; + } + return (flags && !!flags['FLAG_2002_UNLIMITED_MAX']) ? null : 1; + } + public static clampNumber = (number, min, max) => { return Math.max(min, Math.min(number, max)); }; @@ -179,6 +194,10 @@ export class Utils { return (convertedAsdcModel); }; + public static isALaCarte(instantiationType) { + return instantiationType !== 'Macro'; + } + private static convertOldModel(serviceModel ) { let resource = {}; let convertedAsdcModel = { |