From 363d9a6fea48bf6f34e4f1d4ecb37d33812c7626 Mon Sep 17 00:00:00 2001 From: JvD_Ericsson Date: Thu, 2 Jun 2022 10:46:40 +0100 Subject: Service Import - Read metadata from csar 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 Change-Id: I6f8428d9ed385335c05e7b994e622229ea00342b --- .../impl/ServiceImportBusinessLogic.java | 3 - .../be/components/impl/ServiceImportManager.java | 10 +- .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 1 + .../openecomp/sdc/be/model/UploadServiceInfo.java | 60 ++------- .../sdc/be/model/UploadServiceInfoTest.java | 7 -- catalog-ui/package.json | 4 +- catalog-ui/src/app/models.ts | 3 +- catalog-ui/src/app/models/service-csar.ts | 46 +++++++ catalog-ui/src/app/modules/utils.ts | 2 + catalog-ui/src/app/utils.ts | 1 + catalog-ui/src/app/utils/file-utils.ts | 18 +++ catalog-ui/src/app/utils/service-csar-reader.ts | 139 +++++++++++++++++++++ .../workspace/tabs/general/general-view-model.ts | 30 ++++- 13 files changed, 257 insertions(+), 67 deletions(-) create mode 100644 catalog-ui/src/app/models/service-csar.ts create mode 100644 catalog-ui/src/app/utils/service-csar-reader.ts diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index 9a8c181377..dd55ae8612 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -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"); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java index 7958efa3de..6f10aaea9c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java @@ -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) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 586b9f66b9..91d2bd5336 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -510,6 +510,7 @@ public class ToscaExportHandler { toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription()); List 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()); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadServiceInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadServiceInfo.java index 837791af22..1c12a3e463 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadServiceInfo.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadServiceInfo.java @@ -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 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 categorySpecificMetadata; private String derivedFromGenericType; private String derivedFromGenericVersion; - public UploadServiceInfo(String payloadData, String payloadName, String description, List tags, String invariantUUID, String UUID, - String type, String category, String subcategory, String resourceVendor, String resourceVendorRelease, - String serviceRole, String serviceEcompNaming, String ecompGeneratedNaming, String namingPolicy, - List artifactList, String contactId, String name, String resourceIconPath, String icon, - String vendorName, String vendorRelease, String serviceVendorModelNumber, String serviceType, String projectCode, String model, Map 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() { } diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadServiceInfoTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadServiceInfoTest.java index d8ddb75be4..8d0d0b9edc 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadServiceInfoTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadServiceInfoTest.java @@ -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; diff --git a/catalog-ui/package.json b/catalog-ui/package.json index 92e6ef4e01..27bba5889c 100644 --- a/catalog-ui/package.json +++ b/catalog-ui/package.json @@ -94,10 +94,10 @@ "@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", @@ -133,6 +133,8 @@ "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", diff --git a/catalog-ui/src/app/models.ts b/catalog-ui/src/app/models.ts index 78be1e55e4..7604b6797b 100644 --- a/catalog-ui/src/app/models.ts +++ b/catalog-ui/src/app/models.ts @@ -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 index 0000000000..39f8e05a4b --- /dev/null +++ b/catalog-ui/src/app/models/service-csar.ts @@ -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 = new Map(); + +} + +export class ToscaMeta { + + dataMap: Map = new Map(); + + getEntry(toscaMetaEntry: ToscaMetaEntry): string { + return this.dataMap.get(toscaMetaEntry.valueOf()); + } + +} diff --git a/catalog-ui/src/app/modules/utils.ts b/catalog-ui/src/app/modules/utils.ts index 7a57478c1c..a2fb6907ce 100644 --- a/catalog-ui/src/app/modules/utils.ts +++ b/catalog-ui/src/app/modules/utils.ts @@ -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); diff --git a/catalog-ui/src/app/utils.ts b/catalog-ui/src/app/utils.ts index 27c805a762..ccf9156553 100644 --- a/catalog-ui/src/app/utils.ts +++ b/catalog-ui/src/app/utils.ts @@ -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'; diff --git a/catalog-ui/src/app/utils/file-utils.ts b/catalog-ui/src/app/utils/file-utils.ts index d726736bd4..4b6f330354 100644 --- a/catalog-ui/src/app/utils/file-utils.ts +++ b/catalog-ui/src/app/utils/file-utils.ts @@ -66,6 +66,24 @@ export class FileUtils { "cancelable": true }); downloadLink.dispatchEvent(clickEvent); + } + public getEntryDefinitionFileNameFromCsarBlob = (csarBlob:Blob):Promise => { + 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 = 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 => { + 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 index 0000000000..73b77559e2 --- /dev/null +++ b/catalog-ui/src/app/utils/service-csar-reader.ts @@ -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 { + const jsZip = require("jszip"); + return new Promise((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 = toscaMetaFileContent.replace("\r", "").split("\n"); + for(let entity of fileEntities.filter(e => e)) { + let mapEntry:Array = 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 = 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 = new Map(); + 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 diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts index 6b0d49029a..0057ba4669 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts @@ -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 = this.$scope.component; console.log(service.name + ": " + service.csarUUID); - if (service.importedFile) { // Component has imported file. + if (service.importedFile) { this.$scope.isShowFileBrowse = true; - (this.$scope.component).serviceType = '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; + (this.$scope.component).setComponentMetadata(serviceCsar.serviceMetadata); + (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)) { + (this.$scope.component).categorySpecificMetadata[key] = value; + } + }); + (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 -- cgit 1.2.3-korg