Support Tosca DependsOn root node relationship​ 62/102062/2
authorandre.schmid <andre.schmid@est.tech>
Fri, 14 Feb 2020 15:37:17 +0000 (15:37 +0000)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Thu, 12 Mar 2020 09:32:34 +0000 (09:32 +0000)
tosca.nodes.Root supports the use of a DependsOn relationship
to indicate a general dependency relationship between two
nodes. SDC currently disallows this relationship to be created
in the VF/Service composition view.

Change-Id: Ie5f1f5d2e5173b59f878986ee625b27aaa81e4f6
Issue-ID: SDC-2768
Signed-off-by: andre.schmid <andre.schmid@est.tech>
catalog-ui/src/app/ng2/pages/composition/graph/composition-graph.module.ts
catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-general-utils.ts
catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-links-utils.ts
catalog-ui/src/app/ng2/pages/composition/graph/utils/composition-graph-palette-utils.ts
catalog-ui/src/app/ng2/pages/composition/graph/utils/index.ts
catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requirement-utils.spec.ts [moved from catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.spec.ts with 87% similarity]
catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requirement-utils.ts [moved from catalog-ui/src/app/ng2/pages/composition/graph/utils/match-capability-requierment-utils.ts with 97% similarity]

index e58d160..1a20b53 100644 (file)
@@ -8,7 +8,7 @@ import {CommonGraphUtils} from "./common/common-graph-utils";
 import {LinksFactory} from "app/models/graph/graph-links/links-factory";
 import {NodesFactory} from "app/models/graph/nodes/nodes-factory";
 import {ImageCreatorService} from "./common/image-creator.service";
-import {MatchCapabilitiesRequirementsUtils} from "./utils/match-capability-requierment-utils";
+import {MatchCapabilitiesRequirementsUtils} from "./utils/match-capability-requirement-utils";
 import {CompositionGraphNodesUtils} from "./utils/composition-graph-nodes-utils";
 import {ConnectionWizardService} from "app/ng2/pages/composition/graph/connection-wizard/connection-wizard.service";
 import {CompositionGraphPaletteUtils} from "./utils/composition-graph-palette-utils";
index bc8bd69..8b4a294 100644 (file)
@@ -21,7 +21,7 @@
 import * as _ from "lodash";
 import {ComponentInstance, Match, CompositionCiLinkBase, CompositionCiNodeUcpeCp} from "app/models";
 import {Dictionary, GraphUIObjects} from "app/utils";
-import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
+import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requirement-utils";
 import {CommonGraphUtils} from "../common/common-graph-utils";
 import {Injectable} from "@angular/core";
 import {QueueServiceUtils} from "app/ng2/utils/queue-service-utils";
index 6035d05..ba35a98 100644 (file)
@@ -40,7 +40,7 @@ import {
 } from "app/models";
 import {CommonGraphUtils} from "../common/common-graph-utils";
 import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils";
-import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
+import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requirement-utils";
 import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
 import {Injectable} from "@angular/core";
 import {QueueServiceUtils} from "app/ng2/utils/queue-service-utils";
index 1776c2f..922f19c 100644 (file)
@@ -34,7 +34,7 @@ import {CompositionService} from "../../composition.service";
 import {WorkspaceService} from "app/ng2/pages/workspace/workspace.service";
 import { QueueServiceUtils } from "app/ng2/utils/queue-service-utils";
 import {ComponentGenericResponse} from "../../../../services/responses/component-generic-response";
-import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
+import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requirement-utils";
 import {CompositionGraphNodesUtils} from "./index";
 
 @Injectable()
index e7f11af..e1621d1 100644 (file)
@@ -11,7 +11,7 @@
 
 import {CompositionGraphGeneralUtils} from './composition-graph-general-utils';
 import {CompositionGraphNodesUtils} from './composition-graph-nodes-utils';
-import {MatchCapabilitiesRequirementsUtils} from './match-capability-requierment-utils'
+import {MatchCapabilitiesRequirementsUtils} from './match-capability-requirement-utils'
 import {CompositionGraphPaletteUtils} from './composition-graph-palette-utils';
 import {CompositionGraphZoneUtils} from './composition-graph-zone-utils';
 import {ServicePathGraphUtils} from './composition-graph-service-path-utils';
@@ -1,12 +1,17 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { TestBed } from '@angular/core/testing';
 import { Mock } from 'ts-mockery';
 import {
     CapabilitiesGroup,
-    Capability, ComponentInstance, CompositionCiLinkBase, CompositionCiNodeBase, CompositionCiNodeCp,
-    CompositionCiNodeVf, CompositionCiNodeVl,
-    Requirement, RequirementsGroup
+    Capability,
+    ComponentInstance,
+    CompositionCiLinkBase,
+    CompositionCiNodeCp,
+    CompositionCiNodeVf,
+    CompositionCiNodeVl,
+    Requirement,
+    RequirementsGroup
 } from '../../../../../models';
-import { MatchCapabilitiesRequirementsUtils } from './match-capability-requierment-utils';
+import { MatchCapabilitiesRequirementsUtils } from './match-capability-requirement-utils';
 
 describe('match capability requirements utils service ', () => {
 
@@ -38,47 +43,25 @@ describe('match capability requirements utils service ', () => {
         ownerName : 's'
     });
 
-    const vlAttachmentReq = Mock.of<Requirement>({
-        capability: 'tosca.capabilities.Attachment',
-        name: 'local_storage',
-        relationship: 'tosca.relationships.AttachesTo',
-        uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.local_storage',
-        node: 'tosca.nodes.BlockStorage',
-        ownerId : '',
-        ownerName : 's'
-    });
-
-    const extVirtualLinkReq = Mock.of<Requirement>({
-        capability: 'tosca.capabilities.network.Linkable',
-        name: 'external_virtualLink',
-        relationship: 'tosca.relationships.network.LinksTo',
-        uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.external_virtualLink'
-    });
-
     const dependencyReq = Mock.of<Requirement>({
         capability: 'tosca.capabilities.Node',
         name: 'dependency',
+        node: 'tosca.nodes.Root',
         relationship: 'tosca.relationships.DependsOn',
-        uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.dependency'
+        uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.dependency',
+        minOccurrences: 0,
+        maxOccurrences: 'UNBOUNDED'
     });
 
     const featureCap = Mock.of<Capability>({
         type: 'tosca.capabilities.Node',
         name: 'feature',
+        capabilitySources: ['tosca.nodes.Root'],
         uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.feature',
         maxOccurrences: 'UNBOUNDED',
         minOccurrences: '1'
     });
 
-    const internalConnPointCap = Mock.of<Capability>({
-        type: 'tosca.capabilities.Node',
-        name: 'internal_connectionPoint',
-        capabilitySources : ['org.openecomp.resource.cp.extCP'],
-        uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.internal_connectionPoint',
-        maxOccurrences: 'UNBOUNDED',
-        minOccurrences: '1'
-    });
-
     const blockStoreAttachmentCap = Mock.of<Capability>({
         type: 'tosca.capabilities.Attachment',
         name: 'attachment',
@@ -111,12 +94,10 @@ describe('match capability requirements utils service ', () => {
             componentName: 'Compute',
             uniqueId : 'compute0',
             requirements: Mock.of<RequirementsGroup>({
-                'tosca.capabilities.Node' : [ dependencyReq ],
                 'tosca.capabilities.Attachment' : [ storeAttachmentReq ]
             }),
             capabilities: Mock.of<CapabilitiesGroup>({
                 'tosca.capabilities.network.Bindable' : [ bindingCap ],
-                'tosca.capabilities.Node' : [ featureCap ]
             })
         })
     });
@@ -126,12 +107,8 @@ describe('match capability requirements utils service ', () => {
         componentInstance: Mock.of<ComponentInstance>({
             componentName: 'BlockStorage',
             uniqueId : 'blockstorage0',
-            requirements: Mock.of<RequirementsGroup>({
-                'tosca.capabilities.Node' : [ dependencyReq ]
-            }),
             capabilities: Mock.of<CapabilitiesGroup>({
                 'tosca.capabilities.Attachment' : [ blockStoreAttachmentCap ],
-                'tosca.capabilities.Node' : [ featureCap ]
             })
         })
     });
@@ -141,12 +118,8 @@ describe('match capability requirements utils service ', () => {
         componentInstance: Mock.of<ComponentInstance>({
             componentName: 'BlockStorage',
             uniqueId : 'extvl0',
-            requirements: Mock.of<RequirementsGroup>({
-                'tosca.capabilities.Node' : [ dependencyReq ]
-            }),
             capabilities: Mock.of<CapabilitiesGroup>({
                 'tosca.capabilities.network.Linkable' : [ linkableCap ],
-                'tosca.capabilities.Node' : [ featureCap ]
             })
         })
     });
@@ -160,9 +133,6 @@ describe('match capability requirements utils service ', () => {
                 'tosca.capabilities.network.Linkable' : [ virtualLinkReq ],
                 'tosca.capabilities.network.Bindable' : [ bindableReq ]
             }),
-            capabilities: Mock.of<CapabilitiesGroup>({
-                'tosca.capabilities.Node' : [ featureCap ]
-            })
         })
     });
 
@@ -274,6 +244,39 @@ describe('match capability requirements utils service ', () => {
             jest.spyOn(service, 'isMatch').mockReturnValue(true);
             expect(service.getMatches({}, capabilities, [], fromId, toId, true)).toHaveLength(4);
         });
+
+        it('node have 3 unfulfilled requirements: DependsOn tosca.nodes.Root, BindsTo and LinksTo;' +
+            ' and DependsOn and BindsTo matching capabilities, ' +
+            'should return 2 matches', () => {
+            const dependencyList = [dependencyReq, bindableReq, virtualLinkReq];
+            jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue(dependencyList);
+            const capabilities = {
+                cap1Match: featureCap, cap2NotMatch: Mock.of<Capability>(), cap3Match: bindingCap
+            };
+            const expectedMatchDependsOn = {
+                requirement: dependencyReq,
+                capability: featureCap,
+                isFromTo: true,
+                fromNode: fromId,
+                toNode: toId
+            };
+            const expectedMatchBindsTo = {
+                requirement: bindableReq,
+                capability: bindingCap,
+                isFromTo: true,
+                fromNode: fromId,
+                toNode: toId
+            };
+            const matches = service.getMatches({}, capabilities, [], fromId, toId, true);
+            expect(matches).toHaveLength(2);
+            expect(matches).toEqual(
+                expect.arrayContaining([
+                    expect.objectContaining(expectedMatchDependsOn),
+                    expect.objectContaining(expectedMatchBindsTo)
+                ])
+            );
+
+        });
     });
 
     describe('Find matching nodes ===>', () => {
@@ -113,13 +113,12 @@ export class MatchCapabilitiesRequirementsUtils {
     public getUnfulfilledRequirements = (fromNodeId: string, requirements: RequirementsGroup, links: CompositionCiLinkBase[]): Requirement[] => {
         const requirementArray: Requirement[] = [];
         _.forEach(_.flatten(_.values(requirements)), (requirement: Requirement) => {
-            const reqFulfilled = this.isRequirementFulfilled(fromNodeId, requirement, links);
-            if (requirement.name !== 'dependency' && requirement.parentName !== 'dependency' && !reqFulfilled) {
+            if (!this.isRequirementFulfilled(fromNodeId, requirement, links)) {
                 requirementArray.push(requirement);
             }
         });
         return requirementArray;
-    }
+    };
 
     /**
      * Returns true if there is a match between the capabilities and requirements that are passed in