diff options
author | JvD_Ericsson <jeff.van.dam@est.tech> | 2022-06-02 10:46:40 +0100 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2022-06-24 13:17:23 +0000 |
commit | 363d9a6fea48bf6f34e4f1d4ecb37d33812c7626 (patch) | |
tree | 6d5023023b0f93346ed40e62f6cf3f4bc23792b9 /catalog-ui | |
parent | 2dcfb0996a8345de5c8be73a5600ee995309664a (diff) |
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 <jeff.van.dam@est.tech>
Change-Id: I6f8428d9ed385335c05e7b994e622229ea00342b
Diffstat (limited to 'catalog-ui')
-rw-r--r-- | catalog-ui/package.json | 4 | ||||
-rw-r--r-- | catalog-ui/src/app/models.ts | 3 | ||||
-rw-r--r-- | catalog-ui/src/app/models/service-csar.ts | 46 | ||||
-rw-r--r-- | catalog-ui/src/app/modules/utils.ts | 2 | ||||
-rw-r--r-- | catalog-ui/src/app/utils.ts | 1 | ||||
-rw-r--r-- | catalog-ui/src/app/utils/file-utils.ts | 18 | ||||
-rw-r--r-- | catalog-ui/src/app/utils/service-csar-reader.ts | 139 | ||||
-rw-r--r-- | catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts | 30 |
8 files changed, 237 insertions, 6 deletions
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<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()); + } + +} 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<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 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<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 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 = <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 |