Service Import - Read metadata from csar 90/129590/12
authorJvD_Ericsson <jeff.van.dam@est.tech>
Thu, 2 Jun 2022 09:46:40 +0000 (10:46 +0100)
committerMichael Morris <michael.morris@est.tech>
Fri, 24 Jun 2022 13:17:23 +0000 (13:17 +0000)
Also exports metadata to the tosca template and
fixes service metadata not being set when the create button is clicked

Issue-ID: SDC-4044
Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
Change-Id: I6f8428d9ed385335c05e7b994e622229ea00342b

13 files changed:
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadServiceInfo.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadServiceInfoTest.java
catalog-ui/package.json
catalog-ui/src/app/models.ts
catalog-ui/src/app/models/service-csar.ts [new file with mode: 0644]
catalog-ui/src/app/modules/utils.ts
catalog-ui/src/app/utils.ts
catalog-ui/src/app/utils/file-utils.ts
catalog-ui/src/app/utils/service-csar-reader.ts [new file with mode: 0644]
catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts

index 9a8c181..dd55ae8 100644 (file)
@@ -210,9 +210,6 @@ public class ServiceImportBusinessLogic {
         service.setVersion(INITIAL_VERSION);
         service.setConformanceLevel(ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel());
         service.setDistributionStatus(DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED);
-        service.setInstantiationType("A-la-carte");
-        service.setEnvironmentContext("General_Revenue-Bearing");
-        service.setEcompGeneratedNaming(true);
         try {
             serviceBusinessLogic.validateServiceBeforeCreate(service, user, auditingAction);
             log.debug("enter createService,validateServiceBeforeCreate success");
index 7958efa..6f10aae 100644 (file)
@@ -71,7 +71,15 @@ public class ServiceImportManager {
             ServiceMetadataDataDefinition serviceMetadataDataDefinition = (ServiceMetadataDataDefinition) service.getComponentMetadataDefinition()
                 .getMetadataDataDefinition();
             serviceMetadataDataDefinition.getServiceVendorModelNumber();
-            service.setServiceType("");
+            service.setServiceType(serviceMetaData.getServiceType());
+            service.setServiceRole(serviceMetaData.getServiceRole());
+            service.setNamingPolicy(serviceMetaData.getNamingPolicy());
+            boolean ecompGeneratedNaming = serviceMetaData.getEcompGeneratedNaming() == null
+                || serviceMetaData.getEcompGeneratedNaming().equals("true");
+            service.setEcompGeneratedNaming(ecompGeneratedNaming);
+            service.setServiceFunction(serviceMetaData.getServiceFunction());
+            service.setInstantiationType(serviceMetaData.getInstantiationType());
+            service.setEnvironmentContext(serviceMetaData.getEnvironmentContext());
             service.setProjectCode(serviceMetaData.getProjectCode());
             service.setModel(serviceMetaData.getModel());
             if (serviceMetaData.getVendorName() != null) {
index 586b9f6..91d2bd5 100644 (file)
@@ -510,6 +510,7 @@ public class ToscaExportHandler {
         toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription());
         List<CategoryDefinition> categories = component.getCategories();
         CategoryDefinition categoryDefinition = categories.get(0);
+        toscaMetadata.put(JsonPresentationFields.MODEL.getPresentation(), component.getModel());
         toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName());
         if (isInstance) {
             toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion());
index 837791a..1c12a3e 100644 (file)
@@ -48,64 +48,24 @@ public class UploadServiceInfo {
     private String serviceEcompNaming;
     private String ecompGeneratedNaming;
     private String namingPolicy;
+    private String serviceFunction;
+    private String environmentContext;
+    private String instantiationType;
     private String projectCode;
     private List<UploadArtifactInfo> artifactList;
-    private String contactId, name, serviceIconPath, icon, vendorName, vendorRelease, serviceVendorModelNumber;
+    private String contactId;
+    private String name;
+    private String serviceIconPath;
+    private String icon;
+    private String vendorName;
+    private String vendorRelease;
+    private String serviceVendorModelNumber;
     private String serviceType = "";
     private String model;
     private Map<String, String> categorySpecificMetadata;
     private String derivedFromGenericType;
     private String derivedFromGenericVersion;
 
-    public UploadServiceInfo(String payloadData, String payloadName, String description, List<String> tags, String invariantUUID, String UUID,
-                             String type, String category, String subcategory, String resourceVendor, String resourceVendorRelease,
-                             String serviceRole, String serviceEcompNaming, String ecompGeneratedNaming, String namingPolicy,
-                             List<UploadArtifactInfo> artifactList, String contactId, String name, String resourceIconPath, String icon,
-                             String vendorName, String vendorRelease, String serviceVendorModelNumber, String serviceType, String projectCode, String model, Map<String, String> categorySpecificMetadata,
-                             String derivedFromGenericType, String derivedFromGenericVersion) {
-        this.payloadData = payloadData;
-        this.payloadName = payloadName;
-        this.description = description;
-        this.tags = tags;
-        this.invariantUUID = invariantUUID;
-        this.UUID = UUID;
-        this.type = type;
-        this.category = category;
-        this.subcategory = subcategory;
-        this.resourceVendor = resourceVendor;
-        this.resourceVendorRelease = resourceVendorRelease;
-        this.serviceRole = serviceRole;
-        this.serviceEcompNaming = serviceEcompNaming;
-        this.ecompGeneratedNaming = ecompGeneratedNaming;
-        this.namingPolicy = namingPolicy;
-        this.artifactList = artifactList;
-        this.contactId = contactId;
-        this.name = name;
-        this.serviceIconPath = serviceIconPath;
-        this.icon = icon;
-        this.vendorName = vendorName;
-        this.vendorRelease = vendorRelease;
-        this.serviceVendorModelNumber = serviceVendorModelNumber;
-        this.serviceType = serviceType;
-        this.projectCode = projectCode;
-        this.model = model;
-        if (category != null) {
-            String[] arr = category.split("/");
-            if (arr.length >= 2) {
-                categories = new ArrayList<>();
-                CategoryDefinition catDef = new CategoryDefinition();
-                catDef.setName(arr[0]);
-                SubCategoryDefinition subCat = new SubCategoryDefinition();
-                subCat.setName(arr[1]);
-                catDef.addSubCategory(subCat);
-                categories.add(catDef);
-            }
-        }
-        this.categorySpecificMetadata = categorySpecificMetadata;
-        this.derivedFromGenericType = derivedFromGenericType;
-        this.derivedFromGenericVersion = derivedFromGenericVersion;
-    }
-
     public UploadServiceInfo() {
     }
 
index d8ddb75..8d0d0b9 100644 (file)
@@ -36,13 +36,6 @@ public class UploadServiceInfoTest {
         return new UploadServiceInfo();
     }
 
-    @Test
-    public void testCtor() {
-        new UploadServiceInfo("mock", "mock", "mock", new LinkedList<>(), "mock", "mock", "mock", "mock/mock/mock",
-                "mock", "mock", "mock", "mock", "mock", "mock", "mock", new LinkedList<>(), "mock", "mock", "mock",
-                "mock", "mock", "mock", "mock", "mock", "mock", "mock", new HashMap<>(), "mock", "mock");
-    }
-
     @Test
     public void testAddSubCategory() {
         UploadServiceInfo testSubject;
index 92e6ef4..27bba58 100644 (file)
     "@angular/upgrade": "^5.0.0",
     "@bardit/cytoscape-expand-collapse": "^2.0.3",
     "@bardit/cytoscape-qtip": "^2.5.1",
+    "@ng-select/ng-select": "^1.0.2",
     "@ngxs/devtools-plugin": "3.3.4",
     "@ngxs/logger-plugin": "3.3.4",
     "@ngxs/store": "^2.1.0-dev.d538580",
-    "@ng-select/ng-select": "^1.0.2",
     "@swimlane/ngx-datatable": "^14.0.0",
     "@types/core-js": "^0.9.35",
     "@types/jquery": "^2.0.52",
     "jquery": "^3.6.0",
     "jqueryui": "^1.11.1",
     "js-md5": "^0.4.2",
+    "js-yaml": "^4.1.0",
+    "jszip": "^3.10.0",
     "less": "~3.9.0",
     "lodash": "^4.17.2",
     "ng-infinite-scroll": "^1.3.0",
index 78be1e5..7604b67 100644 (file)
@@ -127,4 +127,5 @@ export * from './models/service-instance-properties-and-interfaces';
 export * from './models/relationship-types';
 export * from './models/tosca-presentation';
 export * from './models/node-types';
-export * from './models/capability-types';
\ No newline at end of file
+export * from './models/capability-types';
+export * from './models/service-csar';
\ No newline at end of file
diff --git a/catalog-ui/src/app/models/service-csar.ts b/catalog-ui/src/app/models/service-csar.ts
new file mode 100644 (file)
index 0000000..39f8e05
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {ComponentMetadata} from "./component-metadata";
+
+export enum ToscaMetaEntry {
+    ENTRY_DEFINITIONS = "Entry-Definitions"
+}
+
+export class ServiceCsar {
+
+    entryDefinitionFileName: string;
+    interfaceDefinitionFileName: string;
+    substitutionNodeType:string;
+    toscaMeta: ToscaMeta = new ToscaMeta();
+    serviceMetadata: ComponentMetadata = new ComponentMetadata();
+    extraServiceMetadata: Map<string, string> = new Map<string, string>();
+
+}
+
+export class ToscaMeta {
+
+    dataMap: Map<string, string> = new Map<string, string>();
+
+    getEntry(toscaMetaEntry: ToscaMetaEntry): string {
+        return this.dataMap.get(toscaMetaEntry.valueOf());
+    }
+
+}
index 7a57478..a2fb690 100644 (file)
@@ -23,6 +23,7 @@ import {ComponentInstanceFactory} from "../utils/component-instance-factory";
 import {ChangeLifecycleStateHandler} from "../utils/change-lifecycle-state-handler";
 import {ModalsHandler} from "../utils/modals-handler";
 import {MenuHandler} from "../utils/menu-handler";
+import {ServiceCsarReader} from "../utils/service-csar-reader";
 
 let moduleName:string = 'Sdc.Utils';
 let serviceModule:ng.IModule = angular.module(moduleName, []);
@@ -33,4 +34,5 @@ serviceModule.service('ComponentInstanceFactory', ComponentInstanceFactory);
 serviceModule.service('ChangeLifecycleStateHandler', ChangeLifecycleStateHandler);
 serviceModule.service('ModalsHandler', ModalsHandler);
 serviceModule.service('MenuHandler', MenuHandler);
+serviceModule.service('ServiceCsarReader', ServiceCsarReader);
 
index 27c805a..ccf9156 100644 (file)
@@ -32,3 +32,4 @@ export * from './utils/menu-handler';
 export * from './utils/constants';
 export * from './utils/common-utils';
 export * from './utils/functions';
+export * from './utils/service-csar-reader';
index d726736..4b6f330 100644 (file)
@@ -66,6 +66,24 @@ export class FileUtils {
             "cancelable": true
         });
         downloadLink.dispatchEvent(clickEvent);
+    }
 
+    public getEntryDefinitionFileNameFromCsarBlob = (csarBlob:Blob):Promise<any> => {
+        let JSZip = require("jszip");
+        return JSZip.loadAsync(csarBlob).then(zip => {
+            return zip.file("TOSCA-Metadata/TOSCA.meta").async("string");
+        }).then((toscaMetaData: string) => {
+            let fileEntities:Array<string> = toscaMetaData.replace("\r", "").split("\n");
+            let entryDefinitionFilename:string = fileEntities.find(element => !element.search("Entry-Definitions"))
+                .replace("Entry-Definitions:", "").trim();
+            return entryDefinitionFilename;
+        });
+    }
+
+    public getFileNameDataFromCsarBlob = (csarBlob:Blob, fileName:string):Promise<any> => {
+        let JSZip = require("jszip");
+        return JSZip.loadAsync(csarBlob).then(zip => {
+            return zip.file(fileName).async("string");
+        });
     }
 }
diff --git a/catalog-ui/src/app/utils/service-csar-reader.ts b/catalog-ui/src/app/utils/service-csar-reader.ts
new file mode 100644 (file)
index 0000000..73b7755
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2022 Nordix Foundation. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+import {ServiceCsar, ToscaMetaEntry} from "../models";
+import {load} from 'js-yaml';
+import { ComponentType } from "./constants";
+
+export class ServiceCsarReader {
+
+    private serviceCsar = new ServiceCsar();
+
+    public read(serviceCsarBlob:Blob): Promise<ServiceCsar> {
+        const jsZip = require("jszip");
+        return new Promise<ServiceCsar>((resolve) => {
+            jsZip.loadAsync(serviceCsarBlob).then(async zip => {
+                const toscaMetaFileContent = await zip.file("TOSCA-Metadata/TOSCA.meta").async("string");
+                this.readToscaMeta(toscaMetaFileContent);
+                const entryDefinitionFileContent = await zip.file(this.serviceCsar.entryDefinitionFileName).async("string");
+                this.readServiceMetadata(entryDefinitionFileContent);
+                const interfaceDefinitionFileContent = await zip.file(this.serviceCsar.interfaceDefinitionFileName).async("string");
+                this.readServiceSubstitutionNode(interfaceDefinitionFileContent);
+                resolve(this.serviceCsar);
+            });
+        });
+    }
+
+    private readToscaMeta(toscaMetaFileContent:string) {
+        let fileEntities:Array<string> = toscaMetaFileContent.replace("\r", "").split("\n");
+        for(let entity of fileEntities.filter(e => e)) {
+            let mapEntry:Array<string> = entity.split(":");
+            let key:string = mapEntry[0].trim();
+            let value:string = mapEntry[1].trim();
+            this.serviceCsar.toscaMeta.dataMap.set(key, value);
+        }
+        this.readEntryDefinitionFileName();
+        this.readInterfaceDefinitionFileName();
+    }
+
+    private readEntryDefinitionFileName() {
+        this.serviceCsar.entryDefinitionFileName = this.serviceCsar.toscaMeta.getEntry(ToscaMetaEntry.ENTRY_DEFINITIONS);
+    }
+
+    private readInterfaceDefinitionFileName() {
+        let fileNameArray:Array<string> = this.serviceCsar.entryDefinitionFileName.split(".");
+        fileNameArray.splice(fileNameArray.length - 1, 0, "-interface.");
+        this.serviceCsar.interfaceDefinitionFileName = fileNameArray.join("");
+    }
+
+    private readServiceMetadata(entryDefinitionFileContent) {
+        const metadata = load(entryDefinitionFileContent).metadata;
+        this.setMetadata(metadata);
+    }
+
+    private readServiceSubstitutionNode(interfaceDefinitionFileContent) {
+        const nodeTypes = load(interfaceDefinitionFileContent).node_types;
+        let nodeType = Object.keys(nodeTypes).values().next().value;
+        this.serviceCsar.substitutionNodeType = nodeTypes[nodeType]["derived_from"];
+    }
+
+    private setMetadata = (metadata:object) : void => {
+        let extraServiceMetadata: Map<string, string> = new Map<string, string>();
+        this.serviceCsar.serviceMetadata.componentType = ComponentType.SERVICE;
+        this.serviceCsar.serviceMetadata.serviceType = "Service";
+        Object.keys(metadata).forEach(variable => {
+            switch(variable) {
+                case "description": {
+                    this.serviceCsar.serviceMetadata.description = metadata[variable];
+                    break;
+                }
+                case "name": {
+                    this.serviceCsar.serviceMetadata.name = metadata[variable];
+                    break;
+                }
+                case "model": {
+                    this.serviceCsar.serviceMetadata.model = metadata[variable];
+                    break;
+                }
+                case "category": {
+                    this.serviceCsar.serviceMetadata.selectedCategory = metadata[variable];
+                    break;
+                }
+                case "serviceRole": {
+                    this.serviceCsar.serviceMetadata.serviceRole = metadata[variable];
+                    break;
+                }
+                case "serviceFunction": {
+                    this.serviceCsar.serviceMetadata.serviceFunction = metadata[variable];
+                    break;
+                }
+                case "environmentContext": {
+                    if (metadata[variable] != null) {
+                        this.serviceCsar.serviceMetadata.environmentContext = metadata[variable];
+                    }
+                    break;
+                }
+                case "instantiationType": {
+                    if (metadata[variable] != null) {
+                        this.serviceCsar.serviceMetadata.instantiationType = metadata[variable];
+                    }
+                    break;
+                }
+                case "ecompGeneratedNaming": {
+                    if (metadata[variable] != null) {
+                        this.serviceCsar.serviceMetadata.ecompGeneratedNaming = metadata[variable] == "false" ? false : true;
+                    }
+                    break;
+                }
+                case "namingPolicy": {
+                    if (metadata["ecompGeneratedNaming"] != "false") {
+                        this.serviceCsar.serviceMetadata.namingPolicy = metadata[variable];
+                    }
+                    break;
+                }
+                default: {
+                    extraServiceMetadata.set(variable, metadata[variable])
+                    break;
+                }
+            }
+        });
+        this.serviceCsar.extraServiceMetadata = extraServiceMetadata;
+    }
+}
\ No newline at end of file
index 6b0d490..0057ba4 100644 (file)
@@ -30,7 +30,9 @@ import {
     instantiationType,
     ModalsHandler,
     ResourceType,
-    ValidationUtils
+    ValidationUtils,
+    FileUtils,
+    ServiceCsarReader
 } from "app/utils";
 import {EventListenerService, ProgressService} from "app/services";
 import {CacheService, ElementService, ModelService, ImportVSPService, OnboardingService} from "app/services-ng2";
@@ -121,6 +123,7 @@ export class GeneralViewModel {
         'VendorModelNumberValidationPattern',
         'CommentValidationPattern',
         'ValidationUtils',
+        'FileUtils',
         'sdcConfig',
         '$state',
         'ModalsHandler',
@@ -148,6 +151,7 @@ export class GeneralViewModel {
                 private VendorModelNumberValidationPattern:RegExp,
                 private CommentValidationPattern:RegExp,
                 private ValidationUtils:ValidationUtils,
+                private FileUtils: FileUtils,
                 private sdcConfig:IAppConfigurtaion,
                 private $state:ng.ui.IStateService,
                 private ModalsHandler:ModalsHandler,
@@ -276,9 +280,25 @@ export class GeneralViewModel {
         } else if(this.$scope.component.isService()){
             let service: Service = <Service>this.$scope.component;
             console.log(service.name + ": " + service.csarUUID);
-            if (service.importedFile) { // Component has imported file.
+            if (service.importedFile) {
                 this.$scope.isShowFileBrowse = true;
-                (<Service>this.$scope.component).serviceType = 'Service';
+                (<Service>this.$scope.component).ecompGeneratedNaming = true;
+                let blob = this.FileUtils.base64toBlob(service.importedFile.base64, "zip");
+                new ServiceCsarReader().read(blob).then((serviceCsar) => {
+                    serviceCsar.serviceMetadata.contactId = this.cacheService.get("user").userId;
+                    (<Service>this.$scope.component).setComponentMetadata(serviceCsar.serviceMetadata);
+                    (<Service>this.$scope.component).model = serviceCsar.serviceMetadata.model;
+                    this.$scope.onModelChange();
+                    this.$scope.componentCategories.selectedCategory = serviceCsar.serviceMetadata.selectedCategory;
+                    this.$scope.onCategoryChange();
+                    serviceCsar.extraServiceMetadata.forEach((value: string, key: string) => {
+                        if(this.getMetadataKey(key)) {
+                            (<Service>this.$scope.component).categorySpecificMetadata[key] = value;
+                        }
+                    });
+                    (<Service>this.$scope.component).derivedFromGenericType = serviceCsar.substitutionNodeType;
+                    this.$scope.onBaseTypeChange();
+                });
             }
             if (this.$scope.isEditMode() && service.serviceType == 'Service' && !service.csarUUID) {
                 this.$scope.isShowFileBrowse = true;
@@ -878,7 +898,9 @@ export class GeneralViewModel {
         if (this.$scope.isBaseTypeRequired) {
             const baseType = baseTypeResponseList.baseTypes[0];
             baseType.versions.reverse().forEach(version => this.$scope.baseTypeVersions.push(version));
-            this.$scope.component.derivedFromGenericType = baseType.toscaResourceName;
+            if(!this.$scope.component.derivedFromGenericType) {
+                this.$scope.component.derivedFromGenericType = baseType.toscaResourceName;
+            }
             this.$scope.component.derivedFromGenericVersion = this.$scope.baseTypeVersions[0];
             this.$scope.showBaseTypeVersions = true;
             return