Import of VFC will maintain interface implementations 69/101969/6
authorMichaelMorris <michael.morris@est.tech>
Wed, 12 Feb 2020 14:59:19 +0000 (14:59 +0000)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Tue, 24 Mar 2020 14:19:28 +0000 (14:19 +0000)
Issue-ID: SDC-2772
Signed-off-by: MichaelMorris <michael.morris@est.tech>
Change-Id: Id387ebd67ff0b136d532df70fe8b2b8760edc433

catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/OperationArtifactUtil.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ImportUtilsTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/utils/OperationArtifactUtilTest.java
catalog-be/src/test/resources/customTypes/custom-types-node-type-with-interface-impl-unknown-operation.yml [new file with mode: 0644]
catalog-be/src/test/resources/customTypes/custom-types-node-type-with-interface-impl.yml [new file with mode: 0644]
catalog-be/src/test/resources/customTypes/custom-types-node-type-with-unknown-interface-impl.yml [new file with mode: 0644]

index d557de1..687b18e 100644 (file)
@@ -169,6 +169,7 @@ public final class ImportUtils {
         public static final String USER_DEFINED_RESOURCE_NAMESPACE_PREFIX = "org.openecomp.resource.";
         public static final String UI_JSON_PAYLOAD_NAME = "payloadName";
         public static final String CVFC_DESCRIPTION = "Complex node type that is used as nested type in VF";
+        public static final String ESCAPED_DOUBLE_QUOTE = "\"";
 
         private Constants() {}
     }
index 7e26cb3..6b0b6bf 100644 (file)
@@ -39,6 +39,8 @@ import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
@@ -92,11 +94,14 @@ import java.util.stream.Collectors;
 @Component("resourceImportManager")
 public class ResourceImportManager {
     static final Pattern PROPERTY_NAME_PATTERN_IGNORE_LENGTH = Pattern.compile("[\\w\\-\\_\\d\\:]+");
+    private static final String IMPLEMENTATION = "implementation";
 
     private ServletContext servletContext;
 
     private AuditingManager auditingManager;
     private ResourceBusinessLogic resourceBusinessLogic;
+    private InterfaceOperationBusinessLogic interfaceOperationBusinessLogic;
+
     private IGraphLockOperation graphLockOperation;
     protected ToscaOperationFacade toscaOperationFacade;
 
@@ -310,7 +315,7 @@ public class ResourceImportManager {
             while (interfacesNameValue.hasNext()) {
                 Entry<String, Object> interfaceNameValue = interfacesNameValue.next();
                 Either<InterfaceDefinition, ResultStatusEnum> eitherInterface = createModuleInterface(interfaceNameValue
-                        .getValue());
+                        .getValue(), resource);
                 if (eitherInterface.isRight()) {
                     log.info("error when creating interface:{}, for resource:{}", interfaceNameValue.getKey(), resource.getName());
                 }
@@ -325,7 +330,7 @@ public class ResourceImportManager {
         }
     }
 
-    private Either<InterfaceDefinition, ResultStatusEnum> createModuleInterface(Object interfaceJson) {
+    private Either<InterfaceDefinition, ResultStatusEnum> createModuleInterface(Object interfaceJson, Resource resource) {
         InterfaceDefinition interf = new InterfaceDefinition();
         Either<InterfaceDefinition, ResultStatusEnum> result = Either.left(interf);
 
@@ -334,12 +339,31 @@ public class ResourceImportManager {
                 String requirementJsonString = (String) interfaceJson;
                 interf.setType(requirementJsonString);
             }
-            else if (interfaceJson instanceof Map) {
+            else if (interfaceJson instanceof Map && ResourceTypeEnum.VFC.equals(resource.getResourceType())) {
                 Map<String, Object> requirementJsonMap = (Map<String, Object>) interfaceJson;
-                if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
-                    String type = (String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName());
-                    interf.setType(type);
-                    interf.setUniqueId(type.toLowerCase());
+               Map<String, OperationDataDefinition> operations = new HashMap<>();
+
+                for (final Entry<String, Object> entry : requirementJsonMap.entrySet()) {
+                       if (entryIsInterfaceType(entry)) {
+                        String type = (String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName());
+                        interf.setType(type);
+                        interf.setUniqueId(type.toLowerCase());
+                    } else if (entryContainsImplementationForAKnownOperation(entry, interf.getType())){
+                       
+                       OperationDataDefinition operation = new OperationDataDefinition();
+                       operation.setName(entry.getKey());
+
+                       ArtifactDataDefinition implementation = new ArtifactDataDefinition();
+                       // Adding the artifact name in quotes to indicate that this is a literal value, rather than a reference to
+                       // an SDC artifact
+                       implementation.setArtifactName(Constants.ESCAPED_DOUBLE_QUOTE + ((Map<String, String>)entry.getValue()).get(IMPLEMENTATION) + Constants.ESCAPED_DOUBLE_QUOTE);
+                       operation.setImplementation(implementation);
+
+                       operations.put(entry.getKey(), operation);
+                    }
+                }
+                if (!operations.isEmpty()) {
+                       interf.setOperations(operations);
                 }
             }
             else {
@@ -355,6 +379,51 @@ public class ResourceImportManager {
 
         return result;
     }
+    
+    private boolean entryIsInterfaceType(final Entry<String, Object> entry) {
+       if(entry.getKey().equals(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
+               if (entry.getValue() instanceof String) {
+                       return true;
+               }
+               throw new ByActionStatusComponentException(ActionStatus.INVALID_YAML);
+       }
+       return false;
+    }
+    
+    private boolean entryContainsImplementationForAKnownOperation(final Entry<String, Object> entry, final String interfaceType) {
+       if (entry.getValue() instanceof Map && ((Map<?, ?>)entry.getValue()).containsKey(IMPLEMENTATION)) {
+               if (isAKnownOperation(interfaceType, entry.getKey())){
+                       return true;
+               }
+               throw new ByActionStatusComponentException(ActionStatus.INTERFACE_OPERATION_NOT_FOUND);
+       }
+       return false;
+    }
+    
+    private boolean isAKnownOperation(String interfaceType, String operation) {        
+        Either<Map<String, InterfaceDefinition>, ResponseFormat> interfaceLifecycleTypes = interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes();
+         if (interfaceLifecycleTypes.isRight() || interfaceLifecycleTypes.left().value() == null) {
+             return false;
+         }
+         
+         for (Entry<String, InterfaceDefinition> interfaceLifecycleType : interfaceLifecycleTypes.left().value().entrySet()) {
+                if (interfaceTypeAndOperationMatches(interfaceLifecycleType, interfaceType, operation)) {
+                        return true;
+                }
+         }
+         return false;
+    }
+    
+    private boolean interfaceTypeAndOperationMatches(Entry<String, InterfaceDefinition> interfaceLifecycleType, String interfaceType, String operation) {
+       if (interfaceLifecycleType.getKey().equalsIgnoreCase(interfaceType) && interfaceLifecycleType.getValue().getOperations() != null) {
+               for (String interfaceLifecycleTypeOperation : interfaceLifecycleType.getValue().getOperations().keySet()) {
+                       if (interfaceLifecycleTypeOperation != null && interfaceLifecycleTypeOperation.equalsIgnoreCase(operation)){
+                               return true;
+                       }
+               }
+       }
+       return false;
+    }
 
     private void setRequirements(Map<String, Object> toscaJson, Resource resource, Resource parentResource) {// Note that parentResource can be null
         Either<List<Object>, ResultStatusEnum> toscaRequirements = ImportUtils.findFirstToscaListElement(toscaJson, TypeUtils.ToscaTagNamesEnum.REQUIREMENTS);
@@ -898,6 +967,11 @@ public class ResourceImportManager {
     public void setResourceBusinessLogic(ResourceBusinessLogic resourceBusinessLogic) {
         this.resourceBusinessLogic = resourceBusinessLogic;
     }
+    
+    @Autowired
+    public void setInterfaceOperationBusinessLogic(InterfaceOperationBusinessLogic interfaceOperationBusinessLogic) {
+        this.interfaceOperationBusinessLogic = interfaceOperationBusinessLogic;
+    }
 
     public IGraphLockOperation getGraphLockOperation() {
         return graphLockOperation;
index e505238..604715d 100644 (file)
@@ -51,6 +51,7 @@ import org.apache.commons.lang3.tuple.ImmutableTriple;
 import org.apache.commons.lang3.tuple.Triple;
 import org.onap.sdc.tosca.services.YamlUtil;
 import org.openecomp.sdc.be.components.impl.ImportUtils;
+import org.openecomp.sdc.be.components.impl.ImportUtils.Constants;
 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
 import org.openecomp.sdc.be.config.Configuration.ArtifactTypeConfig;
 import org.openecomp.sdc.be.config.ConfigurationManager;
@@ -1004,6 +1005,12 @@ public class CsarUtils {
                     operation.getName());
             return true;
         }
+        if (operation.getImplementation().getArtifactName().startsWith(Constants.ESCAPED_DOUBLE_QUOTE) && operation.getImplementation().getArtifactName().endsWith(Constants.ESCAPED_DOUBLE_QUOTE)) {
+            log.debug("Component Name {}, Interface Id {}, Operation Name {} - artifact name is a literal value rather than an SDC artifact",
+                    component.getNormalizedName(), interfaceEntry.getValue().getUniqueId(),
+                    operation.getName());
+            return true;
+        }
         return false;
     }
 
index a58d035..bab82ad 100644 (file)
@@ -18,6 +18,7 @@ package org.openecomp.sdc.be.tosca.utils;
 
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.WordUtils;
+import org.openecomp.sdc.be.components.impl.ImportUtils.Constants;
 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
@@ -32,6 +33,7 @@ import org.openecomp.sdc.be.tosca.CsarUtils;
 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
 
+
 import java.io.File;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -79,9 +81,18 @@ public class OperationArtifactUtil {
 
 
     private static String createOperationArtifactPathInComponent(OperationDataDefinition operation) {
-        return CsarUtils.ARTIFACTS + File.separator + WordUtils.capitalizeFully(ArtifactGroupTypeEnum.DEPLOYMENT.name())
-                + File.separator + ArtifactTypeEnum.WORKFLOW.name() + File.separator + BPMN_ARTIFACT_PATH
-                + File.separator + operation.getImplementation().getArtifactName();
+       if (artifactNameIsALiteralValue(operation.getImplementation().getArtifactName())) {
+               final String implementationArtifactName = operation.getImplementation().getArtifactName();
+               return implementationArtifactName.substring(1, implementationArtifactName.length()-1);
+       } else {
+               return CsarUtils.ARTIFACTS + File.separator + WordUtils.capitalizeFully(ArtifactGroupTypeEnum.DEPLOYMENT.name())
+                   + File.separator + ArtifactTypeEnum.WORKFLOW.name() + File.separator + BPMN_ARTIFACT_PATH
+                   + File.separator + operation.getImplementation().getArtifactName();
+       }
+    }
+    
+    private static boolean artifactNameIsALiteralValue(final String artifactName) {
+       return artifactName.startsWith(Constants.ESCAPED_DOUBLE_QUOTE) && artifactName.endsWith(Constants.ESCAPED_DOUBLE_QUOTE);
     }
 
     private static String createOperationArtifactPathInService(String toscaComponentName,
index 88eff33..58d93fb 100644 (file)
@@ -32,6 +32,7 @@ import org.mockito.stubbing.Answer;
 import org.openecomp.sdc.be.auditing.impl.AuditingManager;
 import org.openecomp.sdc.be.components.impl.ImportUtils;
 import org.openecomp.sdc.be.components.impl.ImportUtilsTest;
+import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
@@ -40,8 +41,10 @@ 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.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.PropertyConstraint;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.RequirementDefinition;
@@ -68,6 +71,7 @@ import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.when;
@@ -79,6 +83,8 @@ public class ResourceImportManagerTest {
     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 UserBusinessLogic userAdmin = Mockito.mock(UserBusinessLogic.class);
     static ToscaOperationFacade toscaOperationFacade =  Mockito.mock(ToscaOperationFacade.class);
 
@@ -92,6 +98,7 @@ public class ResourceImportManagerTest {
         when(toscaOperationFacade.getLatestByToscaResourceName(Mockito.anyString())).thenReturn(Either.left(null));
         importManager.setResponseFormatManager(responseFormatManager);
         importManager.setResourceBusinessLogic(resourceBusinessLogic);
+        importManager.setInterfaceOperationBusinessLogic(interfaceOperationBusinessLogic);
         importManager.setToscaOperationFacade(toscaOperationFacade);
 
         String appConfigDir = "src/test/resources/config/catalog-be";
@@ -195,6 +202,78 @@ public class ResourceImportManagerTest {
         testSetRequirments(createResource.left);
 
     }
+    
+    @Test
+    public void testResourceCreationWithInterfaceImplementation() throws IOException {
+        UploadResourceInfo resourceMD = createDummyResourceMD();
+        User user = new User();
+        user.setUserId(resourceMD.getContactId());
+        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+
+        setResourceBusinessLogicMock();
+
+        String jsonContent = ImportUtilsTest.loadCustomTypeFileNameToJsonString("custom-types-node-type-with-interface-impl.yml");
+        
+        Map<String, InterfaceDefinition> interfaceTypes = new HashMap<>();
+        final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+        interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard");
+        Map<String, OperationDataDefinition> operations = new HashMap<>();
+        operations.put("configure", new OperationDataDefinition());
+               interfaceDefinition.setOperations(operations );
+        interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
+               when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes()).thenReturn(Either.left(interfaceTypes));
+
+        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+        testSetInterfaceImplementation(createResource.left);
+    }
+    
+    @Test
+    public void testResourceCreationWithInterfaceImplementation_UnknownInterface() throws IOException {
+        UploadResourceInfo resourceMD = createDummyResourceMD();
+        User user = new User();
+        user.setUserId(resourceMD.getContactId());
+        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+
+        setResourceBusinessLogicMock();
+
+        String jsonContent = ImportUtilsTest.loadCustomTypeFileNameToJsonString("custom-types-node-type-with-unknown-interface-impl.yml");
+        
+        Map<String, InterfaceDefinition> interfaceTypes = new HashMap<>();
+        final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+        interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard");
+        Map<String, OperationDataDefinition> operations = new HashMap<>();
+        operations.put("configure", new OperationDataDefinition());
+               interfaceDefinition.setOperations(operations );
+        interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
+               when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes()).thenReturn(Either.left(interfaceTypes));
+
+        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+        assertNull(createResource.left.getInterfaces());
+    }
+    
+    @Test
+    public void testResourceCreationWitInterfaceImplementation_UnknownOperation() throws IOException {
+        UploadResourceInfo resourceMD = createDummyResourceMD();
+        User user = new User();
+        user.setUserId(resourceMD.getContactId());
+        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+
+        setResourceBusinessLogicMock();
+
+        String jsonContent = ImportUtilsTest.loadCustomTypeFileNameToJsonString("custom-types-node-type-with-interface-impl-unknown-operation.yml");
+        
+        Map<String, InterfaceDefinition> interfaceTypes = new HashMap<>();
+        final InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
+        interfaceDefinition.setType("tosca.interfaces.node.lifecycle.Standard");
+        Map<String, OperationDataDefinition> operations = new HashMap<>();
+        operations.put("configure", new OperationDataDefinition());
+               interfaceDefinition.setOperations(operations );
+        interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
+               when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes()).thenReturn(Either.left(interfaceTypes));
+
+        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+        assertNull(createResource.left.getInterfaces());
+    }
 
     private void setResourceBusinessLogicMock() {
         when(resourceBusinessLogic.getUserAdmin()).thenReturn(userAdmin);
@@ -318,6 +397,22 @@ public class ResourceImportManagerTest {
         assertEquals("binding", requirement.getName());
 
     }
+    
+    private void testSetInterfaceImplementation(Resource resource) {
+       Map<String, InterfaceDefinition> interfaces = resource.getInterfaces();
+        assertEquals(1, interfaces.size());
+        assertTrue(interfaces.containsKey("Standard"));
+        
+        InterfaceDefinition interfaceDefinition = interfaces.get("Standard");
+        assertEquals("tosca.interfaces.node.lifecycle.Standard", interfaceDefinition.getType());
+        assertEquals("tosca.interfaces.node.lifecycle.standard", interfaceDefinition.getUniqueId());
+        Map<String, OperationDataDefinition> operations = interfaceDefinition.getOperations();
+        assertEquals(1, operations.size());
+
+        OperationDataDefinition operation = operations.get("configure");
+        assertEquals("\"camunda/vnfConfigure\"", operation.getImplementation().getArtifactName());
+
+    }
 
     private void testSetDerivedFrom(Resource resource) {
         assertEquals(1, resource.getDerivedFrom().size());
index 681e9cd..e47cdc9 100644 (file)
@@ -540,11 +540,21 @@ public class ImportUtilsTest {
 
     public static String loadFileNameToJsonString(String fileName) throws IOException {
         String sourceDir = "src/test/resources/normativeTypes";
+       return loadFileNameToJsonString(sourceDir, fileName);
+    }
+    
+    public static String loadCustomTypeFileNameToJsonString(String fileName) throws IOException {
+        String sourceDir = "src/test/resources/customTypes";
+       return loadFileNameToJsonString(sourceDir, fileName);
+    }
+    
+    private static String loadFileNameToJsonString(String sourceDir, String fileName) throws IOException {
         java.nio.file.Path filePath = FileSystems.getDefault().getPath(sourceDir, fileName);
         byte[] fileContent = Files.readAllBytes(filePath);
         return new String(fileContent);
     }
 
+
     private static Object loadJsonFromFile(String fileName) throws IOException {
         String content = loadFileNameToJsonString(fileName);
         return new Yaml().load(content);
index dafe0fc..2328858 100644 (file)
@@ -90,6 +90,23 @@ public class OperationArtifactUtilTest {
 
         assertEquals(expectedArtifactPath,actualArtifactPath);
     }
+    
+    @Test
+    public void testCorrectPathForLiteralInterfaceImplementationValue() {
+        ResourceMetadataDataDefinition componentMetadataDataDefinition = new ResourceMetadataDataDefinition();
+        componentMetadataDataDefinition.setToscaResourceName("org.openecomp.resource.vf.TestResource");
+        final ComponentMetadataDefinition componentMetadataDefinition =
+                new ComponentMetadataDefinition(componentMetadataDataDefinition);
+        Component component = new Resource(componentMetadataDefinition);
+        final OperationDataDefinition op = new OperationDataDefinition();
+        final ArtifactDataDefinition implementation = new ArtifactDataDefinition();
+        implementation.setArtifactName("\"createBPMN.bpmn\"");
+        op.setImplementation(implementation);
+        final String actualArtifactPath = OperationArtifactUtil.createOperationArtifactPath(component, null, op, false);
+        String expectedArtifactPath = "createBPMN.bpmn";
+
+        assertEquals(expectedArtifactPath,actualArtifactPath);
+    }
 
     @Test
     public void testGetDistinctInterfaceOperationArtifactsByName() {
diff --git a/catalog-be/src/test/resources/customTypes/custom-types-node-type-with-interface-impl-unknown-operation.yml b/catalog-be/src/test/resources/customTypes/custom-types-node-type-with-interface-impl-unknown-operation.yml
new file mode 100644 (file)
index 0000000..af49b43
--- /dev/null
@@ -0,0 +1,26 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+node_types: 
+  org.openecomp.resources.customNodeType:
+    derived_from: tosca.nodes.Root
+    description: A node type derived from tosca.nodes.Root with an interface implementation
+    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
+        unknownoperation:
+          implementation: 'camunda/vnfConfigure'
\ No newline at end of file
diff --git a/catalog-be/src/test/resources/customTypes/custom-types-node-type-with-interface-impl.yml b/catalog-be/src/test/resources/customTypes/custom-types-node-type-with-interface-impl.yml
new file mode 100644 (file)
index 0000000..2fc8e3d
--- /dev/null
@@ -0,0 +1,26 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+node_types: 
+  org.openecomp.resources.customNodeType:
+    derived_from: tosca.nodes.Root
+    description: A node type derived from tosca.nodes.Root with an interface implementation
+    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
+        configure:
+          implementation: 'camunda/vnfConfigure'
\ No newline at end of file
diff --git a/catalog-be/src/test/resources/customTypes/custom-types-node-type-with-unknown-interface-impl.yml b/catalog-be/src/test/resources/customTypes/custom-types-node-type-with-unknown-interface-impl.yml
new file mode 100644 (file)
index 0000000..680b1d7
--- /dev/null
@@ -0,0 +1,26 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+node_types: 
+  org.openecomp.resources.customNodeType:
+    derived_from: tosca.nodes.Root
+    description: A node type derived from tosca.nodes.Root with an interface implementation
+    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.Unknown
+        configure:
+          implementation: 'camunda/vnfConfigure'
\ No newline at end of file