diff options
44 files changed, 1084 insertions, 405 deletions
diff --git a/cds-ui/client/src/app/app.component.html b/cds-ui/client/src/app/app.component.html index 88446ca84..945db342e 100644 --- a/cds-ui/client/src/app/app.component.html +++ b/cds-ui/client/src/app/app.component.html @@ -20,4 +20,10 @@ limitations under the License. --> +<mat-progress-bar mode="indeterminate" *ngIf="loaderStatus === true"></mat-progress-bar> +<div [ngClass]="{'overlay': loaderStatus === true}"> <router-outlet></router-outlet> +<div class="notification-container"> + <app-notification></app-notification> +</div> +</div> diff --git a/cds-ui/client/src/app/app.component.scss b/cds-ui/client/src/app/app.component.scss index bf7a36c2e..8dc7dd0af 100644 --- a/cds-ui/client/src/app/app.component.scss +++ b/cds-ui/client/src/app/app.component.scss @@ -32,4 +32,17 @@ limitations under the License. height: 200px; overflow: auto; border: 1px solid #555; + } + + .overlay { + opacity: 0.5; + pointer-events: none; + } + + .notification-container{ + position: fixed; + top: 1em; + z-index: 1; + right: 1em; + overflow: auto; }
\ No newline at end of file diff --git a/cds-ui/client/src/app/app.component.ts b/cds-ui/client/src/app/app.component.ts index 106417958..d6499cc35 100644 --- a/cds-ui/client/src/app/app.component.ts +++ b/cds-ui/client/src/app/app.component.ts @@ -23,13 +23,22 @@ import { Router } from '@angular/router'; import { Observable} from 'rxjs'; import { Store } from '@ngrx/store'; +import { LoaderService } from './common/core/services/loader.service'; + @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { + loaderStatus: boolean = false; + constructor(private router: Router, + private loaderService: LoaderService + ) { - constructor(private router: Router) { + this.loaderService.subject.subscribe(data=>{ + console.log(data); + this.loaderStatus = data; + }) } } diff --git a/cds-ui/client/src/app/common/core/core.module.ts b/cds-ui/client/src/app/common/core/core.module.ts index 807065ebc..7207178a9 100644 --- a/cds-ui/client/src/app/common/core/core.module.ts +++ b/cds-ui/client/src/app/common/core/core.module.ts @@ -30,6 +30,8 @@ import { appReducers } from './store/reducers/app.reducer'; import { BlueprintEffects } from './store/effects/blueprint.effects'; import { ResourcesEffects } from './store/effects/resources.effects'; import { ApiService } from './services/api.service'; +import { NotificationHandlerService } from './services/notification-handler.service'; +import { LoaderService } from './services/loader.service'; // import { BlueprintService } from './services/blueprint.service'; @NgModule({ @@ -38,10 +40,13 @@ import { ApiService } from './services/api.service'; imports: [ CommonModule, StoreModule.forRoot(appReducers), - EffectsModule.forRoot([BlueprintEffects,ResourcesEffects]), - StoreRouterConnectingModule.forRoot({stateKey: 'router'}), + EffectsModule.forRoot([BlueprintEffects, ResourcesEffects]), + StoreRouterConnectingModule.forRoot({ stateKey: 'router' }), HttpClientModule ], - providers : [ ApiService ] + providers: [ApiService, + NotificationHandlerService, + LoaderService + ] }) export class CoreModule { } diff --git a/cds-ui/client/src/app/common/core/services/notification-handler.service.ts b/cds-ui/client/src/app/common/core/services/notification-handler.service.ts index 296b71e53..b64f2fa0f 100644 --- a/cds-ui/client/src/app/common/core/services/notification-handler.service.ts +++ b/cds-ui/client/src/app/common/core/services/notification-handler.service.ts @@ -23,22 +23,22 @@ limitations under the License. import { Injectable } from '@angular/core'; -// import { NotificationService } from '../../shared/components/notification/notification.service'; +import { NotificationService } from '../../shared/components/notification/notification.service'; @Injectable() export class NotificationHandlerService { constructor( - // private alert: NotificationService + private alert: NotificationService ) { } success(message: string) { - // this.alert.success(message); + this.alert.success(message); } error(message: string) { - // this.alert.error(message); + this.alert.error(message); } info(message: string) { diff --git a/cds-ui/client/src/app/common/shared/shared.module.ts b/cds-ui/client/src/app/common/shared/shared.module.ts index b036f5967..39e4e433f 100644 --- a/cds-ui/client/src/app/common/shared/shared.module.ts +++ b/cds-ui/client/src/app/common/shared/shared.module.ts @@ -30,6 +30,8 @@ import { SearchPipe } from './pipes/search.pipe'; import { SearchDialog } from './components/search-dialog/search-dialog.component'; import { AppMaterialModule } from '../modules/app-material.module'; import { SortPipe } from './pipes/sort.pipe'; +import { NotificationComponent } from './components/notification/notification.component'; +import { NotificationService } from './components/notification/notification.service'; @NgModule({ declarations: [ @@ -37,14 +39,16 @@ import { SortPipe } from './pipes/sort.pipe'; CBAWizardComponent, SearchPipe, SearchDialog, - SortPipe + SortPipe, + NotificationComponent ], exports: [ HomeComponent, CBAWizardComponent, SearchPipe, SearchDialog, - SortPipe + SortPipe, + NotificationComponent ], imports: [ AppMaterialModule, @@ -68,6 +72,7 @@ import { SortPipe } from './pipes/sort.pipe'; MatStepperModule, RouterModule ], + providers: [NotificationService], entryComponents: [SearchDialog] }) export class SharedModule { }
\ No newline at end of file diff --git a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts index b982fa29f..0a3a8d2ef 100644 --- a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts +++ b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts @@ -39,6 +39,9 @@ import { ApiService } from 'src/app/common/core/services/api.service'; import { IMetaData } from 'src/app/common/core/store/models/metadata.model'; import { EditorService } from './editor.service'; import { SortPipe } from '../../../../common/shared/pipes/sort.pipe'; +import { NotificationHandlerService } from 'src/app/common/core/services/notification-handler.service'; +import { LoaderService } from 'src/app/common/core/services/loader.service'; + interface Node { name: string; @@ -107,6 +110,7 @@ export class EditorComponent implements OnInit { private tocsaMetadaData: any; metadata: IMetaData; uploadedFileName: string; + entryDefinition: string; private transformer = (node: Node, level: number) => { return { @@ -126,7 +130,10 @@ export class EditorComponent implements OnInit { artifactName: any; artifactVersion: any; - constructor(private store: Store<IAppState>, private apiservice: EditorService) { + constructor(private store: Store<IAppState>, private apiservice: EditorService, + private alertService: NotificationHandlerService, private loader: LoaderService + ) + { this.dataSource.data = TREE_DATA; this.bpState = this.store.select('blueprint'); // this.dataSource.data = TREE_DATA; @@ -162,6 +169,7 @@ export class EditorComponent implements OnInit { this.dataSource.data = this.filesTree; this.blueprintName = blueprintdata.name; this.uploadedFileName = blueprintdata.uploadedFileName; + this.entryDefinition = blueprintdata.entryDefinition; let blueprint = []; for (let key in this.blueprintdata) { if (this.blueprintdata.hasOwnProperty(key)) { @@ -206,10 +214,10 @@ export class EditorComponent implements OnInit { name: this.blueprintName, files: this.filesTree, filesData: this.filesData, - uploadedFileName: this.uploadedFileName + uploadedFileName: this.uploadedFileName, + entryDefinition: this.entryDefinition } this.store.dispatch(new SetBlueprintState(blueprintState)); - // console.log(this.text); } selectFileToView(file) { @@ -227,7 +235,6 @@ export class EditorComponent implements OnInit { } }) this.fileExtension = this.selectedFile.substr(this.selectedFile.lastIndexOf('.') + 1); - // console.log(this.fileExtension); this.setEditorMode(); } @@ -248,7 +255,10 @@ export class EditorComponent implements OnInit { console.log("processed"); } }); - window.alert('Blueprint enriched successfully'); + this.alertService.success('Blueprint enriched successfully'); + }, + (error)=>{ + this.alertService.error('Enrich:' + error.message); }); }); } @@ -264,8 +274,9 @@ export class EditorComponent implements OnInit { this.apiservice.post("/create-blueprint/", formData) .subscribe( data => { - // console.log(data); - window.alert('Success:' + JSON.stringify(data)); + this.alertService.success('Success:' + JSON.stringify(data)); + }, error=>{ + this.alertService.error('Save -' +error.message); }); }); @@ -280,8 +291,9 @@ export class EditorComponent implements OnInit { formData.append("file", blob); this.apiservice.deployPost("/deploy-blueprint/", formData) .subscribe(data => { - // console.log(data); - window.alert('Saved Successfully:' + JSON.stringify(data)); + this.alertService.success('Saved Successfully:' + JSON.stringify(data)); + }, error=>{ + this.alertService.error('Deploy - ' + error.message); }); }); @@ -295,8 +307,9 @@ export class EditorComponent implements OnInit { formData.append("file", blob); this.apiservice.post("/publish/", formData) .subscribe(data => { - // console.log(data); - window.alert('Published:' + JSON.stringify(data)); + this.alertService.success('Published:' + JSON.stringify(data)) + }, error=>{ + this.alertService.error('Publish - ' + error.message); }); }); @@ -580,6 +593,7 @@ export class EditorComponent implements OnInit { } saveEditedChanges() { + this.loader.showLoader(); this.filesData.forEach(fileNode => { if (this.selectedFile && fileNode.name.includes(this.blueprintName.trim()) && fileNode.name.includes(this.selectedFile.trim())) { fileNode.data = this.text; @@ -596,5 +610,6 @@ export class EditorComponent implements OnInit { } this.updateBlueprint(); + this.loader.hideLoader(); } } diff --git a/cds-ui/client/src/app/feature-modules/blueprint/select-template/metadata/metadata.component.ts b/cds-ui/client/src/app/feature-modules/blueprint/select-template/metadata/metadata.component.ts index 609aacae7..cefe0fd93 100644 --- a/cds-ui/client/src/app/feature-modules/blueprint/select-template/metadata/metadata.component.ts +++ b/cds-ui/client/src/app/feature-modules/blueprint/select-template/metadata/metadata.component.ts @@ -29,6 +29,7 @@ import { IBlueprintState } from 'src/app/common/core/store/models/blueprintState import { IBlueprint } from 'src/app/common/core/store/models/blueprint.model'; import { IMetaData } from '../../../../common/core/store/models/metadata.model'; import { SetBlueprintState } from 'src/app/common/core/store/actions/blueprint.action'; +import { LoaderService } from '../../../../common/core/services/loader.service'; @Component({ selector: 'app-metadata', @@ -48,7 +49,7 @@ export class MetadataComponent implements OnInit { uploadedFileName: string; entryDefinition: string; - constructor(private formBuilder: FormBuilder, private store: Store<IAppState>) { + constructor(private formBuilder: FormBuilder, private store: Store<IAppState>, private loader: LoaderService) { this.bpState = this.store.select('blueprint'); this.CBAMetadataForm = this.formBuilder.group({ template_author: ['', Validators.required], @@ -96,9 +97,16 @@ export class MetadataComponent implements OnInit { } UploadMetadata() { + this.loader.showLoader(); this.metadata = Object.assign({}, this.CBAMetadataForm.value); this.blueprint.metadata = this.metadata; - + if( this.blueprint && + this.blueprint['topology_template'] && + this.blueprint['topology_template'].workflows && + this.blueprint['topology_template'].workflows['resource-assignment'] && + this.blueprint['topology_template'].workflows['resource-assignment'].name) { + delete this.blueprint['topology_template'].workflows['resource-assignment'].name; + } this.filesData.forEach((fileNode) => { if (fileNode.name.includes(this.blueprintName) && fileNode.name == this.entryDefinition) { fileNode.data = JSON.stringify(this.blueprint, null, "\t"); @@ -113,6 +121,6 @@ export class MetadataComponent implements OnInit { entryDefinition: this.entryDefinition } this.store.dispatch(new SetBlueprintState(blueprintState)); + this.loader.hideLoader(); } - }
\ No newline at end of file diff --git a/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.component.ts b/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.component.ts index 92003c919..1221e8f2b 100644 --- a/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.component.ts +++ b/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.component.ts @@ -30,6 +30,7 @@ import { IAppState } from '../../../../common/core/store/state/app.state'; import { LoadBlueprintSuccess, SET_BLUEPRINT_STATE, SetBlueprintState } from '../../../../common/core/store/actions/blueprint.action'; import { json } from 'd3'; import { SortPipe } from '../../../../common/shared/pipes/sort.pipe'; +import { LoaderService } from '../../../../common/core/services/loader.service'; @Component({ selector: 'app-search-template', @@ -56,7 +57,7 @@ export class SearchTemplateComponent implements OnInit { private blueprintName: string; private entryDefinition: string; - constructor(private store: Store<IAppState>) { } + constructor(private store: Store<IAppState>, private loader: LoaderService) { } ngOnInit() { } @@ -68,7 +69,8 @@ export class SearchTemplateComponent implements OnInit { this.zipFile.files = {}; this.zipFile.loadAsync(this.file) .then((zip) => { - if(zip) { + if(zip) { + this.loader.showLoader(); this.buildFileViewData(zip); } }); @@ -157,8 +159,8 @@ export class SearchTemplateComponent implements OnInit { } } }); - }); - console.log('tree', tree); + }); + this.loader.hideLoader(); return tree; } diff --git a/cds-ui/client/src/app/feature-modules/resource-definition/resource-edit/resource-edit.component.ts b/cds-ui/client/src/app/feature-modules/resource-definition/resource-edit/resource-edit.component.ts index 4603c529f..2da1287ba 100644 --- a/cds-ui/client/src/app/feature-modules/resource-definition/resource-edit/resource-edit.component.ts +++ b/cds-ui/client/src/app/feature-modules/resource-definition/resource-edit/resource-edit.component.ts @@ -30,6 +30,7 @@ import { JsonEditorComponent, JsonEditorOptions } from 'ang-jsoneditor'; import { Observable } from 'rxjs'; import { A11yModule } from '@angular/cdk/a11y'; import { ResourceEditService } from './resource-edit.service'; +import { NotificationHandlerService } from 'src/app/common/core/services/notification-handler.service'; @Component({ selector: 'app-resource-edit', @@ -47,7 +48,7 @@ export class ResourceEditComponent implements OnInit { @ViewChild(JsonEditorComponent) editor: JsonEditorComponent; options = new JsonEditorOptions(); - constructor(private store: Store<IAppState>, private resourceEditService: ResourceEditService) { + constructor(private store: Store<IAppState>, private resourceEditService: ResourceEditService, private alertService: NotificationHandlerService) { this.rdState = this.store.select('resources'); this.options.mode = 'text'; this.options.modes = [ 'text', 'tree', 'view']; @@ -100,10 +101,10 @@ export class ResourceEditComponent implements OnInit { saveToBackend() { this.resourceEditService.saveResource(this.data) .subscribe(response=>{ - window.alert("save success"); + this.alertService.success("save success") }, error=>{ - window.alert('Error saving resources'); + this.alertService.error('Error saving resources'); }) } } diff --git a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json index ddbccac93..4945da889 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json +++ b/components/model-catalog/blueprint-model/test-blueprint/remote_scripts/Definitions/node_types.json @@ -8,9 +8,12 @@ "required" : false, "type" : "string" }, - "execute-command-logs" : { - "required" : false, - "type" : "string" + "execute-command-logs": { + "required": false, + "type": "list", + "entry_schema": { + "type": "string" + } } }, "capabilities" : { @@ -179,4 +182,4 @@ "derived_from" : "tosca.nodes.Root" } } -}
\ No newline at end of file +} diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json b/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json index e14b63e58..caab5f7ac 100644 --- a/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json +++ b/components/model-catalog/definition-type/starter-type/node_type/component-remote-python-executor.json @@ -8,7 +8,10 @@ }, "execute-command-logs": { "required": false, - "type": "string" + "type": "list", + "entry_schema": { + "type": "string" + } } }, "capabilities": { @@ -56,4 +59,4 @@ } }, "derived_from": "tosca.nodes.Component" -}
\ No newline at end of file +} diff --git a/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json b/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json index f437a79a9..1c81b7f6e 100644 --- a/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json +++ b/components/model-catalog/definition-type/starter-type/node_type/component-resource-resolution.json @@ -22,6 +22,12 @@ "required": false, "type": "string" }, + "occurrence": { + "description": "Number of time to perform the resolution.", + "required": false, + "default": 1, + "type": "integer" + }, "store-result": { "description": "Whether or not to store the output.", "required": false, diff --git a/components/model-catalog/proto-definition/proto/CommandExecutor.proto b/components/model-catalog/proto-definition/proto/CommandExecutor.proto index bc175dbc1..fd2d4f305 100644 --- a/components/model-catalog/proto-definition/proto/CommandExecutor.proto +++ b/components/model-catalog/proto-definition/proto/CommandExecutor.proto @@ -37,7 +37,7 @@ message Identifiers { message ExecutionOutput { string requestId = 1; - string response = 2; + repeated string response = 2; ResponseStatus status = 3; google.protobuf.Timestamp timestamp = 4; } diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties index e34c02423..a94fdf390 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties @@ -1,57 +1,75 @@ -#
-# Copyright � 2017-2018 AT&T Intellectual Property.
-#
-# Modifications Copyright © 2019 IBM, Bell Canada.
-#
-# 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.
-#
-#logging.level.web=DEBUG
-
-# Web server config
-server.port=8081
-
-blueprintsprocessor.grpcEnable=false
-blueprintsprocessor.httpPort=8081
-blueprintsprocessor.grpcPort=9111
-
-# Blueprint Processor File Execution and Handling Properties
-blueprintsprocessor.blueprintDeployPath=blueprints/deploy
-blueprintsprocessor.blueprintArchivePath=blueprints/archive
-blueprintsprocessor.blueprintWorkingPath=blueprints/work
-# Primary Database Configuration
-blueprintsprocessor.db.primary.url=jdbc:mysql://localhost:3306/sdnctl
-blueprintsprocessor.db.primary.username=sdnctl
-blueprintsprocessor.db.primary.password=sdnctl
-blueprintsprocessor.db.primary.driverClassName=org.mariadb.jdbc.Driver
-blueprintsprocessor.db.primary.hibernateHbm2ddlAuto=update
-blueprintsprocessor.db.primary.hibernateDDLAuto=none
-blueprintsprocessor.db.primary.hibernateNamingStrategy=org.hibernate.cfg.ImprovedNamingStrategy
-blueprintsprocessor.db.primary.hibernateDialect=org.hibernate.dialect.MySQL5InnoDBDialect
-
-# Python executor
-blueprints.processor.functions.python.executor.executionPath=./../../../components/scripts/python/ccsdk_blueprints
-blueprints.processor.functions.python.executor.modulePaths=./../../../components/scripts/python/ccsdk_blueprints
-
-# SDN-C's ODL Restconf Connection Details
-blueprintsprocessor.restconfEnabled=true
-blueprintsprocessor.restclient.sdncodl.type=basic-auth
-blueprintsprocessor.restclient.sdncodl.url=http://localhost:8282/
-blueprintsprocessor.restclient.sdncodl.username=admin
-blueprintsprocessor.restclient.sdncodl.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
-
-# Executor Options
-blueprintprocessor.resourceResolution.enabled=true
-blueprintprocessor.netconfExecutor.enabled=true
-blueprintprocessor.restConfExecutor.enabled=true
-blueprintsprocessor.cliExecutor.enabled=true
-blueprintprocessor.remoteScriptCommand.enabled=false
\ No newline at end of file +# +# Copyright � 2017-2018 AT&T Intellectual Property. +# +# Modifications Copyright © 2019 IBM, Bell Canada. +# +# 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. +# +#logging.level.web=DEBUG + +# Web server config +server.port=8081 + +blueprintsprocessor.grpcEnable=false +blueprintsprocessor.httpPort=8081 +blueprintsprocessor.grpcPort=9111 +###NOTE: for remote executor tests, need to enable grpc and it's properties. +###blueprintsprocessor.grpcEnable=false +# Assuming running locally +###blueprintsprocessor.grpcclient.remote-python.type=token-auth +###blueprintsprocessor.grpcclient.remote-python.host=localhost +###blueprintsprocessor.grpcclient.remote-python.port=50051 +###blueprintsprocessor.grpcclient.remote-python.token=Basic Y2NzZGthcHBzOmNjc2RrYXBwcw== + +# Blueprint Processor File Execution and Handling Properties +### use absolute paths if testing inside docker +### blueprintsprocessor.blueprintDeployPath=/opt/app/onap/blueprints/deploy +### blueprintsprocessor.blueprintArchivePath=/opt/app/onap/blueprints/archive +### blueprintsprocessor.blueprintWorkingPath=/opt/app/onap/blueprints/working +blueprintsprocessor.blueprintDeployPath=blueprints/deploy +blueprintsprocessor.blueprintArchivePath=blueprints/archive +blueprintsprocessor.blueprintWorkingPath=blueprints/work +# Primary Database Configuration +blueprintsprocessor.db.primary.url=jdbc:mysql://localhost:3306/sdnctl +blueprintsprocessor.db.primary.username=sdnctl +blueprintsprocessor.db.primary.password=sdnctl +blueprintsprocessor.db.primary.driverClassName=org.mariadb.jdbc.Driver +blueprintsprocessor.db.primary.hibernateHbm2ddlAuto=update +blueprintsprocessor.db.primary.hibernateDDLAuto=none +blueprintsprocessor.db.primary.hibernateNamingStrategy=org.hibernate.cfg.ImprovedNamingStrategy +blueprintsprocessor.db.primary.hibernateDialect=org.hibernate.dialect.MySQL5InnoDBDialect + +# Python executor +### If testing in docker, use the absolute paths as Docker view of filesystem will not respect relative paths. +### Don't forget to create directory /opt/app/onap and share it with Docker containers on your system. +###blueprints.processor.functions.python.executor.executionPath=/opt/app/onap/scripts/jython/ccsdk_blueprints +###blueprints.processor.functions.python.executor.modulePaths=/opt/app/onap/scripts/jython/ccsdk_blueprints,/opt/app/onap/scripts/jython/ccsdk_netconf,/opt/app/onap/scripts/jython/ccsdk_restconf + +blueprints.processor.functions.python.executor.executionPath=./../../../components/scripts/python/ccsdk_blueprints +blueprints.processor.functions.python.executor.modulePaths=./../../../components/scripts/python/ccsdk_blueprints + +# SDN-C's ODL Restconf Connection Details +blueprintsprocessor.restconfEnabled=true +blueprintsprocessor.restclient.sdncodl.type=basic-auth +blueprintsprocessor.restclient.sdncodl.url=http://localhost:8282/ +blueprintsprocessor.restclient.sdncodl.username=admin +blueprintsprocessor.restclient.sdncodl.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U + +# Executor Options +blueprintprocessor.resourceResolution.enabled=true +blueprintprocessor.netconfExecutor.enabled=true +blueprintprocessor.restConfExecutor.enabled=true +blueprintsprocessor.cliExecutor.enabled=true +### If enabling remote python executor, set this value to true +### blueprintprocessor.remoteScriptCommand.enabled=true +blueprintprocessor.remoteScriptCommand.enabled=false diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt index 1b84964e8..65d1c3eee 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt @@ -49,11 +49,6 @@ abstract class CliComponentFunction : AbstractScriptComponentFunction() { resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) } - fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - } - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt index be7451aa9..4cec6a2bf 100644 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt @@ -44,11 +44,6 @@ abstract class NetconfComponentFunction : AbstractScriptComponentFunction() { resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) } - fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - } - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) diff --git a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt index 4ef1cfbb3..2de22424e 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt @@ -22,6 +22,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServic import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.RemoteScriptExecutionService import org.onap.ccsdk.cds.controllerblueprints.core.* import org.onap.ccsdk.cds.controllerblueprints.core.data.OperationAssignment +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.slf4j.LoggerFactory import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.boot.autoconfigure.condition.ConditionalOnBean @@ -96,7 +97,7 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic ) val prepareEnvOutput = remoteScriptExecutionService.prepareEnv(prepareEnvInput) log.info("$ATTRIBUTE_PREPARE_ENV_LOG - ${prepareEnvOutput.response}") - setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, prepareEnvOutput.response.asJsonPrimitive()) + setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, JacksonUtils.jsonNodeFromObject(prepareEnvOutput.response)) setAttribute(ATTRIBUTE_EXEC_CMD_LOG, "N/A".asJsonPrimitive()) check(prepareEnvOutput.status == StatusType.SUCCESS) { "failed to get prepare remote env response status for requestId(${prepareEnvInput.requestId})" @@ -112,7 +113,7 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic properties = properties) val remoteExecutionOutput = remoteScriptExecutionService.executeCommand(remoteExecutionInput) log.info("$ATTRIBUTE_EXEC_CMD_LOG - ${remoteExecutionOutput.response}") - setAttribute(ATTRIBUTE_EXEC_CMD_LOG, remoteExecutionOutput.response.asJsonPrimitive()) + setAttribute(ATTRIBUTE_EXEC_CMD_LOG, JacksonUtils.jsonNodeFromObject(remoteExecutionOutput.response)) check(remoteExecutionOutput.status == StatusType.SUCCESS) { "failed to get prepare remote command response status for requestId(${remoteExecutionOutput.requestId})" } @@ -128,4 +129,4 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic bluePrintRuntimeService.getBluePrintError() .addError("Failed in ComponentJythonExecutor : ${runtimeException.message}") } -}
\ No newline at end of file +} diff --git a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt index 896d9a648..166d7b136 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt @@ -189,7 +189,7 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService { assertNotNull(prepareEnvInput.packages, "failed to get packages") val remoteScriptExecutionOutput = mockk<RemoteScriptExecutionOutput>() - every { remoteScriptExecutionOutput.response } returns "prepared successfully" + every { remoteScriptExecutionOutput.response } returns listOf("prepared successfully") every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS return remoteScriptExecutionOutput } @@ -198,7 +198,7 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService { assertEquals(remoteExecutionInput.requestId, "123456-1000", "failed to match request id") val remoteScriptExecutionOutput = mockk<RemoteScriptExecutionOutput>() - every { remoteScriptExecutionOutput.response } returns "processed successfully" + every { remoteScriptExecutionOutput.response } returns listOf("processed successfully") every { remoteScriptExecutionOutput.status } returns StatusType.SUCCESS return remoteScriptExecutionOutput } @@ -206,4 +206,4 @@ class MockRemoteScriptExecutionService : RemoteScriptExecutionService { override suspend fun close() { } -}
\ No newline at end of file +} diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt index 8191db74e..7c2c11c06 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt @@ -17,10 +17,11 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution +import com.fasterxml.jackson.databind.node.JsonNodeFactory import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode +import org.onap.ccsdk.cds.controllerblueprints.core.asObjectNode import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.context.annotation.Scope @@ -33,28 +34,41 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re override suspend fun processNB(executionRequest: ExecutionServiceInput) { - val properties: MutableMap<String, Any> = mutableMapOf() + val occurrence = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE) + val key = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY) + val storeResult = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) + val resourceId = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID) + val resourceType = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE) - try { - val key = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY) - val storeResult = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) - properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY] = key.asText() - properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult.asBoolean() - } catch (e: BluePrintProcessorException) { - // NoOp - these property aren't mandatory, so don't fail the process if not provided. - } + + val properties: MutableMap<String, Any> = mutableMapOf() + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult?.asBoolean() ?: false + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY] = key?.asText() ?: "" + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId?.asText() ?: "" + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType?.asText() ?: "" val artifactPrefixNamesNode = getOperationInput(ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES) val artifactPrefixNames = JacksonUtils.getListFromJsonNode(artifactPrefixNamesNode, String::class.java) - val resolvedParamContents = resourceResolutionService.resolveResources(bluePrintRuntimeService, - nodeTemplateName, - artifactPrefixNames, - properties) + val jsonResponse = JsonNodeFactory.instance.objectNode() + for (j in 1..occurrence.asInt()) { + + val response = resourceResolutionService.resolveResources(bluePrintRuntimeService, + nodeTemplateName, + artifactPrefixNames, + properties) + + // provide indexed result in output if we have multiple resolution + if (occurrence.asInt() != 1) { + jsonResponse.set(key?.asText() + "-" + j, response.asJsonNode()) + } else { + jsonResponse.setAll(response.asObjectNode()) + } + } // Set Output Attributes bluePrintRuntimeService.setNodeTemplateAttributeValue(nodeTemplateName, - ResourceResolutionConstants.OUTPUT_ASSIGNMENT_PARAMS, resolvedParamContents.asJsonNode()) + ResourceResolutionConstants.OUTPUT_ASSIGNMENT_PARAMS, jsonResponse) } override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt index d605c8828..929e9e8df 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt @@ -24,8 +24,11 @@ object ResourceResolutionConstants { const val INPUT_ARTIFACT_PREFIX_NAMES = "artifact-prefix-names" const val OUTPUT_ASSIGNMENT_PARAMS = "assignment-params" const val FILE_NAME_RESOURCE_DEFINITION_TYPES = "resources_definition_types.json" - const val RESOURCE_RESOLUTION_INPUT_KEY = "resolution-key"; - const val RESOURCE_RESOLUTION_INPUT_STORE_RESULT = "store-result"; + const val RESOURCE_RESOLUTION_INPUT_KEY = "resolution-key" + const val RESOURCE_RESOLUTION_INPUT_STORE_RESULT = "store-result" + const val RESOURCE_RESOLUTION_INPUT_OCCURRENCE = "occurrence" + const val RESOURCE_RESOLUTION_INPUT_RESOURCE_ID = "resource-id" + const val RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE = "resource-type" }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt index fe5906220..b1482934f 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt @@ -20,6 +20,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResultService import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils @@ -48,27 +49,26 @@ interface ResourceResolutionService { suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, artifactPrefix: String, properties: Map<String, Any>): String - suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactMapping: String, artifactTemplate: String?): String - suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>, resourceDefinitions: MutableMap<String, ResourceDefinition>, resourceAssignments: MutableList<ResourceAssignment>, - identifierName: String) + artifactPrefix: String, + properties: Map<String, Any>) } @Service(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) open class ResourceResolutionServiceImpl(private var applicationContext: ApplicationContext, private var resolutionResultService: ResourceResolutionResultService, - private var blueprintTemplateService: BluePrintTemplateService) : - ResourceResolutionService { + private var blueprintTemplateService: BluePrintTemplateService, + private var resourceResolutionDBService: ResourceResolutionDBService) : + ResourceResolutionService { private val log = LoggerFactory.getLogger(ResourceResolutionService::class.java) override fun registeredResourceSources(): List<String> { return applicationContext.getBeanNamesForType(ResourceAssignmentProcessor::class.java) - .filter { it.startsWith(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } - .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } + .filter { it.startsWith(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } + .map { it.substringAfter(ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR) } } override suspend fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>, @@ -78,12 +78,13 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica } override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactNames: List<String>, properties: Map<String, Any>): MutableMap<String, String> { + artifactNames: List<String>, + properties: Map<String, Any>): MutableMap<String, String> { val resolvedParams: MutableMap<String, String> = hashMapOf() artifactNames.forEach { artifactName -> val resolvedContent = resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactName, properties) + artifactName, properties) resolvedParams[artifactName] = resolvedContent } return resolvedParams @@ -97,52 +98,38 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica // Resource Assignment Artifact Definition Name val artifactMapping = "$artifactPrefix-mapping" - val result = resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - - if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) - && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) { - resolutionResultService.write(properties, result, bluePrintRuntimeService, artifactPrefix) - log.info("resolution saved into database successfully : ($properties)") - } - - return result - } - - - override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String, - artifactMapping: String, artifactTemplate: String?): String { - val resolvedContent: String log.info("Resolving resource for template artifact($artifactTemplate) with resource assignment artifact($artifactMapping)") - val identifierName = artifactTemplate ?: "no-template" - val resourceAssignmentContent = - bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping) + bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactMapping) val resourceAssignments: MutableList<ResourceAssignment> = - JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java) - as? MutableList<ResourceAssignment> - ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions") + JacksonUtils.getListFromJson(resourceAssignmentContent, ResourceAssignment::class.java) + as? MutableList<ResourceAssignment> + ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions") // Get the Resource Dictionary Name val resourceDefinitions: MutableMap<String, ResourceDefinition> = ResourceAssignmentUtils - .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath) + .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath) // Resolve resources - resolveResourceAssignments(bluePrintRuntimeService, resourceDefinitions, resourceAssignments, identifierName) + resolveResourceAssignments(bluePrintRuntimeService, + resourceDefinitions, + resourceAssignments, + artifactPrefix, + properties) val resolvedParamJsonContent = - ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList()) + ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList()) - // Check Template is there - if (artifactTemplate != null) { - resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName, - artifactTemplate, resolvedParamJsonContent) + resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName, + artifactTemplate, resolvedParamJsonContent) - } else { - resolvedContent = resolvedParamJsonContent + if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) + && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) { + resolutionResultService.write(properties, resolvedContent, bluePrintRuntimeService, artifactPrefix) + log.info("template resolution saved into database successfully : ($properties)") } return resolvedContent @@ -156,44 +143,55 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica override suspend fun resolveResourceAssignments(blueprintRuntimeService: BluePrintRuntimeService<*>, resourceDefinitions: MutableMap<String, ResourceDefinition>, resourceAssignments: MutableList<ResourceAssignment>, - identifierName: String) { + artifactPrefix: String, + properties: Map<String, Any>) { val bulkSequenced = BulkResourceSequencingUtils.process(resourceAssignments) val resourceAssignmentRuntimeService = - ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, identifierName) + ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, artifactPrefix) coroutineScope { bulkSequenced.forEach { batchResourceAssignments -> // Execute Non Dependent Assignments in parallel ( ie asynchronously ) val deferred = batchResourceAssignments.filter { it.name != "*" && it.name != "start" } - .map { resourceAssignment -> - async { - val dictionaryName = resourceAssignment.dictionaryName - val dictionarySource = resourceAssignment.dictionarySource - /** - * Get the Processor name - */ - val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions) - - val resourceAssignmentProcessor = - applicationContext.getBean(processorName) as? ResourceAssignmentProcessor - ?: throw BluePrintProcessorException("failed to get resource processor ($processorName) " + - "for resource assignment(${resourceAssignment.name})") - try { - // Set BluePrint Runtime Service - resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService - // Set Resource Dictionaries - resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions - // Invoke Apply Method - resourceAssignmentProcessor.applyNB(resourceAssignment) - // Set errors from RA - blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError()) - } catch (e: RuntimeException) { - log.error("Fail in processing ${resourceAssignment.name}", e) - throw BluePrintProcessorException(e) + .map { resourceAssignment -> + async { + val dictionaryName = resourceAssignment.dictionaryName + val dictionarySource = resourceAssignment.dictionarySource + /** + * Get the Processor name + */ + val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions) + + val resourceAssignmentProcessor = + applicationContext.getBean(processorName) as? ResourceAssignmentProcessor + ?: throw BluePrintProcessorException("failed to get resource processor ($processorName) " + + "for resource assignment(${resourceAssignment.name})") + try { + // Set BluePrint Runtime Service + resourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService + // Set Resource Dictionaries + resourceAssignmentProcessor.resourceDictionaries = resourceDefinitions + // Invoke Apply Method + resourceAssignmentProcessor.applyNB(resourceAssignment) + + if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT) + && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) { + resourceResolutionDBService.write(properties, + blueprintRuntimeService, + artifactPrefix, + resourceAssignment) + log.info("resolution saved into database successfully : ($resourceAssignment)") } + + // Set errors from RA + blueprintRuntimeService.setBluePrintError(resourceAssignmentRuntimeService.getBluePrintError()) + } catch (e: RuntimeException) { + log.error("Fail in processing ${resourceAssignment.name}", e) + throw BluePrintProcessorException(e) } } + } log.debug("Resolving (${deferred.size})resources parallel.") deferred.awaitAll() } @@ -217,10 +215,10 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica } else -> { val resourceDefinition = resourceDefinitions[dictionaryName] - ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dictionaryName") + ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dictionaryName") val resourceSource = resourceDefinition.sources[dictionarySource] - ?: throw BluePrintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)") + ?: throw BluePrintProcessorException("couldn't get resource definition $dictionaryName source($dictionarySource)") ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR.plus(resourceSource.type) } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt new file mode 100644 index 000000000..767a1feaf --- /dev/null +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt @@ -0,0 +1,91 @@ +/* + * Copyright © 2019 Bell Canada + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db + +import com.fasterxml.jackson.annotation.JsonFormat +import com.fasterxml.jackson.annotation.JsonProperty +import org.hibernate.annotations.Proxy +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.io.Serializable +import java.util.* +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.EntityListeners +import javax.persistence.Id +import javax.persistence.Lob +import javax.persistence.Table +import javax.persistence.Temporal +import javax.persistence.TemporalType + +@EntityListeners(AuditingEntityListener::class) +@Entity +@Table(name = "RESOURCE_RESOLUTION") +@Proxy(lazy = false) +class ResourceResolution : Serializable { + + @Id + @Column(name = "resource_resolution_id") + var id: String? = null + + @Column(name = "resolution_key", nullable = false) + var resolutionKey: String? = null + + @Column(name = "resource_type", nullable = false) + var resourceType: String? = null + + @Column(name = "resource_id", nullable = false) + var resourceId: String? = null + + @Column(name = "blueprint_name", nullable = false) + var blueprintName: String? = null + + @Column(name = "blueprint_version", nullable = false) + var blueprintVersion: String? = null + + @Column(name = "artifact_name", nullable = false) + var artifactName: String? = null + + @Column(name = "status", nullable = false) + var status: String? = null + + @Column(name = "name", nullable = false) + var name: String? = null + + @Column(name = "dictionary_vname", nullable = false) + var dictionaryName: String? = null + + @Column(name = "dictionary_status", nullable = false) + var dictionarySource: String? = null + + @Column(name = "dictionary_version", nullable = false) + var dictionaryVersion: Int = 0 + + @Lob + @Column(name = "value", nullable = false) + var value: String? = null + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + @LastModifiedDate + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "creation_date") + var createdDate = Date() + + companion object { + private const val serialVersionUID = 1L + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt new file mode 100644 index 000000000..81239be30 --- /dev/null +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.slf4j.LoggerFactory +import org.springframework.dao.DataIntegrityViolationException +import org.springframework.stereotype.Service +import java.util.* + +@Service +class ResourceResolutionDBService(private val resourceResolutionRepository: ResourceResolutionRepository) { + + private val log = LoggerFactory.getLogger(ResourceResolutionDBService::class.toString()) + + suspend fun readValue(blueprintName: String, + blueprintVersion: String, + artifactPrefix: String, + resolutionKey: String, + name: String): ResourceResolution = withContext(Dispatchers.IO) { + + resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName( + resolutionKey, + blueprintName, + blueprintVersion, + artifactPrefix, + name) + } + + suspend fun readWithResolutionKey(blueprintName: String, + blueprintVersion: String, + artifactPrefix: String, + resolutionKey: String): List<ResourceResolution> = withContext(Dispatchers.IO) { + + resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName( + resolutionKey, + blueprintName, + blueprintVersion, + artifactPrefix) + } + + suspend fun readWithResourceIdAndResourceType(blueprintName: String, + blueprintVersion: String, + resourceId: String, + resourceType: String): List<ResourceResolution> = withContext(Dispatchers.IO) { + + resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType( + blueprintName, + blueprintVersion, + resourceId, + resourceType) + } + + suspend fun write(properties: Map<String, Any>, + bluePrintRuntimeService: BluePrintRuntimeService<*>, + artifactPrefix: String, + resourceAssignment: ResourceAssignment): ResourceResolution = withContext(Dispatchers.IO) { + + val metadata = bluePrintRuntimeService.bluePrintContext().metadata!! + + val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!! + val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!! + val resolutionKey = + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY].toString() + val resourceType = + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE].toString() + val resourceId = + properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID].toString() + + write(blueprintName, + blueprintVersion, + resolutionKey, + resourceId, + resourceType, + artifactPrefix, + resourceAssignment) + } + + suspend fun write(blueprintName: String, + blueprintVersion: String, + resolutionKey: String, + resourceId: String, + resourceType: String, + artifactPrefix: String, + resourceAssignment: ResourceAssignment): ResourceResolution = withContext(Dispatchers.IO) { + + val resourceResolution = ResourceResolution() + resourceResolution.id = UUID.randomUUID().toString() + resourceResolution.artifactName = artifactPrefix + resourceResolution.blueprintVersion = blueprintVersion + resourceResolution.blueprintName = blueprintName + resourceResolution.resolutionKey = resolutionKey + resourceResolution.resourceType = resourceType + resourceResolution.resourceId = resourceId + resourceResolution.value = JacksonUtils.getValue(resourceAssignment.property?.value!!).toString() + resourceResolution.name = resourceAssignment.name + resourceResolution.dictionaryName = resourceAssignment.dictionaryName + resourceResolution.dictionaryVersion = resourceAssignment.version + resourceResolution.dictionarySource = resourceAssignment.dictionarySource + resourceResolution.status = resourceAssignment.status + + try { + resourceResolutionRepository.saveAndFlush(resourceResolution) + } catch (ex: Exception) { + throw BluePrintException("Failed to store resource resolution result.", ex) + } + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt index 72bb4a384..d2cbf8411 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt @@ -17,9 +17,21 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db import org.springframework.data.jpa.repository.JpaRepository -interface ResourceResolutionRepository : JpaRepository<ResourceResolutionResult, String> { +interface ResourceResolutionRepository : JpaRepository<ResourceResolution, String> { - fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(key: String, blueprintName: String?, - blueprintVersion: String?, - artifactName: String): ResourceResolutionResult -} + fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName(key: String, + blueprintName: String?, + blueprintVersion: String?, + artifactName: String, + name: String): ResourceResolution + + fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(resolutionKey: String, + blueprintName: String, + blueprintVersion: String, + artifactPrefix: String): List<ResourceResolution> + + fun findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(blueprintName: String, + blueprintVersion: String, + resourceId: String, + resourceType: String): List<ResourceResolution> +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt new file mode 100644 index 000000000..efc130a84 --- /dev/null +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db + +import org.springframework.data.jpa.repository.JpaRepository + +interface ResourceResolutionResultRepository : JpaRepository<ResourceResolutionResult, String> { + + fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(key: String, blueprintName: String?, + blueprintVersion: String?, + artifactName: String): ResourceResolutionResult +} diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt index 3cb9dec63..ebb34ba4a 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt @@ -27,7 +27,7 @@ import org.springframework.stereotype.Service import java.util.* @Service -class ResourceResolutionResultService(private val resourceResolutionRepository: ResourceResolutionRepository) { +class ResourceResolutionResultService(private val resourceResolutionRepository: ResourceResolutionResultRepository) { suspend fun read(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactPrefix: String, resolutionKey: String): String = withContext(Dispatchers.IO) { diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt index 7eefe954d..6cf1c0be7 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt @@ -19,6 +19,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.pro import com.fasterxml.jackson.databind.node.ArrayNode import com.fasterxml.jackson.databind.node.MissingNode +import com.fasterxml.jackson.databind.node.NullNode import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.RestResourceSource import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils @@ -54,20 +55,20 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS // Check if It has Input val value = getFromInput(resourceAssignment) - if (value == null || value is MissingNode) { + if (value == null || value is MissingNode || value is NullNode) { val dName = resourceAssignment.dictionaryName val dSource = resourceAssignment.dictionarySource val resourceDefinition = resourceDictionaries[dName] - ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dName") + ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dName") val resourceSource = resourceDefinition.sources[dSource] - ?: throw BluePrintProcessorException("couldn't get resource definition $dName source($dSource)") + ?: throw BluePrintProcessorException("couldn't get resource definition $dName source($dSource)") val resourceSourceProperties = - checkNotNull(resourceSource.properties) { "failed to get source properties for $dName " } + checkNotNull(resourceSource.properties) { "failed to get source properties for $dName " } val sourceProperties = - JacksonUtils.getInstanceFromMap(resourceSourceProperties, RestResourceSource::class.java) + JacksonUtils.getInstanceFromMap(resourceSourceProperties, RestResourceSource::class.java) val path = nullToEmpty(sourceProperties.path) val inputKeyMapping = @@ -77,7 +78,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS // Resolving content Variables val payload = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.payload), resolvedInputKeyMapping) val urlPath = - resolveFromInputKeyMapping(checkNotNull(sourceProperties.urlPath), resolvedInputKeyMapping) + resolveFromInputKeyMapping(checkNotNull(sourceProperties.urlPath), resolvedInputKeyMapping) val verb = resolveFromInputKeyMapping(nullToEmpty(sourceProperties.verb), resolvedInputKeyMapping) logger.info("$dSource dictionary information : ($urlPath), ($inputKeyMapping), (${sourceProperties.outputKeyMapping})") @@ -90,7 +91,8 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS if (responseStatusCode in 200..299 && !responseBody.isBlank()) { populateResource(resourceAssignment, sourceProperties, responseBody, path) } else { - val errMsg = "Failed to get $dSource result for dictionary name ($dName) using urlPath ($urlPath) response_code: ($responseStatusCode)" + val errMsg = + "Failed to get $dSource result for dictionary name ($dName) using urlPath ($urlPath) response_code: ($responseStatusCode)" logger.warn(errMsg) throw BluePrintProcessorException(errMsg) } @@ -100,12 +102,12 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS } catch (e: Exception) { ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, e.message) throw BluePrintProcessorException("Failed in template key ($resourceAssignment) assignments with: ${e.message}", - e) + e) } } fun blueprintWebClientService(resourceAssignment: ResourceAssignment, - restResourceSource: RestResourceSource): BlueprintWebClientService { + restResourceSource: RestResourceSource): BlueprintWebClientService { return if (isNotEmpty(restResourceSource.endpointSelector)) { val restPropertiesJson = raRuntimeService.resolveDSLExpression(restResourceSource.endpointSelector!!) blueprintRestLibPropertyService.blueprintWebClientService(restPropertiesJson) @@ -143,7 +145,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS entrySchemaType = checkNotEmpty(resourceAssignment.property?.entrySchema?.type) { "Entry schema is not defined for dictionary ($dName) info" } - val arrayNode = responseNode as ArrayNode + val arrayNode = JacksonUtils.objectMapper.createArrayNode() if (entrySchemaType !in BluePrintTypes.validPrimitiveTypes()) { @@ -155,13 +157,13 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS outputKeyMapping.map { val responseKeyValue = responseSingleJsonNode.get(it.key) val propertyTypeForDataType = ResourceAssignmentUtils - .getPropertyType(raRuntimeService, entrySchemaType, it.key) + .getPropertyType(raRuntimeService, entrySchemaType, it.key) logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), " + "type ({$propertyTypeForDataType})") JacksonUtils.populateJsonNodeValues(it.value, - responseKeyValue, propertyTypeForDataType, arrayChildNode) + responseKeyValue, propertyTypeForDataType, arrayChildNode) } arrayNode.add(arrayChildNode) } @@ -179,7 +181,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS outputKeyMapping.map { val responseKeyValue = responseNode.get(it.key) val propertyTypeForDataType = ResourceAssignmentUtils - .getPropertyType(raRuntimeService, entrySchemaType, it.key) + .getPropertyType(raRuntimeService, entrySchemaType, it.key) logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), type ({$propertyTypeForDataType})") JacksonUtils.populateJsonNodeValues(it.value, responseKeyValue, propertyTypeForDataType, objectNode) diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt index 9c2a100bc..4a3e75cde 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt @@ -128,15 +128,10 @@ class ResourceResolutionServiceTest { val artifactPrefix = "another" - // Templating Artifact Definition Name - val artifactTemplate = "$artifactPrefix-template" - // Resource Assignment Artifact Definition Name - val artifactMapping = "$artifactPrefix-mapping" - // Prepare Inputs PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService, executionServiceInput.payload, "resource-assignment") - resourceResolutionService.resolveResources(bluePrintRuntimeService, "resource-assignment", artifactMapping, artifactTemplate) + resourceResolutionService.resolveResources(bluePrintRuntimeService, "resource-assignment", artifactPrefix, mapOf<String, String>()) } } } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessorTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessorTest.kt index 2e91eb93f..242739067 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessorTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessorTest.kt @@ -15,8 +15,11 @@ */ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.TextNode +import io.mockk.every +import io.mockk.spyk import kotlinx.coroutines.runBlocking -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService @@ -28,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner -import kotlin.test.assertNotNull +import kotlin.test.assertTrue @RunWith(SpringRunner::class) @ContextConfiguration(classes = [InputResourceResolutionProcessor::class]) @@ -38,20 +41,21 @@ class InputResourceResolutionProcessorTest { @Autowired lateinit var inputResourceResolutionProcessor: InputResourceResolutionProcessor - @Ignore @Test - fun `test input resource resolution`() { + fun `InputResourceResolutionProcessor should be able to resolve a value for an input parameter`() { runBlocking { + val bluePrintContext = BluePrintMetadataUtils.getBluePrintContext( "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration") - val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService("1234", bluePrintContext) + val resourceAssignmentRuntimeService = spyk(ResourceAssignmentRuntimeService("1234", bluePrintContext)) - inputResourceResolutionProcessor.raRuntimeService = resourceAssignmentRuntimeService - inputResourceResolutionProcessor.resourceDictionaries = ResourceAssignmentUtils - .resourceDefinitions(bluePrintContext.rootPath) + // mocking input for resource resolution + val textNode: JsonNode = TextNode("any value") + every {resourceAssignmentRuntimeService.getInputValue("rr-name") } returns textNode - //TODO ("Mock the input Values") + inputResourceResolutionProcessor.raRuntimeService = resourceAssignmentRuntimeService + inputResourceResolutionProcessor.resourceDictionaries = ResourceAssignmentUtils.resourceDefinitions(bluePrintContext.rootPath) val resourceAssignment = ResourceAssignment().apply { name = "rr-name" @@ -62,9 +66,8 @@ class InputResourceResolutionProcessorTest { } } - val processorName = inputResourceResolutionProcessor.applyNB(resourceAssignment) - assertNotNull(processorName, "couldn't get Input resource assignment processor name") - println(processorName) + val operationOutcome = inputResourceResolutionProcessor.applyNB(resourceAssignment) + assertTrue(operationOutcome, "An error occurred while trying to test the InputResourceResolutionProcessor") } } -}
\ No newline at end of file +} diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt index 3895c39c8..b2064cb54 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt @@ -47,11 +47,6 @@ abstract class RestconfComponentFunction : AbstractScriptComponentFunction() { return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) } - fun resolveAndGenerateMessage(artifactMapping: String, artifactTemplate: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactMapping, artifactTemplate) - } - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt index 83254cecc..2f9ea4a25 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintRemoteProcessorData.kt @@ -37,7 +37,7 @@ data class RemoteScriptExecutionInput(var requestId: String, data class RemoteScriptExecutionOutput(var requestId: String, - var response: String, + var response: List<String>, var status: StatusType = StatusType.SUCCESS, var timestamp: Date = Date()) @@ -46,4 +46,4 @@ data class PrepareRemoteEnvInput(var requestId: String, var remoteIdentifier: RemoteIdentifier? = null, var packages: JsonNode, var timeOut: Long = 120, - var properties: MutableMap<String, JsonNode> = hashMapOf())
\ No newline at end of file + var properties: MutableMap<String, JsonNode> = hashMapOf()) diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionController.java b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionController.java deleted file mode 100644 index 3e94d79ee..000000000 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionController.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * 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. - */ - -package org.onap.ccsdk.cds.blueprintsprocessor.resource.api; - -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -/** - * ResourceResolutionController - * - * @author Brinda Santh Date : 8/13/2018 - */ - -@RestController -@RequestMapping("/api/v1/resource") -public class ResourceResolutionController { - - private ResourceResolutionService resourceResolutionService; - - public ResourceResolutionController(ResourceResolutionService resourceResolutionService) { - this.resourceResolutionService = resourceResolutionService; - } - - @RequestMapping(path = "/ping", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public @ResponseBody - Mono<String> ping() { - return Mono.just("Success"); - } -} diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt index 69641c628..7f8f7da79 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt @@ -48,7 +48,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> { - log.error(e.message) + log.error(e.message, e) val errorCode = ErrorCode.BLUEPRINT_PATH_MISSING val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) @@ -56,7 +56,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> { - log.error(e.message) + log.error(e.message, e) val errorCode = ErrorCode.INVALID_REQUEST_FORMAT val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) @@ -64,7 +64,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> { - log.error(e.message) + log.error(e.message, e) var errorCode = ErrorCode.RESOURCE_NOT_FOUND val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) @@ -72,7 +72,7 @@ open class ResolutionResultsServiceExceptionHandler { @ExceptionHandler fun ResolutionResultsServiceExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorMessage> { - log.error(e.message) + log.error(e.message, e) var errorCode = ErrorCode.RESOURCE_NOT_FOUND val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) @@ -86,6 +86,12 @@ open class ResolutionResultsServiceExceptionHandler { val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg) return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)) } + + @ExceptionHandler + fun ResolutionResultsServiceExceptionHandler(e: ResourceException): ResponseEntity<ErrorMessage> { + log.error(e.message, e) + return ResponseEntity(ErrorMessage(e.message, e.code, debugMsg), HttpStatus.resolve(e.code)) + } } @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt new file mode 100644 index 000000000..40aa1a3e6 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt @@ -0,0 +1,84 @@ +/* + * Copyright © 2019 Bell Canada + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +import io.swagger.annotations.ApiOperation +import kotlinx.coroutines.runBlocking +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolution +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/api/v1/resources") +open class ResourceController(private var resourceResolutionDBService: ResourceResolutionDBService) { + + @RequestMapping(path = ["/ping"], method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ResponseBody + fun ping(): String = runBlocking { + "Success" + } + + @RequestMapping(path = [""], + method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation(value = "Fetch all resource values associated to a resolution key. ", + notes = "Retrieve a stored resource value using the blueprint metadata, artifact name and the resolution-key.", + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun getAllFromResolutionKeyOrFromResourceTypeAndId(@RequestParam(value = "bpName", required = true) bpName: String, + @RequestParam(value = "bpVersion", required = true) bpVersion: String, + @RequestParam(value = "artifactName", required = false, defaultValue = "") artifactName: String, + @RequestParam(value = "resolutionKey", required = false, defaultValue = "") resolutionKey: String, + @RequestParam(value = "resourceType", required = false, defaultValue = "") resourceType: String, + @RequestParam(value = "resourceId", required = false, defaultValue = "") resourceId: String) + : ResponseEntity<List<ResourceResolution>> = runBlocking { + + if ((resolutionKey.isNotEmpty() || artifactName.isNotEmpty()) && (resourceId.isNotEmpty() || resourceType.isNotEmpty())) { + throw ResourceException("Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") + } else if (resolutionKey.isNotEmpty() && artifactName.isNotEmpty()) { + ResponseEntity.ok() + .body(resourceResolutionDBService.readWithResolutionKey(bpName, bpVersion, artifactName, resolutionKey)) + } else if (resourceType.isNotEmpty() && resourceId.isNotEmpty()){ + ResponseEntity.ok() + .body(resourceResolutionDBService.readWithResourceIdAndResourceType(bpName, bpVersion, resourceId, resourceType)) + } else { + throw ResourceException("Missing param. Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") + } + } + + @RequestMapping(path = ["/resource"], + method = [RequestMethod.GET], + produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation(value = "Fetch a resource value using resolution key.", + notes = "Retrieve a stored resource value using the blueprint metadata, artifact name, resolution-key along with the name of the resource value to retrieve.", + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + @PreAuthorize("hasRole('USER')") + fun getOneFromResolutionKey(@RequestParam(value = "bpName", required = true) bpName: String, + @RequestParam(value = "bpVersion", required = true) bpVersion: String, + @RequestParam(value = "artifactName", required = true) artifactName: String, + @RequestParam(value = "resolutionKey", required = true) resolutionKey: String, + @RequestParam(value = "name", required = true) name: String) + : ResponseEntity<ResourceResolution> = runBlocking { + + ResponseEntity.ok() + .body(resourceResolutionDBService.readValue(bpName, bpVersion, artifactName, resolutionKey, name)) + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt new file mode 100644 index 000000000..6815c05ef --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 Bell Canada. + * + * 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. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +class ResourceException(message: String) : RuntimeException(message) { + var code: Int = 404 +} + diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt new file mode 100644 index 000000000..fa8bf4459 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt @@ -0,0 +1,251 @@ +/* + * Copyright © 2019 Bell Canada. + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api + +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.module.kotlin.readValue +import kotlinx.coroutines.runBlocking +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolution +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition +import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.python.jline.console.internal.ConsoleRunner.property +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.security.SecurityProperties +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest +import org.springframework.context.annotation.ComponentScan +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit4.SpringRunner +import org.springframework.test.web.reactive.server.WebTestClient +import org.springframework.web.reactive.function.BodyInserters +import java.util.function.Consumer +import kotlin.test.BeforeTest +import org.h2.value.DataType.readValue +import java.util.* +import org.h2.value.DataType.readValue +import org.python.bouncycastle.asn1.x500.style.RFC4519Style.l +import org.h2.value.DataType.readValue +import java.lang.reflect.Array + + +@RunWith(SpringRunner::class) +@WebFluxTest +@ContextConfiguration(classes = [ResourceController::class, ResourceResolutionDBService::class, SecurityProperties::class]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@TestPropertySource(locations = ["classpath:application-test.properties"]) +class ResourceControllerTest { + + private val log = LoggerFactory.getLogger(ResourceControllerTest::class.toString()) + + @Autowired + lateinit var resourceResolutionDBService: ResourceResolutionDBService + @Autowired + lateinit var webTestClient: WebTestClient + + val blueprintName = "baseconfiguration" + val blueprintVersion = "1.0.0" + val templatePrefix = "activate" + + @Test + fun `ping return Success`() { + runBlocking { + webTestClient.get().uri("/api/v1/resources/ping") + .exchange() + .expectStatus().isOk + .expectBody() + .equals("Success") + } + } + + @Test + fun getAllFromResolutionKeyTest() { + + val resolutionKey = "1" + val ra1 = createRA("bob") + val ra2 = createRA("dylan") + + runBlocking { + + store(ra1, resKey = resolutionKey) + store(ra2, resKey = resolutionKey) + + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=$resolutionKey") + .exchange() + .expectStatus().isOk + .expectBody() + .consumeWith { + val json = String(it.responseBody!!) + val typeFactory = JacksonUtils.objectMapper.typeFactory + val list: List<ResourceResolution> = JacksonUtils.objectMapper.readValue(json, + typeFactory.constructCollectionType(List::class.java, ResourceResolution::class.java)) + Assert.assertEquals(2, list.size) + assertEqual(ra1, list[0]) + assertEqual(ra1, list[0]) + } + } + } + + @Test + fun getAllFromFromResourceTypeAndIdTest() { + + val resourceId = "1" + val resourceType = "ServiceInstance" + val ra1 = createRA("bob") + val ra2 = createRA("dylan") + + runBlocking { + + store(ra1, resId = resourceId, resType = resourceType) + store(ra2, resId = resourceId, resType = resourceType) + + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion&resourceType=$resourceType&resourceId=$resourceId") + .exchange() + .expectStatus().isOk + .expectBody() + .consumeWith { + val json = String(it.responseBody!!) + val typeFactory = JacksonUtils.objectMapper.typeFactory + val list: List<ResourceResolution> = JacksonUtils.objectMapper.readValue(json, + typeFactory.constructCollectionType(List::class.java, ResourceResolution::class.java)) + Assert.assertEquals(2, list.size) + assertEqual(ra1, list[0]) + assertEqual(ra1, list[0]) + } + } + } + + + @Test + fun getAllFromMissingParamTest() { + runBlocking { + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + .consumeWith { + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorMessage::class.java) + Assert.assertEquals("Missing param. Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.", + r.message) + } + } + } + + @Test + fun getAllFromWrongInputTest() { + runBlocking { + webTestClient + .get() + .uri("/api/v1/resources?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=test&resourceId=1") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + .consumeWith { + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorMessage::class.java) + Assert.assertEquals("Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.", + r.message) + } + } + } + + @Test + fun getOneFromResolutionKeyTest() { + val resolutionKey = "3" + val ra = createRA("joe") + runBlocking { + store(ra, resKey = resolutionKey) + } + runBlocking { + webTestClient.get() + .uri("/api/v1/resources/resource?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=$resolutionKey&name=joe") + .exchange() + .expectStatus().isOk + .expectBody() + .consumeWith { + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ResourceResolution::class.java) + assertEqual(ra, r) + } + } + } + + @Test + fun getOneFromResolutionKey404Test() { + val resolutionKey = "3" + runBlocking { + webTestClient.get() + .uri("/api/v1/resources/resource?bpName=$blueprintName&bpVersion=$blueprintVersion&artifactName=$templatePrefix&resolutionKey=$resolutionKey&name=doesntexist") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + } + } + + private suspend fun store(resourceAssignment: ResourceAssignment, resKey: String = "", resId: String = "", + resType: String = "") { + resourceResolutionDBService.write(blueprintName, + blueprintVersion, + resKey, + resId, + resType, + templatePrefix, + resourceAssignment) + } + + private fun createRA(prefix: String): ResourceAssignment { + val property = PropertyDefinition() + property.value = "value$prefix".asJsonPrimitive() + + val resourceAssignment = ResourceAssignment() + resourceAssignment.name = prefix + resourceAssignment.dictionaryName = "dd$prefix" + resourceAssignment.dictionarySource = "source$prefix" + resourceAssignment.version = 2 + resourceAssignment.status = "SUCCESS" + resourceAssignment.property = property + return resourceAssignment + } + + private fun assertEqual(resourceAssignment: ResourceAssignment, resourceResolution: ResourceResolution) { + Assert.assertEquals(JacksonUtils.getValue(resourceAssignment.property?.value!!).toString(), + resourceResolution.value) + Assert.assertEquals(resourceAssignment.status, resourceResolution.status) + Assert.assertEquals(resourceAssignment.dictionarySource, resourceResolution.dictionarySource) + Assert.assertEquals(resourceAssignment.dictionaryName, resourceResolution.dictionaryName) + Assert.assertEquals(resourceAssignment.version, resourceResolution.dictionaryVersion) + Assert.assertEquals(resourceAssignment.name, resourceResolution.name) + Assert.assertEquals(blueprintVersion, resourceResolution.blueprintVersion) + Assert.assertEquals(blueprintName, resourceResolution.blueprintName) + + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt index 7aee95e11..3af57a22b 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt @@ -148,9 +148,9 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi fun ExecutionOutput.asJavaData(): RemoteScriptExecutionOutput { return RemoteScriptExecutionOutput( requestId = this.requestId, - response = this.response, + response = this.responseList, status = StatusType.valueOf(this.status.name) ) } -}
\ No newline at end of file +} diff --git a/ms/command-executor/src/main/python/command_executor_handler.py b/ms/command-executor/src/main/python/command_executor_handler.py index a5951fdb3..365c00188 100644 --- a/ms/command-executor/src/main/python/command_executor_handler.py +++ b/ms/command-executor/src/main/python/command_executor_handler.py @@ -19,6 +19,7 @@ from subprocess import CalledProcessError, PIPE import logging import os import subprocess +import sys import virtualenv import venv import utils @@ -37,10 +38,7 @@ class CommandExecutorHandler(): self.installed = self.venv_home + '/.installed' def is_installed(self): - if os.path.exists(self.installed): - return True - else: - return False + return os.path.exists(self.installed) def prepare_env(self, request, results): if not self.is_installed(): @@ -78,7 +76,16 @@ class CommandExecutorHandler(): self.logger.info("Command: {}".format(cmd)) try: - results.append(os.popen(cmd).read()) + with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + shell=True, bufsize=1, universal_newlines=True) as newProcess: + while True: + output = newProcess.stdout.readline() + if output == '' and newProcess.poll() is not None: + break + if output: + self.logger.info(output.strip()) + results.append(output.strip()) + rc = newProcess.poll() except Exception as e: self.logger.info("{} - Failed to execute command. Error: {}".format(self.blueprint_id, e)) results.append(e) diff --git a/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py b/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py index 3afeb35fc..478e00959 100644 --- a/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py +++ b/ms/command-executor/src/main/python/proto/CommandExecutor_pb2.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: CommandExecutor.proto @@ -22,7 +23,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( package='org.onap.ccsdk.cds.controllerblueprints.command.api', syntax='proto3', serialized_options=_b('P\001'), - serialized_pb=_b('\n\x15\x43ommandExecutor.proto\x12\x33org.onap.ccsdk.cds.controllerblueprints.command.api\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8f\x02\n\x0e\x45xecutionInput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x15\n\rcorrelationId\x18\x02 \x01(\t\x12U\n\x0bidentifiers\x18\x03 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xd0\x02\n\x0fPrepareEnvInput\x12U\n\x0bidentifiers\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x11\n\trequestId\x18\x02 \x01(\t\x12\x15\n\rcorrelationId\x18\x03 \x01(\t\x12O\n\x08packages\x18\x04 \x03(\x0b\x32=.org.onap.ccsdk.cds.controllerblueprints.command.api.Packages\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\">\n\x0bIdentifiers\x12\x15\n\rblueprintName\x18\x01 \x01(\t\x12\x18\n\x10\x62lueprintVersion\x18\x02 \x01(\t\"\xba\x01\n\x0f\x45xecutionOutput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\x12S\n\x06status\x18\x03 \x01(\x0e\x32\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ResponseStatus\x12-\n\ttimestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"k\n\x08Packages\x12N\n\x04type\x18\x01 \x01(\x0e\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.PackageType\x12\x0f\n\x07package\x18\x02 \x03(\t**\n\x0eResponseStatus\x12\x0b\n\x07SUCCESS\x10\x00\x12\x0b\n\x07\x46\x41ILURE\x10\x01**\n\x0bPackageType\x12\x07\n\x03pip\x10\x00\x12\x12\n\x0e\x61nsible_galaxy\x10\x01\x32\xd1\x02\n\x16\x43ommandExecutorService\x12\x98\x01\n\nprepareEnv\x12\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput\x12\x9b\x01\n\x0e\x65xecuteCommand\x12\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutputB\x02P\x01\x62\x06proto3') + serialized_pb=_b('\n\x15\x43ommandExecutor.proto\x12\x33org.onap.ccsdk.cds.controllerblueprints.command.api\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8f\x02\n\x0e\x45xecutionInput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x15\n\rcorrelationId\x18\x02 \x01(\t\x12U\n\x0bidentifiers\x18\x03 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xd0\x02\n\x0fPrepareEnvInput\x12U\n\x0bidentifiers\x18\x01 \x01(\x0b\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.Identifiers\x12\x11\n\trequestId\x18\x02 \x01(\t\x12\x15\n\rcorrelationId\x18\x03 \x01(\t\x12O\n\x08packages\x18\x04 \x03(\x0b\x32=.org.onap.ccsdk.cds.controllerblueprints.command.api.Packages\x12\x0f\n\x07timeOut\x18\x05 \x01(\x05\x12+\n\nproperties\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12-\n\ttimestamp\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\">\n\x0bIdentifiers\x12\x15\n\rblueprintName\x18\x01 \x01(\t\x12\x18\n\x10\x62lueprintVersion\x18\x02 \x01(\t\"\xba\x01\n\x0f\x45xecutionOutput\x12\x11\n\trequestId\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x03(\t\x12S\n\x06status\x18\x03 \x01(\x0e\x32\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ResponseStatus\x12-\n\ttimestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"k\n\x08Packages\x12N\n\x04type\x18\x01 \x01(\x0e\x32@.org.onap.ccsdk.cds.controllerblueprints.command.api.PackageType\x12\x0f\n\x07package\x18\x02 \x03(\t**\n\x0eResponseStatus\x12\x0b\n\x07SUCCESS\x10\x00\x12\x0b\n\x07\x46\x41ILURE\x10\x01**\n\x0bPackageType\x12\x07\n\x03pip\x10\x00\x12\x12\n\x0e\x61nsible_galaxy\x10\x01\x32\xd1\x02\n\x16\x43ommandExecutorService\x12\x98\x01\n\nprepareEnv\x12\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.PrepareEnvInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput\x12\x9b\x01\n\x0e\x65xecuteCommand\x12\x43.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionInput\x1a\x44.org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutputB\x02P\x01\x62\x06proto3') , dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) @@ -279,8 +280,8 @@ _EXECUTIONOUTPUT = _descriptor.Descriptor( serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='response', full_name='org.onap.ccsdk.cds.controllerblueprints.command.api.ExecutionOutput.response', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + number=2, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), diff --git a/ms/command-executor/src/main/python/utils.py b/ms/command-executor/src/main/python/utils.py index 6260997f3..dc5d0089f 100644 --- a/ms/command-executor/src/main/python/utils.py +++ b/ms/command-executor/src/main/python/utils.py @@ -17,7 +17,6 @@ from google.protobuf.timestamp_pb2 import Timestamp import proto.CommandExecutor_pb2 as CommandExecutor_pb2 - def get_blueprint_id(request): blueprint_name = request.identifiers.blueprintName blueprint_version = request.identifiers.blueprintVersion @@ -32,6 +31,5 @@ def build_response(request, results, is_success=True): timestamp = Timestamp() timestamp.GetCurrentTime() - - return CommandExecutor_pb2.ExecutionOutput(requestId=request.requestId, response="".join(results), status=status, + return CommandExecutor_pb2.ExecutionOutput(requestId=request.requestId, response=results, status=status, timestamp=timestamp) diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeService.kt index 0819ed74b..b48e446d3 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeService.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeService.kt @@ -91,7 +91,8 @@ interface BluePrintRuntimeService<T> { fun setInputValue(propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode) - fun setWorkflowInputValue(workflowName: String, propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode) + fun setWorkflowInputValue(workflowName: String, propertyName: String, propertyDefinition: PropertyDefinition, + value: JsonNode) fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode) @@ -133,7 +134,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl : BluePrintRuntimeService<MutableMap<String, JsonNode>> { @Transient - private val log= LoggerFactory.getLogger(BluePrintRuntimeService::class.toString()) + private val log = LoggerFactory.getLogger(BluePrintRuntimeService::class.toString()) private var store: MutableMap<String, JsonNode> = hashMapOf() @@ -144,7 +145,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl * Load Blueprint Environments Properties */ val absoluteEnvFilePath = bluePrintContext.rootPath.plus(File.separator) - .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR) + .plus(BluePrintConstants.TOSCA_ENVIRONMENTS_DIR) loadEnvironments(BluePrintConstants.PROPERTY_BPP, absoluteEnvFilePath) } @@ -213,7 +214,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl override fun loadEnvironments(type: String, fileName: String) { BluePrintMetadataUtils.environmentFileProperties(fileName).forEach { key, value -> setNodeTemplateAttributeValue(type, key.toString(), value.toString() - .asJsonPrimitive()) + .asJsonPrimitive()) } } @@ -227,7 +228,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf() - propertyDefinitions.forEach { nodeTypePropertyName, nodeTypeProperty -> + propertyDefinitions.forEach { (nodeTypePropertyName, nodeTypeProperty) -> // Get the Express or Value for the Node Template val propertyAssignment: JsonNode? = propertyAssignments[nodeTypePropertyName] @@ -236,13 +237,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl // Resolve the Expressing val propertyAssignmentExpression = PropertyAssignmentService(this) resolvedValue = propertyAssignmentExpression.resolveAssignmentExpression(nodeTemplateName, - nodeTypePropertyName, propertyAssignment) - } else { - // Assign default value to the Operation - nodeTypeProperty.defaultValue?.let { - resolvedValue = nodeTypeProperty.defaultValue!! - } + nodeTypePropertyName, propertyAssignment) } + + // Set default value if null + if (resolvedValue is NullNode) { + nodeTypeProperty.defaultValue?.let { resolvedValue = nodeTypeProperty.defaultValue!! } + } + // Set for Return of method propertyAssignmentValue[nodeTypePropertyName] = resolvedValue } @@ -258,7 +260,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl val expression = propertyDefinition.value ?: propertyDefinition.defaultValue if (expression != null) { propertyAssignmentValue[propertyName] = propertyAssignmentExpression.resolveAssignmentExpression(name, - propertyName, expression) + propertyName, expression) } } return propertyAssignmentValue @@ -272,7 +274,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl propertyAssignments.forEach { propertyName, propertyExpression -> val propertyAssignmentExpression = PropertyAssignmentService(this) propertyAssignmentValue[propertyName] = propertyAssignmentExpression.resolveAssignmentExpression(name, - propertyName, propertyExpression) + propertyName, propertyExpression) } return propertyAssignmentValue } @@ -286,13 +288,13 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl // Get the Node Type Definitions val nodeTypePropertieDefinitions: MutableMap<String, PropertyDefinition> = bluePrintContext - .nodeTypeChainedProperties(nodeTemplate.type)!! + .nodeTypeChainedProperties(nodeTemplate.type)!! /** * Resolve the NodeTemplate Property Assignment Values. */ return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypePropertieDefinitions, - propertyAssignments) + propertyAssignments) } override fun resolveNodeTemplateCapabilityProperties(nodeTemplateName: String, capabilityName: String): @@ -304,13 +306,13 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl val propertyAssignments = nodeTemplate.capabilities?.get(capabilityName)?.properties ?: hashMapOf() val propertyDefinitions = bluePrintContext.nodeTemplateNodeType(nodeTemplateName) - .capabilities?.get(capabilityName)?.properties ?: hashMapOf() + .capabilities?.get(capabilityName)?.properties ?: hashMapOf() /** * Resolve the Capability Property Assignment Values. */ return resolveNodeTemplatePropertyAssignments(nodeTemplateName, propertyDefinitions, - propertyAssignments) + propertyAssignments) } override fun resolveNodeTemplateInterfaceOperationInputs(nodeTemplateName: String, @@ -320,14 +322,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl "($interfaceName), operationName($operationName)") val propertyAssignments: MutableMap<String, JsonNode> = - bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName) - ?: hashMapOf() + bluePrintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName) + ?: hashMapOf() val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type val nodeTypeInterfaceOperationInputs: MutableMap<String, PropertyDefinition> = - bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName) - ?: hashMapOf() + bluePrintContext.nodeTypeInterfaceOperationInputs(nodeTypeName, interfaceName, operationName) + ?: hashMapOf() log.info("input definition for node template ($nodeTemplateName), values ($propertyAssignments)") @@ -335,7 +337,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl * Resolve the Property Input Assignment Values. */ return resolveNodeTemplatePropertyAssignments(nodeTemplateName, nodeTypeInterfaceOperationInputs, - propertyAssignments) + propertyAssignments) } @@ -347,19 +349,19 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl "($interfaceName), operationName($operationName)") val propertyAssignments: MutableMap<String, JsonNode> = - bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName) - ?: hashMapOf() + bluePrintContext.nodeTemplateInterfaceOperationOutputs(nodeTemplateName, interfaceName, operationName) + ?: hashMapOf() val nodeTypeName = bluePrintContext.nodeTemplateByName(nodeTemplateName).type val nodeTypeInterfaceOperationOutputs: MutableMap<String, PropertyDefinition> = - bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName) - ?: hashMapOf() + bluePrintContext.nodeTypeInterfaceOperationOutputs(nodeTypeName, interfaceName, operationName) + ?: hashMapOf() /** * Resolve the Property Output Assignment Values. */ val propertyAssignmentValue = resolveNodeTemplatePropertyAssignments(nodeTemplateName, - nodeTypeInterfaceOperationOutputs, propertyAssignments) + nodeTypeInterfaceOperationOutputs, propertyAssignments) // Store operation output values into context propertyAssignmentValue.forEach { key, value -> @@ -369,17 +371,19 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl } override fun resolveNodeTemplateArtifact(nodeTemplateName: String, artifactName: String): String { - val artifactDefinition: ArtifactDefinition = resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) + val artifactDefinition: ArtifactDefinition = + resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) val propertyAssignmentExpression = PropertyAssignmentService(this) return propertyAssignmentExpression.artifactContent(artifactDefinition) } - override fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, artifactName: String): ArtifactDefinition { + override fun resolveNodeTemplateArtifactDefinition(nodeTemplateName: String, + artifactName: String): ArtifactDefinition { val nodeTemplate = bluePrintContext.nodeTemplateByName(nodeTemplateName) return nodeTemplate.artifacts?.get(artifactName) - ?: throw BluePrintProcessorException("failed to get artifat definition($artifactName) from the node " + - "template") + ?: throw BluePrintProcessorException("failed to get artifat definition($artifactName) from the node " + + "template") } @@ -390,14 +394,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl override fun resolveDSLExpression(dslPropertyName: String): JsonNode { val propertyAssignments = bluePrintContext.dslPropertiesByName(dslPropertyName) return if (BluePrintExpressionService.checkContainsExpression(propertyAssignments) - && propertyAssignments is ObjectNode) { + && propertyAssignments is ObjectNode) { val rootKeyMap = propertyAssignments.rootFieldsToMap() val propertyAssignmentValue: MutableMap<String, JsonNode> = hashMapOf() rootKeyMap.forEach { propertyName, propertyValue -> val propertyAssignmentExpression = PropertyAssignmentService(this) propertyAssignmentValue[propertyName] = propertyAssignmentExpression - .resolveAssignmentExpression("DSL", propertyName, propertyValue) + .resolveAssignmentExpression("DSL", propertyName, propertyValue) } propertyAssignmentValue.asJsonNode() } else { @@ -407,7 +411,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl override fun setInputValue(propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode) { val path = StringBuilder(BluePrintConstants.PATH_INPUTS) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() log.trace("setting input path ({}), values ({})", path, value) put(path, value) } @@ -415,41 +419,42 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl override fun setWorkflowInputValue(workflowName: String, propertyName: String, propertyDefinition: PropertyDefinition, value: JsonNode) { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_WORKFLOWS) - .append(BluePrintConstants.PATH_DIVIDER).append(workflowName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(workflowName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() put(path, value) } override fun setNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String, value: JsonNode) { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() put(path, value) } override fun setNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String, value: JsonNode) { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES) - .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES) + .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString() put(path, value) } - override fun setNodeTemplateOperationPropertyValue(nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String, + override fun setNodeTemplateOperationPropertyValue(nodeTemplateName: String, interfaceName: String, + operationName: String, propertyName: String, value: JsonNode) { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) - .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) - .append(BluePrintConstants.PATH_DIVIDER).append(operationName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) + .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) + .append(BluePrintConstants.PATH_DIVIDER).append(operationName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() log.trace("setting operation property path ({}), values ({})", path, value) put(path, value) } @@ -458,14 +463,14 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl operationName: String, propertyName: String, value: JsonNode) { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) - .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) - .append(BluePrintConstants.PATH_DIVIDER).append(operationName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) + .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) + .append(BluePrintConstants.PATH_DIVIDER).append(operationName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INPUTS) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() put(path, value) } @@ -473,51 +478,51 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl operationName: String, propertyName: String, value: JsonNode) { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) - .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) - .append(BluePrintConstants.PATH_DIVIDER).append(operationName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) + .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) + .append(BluePrintConstants.PATH_DIVIDER).append(operationName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() put(path, value) } override fun getInputValue(propertyName: String): JsonNode { val path = StringBuilder(BluePrintConstants.PATH_INPUTS) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() return getJsonNode(path) } override fun getNodeTemplateOperationOutputValue(nodeTemplateName: String, interfaceName: String, operationName: String, propertyName: String): JsonNode { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) - .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) - .append(BluePrintConstants.PATH_DIVIDER).append(operationName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_INTERFACES) + .append(BluePrintConstants.PATH_DIVIDER).append(interfaceName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OPERATIONS) + .append(BluePrintConstants.PATH_DIVIDER).append(operationName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_OUTPUTS) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() return getJsonNode(path) } override fun getNodeTemplatePropertyValue(nodeTemplateName: String, propertyName: String): JsonNode { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) - .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_PROPERTIES) + .append(BluePrintConstants.PATH_DIVIDER).append(propertyName).toString() return getJsonNode(path) } override fun getNodeTemplateAttributeValue(nodeTemplateName: String, attributeName: String): JsonNode { val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES) - .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES) + .append(BluePrintConstants.PATH_DIVIDER).append(attributeName).toString() return getJsonNode(path) } @@ -525,7 +530,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl log.info("assignInputs from input JSON ({})", jsonNode.toString()) bluePrintContext.inputs()?.forEach { propertyName, property -> val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName) - ?: NullNode.getInstance() + ?: NullNode.getInstance() setInputValue(propertyName, property, valueNode) } } @@ -538,7 +543,7 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl bluePrintContext.workflowByName(workflowName).inputs?.forEach { propertyName, property -> if (propertyName != dynamicInputPropertiesName) { val valueNode: JsonNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName) - ?: NullNode.getInstance() + ?: NullNode.getInstance() setInputValue(propertyName, property, valueNode) } } @@ -546,8 +551,10 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl val workflowDynamicInputs: JsonNode? = jsonNode.get(dynamicInputPropertiesName) workflowDynamicInputs?.let { - bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")?.properties?.forEach { propertyName, property -> - val valueNode: JsonNode = workflowDynamicInputs.at(BluePrintConstants.PATH_DIVIDER + propertyName).returnNullIfMissing() + bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName") + ?.properties?.forEach { propertyName, property -> + val valueNode: JsonNode = + workflowDynamicInputs.at(BluePrintConstants.PATH_DIVIDER + propertyName).returnNullIfMissing() ?: property.defaultValue ?: NullNode.getInstance() setInputValue(propertyName, property, valueNode) @@ -566,9 +573,9 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl val jsonNode: ObjectNode = jacksonObjectMapper().createObjectNode() val path: String = StringBuilder(BluePrintConstants.PATH_NODE_TEMPLATES) - .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) - .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES) - .append(BluePrintConstants.PATH_DIVIDER).toString() + .append(BluePrintConstants.PATH_DIVIDER).append(nodeTemplateName) + .append(BluePrintConstants.PATH_DIVIDER).append(BluePrintConstants.PATH_ATTRIBUTES) + .append(BluePrintConstants.PATH_DIVIDER).toString() store.keys.filter { it.startsWith(path) }.map { diff --git a/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt index 63c8ad74e..de6d4d8e4 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintTemplateServiceTest.kt @@ -29,7 +29,6 @@ import kotlin.test.BeforeTest import kotlin.test.assertEquals import kotlin.test.assertNotNull -@RunWith(SpringRunner::class) class BluePrintTemplateServiceTest { lateinit var blueprintRuntime: BluePrintRuntimeService<*> diff --git a/ms/controllerblueprints/modules/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt b/ms/controllerblueprints/modules/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt index 80ce72e14..a2f1e23e7 100644 --- a/ms/controllerblueprints/modules/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt +++ b/ms/controllerblueprints/modules/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt @@ -79,12 +79,14 @@ open class ResourceAssignment { override fun toString(): String { return StringBuilder() - .append("[") - .append("name=", name) - .append(", dictionaryName=", dictionaryName) - .append(", dictionarySource=", dictionarySource) - .append("]") - .toString() + .append("[") + .append("name=", name) + .append(", status=", status) + .append(", property=", property?.value ?: "") + .append(", dictionaryName=", dictionaryName) + .append(", dictionarySource=", dictionarySource) + .append("]") + .toString() } } |