diff options
54 files changed, 641 insertions, 342 deletions
@@ -37,11 +37,6 @@ 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' @@ -67,3 +62,6 @@ tsc: - 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/deliveries/src/main/docker/docker-files/Dockerfile b/deliveries/src/main/docker/docker-files/Dockerfile index 62feb8c3c..f6070d8b1 100755 --- a/deliveries/src/main/docker/docker-files/Dockerfile +++ b/deliveries/src/main/docker/docker-files/Dockerfile @@ -82,8 +82,6 @@ ENV VID_CONTACT_US_LINK="https://todo_contact_us_link.com" \ # Custom options ENV JAVA_OPTS="-Xmx1536m -Xms1536m" -ENV CATALINA_OPTS="-Dvid.keystore.password=${VID_KEYSTORE_PASSWORD} -Dvid.keyalias=vid@vid.onap.org -Dvid.keystore.filename=${VID_KEYSTORE_FILENAME} -Dcom.att.eelf.logging.file=logback.xml -Dcom.att.eelf.logging.path=/tmp" - ADD maven/config/server.xml ${VID_TOMCAT_PATH} ADD maven/scripts/*.sh /tmp/vid/ diff --git a/deliveries/src/main/scripts/localize.sh b/deliveries/src/main/scripts/localize.sh index aca557f36..918027913 100755 --- a/deliveries/src/main/scripts/localize.sh +++ b/deliveries/src/main/scripts/localize.sh @@ -20,4 +20,10 @@ TEMPLATES_BASE_DIR=/usr/local/tomcat/webapps/vid/WEB-INF fillTemplateProperties ${TEMPLATES_BASE_DIR} +# Set CATALINA_OPTS if not defined previously +# Enables late-evaluation of env variables, such as VID_KEYSTORE_PASSWORD +: "${CATALINA_OPTS:=-Dvid.keystore.password=${VID_KEYSTORE_PASSWORD} -Dvid.keyalias=vid@vid.onap.org -Dvid.keystore.filename=${VID_KEYSTORE_FILENAME} -Dcom.att.eelf.logging.file=logback.xml -Dcom.att.eelf.logging.path=/tmp}" +echo "CATALINA_OPTS: ${CATALINA_OPTS}" +export CATALINA_OPTS + catalina.sh run 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 0dc8eacea..95c1ce271 100755 --- a/epsdk-app-onap/pom.xml +++ b/epsdk-app-onap/pom.xml @@ -16,7 +16,7 @@ <parent> <groupId>org.onap.oparent</groupId> <artifactId>oparent</artifactId> - <version>2.0.0</version> + <version>2.1.0</version> <relativePath/> </parent> @@ -10,7 +10,7 @@ <parent> <groupId>org.onap.oparent</groupId> <artifactId>oparent</artifactId> - <version>2.0.0</version> + <version>2.1.0</version> <relativePath/> </parent> diff --git a/vid-app-common/pom.xml b/vid-app-common/pom.xml index f618ec822..c9356771d 100755 --- a/vid-app-common/pom.xml +++ b/vid-app-common/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.onap.oparent</groupId> <artifactId>oparent</artifactId> - <version>2.0.0</version> + <version>2.1.0</version> <relativePath/> </parent> diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java b/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java index 1c8a465cb..45478e20f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java @@ -360,12 +360,10 @@ public class ServiceModel { " Associated VF Module customizationName=" + vfModuleComponent.getKey() + " with VNF customization name=" + vnfCustomizationName); // now find if this vf module has volume groups, if so, find the volume group with the same customization name and put it under the VNF - if ( vfModuleComponent.getValue().isVolumeGroupAllowed() ) { - if (isVolumeGroupsContainsVfModuleCustomName(vfModuleCustomizationName)) { + if ( vfModuleComponent.getValue().isVolumeGroupAllowed() && isVolumeGroupsContainsVfModuleCustomName(vfModuleCustomizationName) ) { (vnfComponent.getValue().getVolumeGroups()).put(vfModuleCustomizationName, (getVolumeGroups()).get(vfModuleCustomizationName)); } } - } private boolean isVolumeGroupsContainsVfModuleCustomName(String vfModuleCustomizationName) { return (!MapUtils.isEmpty(getVolumeGroups())) && (getVolumeGroups().containsKey((vfModuleCustomizationName))); 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 ba9f0f533..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", @@ -264,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 12dd77953..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 @@ -162,13 +162,10 @@ if ((!($scope.isObjectEmpty(svcModel))) && (!($scope.isObjectEmpty(svcModel.vnfs)))) {
if ((svcModel.isNewFlow) && (vnfModelCustomizationUuid != null)) {
vnfModel = svcModel.vnfs[vnfModelCustomizationUuid];
- if (vnfModel !== undefined) {
-
- if (!($scope.isObjectEmpty(vnfModel.volumeGroups))) {
+ if (vnfModel !== undefined && !($scope.isObjectEmpty(vnfModel.volumeGroups))) {
//console.log ("vnfModel.volumeGroups: "); console.log (JSON.stringify(vnfModel.volumeGroups, null, 4));
return (vnfModel.volumeGroups);
}
- }
}
else {
// old flow
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-automation/pom.xml b/vid-automation/pom.xml index e2ef865f4..34abd22f5 100644 --- a/vid-automation/pom.xml +++ b/vid-automation/pom.xml @@ -167,7 +167,7 @@ <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> - <version>1.9.3</version> + <version>1.9.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> 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 289151b88..01e4b7558 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 @@ -55,6 +55,7 @@ public enum Features implements Feature { FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS, FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND, FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER, + FLAG_2002_UNLIMITED_MAX, ; public boolean isActive() { 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 5a9dc2c01..8a5a2f1d3 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 @@ -121,6 +121,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { private final VidBasePage vidBasePage = new VidBasePage(); public static final String VNF_SET_BUTTON_TEST_ID = "form-set"; private static final Logger logger = LogManager.getLogger(NewServiceInstanceTest.class); + private static final String NO_MAX_INSTANCES_IN_MODEL = "NO_MAX_INSTANCES_IN_MODEL"; @BeforeClass protected void dropAllAsyncJobs() { @@ -234,7 +235,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { 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", false); + 0, NO_MAX_INSTANCES_IN_MODEL, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5", false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetails, false); @@ -281,7 +282,8 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { Collections.singletonList("2017488 pasqualevpe0 asn:"), 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"), + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, + NO_MAX_INSTANCES_IN_MODEL, ImmutableList.of("Bandwidth", "Bandwidth units"), "25284168-24bb-4698-8cb4-3f509146eca5", false); // this is the instance-name that createMacroService is going to use @@ -366,7 +368,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, false); + null, 0, null, new ArrayList<>(), null, false); final String serviceInstanceName = createMacroService(serviceData, false); SimulatorApi.registerExpectationFromPresets(ImmutableList.of( @@ -407,7 +409,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.TRUE, true, true, false, null, - null, 0, 1, new ArrayList<>(), null, false); + null, 0, null, new ArrayList<>(), null, false); createMacroService(serviceData, false, randomAlphabetic(5), true, 1); drawingBoardPage.deploy(); @@ -431,7 +433,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { new ArrayList<>(), IS_GENERATED_NAMING.TRUE, true, true, false, null, - null, 0, 1, new ArrayList<>(), null, false); + null, 0, null, new ArrayList<>(), null, false); createMacroService(serviceData, false, randomAlphabetic(5), false, 1); drawingBoardPage.deploy(); @@ -448,7 +450,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { aLaCarteVnfGroupingService.modelVersionId, ImmutableList.of(), IS_GENERATED_NAMING.FALSE, false, true, false, - null, null, 0, 1, ImmutableList.of(), null, false); + null, null, 0, null, ImmutableList.of(), null, false); prepareServicePreset(aLaCarteVnfGroupingService, false); createALaCarteService(serviceData, randomAlphabetic); @@ -546,7 +548,7 @@ 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, false); + vfModule0Name, 1, "1", new ArrayList<>(), vfModule0UUID, false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetails, false); @@ -563,7 +565,7 @@ 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, false); + vfModule0Name, 1, "1", new ArrayList<>(), vfModule0UUID, false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetailsVnfEcompNamingFalse, false); @@ -580,7 +582,8 @@ 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", false); + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, + NO_MAX_INSTANCES_IN_MODEL, new ArrayList<>(), "25284168-24bb-4698-8cb4-3f509146eca5", false); prepareServicePreset(macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetailsVnfEcompNamingFalse, false); @@ -598,7 +601,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { 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); + 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(); @@ -698,9 +701,9 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { 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); + serviceData.vfData = new VfData("vocg_1804_vf0..Vocg1804Vf..ocgmgr..module-1", true, 0, NO_MAX_INSTANCES_IN_MODEL, 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); + serviceData.vfData = new VfData("vocg_1804_vf0..Vocg1804Vf..ocgapp_001..module-12", true, 0, NO_MAX_INSTANCES_IN_MODEL, emptyList(), "b601eef4-62fd-4201-a788-ae30e06a1aec", null); createVfModule(serviceData, serviceInstanceName, false, false); drawingBoardPage.deploy(); drawingBoardPage.verifyServiceCompletedOnTime(serviceInstanceName, "service "+serviceInstanceName); @@ -767,7 +770,9 @@ 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", false); + "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", 0, + NO_MAX_INSTANCES_IN_MODEL, new ArrayList<>(), + "25284168-24bb-4698-8cb4-3f509146eca5", false); prepareServicePreset(macroSriovWithDynamicFieldsEcompNamingTruePartialModelDetails, false); @@ -1199,8 +1204,6 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { 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"), null, "Min value should not be shown in VNF popup"); - Assert.assertEquals(Get.byTestId("model-item-value-max"), null, "Max value should not be show in VNF popup"); if (!vnfData.isGeneratedNaming) { Assert.assertEquals(Get.byTestId("model-item-value-serviceName").getText(), serviceInstanceName, "Subscriber name should be shown in vf module"); } @@ -1313,7 +1316,16 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { 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.vfData.vfMax!=null) { + if (!serviceData.vfData.vfMax.equals(NO_MAX_INSTANCES_IN_MODEL)) { + Assert.assertEquals(Get.byTestId("model-item-value-max").getText(), serviceData.vfData.vfMax, "Max should be shown"); + } + else { + String defaultMaxText = Features.FLAG_2002_UNLIMITED_MAX.isActive() ? "Unlimited (default)" : "1"; + Assert.assertEquals(Get.byTestId("model-item-value-max").getText(), defaultMaxText, "Max should be shown with default value"); + } + } + 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"); @@ -1406,7 +1418,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { 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) { + String vfName, int vfMin, String vfMax, List<String> vfModuleDynamicFields, String vfVersionId, boolean isALaCarte) { this.modelUuid = modelUuid; this.dynamicFields = dynamicFields; this.isGeneratedNaming = isServiceGeneratedNaming; @@ -1450,7 +1462,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { private static class VfData { - VfData(String vfName, boolean vgEnabled, int vfMin, int vfMax, List<String> dynamicFields, String uuid, String vgName) { + VfData(String vfName, boolean vgEnabled, int vfMin, String vfMax, List<String> dynamicFields, String uuid, String vgName) { this.vfName = vfName; this.vgEnabled = vgEnabled; this.vfMin = vfMin; @@ -1461,7 +1473,7 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest { } final int vfMin; - final int vfMax; + final String vfMax; final String uuid; final String vfName; final boolean vgEnabled; 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 index f6fbd268d..ab59f087d 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/InstantiationTemplatesApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/InstantiationTemplatesApiTest.java @@ -23,6 +23,7 @@ import org.springframework.http.HttpMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import vid.automation.test.Constants; +import vid.automation.test.Constants.Users; import vid.automation.test.model.User; import vid.automation.test.services.AsyncJobsService; import vid.automation.test.services.SimulatorApi.RegistrationStrategy; @@ -59,8 +60,8 @@ public class InstantiationTemplatesApiTest extends AsyncInstantiationBase { @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, "", ""); + User user = usersService.getUser(Users.SILVIA_ROBBINS_TYLER_SILVIA); + return new UserCredentials(user.credentials.userId, user.credentials.password, Users.SILVIA_ROBBINS_TYLER_SILVIA, "", ""); } @AfterMethod diff --git a/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json b/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json index 04b09616e..a874fec4c 100644 --- a/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json +++ b/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json @@ -11,15 +11,15 @@ "modelType": "service", "modelVersion": "1.0" }, - "globalSubscriberId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", - "subscriptionServiceType": "Emanuel", - "owningEntityId": "10c645f5-9924-4b89-bec0-b17cf49d3cad", - "owningEntityName": "EMANUEL-CORE", + "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89", + "subscriptionServiceType": "TYLER SILVIA", + "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc", + "owningEntityName": "WayneHolland", "tenantName": null, "aicZoneId": null, "aicZoneName": null, - "projectName": "Kennedy", - "subscriberName": "Emanuel", + "projectName": "WATKINS", + "subscriberName": "SILVIA ROBBINS", "rollbackOnFailure": "true", "isALaCarte": true, "testApi": "GR_API", @@ -42,11 +42,11 @@ "modelVersion": "1.0" }, "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", - "instanceName": "zolson57arlba007", + "instanceName": "hvf6arlba007", "action": "Create", - "platformName": "NETWORK-CLOUD", - "lcpCloudRegionId": "olson57a", - "tenantId": "dcb28ad99c7341748830c9dc307f85eb", + "platformName": "xxx1", + "lcpCloudRegionId": "hvf6", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", "instanceParams": [ {} ], @@ -64,10 +64,10 @@ "modelType": "vfModule", "modelVersion": "1" }, - "instanceName": "zolson57arlba007_lba_Base_01", + "instanceName": "hvf6arlba007_lba_Base_01", "action": "Create", - "lcpCloudRegionId": "olson57a", - "tenantId": "dcb28ad99c7341748830c9dc307f85eb", + "lcpCloudRegionId": "hvf6", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", "instanceParams": [ {} ], @@ -87,17 +87,17 @@ "modelType": "vfModule", "modelVersion": "1" }, - "instanceName": "zolson57arlba007_lba_dj_01", + "instanceName": "hvf6arlba007_lba_dj_01", "action": "Create", - "lcpCloudRegionId": "olson57a", - "tenantId": "dcb28ad99c7341748830c9dc307f85eb", + "lcpCloudRegionId": "hvf6", + "tenantId": "092eb9e8e4b7412e8787dd091bc58e86", "instanceParams": [ {} ], "rollbackOnFailure": true, "trackById": "b134410e-3bc0-478e-883e-1b6bdf8a28df", "isFailed": false, - "volumeGroupInstanceName": "zolson57arlba007_lba_dj_01_vol", + "volumeGroupInstanceName": "hvf6arlba007_lba_dj_01_vol", "usePreload": true } } @@ -106,7 +106,7 @@ "isFailed": false, "statusMessage": null, "position": null, - "lineOfBusiness": "EMANUEL-CONSUMER" + "lineOfBusiness": "zzz1" } }, "networks": {}, 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 1c91d02ca..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', () => { @@ -242,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; @@ -284,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/drawingBoard.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts index b678702ff..4eb5445ad 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 () { @@ -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(true).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(); }); }); @@ -238,6 +243,38 @@ 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); + + //make sure max instances in model info show Unlimited (default) + cy.drawingBoardTreeOpenContextMenuByElementDataTestId('node-41708296-e443-4c71-953f-d9a010f059e1-vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2', 0) + .drawingBoardTreeClickOnContextMenuOptionByName('Edit') + .getElementByDataTestsId('model-item-value-max').contains('Unlimited (default)') + .getElementByDataTestsId("cancelButton").click(); + }); + + 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(); @@ -6285,7 +6322,7 @@ describe('Drawing board', function () { } } - function getReduxWithVNFS(isEcompGeneratedNaming: boolean) { + function getReduxWithVNFS(isEcompGeneratedNaming: boolean){ return { "global": { "name": null, diff --git a/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts index 8eb70b1fe..8f76908b9 100644 --- a/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts @@ -1,10 +1,13 @@ +import ObjectLike = Cypress.ObjectLike; + describe('Drawing Board: Instantiation Templates', function () { - describe('Load Page and Deploy', () => { + describe('Instantiation templates ', () => { beforeEach(() => { cy.clearSessionStorage(); cy.setTestApiParamToVNF(); + cy.initAAIMock(); cy.initVidMock(); cy.initDrawingBoardUserPermission(); cy.login(); @@ -16,54 +19,115 @@ describe('Drawing Board: Instantiation Templates', function () { cy.screenshot(); }); - it(`Given a stored template - when click "deploy" - then a coherent request should be sent upon deploy`, function () { - const serviceModelId = '6cfeeb18-c2b0-49df-987a-da47493c8e38'; - const templateUuid = "46390edd-7100-46b2-9f18-419bd24fb60b"; + 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', ()=> { - const drawingBoardAction = `RECREATE`; - const templateTopologyEndpoint = "templateTopology"; + loadDrawingBoardWithRecreateMode(); - // Given... + // 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') - 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'); + .getElementByDataTestsId("cancelButton").click(); - // When... + 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') - cy.openIframe(`app/ui/#/servicePlanning/${drawingBoardAction}` + - `?jobId=${templateUuid}` + - `&serviceModelId=${serviceModelId}`); + .getElementByDataTestsId("cancelButton").click(); - cy.wait('@serviceModel'); - cy.wait('@templateTopology'); - cy.getElementByDataTestsId("node-vProbe_NC_VNF 0").should('be.visible'); + 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(); - cy.getDrawingBoardDeployBtn().click(); - // Then... - cy.wait('@expectedPostAsyncInstantiation').then(xhr => { - cy.readFile('../vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json').then((expectedResult) => { - convertRollbackOnFailureValueFromStringToBoolean(expectedResult); - cy.deepCompare(xhr.request.body, expectedResult); + 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', @@ -72,5 +136,3 @@ describe('Drawing Board: Instantiation Templates', function () { 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 index b862e568d..3caa4e81d 100644 --- a/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts @@ -1,6 +1,47 @@ ///<reference path="../../../node_modules/cypress/types/index.d.ts"/> describe('Template', () => { + 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 + } + ]; + beforeEach(() => { cy.clearSessionStorage(); cy.setReduxState(); @@ -8,71 +49,35 @@ describe('Template', () => { 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'); + .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'); + + + + + }); + + afterEach(() => { + cy.screenshot(); + }); + + it('when open service popup should show template button', function () { cy.getElementByDataTestsId('templateButton').contains('Template') .getElementByDataTestsId('templateButton').click({force: true}) // Open template Modal .getElementByDataTestsId('template-modal-title').contains('Templates') // Check Modal header @@ -106,5 +111,24 @@ describe('Template', () => { cy.getElementByDataTestsId('LoadTemplateButton').should('not.be.disabled') }); + + it('clicking on load template button, go to expected url', function () { + + cy.getElementByDataTestsId('templateButton').contains('Template') + .getElementByDataTestsId('templateButton').click({force: true}) // Open template Modal + + const serviceModelId = 'e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0'; + const jobId = '5c2cd8e5-27d0-42e3-85a1-85db5eaba459'; + const vidBaseUrl = `http://localhost:8080/vid/serviceModels.htm`; + + cy.getElementByDataTestsId('row-5c2cd8e5-27d0-42e3-85a1-85db5eaba459').click(); + cy.getElementByDataTestsId('LoadTemplateButton').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/instantiationStatus.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/instantiationStatus.e2e.ts index c510391cb..342818a71 100644 --- a/vid-webpack-master/cypress/integration/iFrames/instantiationStatus.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/instantiationStatus.e2e.ts @@ -7,7 +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'; + const contextMenuCreateAnotherOne = 'context-menu-create-another-one'; beforeEach(() => { cy.clearSessionStorage(); @@ -126,6 +126,7 @@ describe('Instantiation status', function () { cy.openIframe('app/ui/#/instantiationStatus'); clickOnTitleAndThenOnMenuWithJobId(jobId); + cy.get('.dropdown-menu').getElementByDataTestsId(contextMenuCreateAnotherOne).contains('Create another one'); 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/viewOnlyDrawingBoard.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/viewOnlyDrawingBoard.e2e.ts index d77460a69..60b2e123d 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', @@ -345,6 +345,7 @@ describe('View only drawing board', function () { ['Model customization ID', '55b1be94-671a-403e-a26c-667e9c47d091'], ['Base module', 'false'], ['Min instances', '0'], + ['Max instances', 'Unlimited (default)'], ['Initial instances count', '0'] ]; const extraLabelsAndValuesForInstance = [['In maintenance','true'], ['Instance ID', '2c1ca484-cbc2-408b-ab86-25a2c15ce280']]; @@ -356,6 +357,8 @@ describe('View only drawing board', function () { function testComponentInfoForNetwork(){ const labelsAndValuesForModel = [ ['Model version', '37.0'], + ['Min instances', '0'], + ['Max instances', 'Unlimited (default)'], ['Model customization ID', '94fdd893-4a36-4d70-b16a-ec29c54c184f'], ['Network role','network role 1, network role 2'] ]; 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 b1adff1e5..74ce2a772 100644 --- a/vid-webpack-master/cypress/integration/iFrames/vnf.popup.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/vnf.popup.e2e.ts @@ -49,10 +49,10 @@ describe('Vnf popup', function () { cy.setReduxState(<any>res); cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); cy.getElementByDataTestsId('node-2017-488_PASQUALE-vPE 0-add-btn').click({force : true}); - cy.getElementByDataTestsId('model-item-label-vnf-min').contains('Minimum to instantiate'); - cy.getElementByDataTestsId('model-item-value-vnf-min').contains('100'); - cy.getElementByDataTestsId('model-item-label-vnf-max').contains('Maximum to instantiate'); - cy.getElementByDataTestsId('model-item-value-vnf-max').contains('200'); + cy.getElementByDataTestsId('model-item-label-min').contains('Minimum to instantiate'); + cy.getElementByDataTestsId('model-item-value-min').contains('100'); + cy.getElementByDataTestsId('model-item-label-max').contains('Maximum to instantiate'); + cy.getElementByDataTestsId('model-item-value-max').contains('200'); }) }); @@ -63,10 +63,10 @@ describe('Vnf popup', function () { cy.setReduxState(<any>res); cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); cy.getElementByDataTestsId('node-2017-488_PASQUALE-vPE 0-add-btn').click({force : true}); - 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-label-min').contains('Minimum to instantiate'); + cy.getElementByDataTestsId('model-item-value-min').contains('0'); + cy.getElementByDataTestsId('model-item-label-max').contains('Maximum to instantiate'); + cy.getElementByDataTestsId('model-item-value-max').contains('Unlimited (default)'); }) }); 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/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/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/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/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 089f812a7..f26ab0cf1 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 @@ -311,13 +311,21 @@ describe('Network Model Info', () => { const instance = getNetworkInstance(); let actualNetworkInfo = networkModel.getInfo(model, instance); let expectedNetworkInfo = [ + ModelInformationItem.createInstance("Min instances", "0"), + ModelInformationItem.createInstance("Max instances", "1"), ModelInformationItem.createInstance('Network role', "network role 1, network role 2"), ModelInformationItem.createInstance("Route target id", null), - ModelInformationItem.createInstance("Route target role", null) + ModelInformationItem.createInstance("Route target role", null), ]; expect(actualNetworkInfo).toEqual(expectedNetworkInfo); }); + test('When there is no max Max instances text is: Unlimited (default)', () => { + let actualVNFInfo = networkModel.getInfo({just:"not empty"},null); + const maxInstancesItem = actualVNFInfo.find((item)=> item.label == 'Max instances'); + expect(maxInstancesItem.values[0]).toEqual('Unlimited (default)'); + }); + function getNetworkModel() { return { "customizationUuid": "94fdd893-4a36-4d70-b16a-ec29c54c184f", 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 3ba4a2c4b..486ac93c0 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 @@ -7,10 +7,7 @@ import {SharedTreeService} from "../../shared.tree.service"; import {InputType} from "../../../../../shared/models/inputTypes"; import {NgRedux} from "@angular-redux/store"; import {AppState} from "../../../../../shared/store/reducers"; -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 {NetworkPopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/network/network.popup.service"; import * as _ from "lodash"; @@ -22,11 +19,7 @@ import {IframeService} from "../../../../../shared/utils/iframe.service"; import {SdcUiServices} from "onap-ui-angular"; import {DuplicateService} from "../../../duplicate/duplicate.service"; import {ServiceInstanceActions} from "../../../../../shared/models/serviceInstanceActions"; -import { - deleteActionNetworkInstance, - undoDeleteActionNetworkInstance, - updateNetworkPosition -} from "../../../../../shared/storeUtil/utils/network/network.actions"; +import {deleteActionNetworkInstance, undoDeleteActionNetworkInstance, updateNetworkPosition} from "../../../../../shared/storeUtil/utils/network/network.actions"; 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"; @@ -265,10 +258,15 @@ export class NetworkModelInfo implements ILevelNodeInfo { } getInfo(model, instance): ModelInformationItem[] { - const modelInformation = !_.isEmpty(model) && !_.isEmpty(model.properties) ? [ - ModelInformationItem.createInstance("Network role", model.properties.network_role)] : []; - ModelInformationItem.createInstance("Min instances", !_.isNull(model.min) ? String(model.min) : null), - ModelInformationItem.createInstance("Max instances", !_.isNull(model.max) ? String(model.max) : null) + const modelInformation = !_.isEmpty(model) ? [ + ModelInformationItem.createInstance("Min instances", !_.isNull(model.min) ? String(model.min) : null), + this._sharedTreeService.createMaximumToInstantiateModelInformationItem(model) + ] : []; + + if (!_.isEmpty(model) && !_.isEmpty(model.properties)) { + modelInformation.push(ModelInformationItem.createInstance("Network role", model.properties.network_role)) + } + const instanceInfo = !_.isEmpty(instance) ? [ ModelInformationItem.createInstance("Route target id", instance.routeTargetId ? instance.routeTargetId : null), ModelInformationItem.createInstance("Route target role", instance.routeTargetRole ? instance.routeTargetRole : null)] : 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 225d84b4c..85e57613a 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 @@ -17,6 +17,8 @@ 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() { @@ -44,7 +46,8 @@ describe('VFModule Model Info', () => { let _vfModuleUpgradePopupService : VfModuleUpgradePopupService; let _iframeService : IframeService; let _componentInfoService : ComponentInfoService; - let _featureFlagsService : FeatureFlagsService; + let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService); + let mockFeatureFlagsServiceInstance: FeatureFlagsService = instance(mockFeatureFlagsService); beforeAll(done => (async () => { @@ -62,7 +65,7 @@ describe('VFModule Model Info', () => { AaiService, HttpClient, HttpHandler, - {provide: FeatureFlagsService, useClass: MockFeatureFlagsService}, + {provide: FeatureFlagsService, useValue: mockFeatureFlagsServiceInstance}, ComponentInfoService ] }); @@ -70,9 +73,9 @@ describe('VFModule Model Info', () => { injector = getTestBed(); _sharedTreeService = injector.get(SharedTreeService); - _componentInfoService = injector.get(ComponentInfoService) - _featureFlagsService = injector.get(FeatureFlagsService); - vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, _iframeService,_featureFlagsService, 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)); @@ -474,12 +477,39 @@ describe('VFModule Model Info', () => { let expectedVNFInfo = [ ModelInformationItem.createInstance('Base module', false), ModelInformationItem.createInstance('Min instances', "0"), - ModelInformationItem.createInstance("Max instances", null), + ModelInformationItem.createInstance("Max instances", 'Unlimited (default)'), ModelInformationItem.createInstance('Initial instances count',"0") ]; 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 e182b8a6f..1e4a22c45 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,19 +16,13 @@ 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, deleteVFModuleField, - removeVfModuleInstance, - undoDeleteVfModuleInstance, - undoUgradeVFModule, updateVFModuleField, - 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, @@ -301,12 +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 } } { @@ -423,7 +418,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo { 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), + this._sharedTreeService.createMaximumToInstantiateModelInformationItem(model), ModelInformationItem.createInstance("Initial instances count", !_.isNull(model.properties.initialCount) ? String(model.properties.initialCount) : null) ] : []; 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 d89280f0a..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 @@ -23,6 +23,7 @@ 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 {}; @@ -467,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 c1255f57c..a5a85c41a 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,13 +23,7 @@ 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"; @@ -326,8 +317,8 @@ 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), + this._sharedTreeService.createMaximumToInstantiateModelInformationItem(model) ] : []; const instanceInfo = !_.isEmpty(instance) ? [ 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 b330b72dc..504dc86bd 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 @@ -186,6 +186,14 @@ describe('Shared Tree Service', () => { "type": instanceTypeMock }); }); + each([ + ['undefined', 'Unlimited (default)', {}], + ['null', 'Unlimited (default)', {max:null}], + ['3', '3', {max:3}], + ]). + test("when there is %s max instances in model , shell return %s text", (desc, expected, model) =>{ + expect(service.createMaximumToInstantiateModelInformationItem(model).values[0]).toBe(expected); + }); test('shouldShowDeleteInstanceWithChildrfenModal should not open modal if all childs with action None', () => { let foo = () => { 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 b8eddbbf7..7f5b6e33c 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 @@ -14,6 +14,7 @@ import {undoUpgradeService, upgradeService} from "../../../shared/storeUtil/util 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"; +import {Constants} from "../../../shared/utils/constants"; @Injectable() export class SharedTreeService { @@ -368,4 +369,11 @@ export class SharedTreeService { const modelInfoItemsWithoutEmpty = _.filter(modelInfoItems, function(item){ return !item.values.every(_.isNil)}); return new ComponentInfoModel(type, modelInfoItemsWithoutEmpty, [], instance != null); } + + createMaximumToInstantiateModelInformationItem(model): ModelInformationItem { + return ModelInformationItem.createInstance( + "Max instances", + !_.isNil(model.max) ? String(model.max) : Constants.ModelInfo.UNLIMITED_DEFAULT + ); + } } 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 4bfedd913..229beb443 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts @@ -13,6 +13,7 @@ import {Router, UrlTree} from "@angular/router"; import {of} from "rxjs"; import {MsoService} from "../shared/services/msoService/mso.service"; import {ServiceAction} from "../shared/models/serviceInstanceActions"; +import {InstantiationBase} from "../shared/models/serviceBase"; export let PENDING : string = "pending"; export let INPROGRESS : string = "in_progress"; @@ -112,21 +113,21 @@ export class InstantiationStatusComponentService { window.parent.location.assign('../../serviceModels.htm#/instantiate?' + query); } - navigateToNewViewEdit(item: ServiceInfoModel, mode: DrawingBoardModes): void{ + navigateToNewViewEdit(item: InstantiationBase, mode: DrawingBoardModes): void { this._store.dispatch(updateDrawingBoardStatus(mode)); const viewEditUrlTree:UrlTree = this.getNewViewEditUrlTree(item, mode); this._router.navigateByUrl(viewEditUrlTree); window.parent.location.assign(this.getViewEditUrl(viewEditUrlTree)); } - getNewViewEditUrlTree(item: ServiceInfoModel, mode: DrawingBoardModes): UrlTree { + getNewViewEditUrlTree(item: InstantiationBase, mode: DrawingBoardModes): UrlTree { return this._router.createUrlTree( ['/servicePlanning/' + mode], { queryParams: mode==DrawingBoardModes.RECREATE ? this.getRecreateQueryParams(item) : - this.getDefaultViewEditQueryParams(item) + this.getDefaultViewEditQueryParams(<ServiceInfoModel> item) }); } @@ -140,7 +141,7 @@ export class InstantiationStatusComponentService { }; } - private getRecreateQueryParams(item: ServiceInfoModel) { + private getRecreateQueryParams(item: InstantiationBase) { return { serviceModelId: item.serviceModelId, jobId: item.jobId diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts index 58227c9eb..4f84b7125 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts @@ -59,8 +59,8 @@ export class InstantiationStatusComponent implements OnInit { visible: () => true, }, { - name: "Recreate", - dataTestId: "context-menu-recreate", + name: "Create another one", + dataTestId: "context-menu-create-another-one", className: "fa-clone", click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.recreate(item), enabled: (item: ServiceInfoModel) => this.instantiationStatusComponentService.isRecreateEnabled(item), 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 f9da42607..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 @@ -61,7 +61,7 @@ (click)="openTemplateModal()" ><span>Template</span></button> <button - *ngIf=isInstantiationStatusFilterFlagOn() + *ngIf="isShowPreviousInstantiationBtn" [attr.data-tests-id]="'ShowPreviousInstancesButton'" type="button" class="btn btn-success submit" (click)="formPopupDetails.onOtherAction(formPopupDetails.that, dynamicForm)"> 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 159871f45..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 @@ -46,6 +46,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole type: PopupType; uuidData: UUIDData; showTemplateBtn: boolean = false; + isShowPreviousInstantiationBtn: boolean = false; isUpdateMode: boolean; node: ITreeNode = null; hasGeneralApiError: boolean = false; @@ -85,29 +86,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole .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.showTemplateBtn = !!this._store.getState().global.flags["FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"]; - - 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 - ); - }); + this.onInitForCreateNewServicePopup(); } }); @@ -125,6 +104,34 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole } } + 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 { @@ -148,9 +155,6 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole this._dialogService.addDialog(InstantiationTemplatesModalComponent, {}); } - isInstantiationStatusFilterFlagOn() { - return FeatureFlagsService.getFlagState(Features.FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER, this._store); - } } 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 a3c83263c..ebabc89b7 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 @@ -2032,4 +2032,8 @@ describe('Basic popup service', () => { }, 'modelType', 'modelName'); expect(result).toBeUndefined(); }); + + test('when there is no max instances in model , shell return maximum item with Unlimited text', () =>{ + expect(service.createMaximumToInstantiateModelInformationItem({}).values[0]).toEqual('Unlimited (default)'); + }); }); 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 c18b20d7e..f8b40dd99 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 @@ -11,6 +11,8 @@ import {VfModule} from "../../../models/vfModule"; import {VNFModel} from "../../../models/vnfModel"; import {VnfGroupModel} from "../../../models/vnfGroupModel"; import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service"; +import {ModelInformationItem} from "../../model-information/model-information.component"; +import {Constants} from "../../../utils/constants"; @Injectable() export class BasicPopupService { @@ -38,7 +40,7 @@ export class BasicPopupService { return new VNFModel(rawModel, flags); } case 'vfModules' : { - return new VfModule(rawModel); + return new VfModule(rawModel, flags); } case 'networks' : { return new NetworkModel(rawModel, flags); @@ -53,4 +55,14 @@ export class BasicPopupService { let dynamic = this._defaultDataGeneratorService.getArbitraryInputs(this._store.getState().service.serviceHierarchy[serviceId][type][modelName].inputs); return this._basicControlGenerator.getDynamicInputsByType(dynamic, serviceId, storeKey, type ); } + + createMaximumToInstantiateModelInformationItem(model): ModelInformationItem { + return new ModelInformationItem( + "Maximum to instantiate", + "max", + [!_.isNil(model.max) ? model.max.toString() : Constants.ModelInfo.UNLIMITED_DEFAULT], + "", + true + ); + } } 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 20336e5eb..3119cc8f8 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 @@ -81,7 +81,7 @@ export abstract class VfModulePopupServiceBase { new ModelInformationItem("Service type", "serviceType", [this.serviceModel.serviceType]), new ModelInformationItem("Service role", "serviceRole", [this.serviceModel.serviceRole]), new ModelInformationItem("Minimum to instantiate", "min", this.model.min == undefined ? ['0'] : [this.model.min.toString()], "", true), - new ModelInformationItem("Maximum to instantiate", "max", this.model.max == undefined ? ['1'] : [this.model.max.toString()], "", true), + this._basicPopupService.createMaximumToInstantiateModelInformationItem(this.model), new ModelInformationItem("Recommended to instantiate", "initial", [this.model.initial]) ]; }); 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..3e117ca74 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 @@ -96,8 +96,8 @@ export class VnfPopupService implements GenericPopupInterface{ new ModelInformationItem("Invariant UUID", "invariantUuid", [this.model.invariantUuid], Constants.ServicePopup.TOOLTIP_INVARIANT_UUID, true), 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) + new ModelInformationItem("Minimum to instantiate", "min", [!_.isNil(this.model.min) ? this.model.min.toString() : '0'], "", false), + this._basicPopupService.createMaximumToInstantiateModelInformationItem(this.model) ]; }) } 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 index c231c6081..86c46ab3b 100644 --- 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 @@ -23,12 +23,15 @@ </div> </div> <div class="col-md-6"> - <input - (keypress)="onFilterKeypress($event)" - class="filter-input form-control input-text" - placeholder="Filter..."> + <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"> @@ -37,7 +40,7 @@ <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">Instantiation Status</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> @@ -46,9 +49,9 @@ </thead> <tbody> <tr class="member-table-row" - *ngFor="let item of filterTableData;" - (click)="selectedJobId = item.jobId" - [ngClass]="{'selected' : selectedJobId === item.jobId}" + *ngFor="let item of filterTableData | searchFilter: filterText ;" + (click)="selectedInstantiation = item" + [ngClass]="{'selected' : selectedInstantiation && selectedInstantiation.jobId === item.jobId}" [attr.data-tests-id]="'row-' + item.jobId"> <td> <div> @@ -145,7 +148,7 @@ </div> <div class="col-md-6" style="padding: 15px;padding-right: 35px;"> <button - [disabled]="selectedJobId === null" + [disabled]="selectedInstantiation && selectedInstantiation.jobId === null" [attr.data-tests-id]="'LoadTemplateButton'" type="button" class="btn btn-primary submit" (click)="loadTemplate()"><span>Load Template</span> 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 index ef8d01a75..267d2cee0 100644 --- 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 @@ -166,7 +166,11 @@ $grid-border: 1px #d2d2d2 solid; .filter-input { float: right; - width: 25%; + width: 50%; + } + + .details-item { + text-align: right; } @@ -187,6 +191,6 @@ $grid-border: 1px #d2d2d2 solid; } .member-table-row.selected { - background: #009fdbb5 !important; + 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 index 56abe5b4c..7b16b6677 100644 --- 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 @@ -5,6 +5,8 @@ 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"; +import {DrawingBoardModes} from "../../../../drawingBoard/service-planning/drawing-board.modes"; +import {InstantiationStatusComponentService} from "../../../../instantiationStatus/instantiationStatus.component.service"; @Component({ selector: 'template-modal', @@ -14,21 +16,24 @@ import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.mode export class InstantiationTemplatesModalComponent extends DialogComponent<string, boolean> implements OnInit, OnDestroy { - selectedJobId : string = null; + selectedInstantiation: InstantiationTemplatesRowModel = null; templateModalComponentService: InstantiationTemplatesModalService; originalTableData: InstantiationTemplatesRowModel[] = []; filterTableData : InstantiationTemplatesRowModel[] = []; + filterText: string; constructor(dialogService: DialogService, private _iframeService: IframeService, private _serviceInfoService: ServiceInfoService, private _templateModalComponentService: InstantiationTemplatesModalService, + private _instantiationStatusComponentService: InstantiationStatusComponentService, private _route: ActivatedRoute) { super(dialogService); this.templateModalComponentService = _templateModalComponentService; } ngOnInit(): void { + this.filterText = ''; this._route .queryParams .subscribe(params => { @@ -40,16 +45,17 @@ export class InstantiationTemplatesModalComponent extends DialogComponent<string } loadTemplate = () => { + this._instantiationStatusComponentService.navigateToNewViewEdit(this.selectedInstantiation, DrawingBoardModes.RECREATE) }; - onFilterKeypress = (event : KeyboardEvent) => { - //event.target.value - console.log(event.altKey); - }; - 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.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts index 7126da36a..8377ccf42 100644 --- 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 @@ -3,6 +3,7 @@ import {InstantiationTemplatesRowModel} from "./instantiation.templates.row.mode @Injectable() export class InstantiationTemplatesModalService { + convertResponseToUI = (jobsResponse: any[]): InstantiationTemplatesRowModel[] => { let tableRows: InstantiationTemplatesRowModel[] = []; @@ -12,4 +13,5 @@ export class InstantiationTemplatesModalService { 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 index 08982cc67..f4609ee35 100644 --- 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 @@ -1,8 +1,8 @@ import * as moment from 'moment'; import * as _ from 'lodash'; +import {InstantiationBase} from "../../../models/serviceBase"; -export class InstantiationTemplatesRowModel { - readonly jobId: string; +export class InstantiationTemplatesRowModel extends InstantiationBase{ readonly userId ?: string; readonly createDate ?: string; readonly instanceName ?: string; @@ -13,7 +13,7 @@ export class InstantiationTemplatesRowModel { readonly aicZone?: string; constructor(data) { - this.jobId = data.jobId; + super(data); 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); @@ -22,7 +22,6 @@ export class InstantiationTemplatesRowModel { this.region = this.getRegion(data.regionId, data.owningEntityName); this.tenant = !_.isNil(data.tenantName) ? data.tenantName : null; this.aicZone = !_.isNil(data.aicZoneName) ? data.aicZoneName : null; - } diff --git a/vid-webpack-master/src/app/shared/models/serviceBase.ts b/vid-webpack-master/src/app/shared/models/serviceBase.ts new file mode 100644 index 000000000..afa8a8136 --- /dev/null +++ b/vid-webpack-master/src/app/shared/models/serviceBase.ts @@ -0,0 +1,11 @@ +export class InstantiationBase { + readonly jobId: string; + readonly serviceModelId: string; + + constructor(data?) { + if(data){ + this.jobId = data.jobId; + this.serviceModelId = data.serviceModelId; + } + } +} 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/server/serviceInfo/serviceInfo.model.ts b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.model.ts index a507e073e..fa26a61a6 100644 --- a/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.model.ts +++ b/vid-webpack-master/src/app/shared/server/serviceInfo/serviceInfo.model.ts @@ -1,7 +1,8 @@ import {ServiceStatus} from '../../../instantiationStatus/instantiationStatus.component.service'; import {ServiceAction} from "../../models/serviceInstanceActions"; +import {InstantiationBase} from "../../models/serviceBase"; -export class ServiceInfoModel { +export class ServiceInfoModel extends InstantiationBase{ id: number; created: Date; modified: Date; @@ -28,12 +29,10 @@ export class ServiceInfoModel { subscriberId: string; serviceInstanceId: string; serviceInstanceName: string; - serviceModelId: string; serviceModelName: string; serviceModelVersion: string; templateId: string; auditUserId: string; - jobId: string; action: ServiceAction; isRetryEnabled: boolean; } diff --git a/vid-webpack-master/src/app/shared/utils/constants.ts b/vid-webpack-master/src/app/shared/utils/constants.ts index 4f11cd1be..f793e05db 100644 --- a/vid-webpack-master/src/app/shared/utils/constants.ts +++ b/vid-webpack-master/src/app/shared/utils/constants.ts @@ -297,4 +297,8 @@ export module Constants { export class LegacyRegion { public static MEGA_REGION = ['AAIAIC25']; } + + export class ModelInfo { + public static UNLIMITED_DEFAULT = 'Unlimited (default)'; + } } |