Max boundary check for instances relationships 38/105138/3
authorandre.schmid <andre.schmid@est.tech>
Fri, 3 Apr 2020 16:41:23 +0000 (17:41 +0100)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Sun, 19 Apr 2020 10:36:00 +0000 (10:36 +0000)
Considering the max boundary of a requirement during a component
composition, allowing the correct number of the requirement
relationships between instances.

Change-Id: I82a1a6daeda8fadcf1c232b117d5b099db7b35d7
Issue-ID: SDC-2872
Signed-off-by: andre.schmid <andre.schmid@est.tech>
catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requirement-utils.spec.ts
catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requirement-utils.ts

index 10b26fc..1045e56 100644 (file)
@@ -21,7 +21,9 @@ describe('match capability requirements utils service ', () => {
         relationship: 'tosca.relationships.network.BindsTo',
         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.virtualBinding',
         ownerId : 'extcp0',
-        ownerName : 's'
+        ownerName : 's',
+        minOccurrences: 0,
+        maxOccurrences: 'UNBOUNDED'
     });
 
     const virtualLinkReq = Mock.of<Requirement>({
@@ -29,8 +31,10 @@ describe('match capability requirements utils service ', () => {
         name: 'virtualLink',
         relationship: 'tosca.relationships.network.LinksTo',
         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.virtualLink',
-        ownerId : '',
-        ownerName : 's'
+        ownerId : 'extcp0',
+        ownerName : 's',
+        minOccurrences: 0,
+        maxOccurrences: '1'
     });
 
     const storeAttachmentReq = Mock.of<Requirement>({
@@ -315,31 +319,56 @@ describe('match capability requirements utils service ', () => {
             expect(matchingNodes).toHaveLength(0);
         });
 
-       it('should detect fulfilled connection with compute node', () => {
-            const nodes = [ nodeBlockStorage, nodeCompute, nodeVl ];
+        it('should detect fulfilled connection with compute node', () => {
+            const nodes = [nodeBlockStorage, nodeCompute, nodeVl];
             let matchingNodes: any;
-            const link = {
+
+            // add one fulfilled relationship from nodeCp.bindableReq (0,N) to nodeCompute.bindingCap
+            let link = {
                 relation: {
-                    fromNode: 'extcp0',
-                    toNode: 'compute0',
+                    fromNode: nodeCp.componentInstance.uniqueId,
+                    toNode: nodeCompute.componentInstance.uniqueId,
                     relationships: [{
                         relation: {
-                            requirementOwnerId: 'extcp0',
-                            requirement: 'virtualBinding',
+                            requirementOwnerId: nodeCp.componentInstance.uniqueId,
+                            requirement: bindableReq.name,
                             relationship: {
-                                type: 'tosca.relationships.network.BindsTo'
+                                type: bindableReq.relationship
                             }
+                        }
+                    }]
+                }
+            };
 
+            matchingNodes = service.findMatchingNodesToComponentInstance(nodeCp.componentInstance, nodes, [link] as CompositionCiLinkBase[]);
+            expect(matchingNodes).toHaveLength(2);
+            // nodeCp.virtualLinkReq (0,1) should be able to connect to nodeVl.linkableCap
+            expect(matchingNodes).toContain(nodeVl);
+            // nodeCp.bindableReq (0,N) should be able to connect to nodeCompute.bindingCap
+            expect(matchingNodes).toContain(nodeCompute);
+
+            // add one relationship from nodeCp.virtualLinkReq (0,1) to nodeVl.linkableCap
+            // so it is fulfilled, you cannot have another one from nodeCp.virtualLinkReq
+            link = {
+                relation: {
+                    fromNode: nodeCp.componentInstance.uniqueId,
+                    toNode: nodeVl.componentInstance.uniqueId,
+                    relationships: [{
+                        relation: {
+                            requirementOwnerId: nodeCp.componentInstance.uniqueId,
+                            requirement: virtualLinkReq.name,
+                            relationship: {
+                                type: virtualLinkReq.relationship
+                            }
                         }
                     }]
                 }
             };
 
-            const links = [link];
-            // CP should be able to connect to VL only since it already has a link with compute
-            matchingNodes = service.findMatchingNodesToComponentInstance(nodeCp.componentInstance, nodes, links as CompositionCiLinkBase[]);
+            matchingNodes = service.findMatchingNodesToComponentInstance(nodeCp.componentInstance, nodes, [link] as CompositionCiLinkBase[]);
             expect(matchingNodes).toHaveLength(1);
-            expect(matchingNodes).toContain(nodeVl);
+            // nodeCp.bindableReq (0,N) should be able to connect to nodeCompute.bindingCap
+            expect(matchingNodes).toContain(nodeCompute);
         });
     });
 });
index ec7f8d1..a182932 100644 (file)
@@ -174,8 +174,12 @@ export class MatchCapabilitiesRequirementsUtils {
         return false;
     }
 
-    private isRequirementFulfilled(fromNodeId: string, requirement: any, links: CompositionCiLinkBase[]): boolean {
-        return _.some(links, {
+    private isRequirementFulfilled(fromNodeId: string, requirement: Requirement, links: CompositionCiLinkBase[]): boolean {
+        if (!requirement.maxOccurrences || requirement.maxOccurrences === 'UNBOUNDED') {
+            return false;
+        }
+
+        let list =_.filter(links, {
             relation: {
                 fromNode: fromNodeId,
                 relationships: [{
@@ -190,6 +194,8 @@ export class MatchCapabilitiesRequirementsUtils {
                 }]
             }
         });
+
+        return list.length >= parseInt(requirement.maxOccurrences);
     }
 
 }