aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-be/src/test
diff options
context:
space:
mode:
authorandre.schmid <andre.schmid@est.tech>2021-10-01 18:45:17 +0100
committerAndré Schmid <andre.schmid@est.tech>2021-10-15 14:26:03 +0000
commit1b61e72f6506de7c1f64098dd25adf7af7b31dc1 (patch)
tree53036d7bb556547059f1207ec7c8a42959cd05a7 /catalog-be/src/test
parent08ba15073ff236c67303d084d56a026975ba1a25 (diff)
Import multiple node types in a single endpoint
Change-Id: I7aa914d459a083146b92ef82197c8df265b8c5b6 Issue-ID: SDC-3752 Signed-off-by: andre.schmid <andre.schmid@est.tech>
Diffstat (limited to 'catalog-be/src/test')
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java185
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java168
-rw-r--r--catalog-be/src/test/resources/node-types/nodeTypes.yaml408
-rw-r--r--catalog-be/src/test/resources/node-types/payload.json304
4 files changed, 961 insertions, 104 deletions
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java
index 1609299e66..40c9b437c1 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java
@@ -32,20 +32,23 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import fj.data.Either;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.openecomp.sdc.be.auditing.impl.AuditingManager;
import org.openecomp.sdc.be.components.impl.ImportUtils;
@@ -61,6 +64,7 @@ import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
import org.openecomp.sdc.be.config.Configuration;
import org.openecomp.sdc.be.config.ConfigurationManager;
import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
@@ -68,6 +72,8 @@ import org.openecomp.sdc.be.impl.ComponentsUtils;
import org.openecomp.sdc.be.model.CapabilityDefinition;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.NodeTypeMetadata;
+import org.openecomp.sdc.be.model.NodeTypesMetadataList;
import org.openecomp.sdc.be.model.PropertyConstraint;
import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.RequirementDefinition;
@@ -88,34 +94,23 @@ import org.openecomp.sdc.common.impl.FSConfigurationSource;
import org.openecomp.sdc.exception.PolicyException;
import org.openecomp.sdc.exception.ResponseFormat;
-import fj.data.Either;
-
public class ResourceImportManagerTest {
- static ResourceImportManager importManager;
- static AuditingManager auditingManager = Mockito.mock(AuditingManager.class);
- static ResponseFormatManager responseFormatManager = Mockito.mock(ResponseFormatManager.class);
- static ResourceBusinessLogic resourceBusinessLogic = Mockito.mock(ResourceBusinessLogic.class);
- static InterfaceOperationBusinessLogic interfaceOperationBusinessLogic = Mockito.mock(InterfaceOperationBusinessLogic.class);
- static InterfaceDefinitionHandler interfaceDefinitionHandler =
- new InterfaceDefinitionHandler(interfaceOperationBusinessLogic);
-
- static UserBusinessLogic userAdmin = Mockito.mock(UserBusinessLogic.class);
- static ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class);
+ private ResourceImportManager importManager;
- protected static final ComponentsUtils componentsUtils = Mockito.mock(ComponentsUtils.class);
- private static final CapabilityTypeOperation capabilityTypeOperation = Mockito.mock(CapabilityTypeOperation.class);
+ private final AuditingManager auditingManager = mock(AuditingManager.class);
+ private final ResponseFormatManager responseFormatManager = mock(ResponseFormatManager.class);
+ private final ResourceBusinessLogic resourceBusinessLogic = mock(ResourceBusinessLogic.class);
+ private final InterfaceOperationBusinessLogic interfaceOperationBusinessLogic = mock(InterfaceOperationBusinessLogic.class);
+ private final InterfaceDefinitionHandler interfaceDefinitionHandler = new InterfaceDefinitionHandler(interfaceOperationBusinessLogic);
+ private final JanusGraphDao janusGraphDao = mock(JanusGraphDao.class);
+ private final UserBusinessLogic userAdmin = mock(UserBusinessLogic.class);
+ private final ToscaOperationFacade toscaOperationFacade = mock(ToscaOperationFacade.class);
+ private final ComponentsUtils componentsUtils = mock(ComponentsUtils.class);
+ private final CapabilityTypeOperation capabilityTypeOperation = mock(CapabilityTypeOperation.class);
@BeforeAll
public static void beforeClass() {
- importManager = new ResourceImportManager(componentsUtils, capabilityTypeOperation, interfaceDefinitionHandler);
- importManager.setAuditingManager(auditingManager);
- when(toscaOperationFacade.getLatestByToscaResourceName(Mockito.anyString(), Mockito.any())).thenReturn(Either.left(null));
- when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(Mockito.anyString(), Mockito.any())).thenReturn(Either.left(null));
- importManager.setResponseFormatManager(responseFormatManager);
- importManager.setResourceBusinessLogic(resourceBusinessLogic);
- importManager.setToscaOperationFacade(toscaOperationFacade);
-
String appConfigDir = "src/test/resources/config/catalog-be";
ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
@@ -127,7 +122,13 @@ public class ResourceImportManagerTest {
@BeforeEach
public void beforeTest() {
- Mockito.reset(auditingManager, responseFormatManager, resourceBusinessLogic, userAdmin);
+ importManager = new ResourceImportManager(componentsUtils, capabilityTypeOperation, interfaceDefinitionHandler, janusGraphDao);
+ importManager.setAuditingManager(auditingManager);
+ when(toscaOperationFacade.getLatestByToscaResourceName(anyString(), any())).thenReturn(Either.left(null));
+ when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(anyString(), any())).thenReturn(Either.left(null));
+ importManager.setResponseFormatManager(responseFormatManager);
+ importManager.setResourceBusinessLogic(resourceBusinessLogic);
+ importManager.setToscaOperationFacade(toscaOperationFacade);
Either<Component, StorageOperationStatus> notFound = Either.right(StorageOperationStatus.NOT_FOUND);
when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(),
any(JsonParseFlagEnum.class), any())).thenReturn(notFound);
@@ -142,13 +143,14 @@ public class ResourceImportManagerTest {
user.setRole("ADMIN");
user.setFirstName("Jhon");
user.setLastName("Doh");
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
setResourceBusinessLogicMock();
String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-blockStorage.yml");
- ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+ ImmutablePair<Resource, ActionStatus> createResource =
+ importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
Resource resource = createResource.left;
testSetConstantMetaData(resource);
@@ -157,15 +159,74 @@ public class ResourceImportManagerTest {
testSetDerivedFrom(resource);
testSetProperties(resource);
- Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(eq(user), eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+ verify(resourceBusinessLogic).propagateStateToCertified(eq(user), eq(resource), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+ }
+
+ @Test
+ void importAllNormativeResourceSuccessTest() {
+ final List<NodeTypeMetadata> nodeMetadataList = new ArrayList<>();
+ var nodeTypeMetadata1 = new NodeTypeMetadata();
+ nodeTypeMetadata1.setToscaName("my.tosca.Type");
+ nodeMetadataList.add(nodeTypeMetadata1);
+ var nodeTypeMetadata2 = new NodeTypeMetadata();
+ nodeTypeMetadata2.setToscaName("my.tosca.not.in.the.Yaml");
+ nodeMetadataList.add(nodeTypeMetadata2);
+ var nodeTypesMetadataList = new NodeTypesMetadataList();
+ nodeTypesMetadataList.setNodeMetadataList(nodeMetadataList);
+ var user = new User();
+ var yaml = "node_types:\n"
+ + " my.tosca.Type:\n"
+ + " description: a description";
+
+ when(toscaOperationFacade.getLatestByName(any(), any())).thenReturn(Either.left(null));
+ when(resourceBusinessLogic
+ .createOrUpdateResourceByImport(any(Resource.class), any(User.class), eq(true), eq(true), eq(false), eq(null), eq(null), eq(false)))
+ .thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.OK));
+
+ importManager.importAllNormativeResource(yaml, nodeTypesMetadataList, user, false, false);
+ verify(janusGraphDao).commit();
+ }
+
+ @Test
+ void importAllNormativeResourceTest_invalidYaml() {
+ var invalidYaml = "node_types: my.tosca.Type:";
+
+ final ByActionStatusComponentException actualException = assertThrows(ByActionStatusComponentException.class,
+ () -> importManager.importAllNormativeResource(invalidYaml, new NodeTypesMetadataList(), new User(), false, false));
+ assertEquals(ActionStatus.INVALID_NODE_TYPES_YAML, actualException.getActionStatus());
+ }
+
+ @Test
+ void importAllNormativeResourceTest_exceptionDuringImportShouldTriggerRolback() {
+ when(responseFormatManager.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(mock(ResponseFormat.class));
+ when(toscaOperationFacade.getLatestByName(any(), any())).thenThrow(new RuntimeException());
+
+ final List<NodeTypeMetadata> nodeMetadataList = new ArrayList<>();
+ var nodeTypeMetadata1 = new NodeTypeMetadata();
+ nodeTypeMetadata1.setToscaName("my.tosca.Type");
+ nodeMetadataList.add(nodeTypeMetadata1);
+ var nodeTypeMetadata2 = new NodeTypeMetadata();
+ nodeTypeMetadata2.setToscaName("my.tosca.not.in.the.Yaml");
+ nodeMetadataList.add(nodeTypeMetadata2);
+ var nodeTypesMetadataList = new NodeTypesMetadataList();
+ nodeTypesMetadataList.setNodeMetadataList(nodeMetadataList);
+ var user = new User();
+ var yaml = "node_types:\n"
+ + " my.tosca.Type:\n"
+ + " description: a description";
+
+ assertThrows(ComponentException.class,
+ () -> importManager.importAllNormativeResource(yaml, nodeTypesMetadataList, user, false, false));
+ verify(janusGraphDao).rollback();
}
+
@Test()
void testResourceCreationFailed() {
UploadResourceInfo resourceMD = createDummyResourceMD();
User user = new User();
user.setUserId(resourceMD.getContactId());
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
ResponseFormat dummyResponseFormat = createGeneralErrorInfo();
when(responseFormatManager.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(dummyResponseFormat);
@@ -174,15 +235,17 @@ public class ResourceImportManagerTest {
String jsonContent = "this is an invalid yml!";
ComponentException errorInfoFromTest = null;
try {
- importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+ importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
}catch (ComponentException e){
errorInfoFromTest = e;
}
assertNotNull(errorInfoFromTest);
assertEquals(ActionStatus.GENERAL_ERROR, errorInfoFromTest.getActionStatus());
- Mockito.verify(resourceBusinessLogic, Mockito.times(0)).createOrUpdateResourceByImport(Mockito.any(Resource.class), eq(user), eq(true), eq(false), eq(true), eq(null), eq(null), eq(false));
- Mockito.verify(resourceBusinessLogic, Mockito.times(0)).propagateStateToCertified(eq(user), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+ verify(resourceBusinessLogic, times(0))
+ .createOrUpdateResourceByImport(any(Resource.class), eq(user), eq(true), eq(false), eq(true), eq(null), eq(null), eq(false));
+ verify(resourceBusinessLogic, times(0))
+ .propagateStateToCertified(eq(user), any(Resource.class), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
}
@Test
@@ -190,34 +253,37 @@ public class ResourceImportManagerTest {
UploadResourceInfo resourceMD = createDummyResourceMD();
User user = new User();
user.setUserId(resourceMD.getContactId());
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
setResourceBusinessLogicMock();
String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml");
- ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+ ImmutablePair<Resource, ActionStatus> createResource =
+ importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
Resource resource = createResource.left;
testSetCapabilities(resource);
- Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(eq(user), eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
- Mockito.verify(resourceBusinessLogic, Mockito.times(1)).createOrUpdateResourceByImport(resource, user, true, false, true, null, null, false);
+ verify(resourceBusinessLogic)
+ .propagateStateToCertified(eq(user), eq(resource), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+ verify(resourceBusinessLogic).createOrUpdateResourceByImport(resource, user, true, false, true, null, null, false);
}
@Test
- void testResourceCreationWithRequirments() throws IOException {
+ void testResourceCreationWithRequirements() throws IOException {
UploadResourceInfo resourceMD = createDummyResourceMD();
User user = new User();
user.setUserId(resourceMD.getContactId());
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
setResourceBusinessLogicMock();
String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-port.yml");
- ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
- testSetRequirments(createResource.left);
+ ImmutablePair<Resource, ActionStatus> createResource =
+ importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
+ testSetRequirements(createResource.left);
}
@@ -226,7 +292,7 @@ public class ResourceImportManagerTest {
UploadResourceInfo resourceMD = createDummyResourceMD();
User user = new User();
user.setUserId(resourceMD.getContactId());
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
setResourceBusinessLogicMock();
@@ -241,8 +307,8 @@ public class ResourceImportManagerTest {
interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes(any())).thenReturn(Either.left(interfaceTypes));
- final ImmutablePair<Resource, ActionStatus> createResource = importManager
- .importNormativeResource(jsonContent, resourceMD, user, true, true);
+ final ImmutablePair<Resource, ActionStatus> createResource =
+ importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
assertSetInterfaceImplementation(createResource.left);
}
@@ -251,7 +317,7 @@ public class ResourceImportManagerTest {
UploadResourceInfo resourceMD = createDummyResourceMD();
User user = new User();
user.setUserId(resourceMD.getContactId());
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
setResourceBusinessLogicMock();
@@ -266,7 +332,8 @@ public class ResourceImportManagerTest {
interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes(any())).thenReturn(Either.left(interfaceTypes));
- ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+ ImmutablePair<Resource, ActionStatus> createResource =
+ importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
assertNull(createResource.left.getInterfaces());
}
@@ -275,7 +342,7 @@ public class ResourceImportManagerTest {
UploadResourceInfo resourceMD = createDummyResourceMD();
User user = new User();
user.setUserId(resourceMD.getContactId());
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
setResourceBusinessLogicMock();
@@ -290,7 +357,8 @@ public class ResourceImportManagerTest {
interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes(any())).thenReturn(Either.left(interfaceTypes));
- ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+ ImmutablePair<Resource, ActionStatus> createResource =
+ importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
assertNull(createResource.left.getInterfaces());
}
@@ -303,10 +371,10 @@ public class ResourceImportManagerTest {
user.setRole("ADMIN");
user.setFirstName("Jhon");
user.setLastName("Doh");
- when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+ when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
setResourceBusinessLogicMock();
- final Either<Component, StorageOperationStatus> foundResourceEither = Either.left(Mockito.mock(Resource.class));
+ final Either<Component, StorageOperationStatus> foundResourceEither = Either.left(mock(Resource.class));
when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(),
any(JsonParseFlagEnum.class), any())).thenReturn(foundResourceEither);
when(toscaOperationFacade.isNodeAssociatedToModel(eq(null), any(Resource.class))).thenReturn(true);
@@ -314,37 +382,38 @@ public class ResourceImportManagerTest {
String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-blockStorage.yml");
var actualException = assertThrows(ByActionStatusComponentException.class,
- () -> importManager.importNormativeResource(jsonContent, resourceMD, user, true, true));
+ () -> importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false));
assertEquals(ActionStatus.COMPONENT_WITH_VENDOR_RELEASE_ALREADY_EXISTS, actualException.getActionStatus());
}
private void setResourceBusinessLogicMock() {
when(resourceBusinessLogic.getUserAdmin()).thenReturn(userAdmin);
- when(resourceBusinessLogic.createOrUpdateResourceByImport(Mockito.any(Resource.class), Mockito.any(User.class), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyBoolean(), eq(null), eq(null), eq(false)))
+ when(resourceBusinessLogic.createOrUpdateResourceByImport(any(Resource.class), any(User.class), anyBoolean(), anyBoolean(), anyBoolean(), eq(null), eq(null), eq(false)))
.thenAnswer((Answer<ImmutablePair<Resource, ActionStatus>>) invocation -> {
Object[] args = invocation.getArguments();
return new ImmutablePair<>((Resource) args[0], ActionStatus.CREATED);
});
- when(resourceBusinessLogic.propagateStateToCertified(Mockito.any(User.class), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false)))
+ when(resourceBusinessLogic.propagateStateToCertified(any(User.class), any(Resource.class), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false)))
.thenAnswer((Answer<Resource>) invocation -> {
Object[] args = invocation.getArguments();
return (Resource) args[1];
});
- when(resourceBusinessLogic.createResourceByDao(Mockito.any(Resource.class), Mockito.any(User.class), Mockito.any(AuditingActionEnum.class), Mockito.anyBoolean(), Mockito.anyBoolean())).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
+ when(resourceBusinessLogic.createResourceByDao(
+ any(Resource.class), any(User.class), any(AuditingActionEnum.class), anyBoolean(), anyBoolean())).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
Object[] args = invocation.getArguments();
return Either.left((Resource) args[0]);
});
- when(resourceBusinessLogic.validateResourceBeforeCreate(Mockito.any(Resource.class), Mockito.any(User.class), Mockito.any(AuditingActionEnum.class), eq(false), eq(null))).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
+ when(resourceBusinessLogic.validateResourceBeforeCreate(
+ any(Resource.class), any(User.class), any(AuditingActionEnum.class), eq(false), eq(null))).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
Object[] args = invocation.getArguments();
return Either.left((Resource) args[0]);
});
- Boolean either = true;
- when(resourceBusinessLogic.validatePropertiesDefaultValues(Mockito.any(Resource.class))).thenReturn(either);
+ when(resourceBusinessLogic.validatePropertiesDefaultValues(any(Resource.class))).thenReturn(true);
}
private ResponseFormat createGeneralErrorInfo() {
@@ -421,7 +490,7 @@ public class ResourceImportManagerTest {
}
- private void testSetRequirments(Resource resource) {
+ private void testSetRequirements(Resource resource) {
Map<String, List<RequirementDefinition>> requirements = resource.getRequirements();
assertEquals(2, requirements.size());
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java
index 9d0966b770..7a7b07f260 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java
@@ -22,6 +22,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
@@ -29,6 +32,7 @@ import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.file.Path;
import java.util.Optional;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -50,11 +54,8 @@ import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
@@ -62,7 +63,8 @@ import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
import org.openecomp.sdc.be.components.impl.ResourceImportManager;
import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
-import org.openecomp.sdc.be.components.validation.UserValidations;
+import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
+import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
import org.openecomp.sdc.be.config.ConfigurationManager;
import org.openecomp.sdc.be.config.SpringConfig;
import org.openecomp.sdc.be.dao.api.ActionStatus;
@@ -85,9 +87,9 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.context.WebApplicationContext;
-@TestInstance(Lifecycle.PER_CLASS)
class ResourceUploadServletTest extends JerseyTest {
private static final String USER_ID = "cs0008";
+ private static final User USER = new User(USER_ID);
@Mock
private HttpServletRequest request;
@@ -114,39 +116,21 @@ class ResourceUploadServletTest extends JerseyTest {
@Mock
private ResponseFormat responseFormat;
@Mock
- private UserValidations userValidations;
- @Mock
private ModelBusinessLogic modelBusinessLogic;
@Mock
private ResponseFormatManager responseFormatManager;
private final String modelName = "ETSI-SOL001-331";
- private final String rootPath = "/v1/catalog/upload/multipart";
+ private final Path rootPath = Path.of("/v1/catalog/upload");
+ private final Path bulkImportPath = rootPath.resolve("resource/import");
+ private final String multipartPath = "/v1/catalog/upload/multipart";
private User user;
- @BeforeAll
- public void initClass() {
- when(request.getSession()).thenReturn(session);
- when(session.getServletContext()).thenReturn(servletContext);
- when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
- .thenReturn(webAppContextWrapper);
- when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
- when(webApplicationContext.getBean(ModelBusinessLogic.class)).thenReturn(modelBusinessLogic);
- when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID);
- when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
- when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
- final String appConfigDir = "src/test/resources/config/catalog-be";
- final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
- final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
- final org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
- configuration.setJanusGraphInMemoryGraph(true);
- configurationManager.setConfiguration(configuration);
- ExternalConfiguration.setAppName("catalog-be");
- }
-
@BeforeEach
void resetMock() throws Exception {
super.setUp();
+ initMocks();
+ initConfig();
initTestData();
}
@@ -155,13 +139,6 @@ class ResourceUploadServletTest extends JerseyTest {
super.tearDown();
}
- private void initTestData() {
- user = new User();
- user.setUserId(USER_ID);
- user.setRole(Role.ADMIN.name());
- when(userBusinessLogic.getUser(USER_ID)).thenReturn(user);
- }
-
@Override
protected ResourceConfig configure() {
MockitoAnnotations.openMocks(this);
@@ -179,7 +156,6 @@ class ResourceUploadServletTest extends JerseyTest {
bind(resourceImportManager).to(ResourceImportManager.class);
bind(resourceBusinessLogic).to(ResourceBusinessLogic.class);
bind(modelBusinessLogic).to(ModelBusinessLogic.class);
- bind(userValidations).to(UserValidations.class);
}
})
.register(new OperationExceptionMapper(new ServletResponseBuilder(), responseFormatManager))
@@ -192,6 +168,37 @@ class ResourceUploadServletTest extends JerseyTest {
config.register(MultiPartFeature.class);
}
+ void initMocks() {
+ when(request.getSession()).thenReturn(session);
+ when(session.getServletContext()).thenReturn(servletContext);
+ when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
+ .thenReturn(webAppContextWrapper);
+ when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
+ when(webApplicationContext.getBean(ModelBusinessLogic.class)).thenReturn(modelBusinessLogic);
+ when(webApplicationContext.getBean(UserBusinessLogic.class)).thenReturn(userBusinessLogic);
+ when(userBusinessLogic.getUser(USER_ID, false)).thenReturn(USER);
+ when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID);
+ when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
+ when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
+ }
+
+ void initConfig() {
+ final String appConfigDir = "src/test/resources/config/catalog-be";
+ final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
+ final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
+ final org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
+ configuration.setJanusGraphInMemoryGraph(true);
+ configurationManager.setConfiguration(configuration);
+ ExternalConfiguration.setAppName("catalog-be");
+ }
+
+ private void initTestData() {
+ user = new User();
+ user.setUserId(USER_ID);
+ user.setRole(Role.ADMIN.name());
+ when(userBusinessLogic.getUser(USER_ID)).thenReturn(user);
+ }
+
@Test
void uploadMultipartWithModelSuccessTest() throws IOException, ParseException, URISyntaxException {
when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
@@ -199,10 +206,10 @@ class ResourceUploadServletTest extends JerseyTest {
when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic);
when(userBusinessLogic.getUser(anyString())).thenReturn(user);
when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
- when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean()))
+ when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()))
.thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.CREATED));
when(modelBusinessLogic.findModel(modelName)).thenReturn(Optional.of(new Model(modelName)));
- final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+ final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
.header(Constants.USER_ID_HEADER, USER_ID)
.post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip",
"src/test/resources/node-types/nodeTypeWithModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -216,9 +223,9 @@ class ResourceUploadServletTest extends JerseyTest {
when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic);
when(userBusinessLogic.getUser(anyString())).thenReturn(user);
when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
- when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean()))
+ when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()))
.thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.CREATED));
- final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+ final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
.header(Constants.USER_ID_HEADER, USER_ID)
.post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType002.zip",
"src/test/resources/node-types/nodeTypeWithoutModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -233,7 +240,7 @@ class ResourceUploadServletTest extends JerseyTest {
when(userBusinessLogic.getUser(anyString())).thenReturn(user);
when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
when(modelBusinessLogic.findModel("")).thenReturn(Optional.empty());
- final Response response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+ final Response response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
.header(Constants.USER_ID_HEADER, USER_ID)
.post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType002.zip",
"src/test/resources/node-types/nodeTypeWithEmptyModels.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -246,7 +253,7 @@ class ResourceUploadServletTest extends JerseyTest {
when(userBusinessLogic.getUser(anyString())).thenReturn(user);
when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
when(modelBusinessLogic.findModel(modelName)).thenReturn(Optional.empty());
- final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+ final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
.header(Constants.USER_ID_HEADER, USER_ID)
.post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip",
"src/test/resources/node-types/nodeTypeWithModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -260,16 +267,75 @@ class ResourceUploadServletTest extends JerseyTest {
when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic);
when(userBusinessLogic.getUser(anyString())).thenReturn(user);
when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
- final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+ final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
.header(Constants.USER_ID_HEADER, USER_ID)
.post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip",
"src/test/resources/node-types/invalid.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
- private String getInputData(final String jsonFilename) throws IOException, ParseException {
+ @Test
+ void bulkImportSuccessTest() throws IOException, ParseException {
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.CREATED_201);
+ when(componentsUtils.getResponseFormat(ActionStatus.CREATED)).thenReturn(responseFormat);
+
+ final Response response = doValidCallToBulkImport(USER_ID);
+
+ verify(resourceImportManager).importAllNormativeResource(anyString(), any(), eq(USER), eq(false), eq(false));
+ assertThat(response.getStatus()).isEqualTo(HttpStatus.CREATED_201);
+ }
+
+ @Test
+ void bulkImportFailTest_businessException() throws IOException, ParseException {
+ doThrow(new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR))
+ .when(resourceImportManager)
+ .importAllNormativeResource(anyString(), any(), eq(USER), eq(false), eq(false));
+
+ final Response response = doValidCallToBulkImport(USER_ID);
+
+ assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ }
+
+ @Test
+ void bulkImportFailTest_unexpectedException() throws IOException, ParseException {
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
+
+ doThrow(RuntimeException.class)
+ .when(resourceImportManager)
+ .importAllNormativeResource(anyString(), any(), eq(USER), eq(false), eq(false));
+
+ final Response response = doValidCallToBulkImport(USER_ID);
+
+ assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ }
+
+ @Test
+ void bulkImportFailTest_invalidUser() throws IOException, ParseException {
+ var userId = "userId";
+ when(userBusinessLogic.getUser(userId, false)).thenThrow(ComponentException.class);
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ when(componentsUtils.getResponseFormat(any(ComponentException.class))).thenReturn(responseFormat);
+
+ final Response response = doValidCallToBulkImport(userId);
+
+ assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ }
+
+ private Response doValidCallToBulkImport(final String userId) throws IOException, ParseException {
+ final Path nodeTypesYamlPath = Path.of("src/test/resources/node-types/nodeTypes.yaml");
+ final Path nodeTypeMetadataJsonPath = Path.of("src/test/resources/node-types/payload.json");
+ return target().path(bulkImportPath.toString()).request(MediaType.APPLICATION_JSON)
+ .header(Constants.USER_ID_HEADER, userId)
+ .post(
+ Entity.entity(buildBulkImportMultiPartData(nodeTypesYamlPath, nodeTypeMetadataJsonPath), MediaType.MULTIPART_FORM_DATA),
+ Response.class
+ );
+ }
+
+ private String parseFileToJsonString(final Path jsonFilePath) throws IOException, ParseException {
final JSONObject inputData = (JSONObject) new JSONParser().parse(
- new FileReader(jsonFilename));
+ new FileReader(jsonFilePath.toString()));
return inputData.toJSONString();
}
@@ -286,7 +352,17 @@ class ResourceUploadServletTest extends JerseyTest {
final FileDataBodyPart filePart = new FileDataBodyPart("resourceZip", getFile(zipFilePath));
final FormDataMultiPart multipartEntity = new FormDataMultiPart();
multipartEntity.bodyPart(filePart);
- multipartEntity.field("resourceMetadata", getInputData(inputJsonData));
+ multipartEntity.field("resourceMetadata", parseFileToJsonString(Path.of(inputJsonData)));
return multipartEntity;
}
+
+ private FormDataMultiPart buildBulkImportMultiPartData(final Path nodeTypesYamlPath, final Path payloadJsonPath)
+ throws IOException, ParseException {
+ final FileDataBodyPart formDataBodyPart = new FileDataBodyPart("nodeTypesYaml", nodeTypesYamlPath.toFile());
+ final FormDataMultiPart multipartEntity = new FormDataMultiPart();
+ multipartEntity.bodyPart(formDataBodyPart);
+ multipartEntity.field("nodeTypeMetadataJson", parseFileToJsonString(payloadJsonPath), MediaType.APPLICATION_JSON_TYPE);
+ multipartEntity.field("createNewVersion", String.valueOf(false), MediaType.TEXT_PLAIN_TYPE);
+ return multipartEntity;
+ }
}
diff --git a/catalog-be/src/test/resources/node-types/nodeTypes.yaml b/catalog-be/src/test/resources/node-types/nodeTypes.yaml
new file mode 100644
index 0000000000..7f105c447c
--- /dev/null
+++ b/catalog-be/src/test/resources/node-types/nodeTypes.yaml
@@ -0,0 +1,408 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ETSI NFV SOL 001 Root node type definitions version 2.5.1
+
+node_types:
+ tosca.nodes.Root:
+ description: The TOSCA Node Type all other TOSCA base Node Types derive from
+ attributes:
+ tosca_id:
+ type: string
+ tosca_name:
+ type: string
+ state:
+ type: string
+ capabilities:
+ feature:
+ type: tosca.capabilities.Node
+ requirements:
+ - dependency:
+ capability: tosca.capabilities.Node
+ node: tosca.nodes.Root
+ relationship: tosca.relationships.DependsOn
+ occurrences: [ 0, UNBOUNDED ]
+ interfaces:
+ Standard:
+ type: tosca.interfaces.node.lifecycle.Standard
+ tosca.nodes.nfv.VNF:
+ derived_from: tosca.nodes.Root
+ description: The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD
+ properties:
+ descriptor_id: # instead of vnfd_id
+ type: string # GUID
+ description: Globally unique identifier of the VNFD
+ required: true
+ descriptor_version: # instead of vnfd_version
+ type: string
+ description: Identifies the version of the VNFD
+ required: true
+ provider: # instead of vnf_provider
+ type: string
+ description: Provider of the VNF and of the VNFD
+ required: true
+ product_name: # instead of vnf_product_name
+ type: string
+ description: Human readable name for the VNF Product
+ required: true
+ software_version: # instead of vnf_software_version
+ type: string
+ description: Software version of the VNF
+ required: true
+ product_info_name: # instead of vnf_product_info_name
+ type: string
+ description: Human readable name for the VNF Product
+ required: false
+ product_info_description: # instead of vnf_product_info_description
+ type: string
+ description: Human readable description of the VNF Product
+ required: false
+ vnfm_info:
+ type: list
+ required: true
+ description: Identifies VNFM(s) compatible with the VNF
+ entry_schema:
+ type: string
+ localization_languages:
+ type: list
+ description: Information about localization languages of the VNF
+ required: false
+ entry_schema:
+ type: string #IETF RFC 5646 string
+ default_localization_language:
+ type: string #IETF RFC 5646 string
+ description: Default localization language that is instantiated if no information about selected localization language is available
+ required: false
+ #configurable_properties:
+ #type: tosca.datatypes.nfv.VnfConfigurableProperties
+ #description: Describes the configurable properties of the VNF
+ #required: false
+ # derived types are expected to introduce configurable_properties
+ # with its type derived from
+ # tosca.datatypes.nfv.VnfConfigurableProperties
+ #modifiable_attributes:
+ #type: tosca.datatypes.nfv.VnfInfoModifiableAttributes
+ #description: Describes the modifiable attributes of the VNF
+ #required: false
+ # derived types are expected to introduce modifiable_attributes
+ # with its type derived from
+ # tosca.datatypes.nfv.VnfInfoModifiableAttributes
+ lcm_operations_configuration:
+ type: tosca.datatypes.nfv.VnfLcmOperationsConfiguration
+ description: Describes the configuration parameters for the VNF LCM operations
+ required: false
+ monitoring_parameters:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.nfv.VnfMonitoringParameter
+ description: Describes monitoring parameters applicable to the VNF.
+ required: false
+ flavour_id:
+ type: string
+ description: Identifier of the Deployment Flavour within the VNFD
+ required: true
+ flavour_description:
+ type: string
+ description: Human readable description of the DF
+ required: true
+ #vnf_profile:
+ # type: tosca.datatypes.nfv.VnfProfile
+ # description: Describes a profile for instantiating VNFs of a particular NS DF according to a specific VNFD and VNF DF
+ # required: false
+ requirements:
+ - virtual_link:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ occurrences: [ 0, 1 ]
+ # Additional requirements shall be defined in the VNF specific node type (deriving from tosca.nodes.nfv.VNF) corresponding to NS virtual links that need to connect to VnfExtCps
+ interfaces:
+ Vnflcm:
+ type: tosca.interfaces.nfv.Vnflcm
+ tosca.nodes.nfv.Cp:
+ derived_from: tosca.nodes.Root
+ description: Provides information regarding the purpose of the connection point
+ properties:
+ layer_protocols:
+ type: list
+ description: Identifies which protocol the connection point uses for connectivity purposes
+ required: true
+ entry_schema:
+ type: string
+ constraints:
+ - valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
+ role: #Name in ETSI NFV IFA011 v0.7.3: cpRole
+ type: string
+ description: Identifies the role of the port in the context of the traffic flow patterns in the VNF or parent NS
+ required: false
+ constraints:
+ - valid_values: [ root, leaf ]
+ description:
+ type: string
+ description: Provides human-readable information on the purpose of the connection point
+ required: false
+ protocol:
+ type: list
+ description: Provides information on the addresses to be assigned to the connection point(s) instantiated from this Connection Point Descriptor
+ required: false
+ entry_schema:
+ type: tosca.datatypes.nfv.CpProtocolData
+ trunk_mode:
+ type: boolean
+ description: Provides information about whether the CP instantiated from this Cp is in Trunk mode (802.1Q or other), When operating in "trunk mode", the Cp is capable of carrying traffic for several VLANs. Absence of this property implies that trunkMode is not configured for the Cp i.e. It is equivalent to boolean value "false".
+ required: false
+ tosca.nodes.nfv.VnfExtCp:
+ derived_from: tosca.nodes.nfv.Cp
+ description: Describes a logical external connection point, exposed by the VNF enabling connection with an external Virtual Link
+ properties:
+ virtual_network_interface_requirements:
+ type: list
+ description: The actual virtual NIC requirements that is been assigned when instantiating the connection point
+ required: false
+ entry_schema:
+ type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
+ requirements:
+ - external_virtual_link:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ - internal_virtual_link: #name in ETSI NFV IFA011 v0.7.3: intVirtualLinkDesc
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ tosca.nodes.nfv.VnfVirtualLink:
+ derived_from: tosca.nodes.Root
+ description: Describes the information about an internal VNF VL
+ properties:
+ connectivity_type:
+ type: tosca.datatypes.nfv.ConnectivityType
+ description: Specifies the protocol exposed by the VL and the flow pattern supported by the VL
+ required: true
+ description:
+ type: string
+ description: Provides human-readable information on the purpose of the VL
+ required: false
+ test_access:
+ type: list
+ description: Test access facilities available on the VL
+ required: false
+ entry_schema:
+ type: string
+ constraints:
+ - valid_values: [ passive_monitoring, active_loopback ]
+ vl_profile:
+ type: tosca.datatypes.nfv.VlProfile
+ description: Defines additional data for the VL
+ required: true
+ monitoring_parameters:
+ type: list
+ description: Describes monitoring parameters applicable to the VL
+ required: false
+ entry_schema:
+ type: tosca.datatypes.nfv.VirtualLinkMonitoringParameter
+ capabilities:
+ virtual_linkable:
+ type: tosca.capabilities.nfv.VirtualLinkable
+ tosca.nodes.nfv.Vdu.VirtualObjectStorage:
+ derived_from: tosca.nodes.Root
+ description: This node type describes the specifications of requirements related to virtual object storage resources
+ properties:
+ virtual_object_storage_data:
+ type: tosca.datatypes.nfv.VirtualObjectStorageData
+ description: Describes the object storage characteristics.
+ required: true
+ capabilities:
+ virtual_storage:
+ type: tosca.capabilities.nfv.VirtualStorage
+ description: Defines the capabilities of virtual_storage.
+ tosca.nodes.nfv.Vdu.VirtualFileStorage:
+ derived_from: tosca.nodes.Root
+ description: This node type describes the specifications of requirements related to virtual file storage resources
+ properties:
+ virtual_file_storage_data:
+ type: tosca.datatypes.nfv.VirtualFileStorageData
+ description: Describes the file storage characteristics.
+ required: true
+ capabilities:
+ virtual_storage:
+ type: tosca.capabilities.nfv.VirtualStorage
+ description: Defines the capabilities of virtual_storage.
+ requirements:
+ - virtual_link:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ tosca.nodes.nfv.Vdu.VirtualBlockStorage:
+ derived_from: tosca.nodes.Root
+ description: This node type describes the specifications of requirements related to virtual block storage resources
+ properties:
+ virtual_block_storage_data:
+ type: tosca.datatypes.nfv.VirtualBlockStorageData
+ description: Describes the block storage characteristics.
+ required: true
+ sw_image_data:
+ type: tosca.datatypes.nfv.SwImageData
+ description: Defines information related to a SwImage artifact used by this Vdu.Compute node.
+ required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
+ capabilities:
+ virtual_storage:
+ type: tosca.capabilities.nfv.VirtualStorage
+ description: Defines the capabilities of virtual_storage.
+ tosca.nodes.nfv.NsVirtualLink:
+ derived_from: tosca.nodes.Root
+ description: node definition of Virtual Links
+ properties:
+ vl_profile:
+ type: tosca.datatypes.nfv.NsVlProfile # only covers min/max bitrate requirements
+ description: Specifies instantiation parameters for a virtual link of a particular NS deployment flavour.
+ required: true
+ connectivity_type:
+ type: tosca.datatypes.nfv.ConnectivityType
+ required: true
+ test_access:
+ type: list
+ description: Test access facilities available on the VL
+ required: false
+ entry_schema:
+ type: string
+ constraints:
+ - valid_values: [ passive_monitoring, active_loopback ]
+ description:
+ type: string
+ required: false
+ description: Human readable information on the purpose of the virtual link (e.g. VL for control plane traffic).
+ capabilities:
+ virtual_linkable:
+ type: tosca.capabilities.nfv.VirtualLinkable
+ tosca.nodes.nfv.NS:
+ derived_from: tosca.nodes.Root
+ properties:
+ descriptor_id:
+ type: string # GUID
+ description: Identifier of this NS descriptor
+ required: true
+ designer:
+ type: string
+ description: Identifies the designer of the NSD.
+ required: true
+ version:
+ type: string
+ description: Identifies the version of the NSD.
+ required: true
+ name:
+ type: string
+ description: Provides the human readable name of the NSD.
+ required: true
+ invariant_id:
+ type: string
+ description: Identifies an NSD in a version independent manner. This attribute is invariant across versions of NSD.
+ required: true
+ requirements:
+ - virtual_link:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ node: tosca.nodes.nfv.NsVirtualLink
+ occurrences: [ 0, 1 ]
+ interfaces:
+ Nslcm:
+ type: tosca.interfaces.nfv.Nslcm
+ tosca.nodes.nfv.Vdu.Compute:
+ derived_from: tosca.nodes.Root
+ description: Describes the virtual compute part of a VDU which is a construct supporting the description of the deployment and operational behavior of a VNFC
+ properties:
+ name:
+ type: string
+ description: Human readable name of the VDU
+ required: true
+ description:
+ type: string
+ description: Human readable description of the VDU
+ required: true
+ boot_order:
+ type: list # explicit index (boot index) not necessary, contrary to IFA011
+ description: References a node template name from which a valid boot device is created
+ required: false
+ entry_schema:
+ type: string
+ nfvi_constraints:
+ type: list
+ description: Describes constraints on the NFVI for the VNFC instance(s) created from this VDU
+ required: false
+ entry_schema:
+ type: string
+ monitoring_parameters:
+ type: list
+ description: Describes monitoring parameters applicable to a VNFC instantiated from this VDU
+ required: false
+ entry_schema:
+ type: tosca.datatypes.nfv.VnfcMonitoringParameter
+ #configurable_properties:
+ #type: tosca.datatypes.nfv.VnfcConfigurableProperties
+ #required: false
+ # derived types are expected to introduce
+ # configurable_properties with its type derived from
+ # tosca.datatypes.nfv.VnfcConfigurableProperties
+ vdu_profile:
+ type: tosca.datatypes.nfv.VduProfile
+ description: Defines additional instantiation data for the VDU.Compute node
+ required: true
+ sw_image_data:
+ type: tosca.datatypes.nfv.SwImageData
+ description: Defines information related to a SwImage artifact used by this Vdu.Compute node
+ required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
+ boot_data:
+ type: string
+ description: Contains a string or a URL to a file contained in the VNF package used to customize a virtualised compute resource at boot time. The bootData may contain variable parts that are replaced by deployment specific values before being sent to the VIM.
+ required: false
+ capabilities:
+ virtual_compute:
+ type: tosca.capabilities.nfv.VirtualCompute
+ occurrences: [ 1, 1 ]
+ virtual_binding:
+ type: tosca.capabilities.nfv.VirtualBindable
+ occurrences: [ 1, UNBOUNDED ]
+ requirements:
+ - virtual_storage:
+ capability: tosca.capabilities.nfv.VirtualStorage
+ relationship: tosca.relationships.nfv.AttachesTo
+ occurrences: [ 0, UNBOUNDED ]
+ tosca.nodes.nfv.Sap:
+ derived_from: tosca.nodes.nfv.Cp
+ description: node definition of SAP.
+ requirements:
+ - external_virtual_link:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ - internal_virtual_link:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ tosca.nodes.nfv.VduCp:
+ derived_from: tosca.nodes.nfv.Cp
+ description: describes network connectivity between a VNFC instance based on this VDU and an internal VL
+ properties:
+ bitrate_requirement:
+ type: integer # in bits per second
+ description: Bitrate requirement in bit per second on this connection point
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ virtual_network_interface_requirements:
+ type: list
+ description: Specifies requirements on a virtual network interface realising the CPs instantiated from this CPD
+ required: false
+ entry_schema:
+ type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
+ order:
+ type: integer
+ description: The order of the NIC on the compute instance (e.g.eth2)
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ vnic_type:
+ type: string
+ description: Describes the type of the virtual network interface realizing the CPs instantiated from this CPD
+ required: false
+ constraints:
+ - valid_values: [ normal, virtio, direct-physical ]
+ requirements:
+ - virtual_link:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ - virtual_binding:
+ capability: tosca.capabilities.nfv.VirtualBindable
+ relationship: tosca.relationships.nfv.VirtualBindsTo
+ node: tosca.nodes.nfv.Vdu.Compute
diff --git a/catalog-be/src/test/resources/node-types/payload.json b/catalog-be/src/test/resources/node-types/payload.json
new file mode 100644
index 0000000000..2930855c40
--- /dev/null
+++ b/catalog-be/src/test/resources/node-types/payload.json
@@ -0,0 +1,304 @@
+{
+ "nodeMetadataList": [
+ {
+ "contactId": "jh0003",
+ "toscaName": "tosca.nodes.Root",
+ "name": "Root",
+ "model": "ETSI SOL001 v2.5.3",
+ "description": "The TOSCA Node Type all other TOSCA base Node Types derive from",
+ "resourceIconPath": "defaulticon",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Abstract"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "Root",
+ "tosca.nodes.Root"
+ ]
+ },
+ {
+ "contactId": "jh0003",
+ "toscaName": "tosca.nodes.nfv.VNF",
+ "name": "VNF",
+ "model": "ETSI SOL001 v2.5.3",
+ "description": "The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD",
+ "resourceIconPath": "compute",
+ "resourceType": "VFC",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VNF",
+ "tosca.nodes.nfv.VNF"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.Cp",
+ "name": "Cp",
+ "model": "ETSI SOL001 v2.5.3",
+ "description": "Provides information regarding the purpose of the connection point",
+ "contactId": "jh0003",
+ "resourceIconPath": "compute",
+ "resourceType": "VFC",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "Cp",
+ "tosca.nodes.nfv.Cp"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.VnfExtCp",
+ "name": "VNF External CP",
+ "model": "ETSI SOL001 v2.5.3",
+ "description": "Describes a logical external connection point, exposed by the VNF enabling connection with an external Virtual Link",
+ "contactId": "jh0003",
+ "resourceIconPath": "network",
+ "resourceType": "CP",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VNF External CP",
+ "tosca.nodes.nfv.VnfExtCp"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.VnfVirtualLink",
+ "name": "VnfVirtualLink",
+ "model": "ETSI SOL001 v2.5.3",
+ "contactId": "jh0003",
+ "description": "Describes the information about an internal VNF VL",
+ "resourceIconPath": "network",
+ "resourceType": "VL",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VnfVirtualLink",
+ "tosca.nodes.nfv.VnfVirtualLink"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.Vdu.VirtualObjectStorage",
+ "name": "VDU VirtualObjectStorage",
+ "description": "This node type describes the specifications of requirements related to virtual object storage resources",
+ "model": "ETSI SOL001 v2.5.3",
+ "contactId": "jh0003",
+ "resourceIconPath": "objectStorage",
+ "resourceType": "VFC",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VDU VirtualObjectStorage",
+ "tosca.nodes.nfv.Vdu.VirtualObjectStorage"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.Vdu.VirtualFileStorage",
+ "name": "VDU VirtualFileStorage",
+ "description": "This node type describes the specifications of requirements related to virtual file storage resources",
+ "model": "ETSI SOL001 v2.5.3",
+ "contactId": "jh0003",
+ "resourceIconPath": "objectStorage",
+ "resourceType": "VFC",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VDU VirtualFileStorage",
+ "tosca.nodes.nfv.Vdu.VirtualFileStorage"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.Vdu.VirtualBlockStorage",
+ "name": "VDU VirtualBlockStorage",
+ "description": "This node type describes the specifications of requirements related to virtual block storage resources",
+ "model": "ETSI SOL001 v2.5.3",
+ "contactId": "jh0003",
+ "resourceIconPath": "objectStorage",
+ "resourceType": "VFC",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VDU VirtualBlockStorage",
+ "tosca.nodes.nfv.Vdu.VirtualBlockStorage"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.NsVirtualLink",
+ "name": "NsVirtualLink",
+ "description": "Node definition of Virtual Links",
+ "model": "ETSI SOL001 v2.5.3",
+ "contactId": "jh0003",
+ "resourceIconPath": "network",
+ "resourceType": "VL",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "NsVirtualLink",
+ "tosca.nodes.nfv.NsVirtualLink"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.NS",
+ "name": "NS",
+ "contactId": "jh0003",
+ "description": "ETSI Network Service",
+ "model": "ETSI SOL001 v2.5.3",
+ "resourceIconPath": "network",
+ "resourceType": "VFC",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Network Elements"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "NS",
+ "tosca.nodes.nfv.NS"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.Vdu.Compute",
+ "name": "VDU Compute",
+ "contactId": "jh0003",
+ "description": "Represents a real or virtual machine or server. Information specified on the Compute node will be used to find the machine that fits the given requirements in the cloud available machines. If no sizing information are specified the cloud provider default machine will be used. It is strongly recommended to specify the required CPUs and memory at least.",
+ "model": "ETSI SOL001 v2.5.3",
+ "resourceIconPath": "compute",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VDU Compute",
+ "tosca.nodes.nfv.Vdu.Compute"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.Sap",
+ "name": "Sap",
+ "contactId": "jh0003",
+ "description": "Node definition of SAP",
+ "model": "ETSI SOL001 v2.5.3",
+ "resourceIconPath": "network",
+ "resourceType": "VFC",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Infrastructure"
+ }
+ ]
+ }
+ ],
+ "vendorName": "ETSI",
+ "vendorRelease": "2.5.1",
+ "tags": [
+ "Sap",
+ "tosca.nodes.nfv.Sap"
+ ]
+ },
+ {
+ "toscaName": "tosca.nodes.nfv.VduCp",
+ "name": "VDU Cp",
+ "contactId": "jh0003",
+ "description": "Describes network connectivity between a VNFC instance based on this VDU and an internal VL",
+ "model": "ETSI SOL001 v2.5.3",
+ "resourceIconPath": "port",
+ "resourceType": "CP",
+ "categories": [
+ {
+ "name": "Generic",
+ "subcategories": [
+ {
+ "name": "Network Elements"
+ }
+ ]
+ }
+ ],
+ "tags": [
+ "VDU Cp",
+ "tosca.nodes.nfv.VduCp"
+ ]
+ }
+ ]
+}
+