Merge "Created media folders for ResourceDictionary"
authorDan Timoney <dtimoney@att.com>
Mon, 8 Jul 2019 19:19:27 +0000 (19:19 +0000)
committerGerrit Code Review <gerrit@onap.org>
Mon, 8 Jul 2019 19:19:27 +0000 (19:19 +0000)
106 files changed:
cds-ui/client/src/app/common/shared/components/home/home.component.html
cds-ui/client/src/app/common/shared/components/home/home.component.scss
cds-ui/client/src/app/feature-modules/blueprint/blueprint.module.ts
cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.html [new file with mode: 0644]
cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.scss [new file with mode: 0644]
cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.spec.ts [new file with mode: 0644]
cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.ts [new file with mode: 0644]
cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.component.html
cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.component.ts
cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.service.spec.ts [new file with mode: 0644]
cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.service.ts [new file with mode: 0644]
cds-ui/client/src/app/feature-modules/blueprint/select-template/select-template.component.html
cds-ui/client/src/app/feature-modules/blueprint/select-template/select-template.component.ts
cds-ui/client/src/app/feature-modules/blueprint/select-template/template-options/template-options.component.html
cds-ui/server/config/app-config.ts [deleted file]
cds-ui/server/index.js
cds-ui/server/package.json
cds-ui/server/pom.xml
cds-ui/server/server.cert [new file with mode: 0644]
cds-ui/server/server.key [new file with mode: 0644]
cds-ui/server/src/clients/blueprint-management-service-grpc-client.ts [new file with mode: 0644]
cds-ui/server/src/config/app-config.ts [new file with mode: 0644]
cds-ui/server/src/controllers/blueprint-rest.controller.ts
cds-ui/server/src/datasources/blueprint.datasource-template.ts
cds-ui/server/src/datasources/resource-dictionary.datasource-template.ts
cds-ui/server/src/sequence.ts
components/model-catalog/blueprint-model/test-blueprint/baseconfiguration/Definitions/node_types.json
ms/blueprintsprocessor/application/pom.xml
ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java
ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/SwaggerConfig.java
ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/WebConfig.java
ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
ms/blueprintsprocessor/application/src/main/resources/application.properties
ms/blueprintsprocessor/application/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplicationTest.java
ms/blueprintsprocessor/application/src/test/resources/application.properties
ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt [deleted file]
ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt
ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ScriptComponentExtensions.kt [moved from ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceResolutionControllerTest.java with 79% similarity]
ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts
ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt
ms/blueprintsprocessor/functions/netconf-executor/pom.xml
ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt
ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ScriptComponentExtensions.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt
ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponent.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ScriptComponentExtensions.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolution.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionRepository.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultRepository.kt [deleted file]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResultService.kt [deleted file]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolution.kt [moved from ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionResult.kt with 60% similarity]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/CapabilityResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/ResourceAssignmentProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionComponentTest.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionServiceTest.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionServiceTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/mock/MockRestResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceResolutionProcessorTest.kt
ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt
ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ScriptComponentExtensions.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt
ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BlueprintProcessorCatalogServiceImpl.kt
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt
ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/BluePrintCoreConfiguration.kt
ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt
ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/BluePrintSshLibConfiguration.kt
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResolutionException.kt [moved from ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceException.kt with 81% similarity]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceExceptionHandler.kt [moved from ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceExceptionHandler.kt with 56% similarity]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceControllerTest.kt [moved from ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceControllerTest.kt with 90% similarity]
ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceController.kt
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingConfig.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingController.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandlerTest.kt
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/MessagingControllerTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/ProducerConfiguration.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration.zip [new file with mode: 0644]
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractScriptComponentFunction.kt
ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt
ms/blueprintsprocessor/parent/pom.xml
ms/command-executor/src/main/python/command_executor_handler.py
ms/command-executor/src/main/python/command_executor_server.py
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/data/BlueprintErrorCode.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTypeDSLBuilder.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintDependencyService.kt [new file with mode: 0644]
pom.xml

index f8cfc88..ef6880d 100644 (file)
@@ -37,7 +37,18 @@ limitations under the License.
     <mat-sidenav #drawer mode="side" [(opened)]="opened" (opened)="events.push('open!')" (closed)="events.push('close!')">
         <mat-toolbar color="" primary>Menu</mat-toolbar>
         <mat-nav-list>
-            <a mat-list-item [routerLink]="['/blueprint']">Controller Blueprint</a>
+            <!-- <a mat-list-item [routerLink]="['/blueprint']">Controller Blueprint</a> -->
+            <nav class="ng-tns-c12-2 ng-star-inserted">
+                <!-- <button class="docs-nav-content-btn" cdkaccordionitem="" expanded="true"
+          aria-label="Form Controls, section toggle" aria-controls="panel-forms" aria-expanded="false">-->
+                <label>Controller Blueprint</label>
+                <!-- <mat-icon class="mat-icon notranslate material-icons mat-icon-no-color" role="img" aria-hidden="true">
+            keyboard_arrow_down</mat-icon></button> -->
+                <ul>
+                    <a mat-list-item [routerLink]="['/blueprint']">Create Blueprint</a>
+                    <a mat-list-item [routerLink]="['/']">Search Blueprint</a>
+                </ul>
+            </nav>
             <a mat-list-item [routerLink]="['/resource-definition']">Resource Definition</a>
         </mat-nav-list>
     </mat-sidenav>
index df9a48d..be21b75 100644 (file)
@@ -26,22 +26,41 @@ limitations under the License.
 //     left: 0;
 //     right: 0;
 //   }
-  
 //   .example-events {
 //     width: 300px;
 //     height: 200px;
 //     overflow: auto;
 //     border: 1px solid #555;
 //   }
-.mat-sidenav-container{
+.mat-sidenav-container {
     height: 652px;
 }
-.mat-button.mat-primary, .mat-icon-button.mat-primary, .mat-stroked-button.mat-primary {
+
+.mat-button.mat-primary,
+.mat-icon-button.mat-primary,
+.mat-stroked-button.mat-primary {
     color: white !important;
 }
-.menuBar{
+
+.menuBar {
     cursor: pointer;
 }
-.title{
+
+.title {
     margin: 1em;
+}
+
+.docs-component-viewer-nav .docs-component-viewer-nav-content button {
+    padding: 10px 15px;
+    font-weight: 700;
+    line-height: 16px;
+    margin: 0;
+    font-size: 13px;
+    cursor: pointer;
+    position: relative;
+    display: block;
+    width: 100%;
+    text-align: left;
+    background: 0 0;
+    border: none;
 }
\ No newline at end of file
index 3a25e92..ae4df4c 100644 (file)
@@ -30,7 +30,7 @@ import { SelectTemplateModule } from './select-template/select-template.module';
 import { ModifyTemplateModule } from './modify-template/modify-template.module';
 import { DeployTemplateModule } from './deploy-template/deploy-template.module';
 import { TestTemplateModule } from './test-template/test-template.module';
-
+import { SearchEditCBAComponent } from './search-edit-cba/search-edit-cba.component';
 import { AppMaterialModule } from '../../../app/common/modules/app-material.module';
 
 @NgModule({
@@ -45,7 +45,8 @@ import { AppMaterialModule } from '../../../app/common/modules/app-material.modu
     SelectTemplateModule,
     ModifyTemplateModule,
     DeployTemplateModule,
-    TestTemplateModule
+    TestTemplateModule,
+    SearchEditCBAComponent
   ]
 })
 export class BlueprintModule { }
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.html b/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.html
new file mode 100644 (file)
index 0000000..7371d21
--- /dev/null
@@ -0,0 +1,16 @@
+/* ============LICENSE_START========================================== =================================================================== Copyright (C) 2018 IBM Intellectual Property. All rights reserved. ===================================================================
+Unless otherwise specified, all software contained herein is licensed under the Apache License, Version 2.0 (the License); you may not use this software except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing
+permissions and limitations under the License. ============LICENSE_END============================================ */
+
+<form class="search-form" [formGroup]="myControl">
+    <mat-form-field class="search-full-width">
+        <input #resourceSelect type="text" [(ngModel)]="searchText" placeholder="Search Resources" matInput [matAutocomplete]="auto" formControlName="search_input">
+        <button matSuffix mat-icon-button (click)="fetchResourceByName()"><mat-icon>search</mat-icon></button>
+        <!-- <mat-autocomplete #auto="matAutocomplete">
+                <mat-option (click)="selected(option)" *ngFor="let option of options | search : searchText" [value]="option.tags">
+                    {{option.tags}}
+                </mat-option>
+            </mat-autocomplete> -->
+    </mat-form-field>
+</form>
\ No newline at end of file
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.scss b/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.spec.ts b/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.spec.ts
new file mode 100644 (file)
index 0000000..78210cf
--- /dev/null
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SearchEditCBAComponent } from './search-edit-cba.component';
+
+describe('SearchEditCBAComponent', () => {
+  let component: SearchEditCBAComponent;
+  let fixture: ComponentFixture<SearchEditCBAComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SearchEditCBAComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SearchEditCBAComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.ts b/cds-ui/client/src/app/feature-modules/blueprint/search-edit-cba/search-edit-cba.component.ts
new file mode 100644 (file)
index 0000000..14a79e0
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+* ============LICENSE_START=======================================================
+* ONAP : CDS
+* ================================================================================
+* Copyright 2019 TechMahindra
+*
+* Modifications Copyright (C) 2019 IBM
+*=================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END=========================================================
+*/
+
+import { Component, OnInit, ViewChild, EventEmitter, Output  } from '@angular/core';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+
+import { MatAutocompleteTrigger } from '@angular/material'
+@Component({
+  selector: 'app-search-edit-cba',
+  templateUrl: './search-edit-cba.component.html',
+  styleUrls: ['./search-edit-cba.component.scss']
+})
+export class SearchEditCBAComponent implements OnInit {
+
+  myControl: FormGroup;
+  @Output() resourcesData = new EventEmitter();  
+  options: any[]   = [];
+  //['One','One1', 'Two', 'Three'];
+  // @ViewChild('resourceSelect') resourceSelect;
+  @ViewChild('resourceSelect', { read: MatAutocompleteTrigger }) resourceSelect: MatAutocompleteTrigger;
+
+  searchText: string = '';
+  constructor(private _formBuilder: FormBuilder,
+              )  { }
+  
+ ngOnInit() {
+    this.myControl = this._formBuilder.group({
+      search_input: ['', Validators.required]
+    });
+  }
+ selected(value){
+   this.resourcesData.emit(value);
+   }
+
+   fetchResourceByName() {
+      // this.exsistingModelService.searchByTags(this.searchText)
+      // .subscribe(data=>{
+      //     console.log(data);
+      //     data.forEach(element => {
+      //       this.options.push(element)
+      //     });          
+      //   this.resourceSelect.openPanel();
+      // }, error=>{
+      //   window.alert('error' + error);
+      // })
+   }
+
+}
index b58be9f..491c5e0 100644 (file)
@@ -18,9 +18,24 @@ See the License for the specific language governing permissions and
 limitations under the License.
 ============LICENSE_END============================================
 -->
-<div>
-    <input type="file" accept=".zip" (change)="fileChanged($event)">
+<div *ngIf="optionSelected==1">
+    <div>
+        <input type="file" accept=".zip" (change)="fileChanged($event)">
+    </div>
+    <div>
+        <button mat-button matStepperNext (click)="updateBlueprintState()" [ngClass]="{'mat-upload-btn-disabled': !validfile, 'matStepNextBtn': validfile}" [disabled]="!validfile">Upload</button>
+    </div>
 </div>
-<div>
-    <button mat-button matStepperNext (click)="updateBlueprintState()" [ngClass] = "{'mat-upload-btn-disabled': !validfile, 'matStepNextBtn': validfile}" [disabled]="!validfile">Upload</button>
+<div *ngIf="optionSelected==2">
+    <form class="search-form" [formGroup]="myControl">
+        <mat-form-field class="search-full-width">
+            <input #resourceSelect type="text" [(ngModel)]="searchText" placeholder="Search Resources" matInput [matAutocomplete]="auto" formControlName="search_input">
+            <button matSuffix mat-icon-button (click)="fetchResourceByName()"><mat-icon>search</mat-icon></button>
+            <!-- <mat-autocomplete #auto="matAutocomplete">
+                    <mat-option (click)="selected(option)" *ngFor="let option of options | search : searchText" [value]="option.tags">
+                        {{option.tags}}
+                    </mat-option>
+                </mat-autocomplete> -->
+        </mat-form-field>
+    </form>
 </div>
\ No newline at end of file
index 1221e8f..64352b2 100644 (file)
@@ -19,7 +19,7 @@ limitations under the License.
 ============LICENSE_END============================================
 */
 
-import { Component, OnInit, EventEmitter, Output, ViewChild } from '@angular/core';
+import { Component, OnInit, EventEmitter, Output, ViewChild, Input } from '@angular/core';
 import { Store } from '@ngrx/store';
 import * as JSZip from 'jszip';
 import { Observable } from 'rxjs';
@@ -31,6 +31,8 @@ import { LoadBlueprintSuccess, SET_BLUEPRINT_STATE, SetBlueprintState } from '..
 import { json } from 'd3';
 import { SortPipe } from '../../../../common/shared/pipes/sort.pipe';
 import { LoaderService } from '../../../../common/core/services/loader.service';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { MatAutocompleteTrigger } from '@angular/material';
 
 @Component({
   selector: 'app-search-template',
@@ -47,6 +49,12 @@ export class SearchTemplateComponent implements OnInit {
   uploadedFileName: string;
   @ViewChild('fileInput') fileInput;
   result: string = '';
+  @Input() optionSelected: string;
+  myControl: FormGroup;
+  @ViewChild('resourceSelect', { read: MatAutocompleteTrigger }) resourceSelect: MatAutocompleteTrigger;
+  @Output() resourcesData = new EventEmitter();
+  options: any[]   = [];
+  searchText: string = '';
 
   private paths = [];
   private tree;
@@ -57,11 +65,30 @@ export class SearchTemplateComponent implements OnInit {
   private blueprintName: string;
   private entryDefinition: string;
 
-  constructor(private store: Store<IAppState>, private loader: LoaderService) { }
+  constructor(private store: Store<IAppState>, private loader: LoaderService,private formBuilder: FormBuilder) { }
 
   ngOnInit() {
+    this.myControl = this.formBuilder.group({
+      search_input: ['', Validators.required]
+    });
+  }
+
+  selected(value) {
+    this.resourcesData.emit(value);
   }
 
+  fetchResourceByName() {
+    // this.exsistingModelService.searchByTags(this.searchText)
+    //   .subscribe(data => {
+    //     console.log(data);
+    //     data.forEach(element => {
+    //       this.options.push(element)
+    //     });
+    //     this.resourceSelect.openPanel();
+    //   }, error => {
+    //     window.alert('error' + error);
+    //   })
+  }
   fileChanged(e: any) {
     this.paths = [];
     this.file = e.target.files[0];
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.service.spec.ts b/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.service.spec.ts
new file mode 100644 (file)
index 0000000..418b7e9
--- /dev/null
@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { SearchTemplateService } from './search-template.service';
+
+describe('SearchTemplateService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: SearchTemplateService = TestBed.get(SearchTemplateService);
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.service.ts b/cds-ui/client/src/app/feature-modules/blueprint/select-template/search-template/search-template.service.ts
new file mode 100644 (file)
index 0000000..fdb261d
--- /dev/null
@@ -0,0 +1,16 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+import { ApiService } from '../../../../common/core/services/api.service';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class SearchTemplateService {
+
+  constructor(private _http: HttpClient, private api: ApiService) { }
+
+  searchByTags(uri: string, searchText: String): Observable<any>{
+    return this.api.post(uri, searchText);
+  }
+}
index d11b371..97c65b2 100644 (file)
@@ -22,7 +22,7 @@ limitations under the License.
     <mat-step [stepControl]="step1FormGroup">
         <ng-template matStepLabel>Choose CBA Template file</ng-template>
         <div class="matStepContent">
-            <app-template-options></app-template-options>
+            <app-template-options (option)="templateSelected($event)"></app-template-options>
             <br>
             <div>
                 <button mat-button matStepperNext class="matStepNextBtn">Proceed</button>
@@ -30,10 +30,10 @@ limitations under the License.
         </div>
     </mat-step>
 
-    <mat-step [stepControl]="step2FormGroup">
+    <mat-step [stepControl]="step2FormGroup" *ngIf="templateOption==1 || templateOption == 2">
         <ng-template matStepLabel>Browse CBA Template file</ng-template>
         <div class="matStepContent">
-            <app-search-template (cbaFile)="fileChange($event)"></app-search-template>
+            <app-search-template [optionSelected]="templateOption" (cbaFile)="fileChange($event)"></app-search-template>
             <!-- <div>
                 <button mat-button matStepperNext class="matStepNextBtn">Upload</button>
             </div>-->
index d9591dd..561f15a 100644 (file)
@@ -38,6 +38,7 @@ export class SelectTemplateComponent implements OnInit {
   metaData: IMetaData;
   blueprintState: IBlueprintState;
   importModel: IImportModel;
+  templateOption: any;
 
   constructor(private store: Store<IBlueprintState>) {
     // this.importModel.file = '';
@@ -45,6 +46,12 @@ export class SelectTemplateComponent implements OnInit {
 
   ngOnInit() {
   }
+
+  templateSelected(option: any) {
+    this.templateOption = option;
+    console.log(this.templateOption);
+  }
+  
   fileChange(topologyTemp: ITopologyTemplate) {
     this.topologyTemplate = topologyTemp;
     console.log(topologyTemp);
@@ -57,6 +64,7 @@ export class SelectTemplateComponent implements OnInit {
   upload() {
 
   }
+  
   // saveBlueprintModel(){
   //   this.blueprint.toplogyTemplates=this.topologyTemplate;
   //   this.blueprint.metadata= this.metaData;
index d66b559..57ff00d 100644 (file)
@@ -19,7 +19,7 @@ limitations under the License.
 ============LICENSE_END============================================
 -->
 <mat-radio-group>
-    <mat-radio-button value="1" (click)="selected(1)">Upload Template file</mat-radio-button><br><br>
-    <!-- <mat-radio-button value="2" (click)="selected(2)">Starter Template</mat-radio-button><br><br>
-  <mat-radio-button value="3" (click)="selected(3)">Existing Model File</mat-radio-button> -->
+    <mat-radio-button value="1" (click)="selected(1)">Upload Template file</mat-radio-button><br> <br>
+    <mat-radio-button value="2" (click)="selected(2)">Starter Template</mat-radio-button><br> <br>
+    <mat-radio-button value="3" (click)="selected(3)">Existing Model File</mat-radio-button>
 </mat-radio-group>
\ No newline at end of file
diff --git a/cds-ui/server/config/app-config.ts b/cds-ui/server/config/app-config.ts
deleted file mode 100644 (file)
index 80f2464..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-export const controllerApiConfig = Object.freeze({
-    url: process.env.API_BLUEPRINT_CONTROLLER_BASE_URL || "http://localhost:8080/api/v1",
-    authToken: process.env.API_BLUEPRINT_CONTROLLER_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw=="
-});
-
-export const processorApiConfig = Object.freeze({
-    url: process.env.API_BLUEPRINT_PROCESSOR_BASE_URL || "http://localhost:8081/api/v1",
-    authToken: process.env.API_BLUEPRINT_PROCESSOR_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw=="
-});
\ No newline at end of file
index b79f7d6..161a18b 100644 (file)
@@ -20,6 +20,7 @@ limitations under the License.
 */
 
 const application = require('./dist');
+const fs = require('fs')
 
 module.exports = application;
 
@@ -27,6 +28,9 @@ if (require.main === module) {
   // Run the application
   const config = {
     rest: {
+      protocol: 'https',
+      key: fs.readFileSync('server.key'),
+      cert: fs.readFileSync('server.cert'),
       port: +process.env.PORT || 3000,
       host: process.env.HOST || 'localhost',
       openApiSpec: {
index 5b8f7e6..2f33aba 100644 (file)
@@ -12,7 +12,7 @@
     },
     "scripts": {
         "build:apidocs": "lb-apidocs",
-        "build": "lb-tsc es2017 --outDir dist",
+        "build": "npm run copy:proto && lb-tsc es2017 --copy-resources --outDir dist",
         "build:watch": "lb-tsc --watch",
         "clean": "lb-clean dist",
         "lint": "npm run prettier:check && npm run tslint",
@@ -29,7 +29,8 @@
         "migrate": "node ./dist/src/migrate",
         "prestart": "npm run build",
         "start": "node .",
-        "prepublishOnly": "npm run test"
+        "prepublishOnly": "npm run test",
+        "copy:proto": "mkdir -p dist; cp -R target/generated/proto-definition/proto/ dist/proto"
     },
     "repository": {
         "type": "git"
@@ -45,6 +46,7 @@
         "src"
     ],
     "dependencies": {
+        "@grpc/proto-loader": "^0.5.1",
         "@loopback/boot": "^1.0.8",
         "@loopback/context": "^1.16.0",
         "@loopback/core": "^1.1.3",
@@ -55,6 +57,7 @@
         "@loopback/service-proxy": "^1.0.8",
         "@types/form-data": "^2.2.1",
         "@types/jszip": "^3.1.5",
+        "@types/uuid": "^3.4.4",
         "bluebird": "^3.5.3",
         "cors": "^2.8.5",
         "file": "^0.2.2",
         "form-data": "^2.3.3",
         "formidable": "^1.2.1",
         "fs": "0.0.1-security",
+        "grpc": "^1.21.1",
         "jszip": "^3.2.1",
         "loopback-connector-rest": "^3.4.1",
         "multer": "^1.4.1",
         "multiparty": "^4.2.1",
         "nodemon": "^1.18.10",
+        "uuid": "^3.3.2",
         "winston": "^3.2.1"
     },
     "devDependencies": {
index ae9b1b2..8d758c7 100644 (file)
@@ -42,8 +42,37 @@ limitations under the License.
         <docker.push.phase>deploy</docker.push.phase>
     </properties>
 
+
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>3.1.1</version>
+                <executions>
+                    <execution>
+                        <id>unpack-blueprint-grpc-proto</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.onap.ccsdk.cds.components</groupId>
+                                    <artifactId>proto-definition</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.build.directory}/generated/proto-definition/proto</outputDirectory>
+                                    <includes>**/*.proto</includes>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
             <plugin>
                 <groupId>com.github.eirslett</groupId>
                 <artifactId>frontend-maven-plugin</artifactId>
diff --git a/cds-ui/server/server.cert b/cds-ui/server/server.cert
new file mode 100644 (file)
index 0000000..a5b2eca
--- /dev/null
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID6zCCAtOgAwIBAgIUKOL8h9cYkcHjt/7+3zsOUZGBEggwDQYJKoZIhvcNAQEL
+BQAwgYQxCzAJBgNVBAYTAklFMQswCQYDVQQIDAJXSDEQMA4GA1UEBwwHQXRobG9u
+ZTERMA8GA1UECgwIRXJpY3Nzb24xDDAKBgNVBAsMA0VTWTESMBAGA1UEAwwJSGVu
+cnkgWGllMSEwHwYJKoZIhvcNAQkBFhJoZW5yeS54aWVAZXN0LnRlY2gwHhcNMTkw
+NzAzMTU1MzAxWhcNMTkwODAyMTU1MzAxWjCBhDELMAkGA1UEBhMCSUUxCzAJBgNV
+BAgMAldIMRAwDgYDVQQHDAdBdGhsb25lMREwDwYDVQQKDAhFcmljc3NvbjEMMAoG
+A1UECwwDRVNZMRIwEAYDVQQDDAlIZW5yeSBYaWUxITAfBgkqhkiG9w0BCQEWEmhl
+bnJ5LnhpZUBlc3QudGVjaDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALuanknRJk8yXoafxrcbV1JBU57REt4Qpesv4jWt5YybQ+EvdodOCl65Rjsfe38q
+hVzUV/4RWctERXutE0pofDGK5Q29Uu3W627eMuSYitbVvuHcVCCVRgjYVjZDh53j
+y29IrzSiV2W6Sp4hkUZpTciLXNFFoSC8ZIKz7k1uF7Sokrk4ehm38vIcRFsbkxtu
+a41P0/aT1XK/+dr5u2KzyfC/1gj3t4o03vSuBWopcRxabnKg2uygWYHAjzvyUqfj
+y3Su55wjl3pw2/0qKvaYCvDV4DQLxs0yIrV1oYyckoHeW0GUEROrGFQIzk8KyEOS
+WdlqpJco6RonGn1eErEf3gUCAwEAAaNTMFEwHQYDVR0OBBYEFO7nN1ukrhBLZAD7
+yYD1G1g8VGNRMB8GA1UdIwQYMBaAFO7nN1ukrhBLZAD7yYD1G1g8VGNRMA8GA1Ud
+EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADzyzDmN3J2sALTtmjfiAelH
+NfVmNc0ZjiExURCyEreAE78XGz/a/5avQWlLqo0TkaUVnrUh1UAOAFl2sa6uASOe
+xwRk3eIwuQQHiYV+W2BlW0tEiQ6vtmRJ7/CvCDKM9LN/FPWWN0abZ78NXruQSZox
+RJ9z6osrQv5sEkZ9cQ9m7/TW1fG0aysAtHqDccDIOpNEmOCxlLBdnI1IeQjqcCHO
+K1+5mYhf9TiRFmnVulwzPDB1VyXsM17Q2AcwfvP+9A/c9aDBkuzkGuC5hEEgyH1z
+3G/y2KKaZ/L3/cCaB0X0YcY0bvLVHdaKehTpbYn8BzA78zJTQJ27Q1MLl1PX8BY=
+-----END CERTIFICATE-----
diff --git a/cds-ui/server/server.key b/cds-ui/server/server.key
new file mode 100644 (file)
index 0000000..c73a1b9
--- /dev/null
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7mp5J0SZPMl6G
+n8a3G1dSQVOe0RLeEKXrL+I1reWMm0PhL3aHTgpeuUY7H3t/KoVc1Ff+EVnLREV7
+rRNKaHwxiuUNvVLt1utu3jLkmIrW1b7h3FQglUYI2FY2Q4ed48tvSK80oldlukqe
+IZFGaU3Ii1zRRaEgvGSCs+5Nbhe0qJK5OHoZt/LyHERbG5MbbmuNT9P2k9Vyv/na
++btis8nwv9YI97eKNN70rgVqKXEcWm5yoNrsoFmBwI878lKn48t0ruecI5d6cNv9
+Kir2mArw1eA0C8bNMiK1daGMnJKB3ltBlBETqxhUCM5PCshDklnZaqSXKOkaJxp9
+XhKxH94FAgMBAAECggEAdSXMChRMc8/kLvS+xcCQ+pBIgzfTLFABC6fO/e4lFXQv
+IwLcZQlaeGQBcxHpsDMBLEJ83+49wCxVpzEghqpQQy+UcMv0aQh347dk2FJZAGZg
+1/EZp28PWJ6e1yu8F+ATPN6KabemE6QMzEnxyaIgLEa6IwPz5dk+ek+ZU0iYDPrT
+1b7co+ompuOF34huHLks8U65CGlflatsgmPf+iXIOh0qLMJCAxavncbCPIH2BzpK
+T9YLPWHc3g0NVx/uPJi2/AIjaJ7+iC6qJnsEmD6akKpjUCvTkbUDUKjl9V+U5R0Q
+tSA3omnoIAs5CJ2GQuzTG+PNG6gAc3PuXuMfaSCiUQKBgQDzM8b1VokWOu9jNV1a
+2W86r9ShHFc/y7X5sgfHz1waPAyoYkNpjviYMqCtLDKK+A8Q/4qRKFykApN3TdqI
+ZHIZLHFQ32JUC8BbMKjSutnGlm/ovu01xI+fOKIvM4SsnQ5sJtpU1Z63g8IXPsjz
+kItGh2ETFaGxEk65v5j6qrXCOwKBgQDFed3MghVZRLxzbpFR7FN0W+T6G6d0Gp8x
+cSGUGqAcM62FhDI/fDguTwLcQz4ruHKXAwlOuX+FwV9RAQ046EuqZU8iBHpbO8Mh
+QfnoChRgCDHyL9bBSqOiGqNpwFMPk3p/XhQ1yGKjXCDTNtmfDKMZkkz4rM8uc1zC
+AliIuPicvwKBgQDYPR5W/8VOFcLJ5CYIZDJI7RPS2F8fYyJ/THMsjsvmq6PZh91G
+mw+gS8ufjh+2fo7u3ze2jzunvH6f4oI/KYhlp6VtceF8tyImMqK5E9gUgagpOrGx
+T/8fY/yYmWcLD25GbVlNes7vfuBxSKrmHYwofrCqhl5JEe0brSb5IhYQBwKBgEAM
+bqvN5S625Ihr7CYuCENNKs8T+RPnLorSrpliqVt8R2NupP2CRJaAeeUGyjtT75ab
+HYGzGHFBbrDPLoKulRwHD8twuF6u23MF+xAPdNxQzCJI8dZvZvNEwIukHUyIAMse
+sF9hRtzFHMBkoeC8MIoysVRWeDwQnp0uNZjipX/xAoGAFuCuYcN7MghscnoBcgK8
+0S57weKw4l2gNTMBCCQo/FiYHQN2H298oVu19dYSUZ/J5oJSHDp5ezC0Taxc4NB+
+3dQiZbVwiimoNuEj/PG95gA84TVld1igiG4ynQOAjw5s6H7sQX/ePVzorPrmcoGL
+4YZxlJnmWQc201pMXp2mPEY=
+-----END PRIVATE KEY-----
diff --git a/cds-ui/server/src/clients/blueprint-management-service-grpc-client.ts b/cds-ui/server/src/clients/blueprint-management-service-grpc-client.ts
new file mode 100644 (file)
index 0000000..b66b2a7
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+  ~  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.
+*/
+import * as fs from 'fs';
+import * as uuidv1 from 'uuid/v1';
+const grpc = require('grpc');
+import * as protoLoader from '@grpc/proto-loader';
+import {processorApiConfig} from '../config/app-config';
+
+const PROTO_PATH = processorApiConfig.grpc.bluePrintManagement.protoPath;
+
+// Suggested options for similarity to existing grpc.load behavior
+const packageDefinition: protoLoader.PackageDefinition = protoLoader.loadSync(
+    PROTO_PATH,
+    {
+        keepCase: true,
+        longs: String,
+        enums: String,
+        defaults: true,
+        oneofs: true
+    });
+
+const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
+// The protoDescriptor object has the full package hierarchy
+
+const stub = new protoDescriptor.org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementService(
+    "" + processorApiConfig.grpc.host + ":" + processorApiConfig.grpc.port + "",
+    grpc.credentials.createInsecure());
+
+const metadata = new grpc.Metadata();
+metadata.add('Authorization', processorApiConfig.grpc.authToken);
+
+class BluePrintManagementServiceGrpcClient {
+
+    async uploadBlueprint(filePath: string): Promise<any> {
+
+        let input = {
+            commonHeader: {
+                timestamp: new Date(),
+                originatorId: "cds-ui",
+                requestId: uuidv1(),
+                subRequestId: "1234-56",
+            },
+            fileChunk: {
+                chunk: fs.readFileSync(filePath)
+            }
+        }
+
+        let removeTempFile = () => {
+            fs.unlink(filePath, (err: any) => {
+                if (err) {
+                    console.error(err);
+                }
+            });
+        }
+
+        return new Promise<any>((resolve, reject) => {
+            stub.uploadBlueprint(input, metadata, (err: any, output: any) => {
+                if (err) {
+                    removeTempFile();
+                    reject(err);
+                    return;
+                }
+
+                removeTempFile();
+                resolve(output);
+            });
+        });
+
+    }
+}
+
+export const bluePrintManagementServiceGrpcClient = new BluePrintManagementServiceGrpcClient();
+
diff --git a/cds-ui/server/src/config/app-config.ts b/cds-ui/server/src/config/app-config.ts
new file mode 100644 (file)
index 0000000..24aeb26
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+  ~  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.
+*/
+export const appConfig = Object.freeze({
+    action: Object.freeze({
+        deployBlueprint: Object.freeze({
+            grpcEnabled: process.env.APP_ACTION_DEPLOY_BLUEPRINT_GRPC_ENABLED || true
+        })
+    })
+});
+
+export const controllerApiConfig = Object.freeze({
+    http: Object.freeze({
+        url: process.env.API_BLUEPRINT_CONTROLLER_HTTP_BASE_URL || "http://localhost:8080/api/v1",
+        authToken: process.env.API_BLUEPRINT_CONTROLLER_HTTP_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw=="
+    })
+});
+
+export const processorApiConfig = Object.freeze({
+    http: Object.freeze({
+        url: process.env.API_BLUEPRINT_PROCESSOR_HTTP_BASE_URL || "http://localhost:8081/api/v1",
+        authToken: process.env.API_BLUEPRINT_PROCESSOR_HTTP_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw=="
+    }),
+    grpc: Object.freeze({
+        host: process.env.API_BLUEPRINT_PROCESSOR_GRPC_HOST || "localhost",
+        port: process.env.API_BLUEPRINT_PROCESSOR_GRPC_PORT || 9111,
+        authToken: process.env.API_BLUEPRINT_PROCESSOR_GRPC_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==",
+        bluePrintManagement: Object.freeze({
+            //this path is relative to 'dist' folder
+            protoPath: __dirname + '../../../proto/BluePrintManagement.proto'
+        })
+    })
+});
+
+
index 877fa02..52e77ee 100644 (file)
@@ -48,7 +48,8 @@ import { BlueprintService } from '../services';
 import * as fs from 'fs';
 import * as multiparty from 'multiparty';
 import * as request_lib from 'request';
-import {controllerApiConfig, processorApiConfig} from '../../config/app-config';
+import {controllerApiConfig, processorApiConfig, appConfig} from '../config/app-config';
+import {bluePrintManagementServiceGrpcClient} from '../clients/blueprint-management-service-grpc-client';
 
 export class BlueprintRestController {
   constructor(
@@ -197,11 +198,10 @@ export class BlueprintRestController {
   ): Promise<Response> {
     return new Promise((resolve, reject) => { 
        this.getFileFromMultiPartForm(request).then(file=>{
-         this.uploadFileToBlueprintProcessor(file, "/execution-service/upload/", response).then(resp=>{
-          resolve(resp);
-         }, err=>{
-           reject(err);
-         });
+         if(appConfig.action.deployBlueprint.grpcEnabled)
+          return this.uploadFileToBlueprintProcessorGrpc(file, response); 
+         else
+          return this.uploadFileToBlueprintProcessor(file, "/execution-service/upload/", response);
       }, err=>{
         reject(err);
       });
@@ -209,11 +209,11 @@ export class BlueprintRestController {
   }
 
   async uploadFileToBlueprintController(file: multiparty.File, uri: string, response: Response): Promise<Response>{
-    return this.uploadFileToBlueprintService(file, controllerApiConfig.url + uri, controllerApiConfig.authToken, response);
+    return this.uploadFileToBlueprintService(file, controllerApiConfig.http.url + uri, controllerApiConfig.http.authToken, response);
   }
 
   async uploadFileToBlueprintProcessor(file: multiparty.File, uri: string, response: Response): Promise<Response>{
-    return this.uploadFileToBlueprintService(file, processorApiConfig.url + uri, processorApiConfig.authToken, response);
+    return this.uploadFileToBlueprintService(file, processorApiConfig.http.url + uri, processorApiConfig.http.authToken, response);
   }
 
   async uploadFileToBlueprintService(file: multiparty.File, url: string, authToken: string, response: Response): Promise<Response>{
@@ -256,7 +256,7 @@ export class BlueprintRestController {
   }
 
   async downloadFileFromBlueprintController(uri: string, response: Response): Promise<Response> {
-    return this.downloadFileFromBlueprintService(controllerApiConfig.url + uri, controllerApiConfig.authToken, response);
+    return this.downloadFileFromBlueprintService(controllerApiConfig.http.url + uri, controllerApiConfig.http.authToken, response);
   }
 
   async downloadFileFromBlueprintService(url: string, authToken: string, response: Response): Promise<Response> {
@@ -277,4 +277,16 @@ export class BlueprintRestController {
         });
     })
   }
+
+  async uploadFileToBlueprintProcessorGrpc(file: multiparty.File, response: Response): Promise<Response> {
+    return new Promise<Response>((resolve, reject) => {
+      bluePrintManagementServiceGrpcClient.uploadBlueprint(file.path).then(output=>{
+        response.send(output.status.message);
+        resolve(response);
+      }, err=>{
+        response.status(500).send(err);
+        resolve(response);
+      });
+    });
+  }
 }
\ No newline at end of file
index f5dad3a..35edf33 100644 (file)
@@ -1,19 +1,19 @@
-import {controllerApiConfig} from '../../config/app-config';
+import {controllerApiConfig} from '../config/app-config';
 
 export default {
     "name": "blueprint",
     "connector": "rest",
-    "baseURL": controllerApiConfig.url,
+    "baseURL": controllerApiConfig.http.url,
     "crud": false,
     "debug": true,
     "operations": [{
         "template": {
             "method": "GET",
-            "url": controllerApiConfig.url + "/blueprint-model/",
+            "url": controllerApiConfig.http.url + "/blueprint-model/",
             "headers": {
                 "accepts": "application/json",
                 "content-type": "application/json",
-                "authorization": controllerApiConfig.authToken
+                "authorization": controllerApiConfig.http.authToken
             },
             "responsePath": "$.*"
         },
index 1c459e0..c749eee 100644 (file)
@@ -1,19 +1,19 @@
-import {controllerApiConfig} from '../../config/app-config';
+import {controllerApiConfig} from '../config/app-config';
 
 export default {
     "name": "resourceDictionary",
     "connector": "rest",
-    "baseURL": controllerApiConfig.url + "/dictionary",
+    "baseURL": controllerApiConfig.http.url + "/dictionary",
     "crud": false,
     "debug": true,
     "operations": [{
             "template": {
                 "method": "GET",
-                "url": controllerApiConfig.url + "/dictionary/{name}",
+                "url": controllerApiConfig.http.url + "/dictionary/{name}",
                 "headers": {
                     "accepts": "application/json",
                     "content-type": "application/json",
-                    "authorization": controllerApiConfig.authToken
+                    "authorization": controllerApiConfig.http.authToken
                 },
                 "responsePath": "$.*"
             },
@@ -25,11 +25,11 @@ export default {
         {
             "template": {
                 "method": "GET",
-                "url": controllerApiConfig.url + "/dictionary/source-mapping",
+                "url": controllerApiConfig.http.url + "/dictionary/source-mapping",
                 "headers": {
                     "accepts": "application/json",
                     "content-type": "application/json",
-                    "authorization": controllerApiConfig.authToken
+                    "authorization": controllerApiConfig.http.authToken
                 },
                 "responsePath": "$.*"
             },
@@ -41,11 +41,11 @@ export default {
         {
             "template": {
                 "method": "GET",
-                "url": controllerApiConfig.url + "/dictionary/search/{tags}",
+                "url": controllerApiConfig.http.url + "/dictionary/search/{tags}",
                 "headers": {
                     "accepts": "application/json",
                     "content-type": "application/json",
-                    "authorization": controllerApiConfig.authToken
+                    "authorization": controllerApiConfig.http.authToken
                 },
                 "responsePath": "$.*"
             },
@@ -57,11 +57,11 @@ export default {
         {
             "template": {
                 "method": "POST",
-                "url": controllerApiConfig.url + "/dictionary",
+                "url": controllerApiConfig.http.url + "/dictionary",
                 "headers": {
                     "accepts": "application/json",
                     "content-type": "application/json",
-                    "authorization": controllerApiConfig.authToken
+                    "authorization": controllerApiConfig.http.authToken
                 },
                 "body": "{resourceDictionary}",
                 "responsePath": "$.*"
@@ -74,11 +74,11 @@ export default {
         {
             "template": {
                 "method": "POST",
-                "url": controllerApiConfig.url + "/dictionary/by-names",
+                "url": controllerApiConfig.http.url + "/dictionary/by-names",
                 "headers": {
                     "accepts": "application/json",
                     "content-type": "application/json",
-                    "authorization": controllerApiConfig.authToken
+                    "authorization": controllerApiConfig.http.authToken
                 },
                 "body": "{resourceDictionaryList}",
                 "responsePath": "$.*"
index b282cbc..84da524 100644 (file)
@@ -31,6 +31,7 @@ import {
   SequenceHandler,
 } from '@loopback/rest';
 import { logger } from './logger/logger';
+import { v4 as uuid } from 'uuid';
 
 const SequenceActions = RestBindings.SequenceActions;
 
@@ -44,16 +45,22 @@ export class MySequence implements SequenceHandler {
   ) { }
 
   async handle(context: RequestContext) {
+    const { request, response } = context;
     try {
-      const { request, response } = context;
-      logger.info("Incoming request from %s %s and with header %s query %s params %s",
-        request.method, request.url, JSON.stringify(request.headers), JSON.stringify(request.query), JSON.stringify(request.params))
+      if (!('X-ONAP-RequestID' in request.headers || 'x-onap-requestid' in request.headers)) {
+        request.headers = { 'X-ONAP-RequestID': uuid(), ...request.headers}
+        logger.info(JSON.stringify(request.headers))
+      }
       const route = this.findRoute(request);
       const args = await this.parseParams(request, route);
       const result = await this.invoke(route, args);
       this.send(response, result);
     } catch (err) {
       this.reject(context, err);
+    } finally {
+      const { authorization, ...headers} = request.headers;
+      logger.info("Incoming request from %s %s and with header %s query %s params %s and response code: %s",
+        request.method, request.url, JSON.stringify(headers), JSON.stringify(request.query), JSON.stringify(request.params), JSON.stringify(response.statusCode))
     }
   }
 }
index ceb18b2..0af2cd9 100644 (file)
                   "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,
                   "type": "string"
                 },
                 "artifact-prefix-names": {
-                  "description": "Template , Resource Assignment Artifact Prefix names",
                   "required": true,
+                  "description": "Template , Resource Assignment Artifact Prefix names",
                   "type": "list",
                   "entry_schema": {
                     "type": "string"
index 06726ad..f9eead3 100755 (executable)
@@ -17,7 +17,8 @@
   ~  See the License for the specific language governing permissions and
   ~  limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
@@ -31,6 +32,7 @@
     <description>Blueprints Processor Application</description>
 
     <dependencies>
+
         <dependency>
             <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
             <artifactId>blueprint-core</artifactId>
             </resource>
         </resources>
         <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-            </plugin>
             <plugin>
                 <artifactId>maven-resources-plugin</artifactId>
                 <version>2.6</version>
index 2b6f8bc..3d5145a 100644 (file)
@@ -29,13 +29,12 @@ import org.springframework.context.annotation.ComponentScan;
  */
 @SpringBootApplication
 @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
-@ComponentScan(basePackages = {"org.onap.ccsdk.cds.controllerblueprints",
-    "org.onap.ccsdk.cds.blueprintsprocessor"})
+@ComponentScan(basePackages = {"org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"})
 public class BlueprintProcessorApplication {
 
     public static void main(String[] args) {
 
-        // This is required for ResolutionResultsServiceController.getStoredResult to accept a content-type value
+        // This is required for TemplateController.getStoredResult to accept a content-type value
         // as a request parameter, e.g. &format=application%2Fxml is accepted
         System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
 
index 8ad3c08..4df55ff 100644 (file)
@@ -17,8 +17,9 @@
 
 package org.onap.ccsdk.cds.blueprintsprocessor;
 
-
+import io.swagger.annotations.Api;
 import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
 import springfox.documentation.builders.PathSelectors;
 import springfox.documentation.builders.RequestHandlerSelectors;
 import springfox.documentation.service.ApiInfo;
@@ -27,37 +28,36 @@ import springfox.documentation.spi.DocumentationType;
 import springfox.documentation.spring.web.plugins.Docket;
 
 import java.util.Collections;
+import springfox.documentation.swagger2.annotations.EnableSwagger2WebFlux;
 
 /**
  * SwaggerConfig
  *
  * @author Brinda Santh 8/13/2018
  */
-//@Configuration
-//@EnableSwagger2
-@SuppressWarnings("unused")
-@Deprecated
+@Configuration
+@EnableSwagger2WebFlux
 public class SwaggerConfig {
 
     @Bean
     public Docket api() {
         return new Docket(DocumentationType.SWAGGER_2)
-                .select()
-                .apis(RequestHandlerSelectors.any())
-                .paths(PathSelectors.any())
-                .build()
-                .apiInfo(apiInfo());
+            .select()
+            .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
+            .paths(PathSelectors.any())
+            .build()
+            .apiInfo(apiInfo());
     }
 
     private ApiInfo apiInfo() {
         return new ApiInfo(
-                "Blueprints Processor API",
-                "Controller blueprints processor API for VNF Selfservice.",
-                "1.0.0",
-                "Terms of service",
-                new Contact("Brinda Santh", "www.onap.com", "bs2796@onap.com"),
-                "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", Collections.emptyList());
+            "CDS Blueprints Processor APIs",
+            "Provide APIs to interact with CBA, their related resolved resources and templates.",
+            "0.5.0",
+            null,
+            new Contact("CCSDK Team", "www.onap.org", "onap-discuss@lists.onap.org"),
+            "Apache 2.0",
+            "http://www.apache.org/licenses/LICENSE-2.0",
+            Collections.emptyList());
     }
-
-
-}
+}
\ No newline at end of file
index b453b85..32abff0 100644 (file)
@@ -27,7 +27,7 @@ import org.springframework.security.config.web.server.ServerHttpSecurity;
 import org.springframework.security.web.server.SecurityWebFilterChain;
 import org.springframework.web.reactive.config.CorsRegistry;
 import org.springframework.web.reactive.config.ResourceHandlerRegistry;
-import org.springframework.web.reactive.config.WebFluxConfigurationSupport;
+import org.springframework.web.reactive.config.WebFluxConfigurer;
 
 /**
  * WebConfig
@@ -35,7 +35,7 @@ import org.springframework.web.reactive.config.WebFluxConfigurationSupport;
  * @author Brinda Santh 8/13/2018
  */
 @Configuration
-public class WebConfig extends WebFluxConfigurationSupport {
+public class WebConfig implements WebFluxConfigurer {
 
     @Autowired
     private AuthenticationManager authenticationManager;
@@ -45,7 +45,8 @@ public class WebConfig extends WebFluxConfigurationSupport {
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
-        registry.addResourceHandler("swagger-ui.html")
+
+        registry.addResourceHandler("/swagger-ui.html**")
             .addResourceLocations("classpath:/META-INF/resources/");
 
         registry.addResourceHandler("/webjars/**")
index a94fdf3..fae1adb 100755 (executable)
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 #
 #  Copyright � 2017-2018 AT&T Intellectual Property.
 #
@@ -73,3 +74,12 @@ blueprintsprocessor.cliExecutor.enabled=true
 ### If enabling remote python executor, set this value to true
 ### blueprintprocessor.remoteScriptCommand.enabled=true
 blueprintprocessor.remoteScriptCommand.enabled=false
+
+# Kafka-message-lib Configurations
+blueprintsprocessor.messageclient.self-service-api.topic=producer.t
+blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t
+blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageclient.self-service-api.kafkaEnable=false
index 1319d9f..d6e7dc8 100755 (executable)
@@ -72,3 +72,11 @@ blueprintsprocessor.restclient.primary-aai-data.url=https://aai.onap:8443
 blueprintsprocessor.restclient.primary-aai-data.username=aai@aai.onap.org
 blueprintsprocessor.restclient.primary-aai-data.password=demo123456!
 
+# Kafka-message-lib Configuration
+blueprintsprocessor.messageclient.self-service-api.topic=producer.t
+blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t
+blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageclient.self-service-api.kafkaEnable=false
index 90783d4..fc36e62 100644 (file)
@@ -16,7 +16,6 @@
 
 package org.onap.ccsdk.cds.blueprintsprocessor;
 
-
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -34,7 +33,6 @@ import org.springframework.test.context.junit4.SpringRunner;
  * @author Brinda Santh
  * DATE : 8/14/2018
  */
-
 @RunWith(SpringRunner.class)
 @ContextConfiguration(classes = {BlueprintProcessorApplication.class, BluePrintLoadConfiguration.class})
 @SpringBootTest(classes = BlueprintProcessorApplication.class,
index 09ee651..ea2f976 100644 (file)
@@ -46,3 +46,13 @@ blueprintprocessor.netconfExecutor.enabled=true
 blueprintprocessor.restConfExecutor.enabled=true
 blueprintsprocessor.cliExecutor.enabled=true
 blueprintprocessor.remoteScriptCommand.enabled=false
+
+
+# Kafka-message-lib Configuration
+blueprintsprocessor.messageclient.self-service-api.topic=producer.t
+blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t
+blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageclient.self-service-api.kafkaEnable=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
deleted file mode 100644 (file)
index 65d1c3e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Copyright © 2019 IBM.
- *
- *  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.cli.executor
-
-import kotlinx.coroutines.runBlocking
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService
-import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
-import org.onap.ccsdk.cds.blueprintsprocessor.ssh.SshLibConstants
-import org.onap.ccsdk.cds.blueprintsprocessor.ssh.service.BluePrintSshLibPropertyService
-import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
-import org.onap.ccsdk.cds.controllerblueprints.core.readNBLines
-import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
-
-abstract class CliComponentFunction : AbstractScriptComponentFunction() {
-
-    open fun bluePrintSshLibPropertyService(): BluePrintSshLibPropertyService =
-            functionDependencyInstanceAsType(SshLibConstants.SERVICE_BLUEPRINT_SSH_LIB_PROPERTY)
-
-    open fun resourceResolutionService(): ResourceResolutionService =
-            functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
-
-
-    open suspend fun readCommandLinesFromArtifact(artifactName: String): List<String> {
-        val artifactDefinition = bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
-        val file = normalizedFile(bluePrintRuntimeService.bluePrintContext().rootPath, artifactDefinition.file)
-        return file.readNBLines()
-    }
-
-    fun generateMessage(artifactName: String): String {
-        return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
-    }
-
-    fun resolveFromDatabase(resolutionKey: String, artifactName: String): String = runBlocking {
-        resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey)
-    }
-
-    fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking {
-        resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName,
-                artifactPrefix, mapOf())
-    }
-}
\ No newline at end of file
index 0c1c523..e1d8825 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor
 
-import com.fasterxml.jackson.databind.node.ArrayNode
-import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
-import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
-import org.onap.ccsdk.cds.blueprintsprocessor.ssh.SshLibConstants
-import org.onap.ccsdk.cds.controllerblueprints.core.getAsString
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor
 import org.springframework.beans.factory.config.ConfigurableBeanFactory
 import org.springframework.context.annotation.Scope
 import org.springframework.stereotype.Component
@@ -29,43 +25,4 @@ import org.springframework.stereotype.Component
 @Component("component-cli-executor")
 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
 open class ComponentCliExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService)
-    : AbstractComponentFunction() {
-
-    companion object {
-        const val SCRIPT_TYPE = "script-type"
-        const val SCRIPT_CLASS_REFERENCE = "script-class-reference"
-        const val INSTANCE_DEPENDENCIES = "instance-dependencies"
-        const val RESPONSE_DATA = "response-data"
-    }
-
-    private lateinit var scriptComponent: CliComponentFunction
-
-    override suspend fun processNB(executionRequest: ExecutionServiceInput) {
-
-        val scriptType = operationInputs.getAsString(SCRIPT_TYPE)
-        val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE)
-        val instanceDependenciesNode = operationInputs[INSTANCE_DEPENDENCIES] as? ArrayNode
-
-        val scriptDependencies: MutableList<String> = arrayListOf()
-        scriptDependencies.add(SshLibConstants.SERVICE_BLUEPRINT_SSH_LIB_PROPERTY)
-        // May be injected from model, not by default
-        //scriptDependencies.add(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
-
-        instanceDependenciesNode?.forEach { instanceName ->
-            scriptDependencies.add(instanceName.textValue())
-        }
-
-        scriptComponent = componentFunctionScriptingService.scriptInstance(this, scriptType,
-                scriptClassReference, scriptDependencies)
-
-
-        // Handles both script processing and error handling
-        scriptComponent.executeScript(executionServiceInput)
-    }
-
-    override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
-        bluePrintRuntimeService.getBluePrintError()
-                .addError("Failed in ComponentCliExecutor : ${runtimeException.message}")
-
-    }
-}
\ No newline at end of file
+    : ComponentScriptExecutor(componentFunctionScriptingService)
\ No newline at end of file
@@ -1,5 +1,5 @@
 /*
- *  Copyright © 2019 Bell Canada
+ *  Copyright © 2019 IBM.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
  *  limitations under the License.
  */
 
-package org.onap.ccsdk.cds.blueprintsprocessor.resource.api;
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor
 
-// TODO
-public class ResourceResolutionControllerTest {
+/**
+ * Register the CLI module exposed dependency
+ */
 
-}
index 0955ace..e623747 100644 (file)
 @file:Suppress("unused")
 
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor.CliComponentFunction
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor.ComponentCliExecutor
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor
+import org.onap.ccsdk.cds.blueprintsprocessor.ssh.sshClientService
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
-import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.slf4j.LoggerFactory
 
-open class TestCliScriptFunction : CliComponentFunction() {
+open class TestCliScriptFunction : AbstractScriptComponentFunction() {
 
-    private val log = LoggerFactory.getLogger(CliComponentFunction::class.java)!!
+    private val log = LoggerFactory.getLogger(TestCliScriptFunction::class.java.canonicalName)!!
 
     override fun getName(): String {
         return "SimpleCliConfigure"
     }
 
     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
-        log.info("Executing process")
+        log.info("Executing process ...")
     }
 
     override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
@@ -41,9 +42,9 @@ open class TestCliScriptFunction : CliComponentFunction() {
 }
 
 
-open class Check : CliComponentFunction() {
+open class Check : AbstractScriptComponentFunction() {
 
-    private val log = LoggerFactory.getLogger(CliComponentFunction::class.java)!!
+    private val log = LoggerFactory.getLogger(AbstractScriptComponentFunction::class.java)!!
 
     override fun getName(): String {
         return "Check"
@@ -54,12 +55,12 @@ open class Check : CliComponentFunction() {
         val deviceInformation = bluePrintRuntimeService.resolveDSLExpression("device-properties")
 
         // Get the Client Service
-        val sshClientService = bluePrintSshLibPropertyService().blueprintSshClientService(deviceInformation)
+        val sshClientService = BluePrintDependencyService.sshClientService(deviceInformation)
 
         sshClientService.startSessionNB()
 
         // Read Commands
-        val commands = readCommandLinesFromArtifact("command-template")
+        val commands = readLinesFromArtifact("command-template")
 
         // Execute multiple Commands
         val responseLog = sshClientService.executeCommandsNB(commands, 5000)
@@ -68,7 +69,7 @@ open class Check : CliComponentFunction() {
         sshClientService.closeSessionNB()
 
         // Set the Response Data
-        setAttribute(ComponentCliExecutor.RESPONSE_DATA, responseLog.asJsonPrimitive())
+        setAttribute(ComponentScriptExecutor.RESPONSE_DATA, responseLog.asJsonPrimitive())
 
         log.info("Executing process")
     }
index 6455513..658092f 100644 (file)
@@ -17,7 +17,6 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor
 
 import com.fasterxml.jackson.databind.JsonNode
-import com.fasterxml.jackson.databind.node.ArrayNode
 import com.fasterxml.jackson.databind.node.ObjectNode
 import io.mockk.every
 import io.mockk.mockk
@@ -30,11 +29,13 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceConfiguration
 import org.onap.ccsdk.cds.blueprintsprocessor.ssh.BluePrintSshLibConfiguration
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.onap.ccsdk.cds.controllerblueprints.scripts.BluePrintScriptsServiceImpl
@@ -49,7 +50,7 @@ import kotlin.test.assertNotNull
 @ContextConfiguration(classes = [CliExecutorConfiguration::class,
     ExecutionServiceConfiguration::class,
     BluePrintSshLibConfiguration::class, BluePrintScriptsServiceImpl::class,
-    BlueprintPropertyConfiguration::class, BluePrintProperties::class])
+    BlueprintPropertyConfiguration::class, BluePrintProperties::class, BluePrintDependencyService::class])
 @DirtiesContext
 @TestPropertySource(properties = [], locations = ["classpath:application-test.properties"])
 class ComponentCliExecutorTest {
@@ -78,10 +79,9 @@ class ComponentCliExecutorTest {
             operationInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] = "activate-cli".asJsonPrimitive()
             operationInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] = "interfaceName".asJsonPrimitive()
             operationInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] = "operationName".asJsonPrimitive()
-            operationInputs[ComponentCliExecutor.SCRIPT_TYPE] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive()
-            operationInputs[ComponentCliExecutor.SCRIPT_CLASS_REFERENCE] =
+            operationInputs[ComponentScriptExecutor.SCRIPT_TYPE] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive()
+            operationInputs[ComponentScriptExecutor.SCRIPT_CLASS_REFERENCE] =
                     "InternalSimpleCli_cba\$TestCliScriptFunction".asJsonPrimitive()
-            operationInputs[ComponentCliExecutor.INSTANCE_DEPENDENCIES] = JacksonUtils.jsonNode("[]") as ArrayNode
 
             val stepInputData = StepData().apply {
                 name = "activate-cli"
index a46e743..ca54234 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~ Copyright © 2017-2018 AT&T Intellectual Property.
+  ~ Copyright © 2017-2019 AT&T, Bell Canada.
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
             <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
             <artifactId>resource-resolution</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.codehaus.jettison</groupId>
-            <artifactId>jettison</artifactId>
-            <version>${jettison.version}</version>
-            <scope>provided</scope>
-        </dependency>
         <dependency>
             <groupId>org.apache.sshd</groupId>
             <artifactId>sshd-core</artifactId>
index 4cec6a2..5e0b4a1 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor
 
-import com.fasterxml.jackson.databind.JsonNode
 import kotlinx.coroutines.runBlocking
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 
+@Deprecated("Methods defined as extension function of AbstractComponentFunction")
 abstract class NetconfComponentFunction : AbstractScriptComponentFunction() {
 
+    @Deprecated(" Use resourceResolutionService method directly",
+            replaceWith = ReplaceWith("resourceResolutionService()",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resourceResolutionService"))
     open fun resourceResolutionService(): ResourceResolutionService =
             functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
 
     // Called from python script
+    @Deprecated(" Use netconfDeviceInfo method directly",
+            replaceWith = ReplaceWith("netconfDeviceInfo(requirementName)",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.netconfDeviceInfo"))
     fun initializeNetconfConnection(requirementName: String): NetconfDevice {
-        val deviceInfo = deviceProperties(requirementName)
+        val deviceInfo = netconfDeviceInfo(requirementName)
         return NetconfDevice(deviceInfo)
     }
 
+    @Deprecated(" Use artifactContent method directly",
+            replaceWith = ReplaceWith("artifactContent(artifactName)",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.artifactContent"))
     fun generateMessage(artifactName: String): String {
         return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
     }
 
+    @Deprecated(" Use storedContentFromResolvedArtifact method directly",
+            replaceWith = ReplaceWith("storedContentFromResolvedArtifact(resolutionKey, artifactName)",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.storedContentFromResolvedArtifact"))
     fun resolveFromDatabase(resolutionKey: String, artifactName: String): String = runBlocking {
         resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey)
     }
 
+    @Deprecated(" Use contentFromResolvedArtifact method directly",
+            replaceWith = ReplaceWith("resolveAndGenerateMessage(artifactPrefix)",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resolveAndGenerateMessage"))
     fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking {
         resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName,
                 artifactPrefix, mapOf())
     }
-
-    private fun deviceProperties(requirementName: String): DeviceInfo {
-
-        val blueprintContext = bluePrintRuntimeService.bluePrintContext()
-
-        val requirement = blueprintContext.nodeTemplateRequirement(nodeTemplateName, requirementName)
-
-        val capabilityProperties = bluePrintRuntimeService.resolveNodeTemplateCapabilityProperties(requirement
-                .node!!, requirement.capability!!)
-
-        return deviceProperties(capabilityProperties)
-    }
-
-    private fun deviceProperties(capabilityProperty: MutableMap<String, JsonNode>): DeviceInfo {
-        return JacksonUtils.getInstanceFromMap(capabilityProperty, DeviceInfo::class.java)
-    }
 }
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ScriptComponentExtensions.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ScriptComponentExtensions.kt
new file mode 100644 (file)
index 0000000..bac211a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  Copyright © 2019 IBM.
+ *
+ *  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.netconf.executor
+
+import com.fasterxml.jackson.databind.JsonNode
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+
+/**
+ * Register the Netconf module exposed dependency
+ */
+fun BluePrintDependencyService.netconfClientService(): ResourceResolutionService =
+        instance(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
+
+
+fun AbstractComponentFunction.netconfDevice(requirementName: String): NetconfDevice {
+    val deviceInfo = netconfDeviceInfo(requirementName)
+    return NetconfDevice(deviceInfo)
+}
+
+fun AbstractComponentFunction.netconfDeviceInfo(requirementName: String): DeviceInfo {
+
+    val blueprintContext = bluePrintRuntimeService.bluePrintContext()
+
+    val requirement = blueprintContext.nodeTemplateRequirement(nodeTemplateName, requirementName)
+
+    val capabilityProperties = bluePrintRuntimeService.resolveNodeTemplateCapabilityProperties(requirement
+            .node!!, requirement.capability!!)
+
+    return netconfDeviceInfo(capabilityProperties)
+}
+
+private fun AbstractComponentFunction.netconfDeviceInfo(capabilityProperty: MutableMap<String, JsonNode>): DeviceInfo {
+    return JacksonUtils.getInstanceFromMap(capabilityProperty, DeviceInfo::class.java)
+}
\ No newline at end of file
index 2de2242..c45fb88 100644 (file)
@@ -16,6 +16,7 @@
 
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor
 
+import com.fasterxml.jackson.databind.JsonNode
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.*
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceConstant
@@ -75,8 +76,19 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic
         val dynamicProperties = getOptionalOperationInput(INPUT_DYNAMIC_PROPERTIES)
         val packages = getOptionalOperationInput(INPUT_PACKAGES)?.returnNullIfMissing()
 
-        val args = getOptionalOperationInput(INPUT_ARGUMENT_PROPERTIES)?.returnNullIfMissing()
-                ?.rootFieldsToMap()?.toSortedMap()?.values?.map { it.textValue() }?.joinToString(" ")
+        val argsNode = getOptionalOperationInput(INPUT_ARGUMENT_PROPERTIES)?.returnNullIfMissing()
+
+        // This prevents unescaping values, as well as quoting the each parameter, in order to allow for spaces in values
+        var args = ""
+        argsNode?.fields()?.forEach {
+            if (it.value.isValueNode) {
+                args = "$args ${it.value}"
+            } else {
+                it.value.fields().forEach { item ->
+                    args = "$args ${item.value}"
+                }
+            }
+        }
 
         val command = getOperationInput(INPUT_COMMAND).asText()
         var scriptCommand = command.replace(pythonScript.name, pythonScript.absolutePath)
index 166d7b1..31aa7c7 100644 (file)
@@ -48,11 +48,12 @@ class ComponentRemotePythonExecutorTest {
 
             val componentRemotePythonExecutor = ComponentRemotePythonExecutor(remoteScriptExecutionService)
 
-            val executionServiceInput = JacksonUtils.readValueFromClassPathFile("payload/requests/sample-activate-request.json",
+            val executionServiceInput =
+                JacksonUtils.readValueFromClassPathFile("payload/requests/sample-activate-request.json",
                     ExecutionServiceInput::class.java)!!
 
             val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("123456-1000",
-                    "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_scripts")
+                "./../../../../components/model-catalog/blueprint-model/test-blueprint/remote_scripts")
 
             val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
             stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "execute-remote-python")
@@ -76,14 +77,17 @@ class ComponentRemotePythonExecutorTest {
     fun testComponentRemotePythonExecutorProcessNB() {
         runBlocking {
             val remoteScriptExecutionService =
-                    MockRemoteScriptExecutionService()
+                MockRemoteScriptExecutionService()
             val componentRemotePythonExecutor = ComponentRemotePythonExecutor(
-                    remoteScriptExecutionService)
+                remoteScriptExecutionService)
             val bluePrintRuntime = mockk<DefaultBluePrintRuntimeService>(
-                    "123456-1000")
-            val input  = getMockedOutput(bluePrintRuntime)
+                "123456-1000")
+
+            every { bluePrintRuntime.setNodeTemplateAttributeValue(any(), any(), any()) } answers {}
+
+            val input = getMockedOutput(bluePrintRuntime)
             componentRemotePythonExecutor.bluePrintRuntimeService =
-                    bluePrintRuntime
+                bluePrintRuntime
             componentRemotePythonExecutor.applyNB(input)
         }
     }
@@ -96,13 +100,13 @@ class ComponentRemotePythonExecutorTest {
         val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
 
         stepMetaData.putJsonElement(
-                BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE,
-                "execute-remote-python")
+            BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE,
+            "execute-remote-python")
         stepMetaData.putJsonElement(
-                BluePrintConstants.PROPERTY_CURRENT_INTERFACE,
-                "ComponentRemotePythonExecutor")
+            BluePrintConstants.PROPERTY_CURRENT_INTERFACE,
+            "ComponentRemotePythonExecutor")
         stepMetaData.putJsonElement(
-                BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
+            BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
 
         val mapper = ObjectMapper()
         val rootNode = mapper.createObjectNode()
@@ -111,13 +115,13 @@ class ComponentRemotePythonExecutorTest {
 
         val operationalInputs: MutableMap<String, JsonNode> = hashMapOf()
         operationalInputs.putJsonElement(
-                BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE,
-                "execute-remote-python")
+            BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE,
+            "execute-remote-python")
         operationalInputs.putJsonElement(
-                BluePrintConstants.PROPERTY_CURRENT_INTERFACE,
-                "ComponentRemotePythonExecutor")
+            BluePrintConstants.PROPERTY_CURRENT_INTERFACE,
+            "ComponentRemotePythonExecutor")
         operationalInputs.putJsonElement(
-                BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
+            BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
         operationalInputs.putJsonElement("endpoint-selector", "aai")
         operationalInputs.putJsonElement("dynamic-properties", rootNode)
         operationalInputs.putJsonElement("command", "./run.sh")
@@ -125,8 +129,8 @@ class ComponentRemotePythonExecutorTest {
 
         every {
             svc.resolveNodeTemplateInterfaceOperationInputs(
-                    "execute-remote-python",
-                    "ComponentRemotePythonExecutor", "process")
+                "execute-remote-python",
+                "ComponentRemotePythonExecutor", "process")
         } returns operationalInputs
 
         val stepInputData = StepData().apply {
@@ -135,42 +139,42 @@ class ComponentRemotePythonExecutorTest {
         }
 
         val executionServiceInput = JacksonUtils
-                .readValueFromClassPathFile(
-                        "payload/requests/sample-remote-python-request.json",
-                        ExecutionServiceInput::class.java)!!
+            .readValueFromClassPathFile(
+                "payload/requests/sample-remote-python-request.json",
+                ExecutionServiceInput::class.java)!!
         executionServiceInput.stepData = stepInputData
 
         val operationOutputs = hashMapOf<String, JsonNode>()
         every {
             svc.resolveNodeTemplateInterfaceOperationOutputs(
-                    "execute-remote-python",
-                    "ComponentRemotePythonExecutor", "process")
+                "execute-remote-python",
+                "ComponentRemotePythonExecutor", "process")
         } returns operationOutputs
         val bluePrintRuntimeService = BluePrintMetadataUtils
-                .getBluePrintRuntime("123456-1000",
-                        "./../../../../components/model-" +
-                                "catalog/blueprint-model/test-blueprint/" +
-                                "remote_scripts")
+            .getBluePrintRuntime("123456-1000",
+                "./../../../../components/model-" +
+                        "catalog/blueprint-model/test-blueprint/" +
+                        "remote_scripts")
         every {
             svc.resolveNodeTemplateArtifactDefinition(
-                    "execute-remote-python", "component-script")
-        } returns bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(
                 "execute-remote-python", "component-script")
+        } returns bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(
+            "execute-remote-python", "component-script")
         every {
             svc.setNodeTemplateAttributeValue(
-                    "execute-remote-python", "prepare-environment-logs",
-                    "prepared successfully".asJsonPrimitive())
+                "execute-remote-python", "prepare-environment-logs",
+                "prepared successfully".asJsonPrimitive())
         } returns Unit
         every {
             svc.setNodeTemplateAttributeValue(
-                    "execute-remote-python",
-                    "execute-command-logs", "N/A".asJsonPrimitive())
+                "execute-remote-python",
+                "execute-command-logs", "N/A".asJsonPrimitive())
         } returns Unit
         every {
             svc.setNodeTemplateAttributeValue(
-                    "execute-remote-python",
-                    "execute-command-logs",
-                    "processed successfully".asJsonPrimitive())
+                "execute-remote-python",
+                "execute-command-logs",
+                "processed successfully".asJsonPrimitive())
         } returns Unit
 
         every {
index 7c2c11c..ee7c31a 100644 (file)
@@ -20,6 +20,7 @@ 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
@@ -34,24 +35,38 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
 
     override suspend fun processNB(executionRequest: ExecutionServiceInput) {
 
-        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)
-
+        val occurrence = getOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE).asInt()
+        val resolutionKey = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY)?.asText() ?: ""
+        val storeResult = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)?.asBoolean() ?: false
+        val resourceId = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID)?.asText() ?: ""
+        val resourceType = getOptionalOperationInput(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE)?.asText() ?: ""
 
         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() ?: ""
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = storeResult
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+
+        val jsonResponse = JsonNodeFactory.instance.objectNode()
+
+        // validate inputs if we need to store the resource and template resolution.
+        if (storeResult) {
+            if (resolutionKey.isNotEmpty() && (resourceId.isNotEmpty() || resourceType.isNotEmpty())) {
+                throw BluePrintProcessorException("Can't proceed with the resolution: either provide resolution-key OR combination of resource-id and resource-type.")
+            } else if ((resourceType.isNotEmpty() && resourceId.isEmpty()) || (resourceType.isEmpty() && resourceId.isNotEmpty())) {
+                throw BluePrintProcessorException("Can't proceed with the resolution: both resource-id and resource-type should be provided, one of them is missing.")
+            } else if (resourceType.isEmpty() && resourceId.isEmpty() && resolutionKey.isEmpty()) {
+                throw BluePrintProcessorException("Can't proceed with the resolution: can't persist resolution without a correlation key. " +
+                        "Either provide a resolution-key OR combination of resource-id and resource-type OR set `storeResult` to false.")
+            }
+        }
 
         val artifactPrefixNamesNode = getOperationInput(ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES)
         val artifactPrefixNames = JacksonUtils.getListFromJsonNode(artifactPrefixNamesNode, String::class.java)
 
-        val jsonResponse = JsonNodeFactory.instance.objectNode()
-        for (j in 1..occurrence.asInt()) {
+        for (j in 1..occurrence) {
+            properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = j
 
             val response = resourceResolutionService.resolveResources(bluePrintRuntimeService,
                 nodeTemplateName,
@@ -59,11 +74,12 @@ open class ResourceResolutionComponent(private val resourceResolutionService: Re
                 properties)
 
             // provide indexed result in output if we have multiple resolution
-            if (occurrence.asInt() != 1) {
-                jsonResponse.set(key?.asText() + "-" + j, response.asJsonNode())
+            if (occurrence != 1) {
+                jsonResponse.set(Integer.toString(j), response.asJsonNode())
             } else {
                 jsonResponse.setAll(response.asObjectNode())
             }
+
         }
 
         // Set Output Attributes
index 929e9e8..fb32aa7 100644 (file)
@@ -24,7 +24,7 @@ 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_RESOLUTION_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"
index b148293..0e97267 100644 (file)
@@ -20,11 +20,14 @@ 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.ResourceResolution
 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.db.TemplateResolutionService
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
@@ -58,7 +61,7 @@ interface ResourceResolutionService {
 
 @Service(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
 open class ResourceResolutionServiceImpl(private var applicationContext: ApplicationContext,
-                                         private var resolutionResultService: ResourceResolutionResultService,
+                                         private var templateResolutionDBService: TemplateResolutionService,
                                          private var blueprintTemplateService: BluePrintTemplateService,
                                          private var resourceResolutionDBService: ResourceResolutionDBService) :
     ResourceResolutionService {
@@ -74,22 +77,30 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
     override suspend fun resolveFromDatabase(bluePrintRuntimeService: BluePrintRuntimeService<*>,
                                              artifactTemplate: String,
                                              resolutionKey: String): String {
-        return resolutionResultService.read(bluePrintRuntimeService, artifactTemplate, resolutionKey)
+        return templateResolutionDBService.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+            bluePrintRuntimeService,
+            artifactTemplate,
+            resolutionKey)
     }
 
     override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
                                           artifactNames: List<String>,
                                           properties: Map<String, Any>): MutableMap<String, String> {
 
+
+        val resourceAssignmentRuntimeService =
+            ResourceAssignmentUtils.transformToRARuntimeService(bluePrintRuntimeService, artifactNames.toString())
+
         val resolvedParams: MutableMap<String, String> = hashMapOf()
         artifactNames.forEach { artifactName ->
-            val resolvedContent = resolveResources(bluePrintRuntimeService, nodeTemplateName,
+            val resolvedContent = resolveResources(resourceAssignmentRuntimeService, nodeTemplateName,
                 artifactName, properties)
             resolvedParams[artifactName] = resolvedContent
         }
         return resolvedParams
     }
 
+
     override suspend fun resolveResources(bluePrintRuntimeService: BluePrintRuntimeService<*>, nodeTemplateName: String,
                                           artifactPrefix: String, properties: Map<String, Any>): String {
 
@@ -109,6 +120,13 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                     as? MutableList<ResourceAssignment>
                 ?: throw BluePrintProcessorException("couldn't get Dictionary Definitions")
 
+        if (isToStore(properties)) {
+            val existingResourceResolution = isNewResolution(bluePrintRuntimeService, properties, artifactPrefix)
+            if (existingResourceResolution.isNotEmpty()) {
+                updateResourceAssignmentWithExisting(existingResourceResolution, resourceAssignments)
+            }
+        }
+
         // Get the Resource Dictionary Name
         val resourceDefinitions: MutableMap<String, ResourceDefinition> = ResourceAssignmentUtils
             .resourceDefinitions(bluePrintRuntimeService.bluePrintContext().rootPath)
@@ -126,10 +144,9 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
         resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName,
             artifactTemplate, 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)")
+        if (isToStore(properties)) {
+            templateResolutionDBService.write(properties, resolvedContent, bluePrintRuntimeService, artifactPrefix)
+            log.info("Template resolution saved into database successfully : ($properties)")
         }
 
         return resolvedContent
@@ -147,20 +164,19 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                                                     properties: Map<String, Any>) {
 
         val bulkSequenced = BulkResourceSequencingUtils.process(resourceAssignments)
-        val resourceAssignmentRuntimeService =
-            ResourceAssignmentUtils.transformToRARuntimeService(blueprintRuntimeService, artifactPrefix)
+        val resourceAssignmentRuntimeService = blueprintRuntimeService as ResourceAssignmentRuntimeService
 
         coroutineScope {
             bulkSequenced.forEach { batchResourceAssignments ->
                 // Execute Non Dependent Assignments in parallel ( ie asynchronously )
-                val deferred = batchResourceAssignments.filter { it.name != "*" && it.name != "start" }
+                val deferred = batchResourceAssignments
+                    .filter { it.name != "*" && it.name != "start" }
+                    .filter { it.status != BluePrintConstants.STATUS_SUCCESS }
                     .map { resourceAssignment ->
                         async {
                             val dictionaryName = resourceAssignment.dictionaryName
                             val dictionarySource = resourceAssignment.dictionarySource
-                            /**
-                             * Get the Processor name
-                             */
+
                             val processorName = processorName(dictionaryName!!, dictionarySource!!, resourceDefinitions)
 
                             val resourceAssignmentProcessor =
@@ -175,13 +191,12 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                                 // Invoke Apply Method
                                 resourceAssignmentProcessor.applyNB(resourceAssignment)
 
-                                if (properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)
-                                    && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean) {
+                                if (isToStore(properties)) {
                                     resourceResolutionDBService.write(properties,
                                         blueprintRuntimeService,
                                         artifactPrefix,
                                         resourceAssignment)
-                                    log.info("resolution saved into database successfully : ($resourceAssignment)")
+                                    log.info("Resource resolution saved into database successfully : ($resourceAssignment)")
                                 }
 
                                 // Set errors from RA
@@ -199,7 +214,6 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
 
     }
 
-
     /**
      * If the Source instance is "input", then it is not mandatory to have source Resource Definition, So it can
      *  derive the default input processor.
@@ -230,4 +244,74 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
         return processorName
 
     }
+
+    // Check whether to store or not the resolution of resource and template
+    private fun isToStore(properties: Map<String, Any>): Boolean {
+        return properties.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT)
+                && properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] as Boolean
+    }
+
+    // Check whether resolution already exist in the database for the specified resolution-key or resourceId/resourceType
+    private suspend fun isNewResolution(bluePrintRuntimeService: BluePrintRuntimeService<*>,
+                                        properties: Map<String, Any>,
+                                        artifactPrefix: String): List<ResourceResolution> {
+        val occurrence = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] as Int
+        val resolutionKey = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] as String
+        val resourceId = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] as String
+        val resourceType = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] as String
+
+        if (resolutionKey.isNotEmpty()) {
+            val existingResourceAssignments =
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+                    bluePrintRuntimeService,
+                    resolutionKey,
+                    occurrence,
+                    artifactPrefix)
+            if (existingResourceAssignments.isNotEmpty()) {
+                log.info("Resolution with resolutionKey=($resolutionKey) already exist - will resolve all resources not already resolved.",
+                    resolutionKey)
+            }
+            return existingResourceAssignments
+        } else if (resourceId.isNotEmpty() && resourceType.isNotEmpty()) {
+            val existingResourceAssignments =
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+                    bluePrintRuntimeService,
+                    resourceId,
+                    resourceType,
+
+                    occurrence,
+                    artifactPrefix)
+            if (existingResourceAssignments.isNotEmpty()) {
+                log.info("Resolution with resourceId=($resourceId) and resourceType=($resourceType) already exist - will resolve " +
+                        "all resources not already resolved.")
+            }
+            return existingResourceAssignments
+        }
+        return emptyList()
+    }
+
+    // Update the resource assignment list with the status of the resource that have already been resolved
+    private fun updateResourceAssignmentWithExisting(resourceResolutionList: List<ResourceResolution>,
+                                                     resourceAssignmentList: MutableList<ResourceAssignment>) {
+        resourceResolutionList.forEach { resourceResolution ->
+            if (resourceResolution.status == BluePrintConstants.STATUS_SUCCESS) {
+                resourceAssignmentList.forEach {
+                    if (compareOne(resourceResolution, it)) {
+                        log.info("Resource ({}) already resolve: value=({})", it.name, resourceResolution.value)
+                        it.property!!.value = resourceResolution.value!!.asJsonPrimitive()
+                        it.status = resourceResolution.status
+                    }
+                }
+            }
+        }
+    }
+
+    // Comparision between what we have in the database vs what we have to assign.
+    private fun compareOne(resourceResolution: ResourceResolution, resourceAssignment: ResourceAssignment): Boolean {
+        return (resourceResolution.name == resourceAssignment.name
+                && resourceResolution.dictionaryName == resourceAssignment.dictionaryName
+                && resourceResolution.dictionarySource == resourceAssignment.dictionarySource
+                && resourceResolution.dictionaryVersion == resourceAssignment.version)
+    }
+
 }
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ScriptComponentExtensions.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ScriptComponentExtensions.kt
new file mode 100644 (file)
index 0000000..ab01b15
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright © 2019 IBM.
+ *
+ *  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
+
+import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
+
+
+/**
+ * Register the Resolution module exposed dependency
+ */
+fun BluePrintDependencyService.resourceResolutionService(): ResourceResolutionService =
+        instance(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
+
+
+suspend fun AbstractComponentFunction.storedContentFromResolvedArtifactNB(resolutionKey: String,
+                                                                          artifactName: String): String {
+    return BluePrintDependencyService.resourceResolutionService()
+            .resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey)
+}
+
+/**
+ * Return resolved and mashed artifact content for artifact prefix [artifactPrefix]
+ */
+suspend fun AbstractComponentFunction.contentFromResolvedArtifactNB(artifactPrefix: String): String {
+    return BluePrintDependencyService.resourceResolutionService()
+            .resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf())
+}
+
+
+/**
+ * Blocking Methods called from Jython Scripts
+ */
+
+fun AbstractComponentFunction.storedContentFromResolvedArtifact(resolutionKey: String, artifactName: String)
+        : String = runBlocking {
+    storedContentFromResolvedArtifactNB(resolutionKey, artifactName)
+}
+
+fun AbstractComponentFunction.contentFromResolvedArtifact(artifactPrefix: String): String = runBlocking {
+    contentFromResolvedArtifactNB(artifactPrefix)
+}
index 767a1fe..baabfd9 100644 (file)
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
 
 import com.fasterxml.jackson.annotation.JsonFormat
-import com.fasterxml.jackson.annotation.JsonProperty
+import io.swagger.annotations.ApiModelProperty
 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.ElementCollection
 import javax.persistence.Entity
 import javax.persistence.EntityListeners
 import javax.persistence.Id
@@ -38,47 +39,67 @@ import javax.persistence.TemporalType
 @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
-
+    @get:ApiModelProperty(value = "Name of the CBA.", required = true)
     @Column(name = "blueprint_name", nullable = false)
     var blueprintName: String? = null
 
+    @get:ApiModelProperty(value = "Version of the CBA.", required = true)
     @Column(name = "blueprint_version", nullable = false)
     var blueprintVersion: String? = null
 
+    @get:ApiModelProperty(value = "Artifact name for which to retrieve a resolved resource.", required = true)
     @Column(name = "artifact_name", nullable = false)
     var artifactName: String? = null
 
+    @get:ApiModelProperty(value = "Name of the resource.", required = true)
+    @Column(name = "name", nullable = false)
+    var name: String? = null
+
+    @get:ApiModelProperty(value = "Value of the resolution.", required = true)
+    @Lob
+    @Column(name = "value", nullable = false)
+    var value: String? = null
+
+    @get:ApiModelProperty(value = "Whether success of failure.", required = true)
     @Column(name = "status", nullable = false)
     var status: String? = null
 
-    @Column(name = "name", nullable = false)
-    var name: String? = null
+    @get:ApiModelProperty(value = "Resolution Key uniquely identifying the resolution of a given artifact within a CBA.",
+        required = true)
+    @Column(name = "resolution_key", nullable = false)
+    var resolutionKey: String? = null
+
+    @get:ApiModelProperty(value = "Resolution type.", required = true, example = "ServiceInstance, VfModule, VNF")
+    @Column(name = "resource_type", nullable = false)
+    var resourceType: String? = null
+
+    @get:ApiModelProperty(value = "ID associated with the resolution type in the inventory system.", required = true)
+    @Column(name = "resource_id", nullable = false)
+    var resourceId: String? = null
+
+    @get:ApiModelProperty(value = "If resolution occurred multiple time, this field provides the index.",
+        required = true)
+    @Column(name = "occurrence", nullable = false)
+    var occurrence: Int = 0
 
-    @Column(name = "dictionary_vname", nullable = false)
+    @get:ApiModelProperty(value = "Name of the data dictionary used for the resolution.", required = true)
+    @Column(name = "dictionary_name", nullable = false)
     var dictionaryName: String? = null
 
+    @get:ApiModelProperty(value = "Source associated with the data dictionary used for the resolution.",
+        required = true)
     @Column(name = "dictionary_status", nullable = false)
     var dictionarySource: String? = null
 
+    @get:ApiModelProperty(value = "Version of the data dictionary used for the resolution.", required = true)
     @Column(name = "dictionary_version", nullable = false)
     var dictionaryVersion: Int = 0
 
-    @Lob
-    @Column(name = "value", nullable = false)
-    var value: String? = null
+    @Id
+    @Column(name = "resource_resolution_id")
+    var id: String? = null
 
+    @get:ApiModelProperty(value = "Creation date of the resolution.", required = true)
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
     @LastModifiedDate
     @Temporal(TemporalType.TIMESTAMP)
index 81239be..5335b14 100644 (file)
@@ -24,7 +24,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeServ
 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.dao.EmptyResultDataAccessException
 import org.springframework.stereotype.Service
 import java.util.*
 
@@ -33,6 +33,49 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
 
     private val log = LoggerFactory.getLogger(ResourceResolutionDBService::class.toString())
 
+    suspend fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>, key: String,
+        occurrence: Int, artifactPrefix: String): List<ResourceResolution> {
+        return try {
+            val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+
+            val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
+            val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
+
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+                blueprintName,
+                blueprintVersion,
+                artifactPrefix,
+                key,
+                occurrence)
+        } catch (e: EmptyResultDataAccessException) {
+            emptyList()
+        }
+    }
+
+    suspend fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>, resourceId: String,
+        resourceType: String, occurrence: Int,
+        artifactPrefix: String): List<ResourceResolution> {
+        return try {
+
+            val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+
+            val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
+            val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
+
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+                blueprintName,
+                blueprintVersion,
+                artifactPrefix,
+                resourceId,
+                resourceType,
+                occurrence)
+        } catch (e: EmptyResultDataAccessException) {
+            emptyList()
+        }
+    }
+
     suspend fun readValue(blueprintName: String,
                           blueprintVersion: String,
                           artifactPrefix: String,
@@ -62,14 +105,15 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
     suspend fun readWithResourceIdAndResourceType(blueprintName: String,
                                                   blueprintVersion: String,
                                                   resourceId: String,
-                                                  resourceType: String): List<ResourceResolution> = withContext(Dispatchers.IO) {
-
-        resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
-            blueprintName,
-            blueprintVersion,
-            resourceId,
-            resourceType)
-    }
+                                                  resourceType: String): List<ResourceResolution> =
+        withContext(Dispatchers.IO) {
+
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
+                blueprintName,
+                blueprintVersion,
+                resourceId,
+                resourceType)
+        }
 
     suspend fun write(properties: Map<String, Any>,
                       bluePrintRuntimeService: BluePrintRuntimeService<*>,
@@ -80,12 +124,11 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
 
         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()
+
+        val resolutionKey = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] as String
+        val resourceId = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] as String
+        val resourceType = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] as String
+        val occurrence = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] as Int
 
         write(blueprintName,
             blueprintVersion,
@@ -93,7 +136,8 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
             resourceId,
             resourceType,
             artifactPrefix,
-            resourceAssignment)
+            resourceAssignment,
+            occurrence)
     }
 
     suspend fun write(blueprintName: String,
@@ -102,17 +146,23 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso
                       resourceId: String,
                       resourceType: String,
                       artifactPrefix: String,
-                      resourceAssignment: ResourceAssignment): ResourceResolution = withContext(Dispatchers.IO) {
+                      resourceAssignment: ResourceAssignment,
+                      occurrence: Int = 0): ResourceResolution = withContext(Dispatchers.IO) {
 
         val resourceResolution = ResourceResolution()
         resourceResolution.id = UUID.randomUUID().toString()
         resourceResolution.artifactName = artifactPrefix
+        resourceResolution.occurrence = occurrence
         resourceResolution.blueprintVersion = blueprintVersion
         resourceResolution.blueprintName = blueprintName
         resourceResolution.resolutionKey = resolutionKey
         resourceResolution.resourceType = resourceType
         resourceResolution.resourceId = resourceId
-        resourceResolution.value = JacksonUtils.getValue(resourceAssignment.property?.value!!).toString()
+        if (BluePrintConstants.STATUS_SUCCESS == resourceAssignment.status) {
+            resourceResolution.value = JacksonUtils.getValue(resourceAssignment.property?.value!!).toString()
+        } else {
+            resourceResolution.value = ""
+        }
         resourceResolution.name = resourceAssignment.name
         resourceResolution.dictionaryName = resourceAssignment.dictionaryName
         resourceResolution.dictionaryVersion = resourceAssignment.version
index d2cbf84..429041e 100644 (file)
@@ -34,4 +34,19 @@ interface ResourceResolutionRepository : JpaRepository<ResourceResolution, Strin
                                                                            blueprintVersion: String,
                                                                            resourceId: String,
                                                                            resourceType: String): List<ResourceResolution>
+
+    fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+        blueprintName: String?,
+        blueprintVersion: String?,
+        artifactName: String,
+        resolutionKey: String,
+        occurrence: Int): List<ResourceResolution>
+
+    fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+        blueprintName: String?,
+        blueprintVersion: String?,
+        artifactName: String,
+        resourceId: String,
+        resourceType: String,
+        occurrence: Int): 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
deleted file mode 100644 (file)
index efc130a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index ebb34ba..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 Bell Canada.
- * Modifications Copyright © 2019 IBM.
- *
- * 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.springframework.dao.DataIntegrityViolationException
-import org.springframework.stereotype.Service
-import java.util.*
-
-@Service
-class ResourceResolutionResultService(private val resourceResolutionRepository: ResourceResolutionResultRepository) {
-
-    suspend fun read(bluePrintRuntimeService: BluePrintRuntimeService<*>, artifactPrefix: String,
-                     resolutionKey: String): String = withContext(Dispatchers.IO) {
-
-        val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
-
-        val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]
-        val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]
-
-        resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
-                resolutionKey,
-                blueprintName,
-                blueprintVersion,
-                artifactPrefix).result!!
-    }
-
-    suspend fun write(properties: Map<String, Any>, result: String, bluePrintRuntimeService: BluePrintRuntimeService<*>,
-                      artifactPrefix: String) = withContext(Dispatchers.IO) {
-
-        val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
-
-        val resourceResolutionResult = ResourceResolutionResult()
-        resourceResolutionResult.id = UUID.randomUUID().toString()
-        resourceResolutionResult.artifactName = artifactPrefix
-        resourceResolutionResult.blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]
-        resourceResolutionResult.blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]
-        resourceResolutionResult.resolutionKey =
-                properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY].toString()
-        resourceResolutionResult.result = result
-
-        try {
-            resourceResolutionRepository.saveAndFlush(resourceResolutionResult)
-        } catch (ex: DataIntegrityViolationException) {
-            throw BluePrintException("Failed to store resource resolution result.", ex)
-        }
-    }
-
-    suspend fun readByKey(resolutionResultId: String): String = withContext(Dispatchers.IO) {
-
-        resourceResolutionRepository.getOne(resolutionResultId).result!!
-    }
-
-    suspend fun deleteByKey(resolutionResultId: String): Unit = withContext(Dispatchers.IO) {
-
-        val row = resourceResolutionRepository.getOne(resolutionResultId)
-        resourceResolutionRepository.delete(row)
-        resourceResolutionRepository.flush()
-    }
-}
\ No newline at end of file
@@ -17,6 +17,7 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
 
 import com.fasterxml.jackson.annotation.JsonFormat
+import io.swagger.annotations.ApiModelProperty
 import org.hibernate.annotations.Proxy
 import org.springframework.data.annotation.LastModifiedDate
 import org.springframework.data.jpa.domain.support.AuditingEntityListener
@@ -33,30 +34,50 @@ import javax.persistence.TemporalType
 
 @EntityListeners(AuditingEntityListener::class)
 @Entity
-@Table(name = "RESOURCE_RESOLUTION_RESULT")
+@Table(name = "TEMPLATE_RESOLUTION")
 @Proxy(lazy = false)
-class ResourceResolutionResult : Serializable {
-
-    @Id
-    @Column(name = "resource_resolution_result_id")
-    var id: String? = null
-
-    @Column(name = "resolution_key", nullable = false)
-    var resolutionKey: String? = null
+class TemplateResolution : Serializable {
 
+    @get:ApiModelProperty(value = "Name of the CBA.", required = true)
     @Column(name = "blueprint_name", nullable = false)
     var blueprintName: String? = null
 
+    @get:ApiModelProperty(value = "Version of the CBA.", required = true)
     @Column(name = "blueprint_version", nullable = false)
     var blueprintVersion: String? = null
 
+    @get:ApiModelProperty(value = "Artifact name for which to retrieve a resolved resource.", required = true)
     @Column(name = "artifact_name", nullable = false)
     var artifactName: String? = null
 
+    @get:ApiModelProperty(value = "Rendered template.", required = true)
     @Lob
     @Column(name = "result", nullable = false)
     var result: String? = null
 
+    @get:ApiModelProperty(value = "Resolution Key uniquely identifying the resolution of a given artifact within a CBA.",
+        required = true)
+    @Column(name = "resolution_key", nullable = false)
+    var resolutionKey: String? = null
+
+    @get:ApiModelProperty(value = "Resolution type.", required = true, example = "ServiceInstance, VfModule, VNF")
+    @Column(name = "resource_type", nullable = false)
+    var resourceType: String? = null
+
+    @get:ApiModelProperty(value = "ID associated with the resolution type in the inventory system.", required = true)
+    @Column(name = "resource_id", nullable = false)
+    var resourceId: String? = null
+
+    @get:ApiModelProperty(value = "If resolution occurred multiple time, this field provides the index.",
+        required = true)
+    @Column(name = "occurrence", nullable = false)
+    var occurrence: Int = 0
+
+    @Id
+    @Column(name = "template_resolution_id")
+    var id: String? = null
+
+    @get:ApiModelProperty(value = "Creation date of the resolution.", required = true)
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
     @LastModifiedDate
     @Temporal(TemporalType.TIMESTAMP)
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionRepository.kt
new file mode 100644 (file)
index 0000000..440663f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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
+import javax.transaction.Transactional
+
+interface TemplateResolutionRepository : JpaRepository<TemplateResolution, String> {
+
+    fun findByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+        resourceId: String,
+        resourceType: String,
+        blueprintName: String?,
+        blueprintVersion: String?,
+        artifactName: String,
+        occurrence: Int): TemplateResolution ?
+
+    fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+        key: String,
+        blueprintName: String?,
+        blueprintVersion: String?,
+        artifactName: String,
+        occurrence: Int): TemplateResolution ?
+
+    @Transactional
+    fun deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+        resourceId: String,
+        resourceType: String,
+        blueprintName: String?,
+        blueprintVersion: String?,
+        artifactName: String,
+        occurrence: Int)
+
+    @Transactional
+    fun deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+        key: String,
+        blueprintName: String?,
+        blueprintVersion: String?,
+        artifactName: String,
+        occurrence: Int)
+}
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionService.kt
new file mode 100644 (file)
index 0000000..55f7e77
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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.slf4j.LoggerFactory
+import org.springframework.dao.DataIntegrityViolationException
+import org.springframework.dao.EmptyResultDataAccessException
+import org.springframework.stereotype.Service
+import java.util.*
+
+@Service
+class TemplateResolutionService(private val templateResolutionRepository: TemplateResolutionRepository) {
+
+    private val log = LoggerFactory.getLogger(TemplateResolutionService::class.toString())
+
+    suspend fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+        bluePrintRuntimeService: BluePrintRuntimeService<*>,
+        artifactPrefix: String,
+        resolutionKey: String): String =
+        withContext(Dispatchers.IO) {
+
+            val metadata = bluePrintRuntimeService.bluePrintContext().metadata!!
+
+            val blueprintVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION]!!
+            val blueprintName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME]!!
+
+            findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(blueprintName,
+                blueprintVersion,
+                artifactPrefix,
+                resolutionKey)
+        }
+
+    suspend fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(blueprintName: String,
+                                                                                      blueprintVersion: String,
+                                                                                      artifactPrefix: String,
+                                                                                      resolutionKey: String,
+                                                                                      occurrence: Int = 0): String =
+        withContext(Dispatchers.IO) {
+
+            templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                resolutionKey,
+                blueprintName,
+                blueprintVersion,
+                artifactPrefix,
+                occurrence)?.result ?: throw EmptyResultDataAccessException(1)
+        }
+
+    suspend fun findByResoureIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactName(blueprintName: String,
+                                                                                                 blueprintVersion: String,
+                                                                                                 artifactPrefix: String,
+                                                                                                 resourceId: String,
+                                                                                                 resourceType: String,
+                                                                                                 occurrence: Int = 0): String =
+        withContext(Dispatchers.IO) {
+
+            templateResolutionRepository.findByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                resourceId,
+                resourceType,
+                blueprintName,
+                blueprintVersion,
+                artifactPrefix,
+                occurrence)?.result!!
+        }
+
+    suspend fun write(properties: Map<String, Any>,
+                      result: String, bluePrintRuntimeService: BluePrintRuntimeService<*>,
+                      artifactPrefix: String): TemplateResolution = 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_RESOLUTION_KEY] as String
+        val resourceId = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] as String
+        val resourceType = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] as String
+        val occurrence = properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] as Int
+
+        write(blueprintName,
+            blueprintVersion,
+            artifactPrefix,
+            result,
+            occurrence,
+            resolutionKey,
+            resourceId,
+            resourceType)
+    }
+
+    suspend fun write(blueprintName: String, blueprintVersion: String, artifactPrefix: String,
+                      template: String, occurrence: Int = 0, resolutionKey: String = "", resourceId: String = "",
+                      resourceType: String = ""): TemplateResolution =
+        withContext(Dispatchers.IO) {
+
+            val resourceResolutionResult = TemplateResolution()
+            resourceResolutionResult.id = UUID.randomUUID().toString()
+            resourceResolutionResult.artifactName = artifactPrefix
+            resourceResolutionResult.blueprintVersion = blueprintVersion
+            resourceResolutionResult.blueprintName = blueprintName
+            resourceResolutionResult.resolutionKey = resolutionKey
+            resourceResolutionResult.resourceId = resourceId
+            resourceResolutionResult.resourceType = resourceType
+            resourceResolutionResult.result = template
+            resourceResolutionResult.occurrence = occurrence
+
+            // Overwrite template resolution-key of resourceId/resourceType already existant
+            if (resolutionKey.isNotEmpty()) {
+                templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    resolutionKey, blueprintName, blueprintVersion, artifactPrefix, occurrence)?.let {
+                    log.info("Overwriting template resolution for blueprintName=($blueprintVersion), blueprintVersion=($blueprintName), " +
+                            "artifactName=($artifactPrefix) and resolutionKey=($resolutionKey)")
+                    templateResolutionRepository.deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                        resolutionKey,
+                        blueprintName,
+                        blueprintVersion,
+                        artifactPrefix,
+                        occurrence)
+                }
+            } else if (resourceId.isNotEmpty() && resourceType.isNotEmpty()) {
+                templateResolutionRepository.findByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    resourceId, resourceType, blueprintName, blueprintVersion, artifactPrefix, occurrence)?.let {
+                    log.info("Overwriting template resolution for blueprintName=($blueprintVersion), blueprintVersion=($blueprintName), " +
+                            "artifactName=($artifactPrefix), resourceId=($resourceId) and resourceType=($resourceType)")
+                    templateResolutionRepository.deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                        resourceId,
+                        resourceType,
+                        blueprintName,
+                        blueprintVersion,
+                        artifactPrefix,
+                        occurrence)
+                }
+            }
+            try {
+                templateResolutionRepository.saveAndFlush(resourceResolutionResult)
+            } catch (ex: DataIntegrityViolationException) {
+                throw BluePrintException("Failed to store resource api result.", ex)
+            }
+        }
+}
\ No newline at end of file
index 7a8d6ec..49cb83e 100644 (file)
@@ -20,6 +20,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.pro
 
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.CapabilityResourceSource
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
@@ -82,6 +83,7 @@ open class CapabilityResourceResolutionProcessor(private val applicationContext:
     override suspend fun recoverNB(runtimeException: RuntimeException, resourceAssignment: ResourceAssignment) {
         raRuntimeService.getBluePrintError()
                 .addError("Failed in CapabilityResourceResolutionProcessor : ${runtimeException.message}")
+        ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, runtimeException.message)
     }
 
     suspend fun scriptInstance(scriptType: String, scriptClassReference: String, instanceDependencies: List<String>)
index 39ffe5e..1abcea8 100644 (file)
@@ -93,6 +93,7 @@ abstract class ResourceAssignmentProcessor : BlueprintFunctionNode<ResourceAssig
         } catch (runtimeException: RuntimeException) {
             log.error("failed in ${getName()} : ${runtimeException.message}", runtimeException)
             recoverNB(runtimeException, resourceAssignment)
+            return false
         }
         return true
     }
index 3a30ae9..39076b4 100644 (file)
@@ -1,9 +1,5 @@
 /*
- * Copyright © 2017-2018 AT&T Intellectual Property.
- *
- * Modifications Copyright © 2018 IBM.
- *
- *  Modifications Copyright © 2019 IBM, Bell Canada.
+ * Copyright © 2018 Bell Canada
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution
 
 import com.fasterxml.jackson.databind.JsonNode
+import io.mockk.coEvery
+import io.mockk.every
+import io.mockk.mockk
 import kotlinx.coroutines.runBlocking
+import org.junit.Before
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties
-import org.onap.ccsdk.cds.blueprintsprocessor.core.BlueprintPropertyConfiguration
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
-import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
-import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.PayloadUtils
-import org.onap.ccsdk.cds.blueprintsprocessor.db.BluePrintDBLibConfiguration
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.*
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
-import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
-import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
-import org.onap.ccsdk.cds.controllerblueprints.core.putJsonElement
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintError
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration
-import org.springframework.context.annotation.ComponentScan
-import org.springframework.test.context.ContextConfiguration
-import org.springframework.test.context.TestPropertySource
-import org.springframework.test.context.junit4.SpringRunner
-
-@RunWith(SpringRunner::class)
-@ContextConfiguration(classes = [ResourceResolutionServiceImpl::class,
-    InputResourceResolutionProcessor::class, DefaultResourceResolutionProcessor::class,
-    DatabaseResourceAssignmentProcessor::class, RestResourceResolutionProcessor::class,
-    CapabilityResourceResolutionProcessor::class,
-    BlueprintPropertyConfiguration::class, BluePrintProperties::class,
-    BluePrintDBLibConfiguration::class, BluePrintLoadConfiguration::class])
-@TestPropertySource(locations = ["classpath:application-test.properties"])
-@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
-@EnableAutoConfiguration
+import java.lang.RuntimeException
+import kotlin.test.assertEquals
+import kotlin.test.fail
+
 class ResourceResolutionComponentTest {
 
-    @Autowired
-    lateinit var resourceResolutionComponent: ResourceResolutionComponent
+    private val resourceResolutionService = mockk<ResourceResolutionService>()
+    private val resourceResolutionComponent = ResourceResolutionComponent(resourceResolutionService)
 
-    @Test
-    fun testProcess() {
-        runBlocking {
+    private val resolutionKey = "resolutionKey"
+    private val resourceId = "1"
+    private val resourceType = "ServiceInstance"
+    private val occurrence = 1
+    private val props = mutableMapOf<String, JsonNode>()
+    private val bluePrintRuntimeService = mockk<BluePrintRuntimeService<*>>()
+    private val artifactNames = listOf("template")
+    private val nodeTemplateName = "nodeTemplateName"
 
-            val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234",
-                    "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+    private val executionRequest = ExecutionServiceInput()
 
-            val executionServiceInput = JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
-                    ExecutionServiceInput::class.java)!!
 
-            // Prepare Inputs
-            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService, executionServiceInput.payload, "resource-assignment")
+    @Before
+    fun setup() {
 
-            val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
-            stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "resource-assignment")
-            stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_INTERFACE, "ResourceResolutionComponent")
-            stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
-            bluePrintRuntimeService.put("resource-assignment-step-inputs", stepMetaData.asJsonNode())
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = true.asJsonPrimitive()
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey.asJsonPrimitive()
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId.asJsonPrimitive()
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType.asJsonPrimitive()
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence.asJsonPrimitive()
+        props[ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES] = JacksonUtils.jsonNodeFromObject(artifactNames)
 
-            resourceResolutionComponent.bluePrintRuntimeService = bluePrintRuntimeService
-            val stepInputData = StepData().apply {
-                name = "resource-assignment"
-                properties = stepMetaData
+        resourceResolutionComponent.operationInputs = props
+        resourceResolutionComponent.bluePrintRuntimeService = bluePrintRuntimeService
+        resourceResolutionComponent.nodeTemplateName = nodeTemplateName
+
+        resourceResolutionComponent.executionServiceInput = executionRequest
+        resourceResolutionComponent.processId = "12"
+        resourceResolutionComponent.workflowName = "workflow"
+        resourceResolutionComponent.stepName = "step"
+        resourceResolutionComponent.interfaceName = "interfaceName"
+        resourceResolutionComponent.operationName = "operationName"
+    }
+
+    @Test
+    fun processNBWithResolutionKeyAndResourceIdAndResourceTypeTestException() {
+        runBlocking {
+            try {
+                resourceResolutionComponent.processNB(executionRequest)
+            } catch (e: BluePrintProcessorException) {
+                assertEquals("Can't proceed with the resolution: either provide resolution-key OR combination of resource-id and resource-type.",
+                    e.message)
+                return@runBlocking
             }
-            executionServiceInput.stepData = stepInputData
-            resourceResolutionComponent.applyNB(executionServiceInput)
+            fail()
         }
     }
 
     @Test
-    fun testRecover() {
+    fun processNBWithResourceIdTestException() {
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = "".asJsonPrimitive()
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = "".asJsonPrimitive()
+
+        runBlocking {
+            try {
+                resourceResolutionComponent.processNB(executionRequest)
+            } catch (e: BluePrintProcessorException) {
+                assertEquals("Can't proceed with the resolution: both resource-id and resource-type should be provided, one of them is missing.",
+                    e.message)
+                return@runBlocking
+            }
+            fail()
+        }
+    }
+
+    @Test
+    fun processNBWithEmptyResourceTypeResourceIdResolutionKeyTestException() {
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = "".asJsonPrimitive()
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = "".asJsonPrimitive()
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = "".asJsonPrimitive()
+
         runBlocking {
-            val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234",
-                    "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+            try {
+                resourceResolutionComponent.processNB(executionRequest)
+            } catch (e: BluePrintProcessorException) {
+                assertEquals("Can't proceed with the resolution: can't persist resolution without a correlation key. " +
+                        "Either provide a resolution-key OR combination of resource-id and resource-type OR set `storeResult` to false.",
+                    e.message)
+                return@runBlocking
+            }
+            fail()
+        }
+    }
 
-            val executionServiceInput = JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
-                    ExecutionServiceInput::class.java)!!
+    @Test
+    fun processNBTest() {
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = "".asJsonPrimitive()
 
-            // Prepare Inputs
-            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService, executionServiceInput.payload, "resource-assignment")
+        val properties = mutableMapOf<String, Any>()
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = true
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
+        properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
 
-            val stepMetaData: MutableMap<String, JsonNode> = hashMapOf()
-            stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE, "resource-assignment")
-            stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_INTERFACE, "ResourceResolutionComponent")
-            stepMetaData.putJsonElement(BluePrintConstants.PROPERTY_CURRENT_OPERATION, "process")
-            bluePrintRuntimeService.put("resource-assignment-step-inputs", stepMetaData.asJsonNode())
+        coEvery {
+            resourceResolutionService.resolveResources(any<BluePrintRuntimeService<*>>(),
+                any<String>(),
+                any<List<String>>(),
+                any<MutableMap<String, Any>>())
+        } returns mutableMapOf()
+        every { bluePrintRuntimeService.setNodeTemplateAttributeValue(any(), any(), any()) } returns Unit
 
-            resourceResolutionComponent.bluePrintRuntimeService = bluePrintRuntimeService
-            val stepInputData = StepData().apply {
-                name = "resource-assignment"
-                properties = stepMetaData
-            }
-            executionServiceInput.stepData = stepInputData
-            resourceResolutionComponent.recoverNB(RuntimeException("TEST PASSED"), executionServiceInput)
+
+        runBlocking {
+            resourceResolutionComponent.processNB(executionRequest)
+        }
+
+// FIXME add verification
+//        coVerify {
+//            resourceResolutionService.resolveResources(eq(bluePrintRuntimeService),
+//                eq(nodeTemplateName), eq(artifactNames), eq(properties))
+//        }
+    }
+
+    @Test
+    fun testRecover() {
+        runBlocking {
+            val blueprintError = BluePrintError()
+            val exception = RuntimeException("message")
+            every { bluePrintRuntimeService.getBluePrintError() } returns blueprintError
+            resourceResolutionComponent.recoverNB(exception, executionRequest)
+
+            assertEquals(1, blueprintError.errors.size)
         }
     }
 }
\ No newline at end of file
index 4a3e75c..f1ad030 100644 (file)
@@ -20,6 +20,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution
 
 import kotlinx.coroutines.runBlocking
 import org.junit.Assert
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties
@@ -28,6 +29,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInpu
 import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.PayloadUtils
 import org.onap.ccsdk.cds.blueprintsprocessor.db.BluePrintDBLibConfiguration
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.*
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
@@ -63,12 +65,27 @@ class ResourceResolutionServiceTest {
     @Autowired
     lateinit var resourceResolutionService: ResourceResolutionService
 
+    private val props = hashMapOf<String, Any>()
+    private val resolutionKey = "resolutionKey"
+    private val resourceId = "1"
+    private val resourceType = "ServiceInstance"
+    private val occurrence = 0
+
+    @Before
+    fun setup() {
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = true
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+    }
+
     @Test
     fun testRegisteredSource() {
         val sources = resourceResolutionService.registeredResourceSources()
         assertNotNull(sources, "failed to get registered sources")
         assertTrue(sources.containsAll(arrayListOf("source-input", "source-default", "source-processor-db",
-                "source-rest")), "failed to get registered sources : $sources")
+            "source-rest")), "failed to get registered sources : $sources")
     }
 
     @Test
@@ -79,15 +96,27 @@ class ResourceResolutionServiceTest {
             Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
 
             val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234",
-                    "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+                "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
 
-            val executionServiceInput = JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
+            val executionServiceInput =
+                JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
                     ExecutionServiceInput::class.java)!!
 
+
+            val resourceAssignmentRuntimeService =
+                ResourceAssignmentUtils.transformToRARuntimeService(bluePrintRuntimeService,
+                    "testResolveResource")
+
+
             // Prepare Inputs
-            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService, executionServiceInput.payload, "resource-assignment")
+            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService,
+                executionServiceInput.payload,
+                "resource-assignment")
 
-            resourceResolutionService.resolveResources(bluePrintRuntimeService, "resource-assignment", "baseconfig", mapOf())
+            resourceResolutionService.resolveResources(resourceAssignmentRuntimeService,
+                "resource-assignment",
+                "baseconfig",
+                props)
 
         }
     }
@@ -99,17 +128,23 @@ class ResourceResolutionServiceTest {
             Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
 
             val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234",
-                    "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+                "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
 
-            val executionServiceInput = JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
+            val executionServiceInput =
+                JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
                     ExecutionServiceInput::class.java)!!
 
             val artefactNames = listOf("baseconfig", "another")
 
             // Prepare Inputs
-            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService, executionServiceInput.payload, "resource-assignment")
-
-            resourceResolutionService.resolveResources(bluePrintRuntimeService, "resource-assignment", artefactNames, mapOf())
+            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService,
+                executionServiceInput.payload,
+                "resource-assignment")
+
+            resourceResolutionService.resolveResources(bluePrintRuntimeService,
+                "resource-assignment",
+                artefactNames,
+                props)
         }
 
     }
@@ -121,17 +156,61 @@ class ResourceResolutionServiceTest {
             Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
 
             val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234",
-                    "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+                "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
 
-            val executionServiceInput = JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
+            val executionServiceInput =
+                JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
                     ExecutionServiceInput::class.java)!!
 
+            val resourceAssignmentRuntimeService =
+                ResourceAssignmentUtils.transformToRARuntimeService(bluePrintRuntimeService,
+                    "testResolveResourcesWithMappingAndTemplate")
+
             val artifactPrefix = "another"
 
             // Prepare Inputs
-            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService, executionServiceInput.payload, "resource-assignment")
+            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService,
+                executionServiceInput.payload,
+                "resource-assignment")
+
+            resourceResolutionService.resolveResources(resourceAssignmentRuntimeService,
+                "resource-assignment",
+                artifactPrefix,
+                props)
+        }
+    }
+
+
+    @Test
+    fun testResolveResourcesWithResourceIdAndResourceType() {
 
-            resourceResolutionService.resolveResources(bluePrintRuntimeService, "resource-assignment", artifactPrefix, mapOf<String, String>())
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = ""
+
+        runBlocking {
+            Assert.assertNotNull("failed to create ResourceResolutionService", resourceResolutionService)
+
+            val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime("1234",
+                "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+
+            val executionServiceInput =
+                JacksonUtils.readValueFromClassPathFile("payload/requests/sample-resourceresolution-request.json",
+                    ExecutionServiceInput::class.java)!!
+
+            val resourceAssignmentRuntimeService =
+                ResourceAssignmentUtils.transformToRARuntimeService(bluePrintRuntimeService,
+                    "testResolveResourcesWithMappingAndTemplate")
+
+            val artifactPrefix = "another"
+
+            // Prepare Inputs
+            PayloadUtils.prepareInputsFromWorkflowPayload(bluePrintRuntimeService,
+                executionServiceInput.payload,
+                "resource-assignment")
+
+            resourceResolutionService.resolveResources(resourceAssignmentRuntimeService,
+                "resource-assignment",
+                artifactPrefix,
+                props)
         }
     }
 }
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt
new file mode 100644 (file)
index 0000000..dcf2e64
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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 io.mockk.every
+import io.mockk.mockk
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+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.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
+import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
+import org.springframework.dao.EmptyResultDataAccessException
+import kotlin.test.assertEquals
+
+open class ResourceResolutionDBServiceTest {
+
+    private val resourceResolutionRepository = mockk<ResourceResolutionRepository>()
+
+    private val resourceResolutionDBService = ResourceResolutionDBService(resourceResolutionRepository)
+
+    private val resolutionKey = "resolutionKey"
+    private val resourceId = "1"
+    private val resourceType = "ServiceInstance"
+    private val occurrence = 0
+    private val artifactPrefix = "template"
+    private val blueprintName = "blueprintName"
+    private val blueprintVersion = "1.0.0"
+    private val metadata = hashMapOf<String, String>()
+    private val props = hashMapOf<String, Any>()
+    private val bluePrintContext = mockk<BluePrintContext>()
+    private val bluePrintRuntimeService = mockk<DefaultBluePrintRuntimeService>()
+
+    @Before
+    fun setup() {
+        metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION] = blueprintVersion
+        metadata[BluePrintConstants.METADATA_TEMPLATE_NAME] = blueprintName
+
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+
+        every { bluePrintContext.metadata } returns metadata
+
+        every { bluePrintRuntimeService.bluePrintContext() } returns bluePrintContext
+    }
+
+    @Test
+    fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrenceTest() {
+
+        val rr1 = ResourceResolution()
+        val rr2 = ResourceResolution()
+
+        val list = listOf(rr1, rr2)
+        every {
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+                any(), any(), any(), any(), any())
+        } returns list
+        runBlocking {
+
+            val res =
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+                    bluePrintRuntimeService, resolutionKey, occurrence, artifactPrefix)
+
+            assertEquals(2, res.size)
+        }
+    }
+
+    @Test
+    fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrenceTestException() {
+        every {
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+                any(), any(), any(), any(), any())
+        } throws EmptyResultDataAccessException(1)
+        runBlocking {
+            val res =
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyAndOccurrence(
+                    bluePrintRuntimeService, resolutionKey, occurrence, artifactPrefix)
+
+            assert(res.isEmpty())
+        }
+    }
+
+    @Test
+    fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrenceTest() {
+
+        val rr1 = ResourceResolution()
+        val rr2 = ResourceResolution()
+        val list = listOf(rr1, rr2)
+        every {
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+                any(), any(), any(), any(), any(), any())
+        } returns list
+        runBlocking {
+
+            val res =
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+                    bluePrintRuntimeService, resourceId, resourceType, occurrence, artifactPrefix)
+
+            assertEquals(2, res.size)
+        }
+    }
+
+    @Test
+    fun findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrenceTestException() {
+        every {
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+                any(), any(), any(), any(), any(), any())
+        } throws EmptyResultDataAccessException(1)
+        runBlocking {
+            val res =
+                resourceResolutionDBService.findByBlueprintNameAndBlueprintVersionAndArtifactNameAndResourceIdAndResourceTypeAndOccurrence(
+                    bluePrintRuntimeService, resourceId, resourceType, occurrence, artifactPrefix)
+
+            assert(res.isEmpty())
+        }
+    }
+
+    @Test
+    fun readValueTest() {
+        val rr = ResourceResolution()
+        rr.name = "bob"
+        rr.value = "testValue"
+        every {
+            resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndName(
+                any(), any(), any(), any(), any())
+        } returns rr
+        runBlocking {
+            val res =
+                resourceResolutionDBService.readValue(
+                    blueprintName, blueprintVersion, artifactPrefix, resolutionKey, "bob")
+
+            assertEquals(rr.name, res.name)
+            assertEquals(rr.value, res.value)
+        }
+    }
+
+    @Test
+    fun readWithResolutionKeyTest() {
+        val rr1 = ResourceResolution()
+        val rr2 = ResourceResolution()
+        val list = listOf(rr1, rr2)
+        every {
+            resourceResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+                any(), any(), any(), any())
+        } returns list
+        runBlocking {
+            val res =
+                resourceResolutionDBService.readWithResolutionKey(
+                    blueprintName, blueprintVersion, artifactPrefix, resolutionKey)
+            assertEquals(2, res.size)
+        }
+    }
+
+    @Test
+    fun readWithResourceIdAndResourceTypeTest() {
+        val rr1 = ResourceResolution()
+        val rr2 = ResourceResolution()
+        val list = listOf(rr1, rr2)
+        every {
+            resourceResolutionRepository.findByBlueprintNameAndBlueprintVersionAndResourceIdAndResourceType(
+                any(), any(), any(), any())
+        } returns list
+        runBlocking {
+            val res =
+                resourceResolutionDBService.readWithResourceIdAndResourceType(
+                    blueprintName, blueprintVersion, resourceId, resourceType)
+            assertEquals(2, res.size)
+        }
+    }
+
+    @Test
+    fun writeTest() {
+        val resourceResolution = ResourceResolution()
+        val resourceAssignment = ResourceAssignment()
+        resourceAssignment.property?.status = BluePrintConstants.STATUS_SUCCESS
+        resourceAssignment.property?.value = "result".asJsonPrimitive()
+        resourceAssignment.dictionarySource = "ddSource"
+        resourceAssignment.dictionaryName = "ddName"
+        resourceAssignment.version = 1
+        resourceAssignment.name = "test"
+        every {
+            resourceResolutionRepository.saveAndFlush(any<ResourceResolution>())
+        } returns resourceResolution
+        runBlocking {
+            val res =
+                resourceResolutionDBService.write(
+                    props, bluePrintRuntimeService, artifactPrefix, resourceAssignment)
+
+            assertEquals(resourceResolution, res)
+        }
+    }
+}
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/TemplateResolutionServiceTest.kt
new file mode 100644 (file)
index 0000000..48c6f02
--- /dev/null
@@ -0,0 +1,137 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db
+
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+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.service.BluePrintContext
+import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService
+import org.springframework.dao.EmptyResultDataAccessException
+import kotlin.test.assertEquals
+
+class TemplateResolutionServiceTest {
+
+    private val templateResolutionRepository = mockk<TemplateResolutionRepository>()
+
+    private val templateResolutionService = TemplateResolutionService(templateResolutionRepository)
+
+    private val resolutionKey = "resolutionKey"
+    private val resourceId = "1"
+    private val resourceType = "ServiceInstance"
+    private val occurrence = 0
+    private val artifactPrefix = "template"
+    private val blueprintName = "blueprintName"
+    private val blueprintVersion = "1.0.0"
+    private val result = "result"
+    private val metadata = hashMapOf<String, String>()
+    private val props = hashMapOf<String, Any>()
+    private val bluePrintContext = mockk<BluePrintContext>()
+    private val bluePrintRuntimeService = mockk<DefaultBluePrintRuntimeService>()
+
+    @Before
+    fun setup() {
+        metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION] = blueprintVersion
+        metadata[BluePrintConstants.METADATA_TEMPLATE_NAME] = blueprintName
+
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
+
+        every { bluePrintContext.metadata } returns metadata
+
+        every { bluePrintRuntimeService.bluePrintContext() } returns bluePrintContext
+    }
+
+    @Test
+    fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameTest() {
+        val tr = TemplateResolution()
+        tr.result = "res"
+        runBlocking {
+            every {
+                templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    any(), any(), any(), any(), any())
+            } returns tr
+            val res =
+                templateResolutionService.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+                    bluePrintRuntimeService, artifactPrefix, resolutionKey)
+            assertEquals(tr.result, res)
+        }
+    }
+
+    @Test(expected = EmptyResultDataAccessException::class)
+    fun findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameTestException() {
+        val tr = TemplateResolution()
+        runBlocking {
+            every {
+                templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    any(), any(), any(), any(), any())
+            } returns tr
+            templateResolutionService.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+                bluePrintRuntimeService, artifactPrefix, resolutionKey)
+        }
+    }
+
+    @Test
+    fun writeWithResolutionKeyTest() {
+        val tr = TemplateResolution()
+        runBlocking {
+            every { templateResolutionRepository.saveAndFlush(any<TemplateResolution>()) } returns tr
+            every {
+                templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    any(), any(), any(), any(), any())
+            } returns null
+            val res = templateResolutionService.write(props, result, bluePrintRuntimeService, artifactPrefix)
+            assertEquals(tr, res)
+        }
+    }
+
+    @Test
+    fun writeWithResolutionKeyExistingTest() {
+        val tr = TemplateResolution()
+        runBlocking {
+            every { templateResolutionRepository.saveAndFlush(any<TemplateResolution>()) } returns tr
+            every {
+                templateResolutionRepository.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    any(), any(), any(), any(), any())
+            } returns tr
+            every {
+                templateResolutionRepository.deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    any(), any(), any(), any(), any())
+            } returns Unit
+            val res = templateResolutionService.write(props, result, bluePrintRuntimeService, artifactPrefix)
+            verify {
+                templateResolutionRepository.deleteByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    eq(resolutionKey), eq(blueprintName), eq(blueprintVersion), eq(artifactPrefix), eq(occurrence))
+            }
+            assertEquals(tr, res)
+        }
+    }
+
+    @Test
+    fun writeWithResourceIdResourceTypeExistingTest() {
+        props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = ""
+        val tr = TemplateResolution()
+        runBlocking {
+            every { templateResolutionRepository.saveAndFlush(any<TemplateResolution>()) } returns tr
+            every {
+                templateResolutionRepository.findByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    any(), any(), any(), any(), any(), any())
+            } returns tr
+            every {
+                templateResolutionRepository.deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    any(), any(), any(), any(), any(), any())
+            } returns Unit
+            val res = templateResolutionService.write(props, result, bluePrintRuntimeService, artifactPrefix)
+            verify {
+                templateResolutionRepository.deleteByResourceIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactNameAndOccurrence(
+                    eq(resourceId), eq(resourceType), eq(blueprintName), eq(blueprintVersion), eq(artifactPrefix), eq(occurrence))
+            }
+            assertEquals(tr, res)
+        }
+    }
+}
\ No newline at end of file
index be02330..e806630 100644 (file)
@@ -98,7 +98,7 @@ class MockRestResourceResolutionProcessor(private val blueprintRestLibPropertySe
             }
         } catch (e: Exception) {
             ResourceAssignmentUtils.setFailedResourceDataValue(executionRequest, e.message)
-            throw BluePrintProcessorException("Failed in template key ($executionRequest) assignments with: ${e.message}",
+            throw BluePrintProcessorException("Failed in template resolutionKey ($executionRequest) assignments with: ${e.message}",
                     e)
         }
     }
index f73197e..153e889 100644 (file)
@@ -71,34 +71,6 @@ class DatabaseResourceResolutionProcessorTest {
 
             val processorName = databaseResourceAssignmentProcessor.applyNB(resourceAssignment)
             assertNotNull(processorName, "couldn't get Database resource assignment processor name")
-            println(processorName)
-        }
-    }
-
-    @Test
-    fun `test database resource resolution primary db`() {
-        runBlocking {
-            val bluePrintContext = BluePrintMetadataUtils.getBluePrintContext(
-                    "./../../../../components/model-catalog/blueprint-model/test-blueprint/capability_python")
-
-            val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService("1234", bluePrintContext)
-
-            databaseResourceAssignmentProcessor.raRuntimeService = resourceAssignmentRuntimeService
-            databaseResourceAssignmentProcessor.resourceDictionaries = ResourceAssignmentUtils
-                    .resourceDefinitions(bluePrintContext.rootPath)
-
-            val resourceAssignment = ResourceAssignment().apply {
-                name = "service-instance-id"
-                dictionaryName = "service-instance-id"
-                dictionarySource = "primary-db"
-                property = PropertyDefinition().apply {
-                    type = "string"
-                }
-            }
-
-            val processorName = databaseResourceAssignmentProcessor.applyNB(resourceAssignment)
-            assertNotNull(processorName, "couldn't get Database resource assignment processor name")
-            println(processorName)
         }
     }
 }
\ No newline at end of file
index b2064cb..ede833c 100644 (file)
@@ -25,28 +25,42 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPrope
 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
 
-
+@Deprecated("Methods defined as extension function of AbstractComponentFunction")
 abstract class RestconfComponentFunction : AbstractScriptComponentFunction() {
 
+    @Deprecated("Defined in AbstractScriptComponentFunction extension class")
     open fun bluePrintRestLibPropertyService(): BluePrintRestLibPropertyService =
             functionDependencyInstanceAsType(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY)
 
+    @Deprecated(" Use resourceResolutionService method directly",
+            replaceWith = ReplaceWith("resourceResolutionService()",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resourceResolutionService"))
     open fun resourceResolutionService(): ResourceResolutionService =
             functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION)
 
 
+    @Deprecated("Defined in AbstractScriptComponentFunction extension class")
     fun restClientService(selector: String): BlueprintWebClientService {
         return bluePrintRestLibPropertyService().blueprintWebClientService(selector)
     }
 
+    @Deprecated(" Use storedContentFromResolvedArtifact method directly",
+            replaceWith = ReplaceWith("storedContentFromResolvedArtifact(resolutionKey, artifactName)",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.storedContentFromResolvedArtifact"))
     fun resolveFromDatabase(resolutionKey: String, artifactName: String): String = runBlocking {
         resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey)
     }
 
+    @Deprecated(" Use artifactContent method directly",
+            replaceWith = ReplaceWith("artifactContent(artifactName)",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.artifactContent"))
     fun generateMessage(artifactName: String): String {
         return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
     }
 
+    @Deprecated(" Use contentFromResolvedArtifact method directly",
+            replaceWith = ReplaceWith("resolveAndGenerateMessage(artifactPrefix)",
+                    "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resolveAndGenerateMessage"))
     fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking {
         resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName,
                 artifactPrefix, mapOf())
diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ScriptComponentExtensions.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ScriptComponentExtensions.kt
new file mode 100644 (file)
index 0000000..9fc685e
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  Copyright © 2019 IBM.
+ *
+ *  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.restconf.executor
+
+/**
+ * Register the Restconf module exposed dependency
+ */
+
+
+/**
+ * Generic Mount function
+ */
+
+
+/**
+ * Generic Configure function
+ */
+
+
+/**
+ * Generic Unmount function
+ */
\ No newline at end of file
index 19e482a..efefe02 100644 (file)
@@ -16,7 +16,9 @@
 
 package org.onap.ccsdk.cds.blueprintsprocessor.db
 
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties
+import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.BluePrintDBLibPropertySevice
 import org.springframework.boot.context.properties.EnableConfigurationProperties
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.ComponentScan
@@ -34,8 +36,18 @@ open class BluePrintDBLibConfiguration(private var bluePrintProperties: BluePrin
     }
 }
 
+/**
+ * Exposed Dependency Service by this SSH Lib Module
+ */
+//TODO("right now not wired with name ")
+fun BluePrintDependencyService.dbLibPropertyService(): BluePrintDBLibPropertySevice =
+        instance(DBLibConstants.SERVICE_BLUEPRINT_DB_LIB_PROPERTY)
+
+
 class DBLibConstants {
     companion object {
+        //TODO("right now not wired with name ")
+        const val SERVICE_BLUEPRINT_DB_LIB_PROPERTY = "blueprint-db-lib-property-service"
         const val PREFIX_DB_PRIMARY: String = "blueprintsprocessor.db.primary"
 
         //list of database
index 452dd0f..3e1f071 100755 (executable)
@@ -45,11 +45,6 @@ class BlueprintProcessorCatalogServiceImpl(bluePrintRuntimeValidatorService: Blu
 
     private val log = LoggerFactory.getLogger(BlueprintProcessorCatalogServiceImpl::class.toString())
 
-    init {
-
-        log.info("BlueprintProcessorCatalogServiceImpl initialized")
-    }
-
     override suspend fun delete(name: String, version: String) {
         // Cleaning Deployed Blueprint
         deleteNBDir(bluePrintPathConfiguration.blueprintDeployPath, name, version)
index 52ac346..008e924 100644 (file)
@@ -16,6 +16,7 @@
 
 package org.onap.ccsdk.cds.blueprintsprocessor.message.service
 
+import org.apache.commons.lang.builder.ToStringBuilder
 import org.apache.kafka.clients.producer.ProducerConfig.*
 import org.apache.kafka.common.serialization.StringSerializer
 import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageProducerProperties
@@ -27,7 +28,6 @@ import org.springframework.kafka.core.ProducerFactory
 import org.springframework.kafka.support.SendResult
 import org.springframework.util.concurrent.ListenableFutureCallback
 
-
 class KafkaBasicAuthMessageProducerService(
         private val messageProducerProperties: KafkaBasicAuthMessageProducerProperties)
     : BlueprintMessageProducerService {
@@ -64,9 +64,8 @@ class KafkaBasicAuthMessageProducerService(
         return true
     }
 
-
     private fun producerFactory(additionalConfig: Map<String, Any>? = null): ProducerFactory<String, Any> {
-        log.info("Client Properties : $messageProducerProperties")
+        log.info("Client Properties : ${ToStringBuilder.reflectionToString(messageProducerProperties)}")
         val configProps = hashMapOf<String, Any>()
         configProps[BOOTSTRAP_SERVERS_CONFIG] = messageProducerProperties.bootstrapServers
         configProps[KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java
index 5f1ae7d..1cb66b8 100644 (file)
 package org.onap.ccsdk.cds.blueprintsprocessor.core
 
 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintPathConfiguration
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
+import org.slf4j.LoggerFactory
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.context.properties.bind.Bindable
 import org.springframework.boot.context.properties.bind.Binder
 import org.springframework.boot.context.properties.source.ConfigurationPropertySources
+import org.springframework.context.ApplicationContext
+import org.springframework.context.ApplicationContextAware
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
 import org.springframework.core.env.Environment
 import org.springframework.stereotype.Service
 
-
 @Configuration
 open class BluePrintCoreConfiguration(private val bluePrintProperties: BlueprintProcessorProperties) {
 
@@ -59,4 +62,17 @@ open class BlueprintProcessorProperties(private var bluePrintPropertyBinder: Bin
     fun <T> propertyBeanType(prefix: String, type: Class<T>): T {
         return bluePrintPropertyBinder.bind(prefix, Bindable.of(type)).get()
     }
+}
+
+@Configuration
+// Add Conditional property , If we try to manage on Application level
+open class BlueprintDependencyConfiguration : ApplicationContextAware {
+
+    private val log = LoggerFactory.getLogger(BlueprintDependencyConfiguration::class.java)!!
+
+    override fun setApplicationContext(applicationContext: ApplicationContext) {
+        BluePrintDependencyService.inject(applicationContext)
+        log.info("Dependency Management module created...")
+    }
+
 }
\ No newline at end of file
index c2698c0..c45ebc1 100644 (file)
@@ -30,24 +30,32 @@ import java.util.*
  */
 
 open class ExecutionServiceInput {
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Headers providing request context.")
     lateinit var commonHeader: CommonHeader
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Provide information about the action to execute.")
     lateinit var actionIdentifiers: ActionIdentifiers
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true,
+        value = "Contain the information to be passed as input to the action." +
+                "The payload is constituted of two section: the workflow input which is the higher level block (xxx-request)" +
+                " and the input for resource resolution located within the xxx-request block, contained within xxx-properties")
     lateinit var payload: ObjectNode
+    @get:ApiModelProperty(hidden = true)
     var stepData: StepData? = null
 }
 
 open class ExecutionServiceOutput {
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Headers providing request context.")
     lateinit var commonHeader: CommonHeader
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Provide information about the action to execute.")
     lateinit var actionIdentifiers: ActionIdentifiers
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Status of the request.")
     lateinit var status: Status
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true,
+        value = "Contain the information to be passed as input to the action." +
+                "The payload is constituted of two section: the workflow input which is the higher level block (xxx-request)" +
+                " and the input for resource resolution located within the xxx-request block, contained within xxx-properties")
     lateinit var payload: ObjectNode
+    @get:ApiModelProperty(hidden = true)
     var stepData: StepData? = null
 }
 
@@ -55,53 +63,56 @@ const val ACTION_MODE_ASYNC = "async"
 const val ACTION_MODE_SYNC = "sync"
 
 open class ActionIdentifiers {
-    @get:ApiModelProperty(required = false)
+    @get:ApiModelProperty(required = false, value = "Name of the CBA.")
     lateinit var blueprintName: String
-    @get:ApiModelProperty(required = false)
+    @get:ApiModelProperty(required = false, value = "Version of the CBA.")
     lateinit var blueprintVersion: String
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Name of the workflow to execute.")
     lateinit var actionName: String
-    @get:ApiModelProperty(required = true, allowableValues = "sync, async")
+    @get:ApiModelProperty(required = true,
+        value = "Async processing is only supported for gRPC client.",
+        allowableValues = "sync, async")
     lateinit var mode: String
 }
 
 open class CommonHeader {
-    @get:ApiModelProperty(required = true, example = "2012-04-23T18:25:43.511Z")
+    @get:ApiModelProperty(required = true, value = "Date of the execution", example = "2012-04-23T18:25:43.511Z")
     @get:JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
     var timestamp: Date = Date()
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Identify the system/person triggering the request.")
     lateinit var originatorId: String
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Uniquely identify a request.")
     lateinit var requestId: String
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Allow for fine-grain request identifier")
     lateinit var subRequestId: String
-    @get:ApiModelProperty(required = false)
+    @get:ApiModelProperty(required = false, hidden = true)
     var flags: Flags? = null
 }
 
 open class Flags {
+    @get:ApiModelProperty(value = "Whether or not to force the action.")
     var isForce: Boolean = false
     @get:ApiModelProperty(value = "3600")
     var ttl: Int = 3600
 }
 
 open class Status {
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "HTTP status code equivalent.")
     var code: Int = 200
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Type of the event being emitted by CDS.")
     var eventType: String = ""
-    @get:ApiModelProperty(required = true, example = "2012-04-23T18:25:43.511Z")
+    @get:ApiModelProperty(required = true,
+        value = "Time when the execution ended.",
+        example = "2012-04-23T18:25:43.511Z")
     @get:JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
     var timestamp: Date = Date()
-    @get:ApiModelProperty(required = false)
+    @get:ApiModelProperty(required = false, value = "Error message when system failed")
     var errorMessage: String? = null
-    @get:ApiModelProperty(required = true)
+    @get:ApiModelProperty(required = true, value = "Message providing request status")
     var message: String = "success"
 }
 
 open class StepData {
     lateinit var name: String
     var properties: MutableMap<String, JsonNode> = mutableMapOf()
-}
-
-
+}
\ No newline at end of file
index fa4ff23..25d1de8 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.rest
 
+import com.fasterxml.jackson.databind.JsonNode
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.springframework.boot.context.properties.EnableConfigurationProperties
 import org.springframework.context.annotation.ComponentScan
 import org.springframework.context.annotation.Configuration
@@ -27,6 +31,22 @@ import org.springframework.context.annotation.Configuration
 @EnableConfigurationProperties
 open class BluePrintRestLibConfiguration
 
+/**
+ * Exposed Dependency Service by this Rest Lib Module
+ */
+fun BluePrintDependencyService.restLibPropertyService(): BluePrintRestLibPropertyService =
+        instance(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY)
+
+
+fun BluePrintDependencyService.restClientService(selector: String): BlueprintWebClientService {
+    return restLibPropertyService().blueprintWebClientService(selector)
+}
+
+
+fun BluePrintDependencyService.restClientService(jsonNode: JsonNode): BlueprintWebClientService {
+    return restLibPropertyService().blueprintWebClientService(jsonNode)
+}
+
 
 class RestLibConstants {
     companion object {
index 48e451f..3c625a6 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.ssh
 
+import com.fasterxml.jackson.databind.JsonNode
+import org.onap.ccsdk.cds.blueprintsprocessor.ssh.service.BluePrintSshLibPropertyService
+import org.onap.ccsdk.cds.blueprintsprocessor.ssh.service.BlueprintSshClientService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService
 import org.springframework.boot.context.properties.EnableConfigurationProperties
 import org.springframework.context.annotation.ComponentScan
 import org.springframework.context.annotation.Configuration
@@ -25,6 +29,21 @@ import org.springframework.context.annotation.Configuration
 @EnableConfigurationProperties
 open class BluePrintSshLibConfiguration
 
+/**
+ * Exposed Dependency Service by this SSH Lib Module
+ */
+fun BluePrintDependencyService.sshLibPropertyService(): BluePrintSshLibPropertyService =
+        instance(SshLibConstants.SERVICE_BLUEPRINT_SSH_LIB_PROPERTY)
+
+
+fun BluePrintDependencyService.sshClientService(selector: String): BlueprintSshClientService =
+        sshLibPropertyService().blueprintSshClientService(selector)
+
+
+fun BluePrintDependencyService.sshClientService(jsonNode: JsonNode): BlueprintSshClientService =
+        sshLibPropertyService().blueprintSshClientService(jsonNode)
+
+
 class SshLibConstants {
     companion object {
         const val SERVICE_BLUEPRINT_SSH_LIB_PROPERTY = "blueprint-ssh-lib-property-service"
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceController.kt
deleted file mode 100644 (file)
index 61a9541..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright © 2018-2019 Bell Canada 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.resolutionresults.api
-
-import io.swagger.annotations.ApiOperation
-import kotlinx.coroutines.runBlocking
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.http.MediaType
-import org.springframework.http.ResponseEntity
-import org.springframework.security.access.prepost.PreAuthorize
-import org.springframework.web.bind.annotation.*
-
-/**
- * Exposes Resolution Results API to store and retrieve resource resolution results from external processes,
- * like python or ansible scripts
- *
- * @author Serge Simard
- * @version 1.0
- */
-@RestController
-@RequestMapping("/api/v1/resolution-results")
-open class ResolutionResultsServiceController {
-
-    @Autowired
-    lateinit var resolutionResultsServiceHandler: ResolutionResultsServiceHandler
-
-    @RequestMapping(path = ["/ping"], method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE])
-    @ResponseBody
-    fun ping(): String = runBlocking {
-        "Success"
-    }
-
-    @RequestMapping(path = ["/{resolution_result_id}"], method = [RequestMethod.GET], produces = [MediaType.TEXT_PLAIN_VALUE])
-    @ApiOperation(value = "Fetch a stored result by ID",
-            notes = "Loads a stored result using the resolution_result_id primary key")
-    @ResponseBody
-    @PreAuthorize("hasRole('USER')")
-    fun getStoredResultById(@PathVariable(value = "resolution_result_id") resolutionResultId: String)
-            : String = runBlocking {
-        resolutionResultsServiceHandler.loadStoredResultById(resolutionResultId)
-    }
-
-    @RequestMapping(path = ["/"], method = [RequestMethod.GET], produces = [MediaType.TEXT_PLAIN_VALUE])
-    @ApiOperation(value = "Fetch a stored result ",
-            notes = "Loads a stored result using the blueprint metadata, artifact name and resolution-key")
-    @ResponseBody
-    @PreAuthorize("hasRole('USER')")
-    fun getStoredResult(@RequestParam(value = "bpName") bpName: String,
-                        @RequestParam(value = "bpVersion") bpVersion: String,
-                        @RequestParam(value = "artifactName") artifactName: String,
-                        @RequestParam(value = "resolutionKey") resolutionKey: String,
-                        @RequestParam(value = "format", required = false, defaultValue = "text/plain") format: String)
-            : ResponseEntity<String> = runBlocking {
-
-        val payload = resolutionResultsServiceHandler.loadStoredResult(bpName, bpVersion, artifactName, resolutionKey)
-
-        var expectedContentType = format
-        if (expectedContentType.indexOf('/') < 0) {
-            expectedContentType = "application/$expectedContentType"
-        }
-        val expectedMediaType : MediaType = MediaType.valueOf(expectedContentType)
-
-        ResponseEntity.ok().contentType(expectedMediaType).body(payload)
-    }
-
-
-    @PostMapping("/{bpName}/{bpVersion}/{artifactName}/{resolutionKey}", produces = [MediaType.TEXT_PLAIN_VALUE])
-    @ApiOperation(value = "Store result ",
-            notes = "Store result under resolution-key for the specified blueprint/version/artifact.")
-    @ResponseBody
-    @PreAuthorize("hasRole('USER')")
-    fun putStoredResult(@PathVariable(value = "bpName") bpName: String,
-                      @PathVariable(value = "bpVersion") bpVersion: String,
-                      @PathVariable(value = "artifactName") artifactName: String,
-                      @PathVariable(value = "resolutionKey") resolutionKey: String,
-                      @RequestBody result : String): String? = runBlocking {
-        resolutionResultsServiceHandler.saveNewStoredResult(bpName, bpVersion, artifactName, resolutionKey, result).id
-    }
-
-
-    @DeleteMapping(path = ["/{resolution_result_id}"])
-    @ApiOperation(value = "Deletes a stored result by ID",
-            notes = "Removes a stored result, using the resolution_result_id primary key")
-    @ResponseBody
-    @PreAuthorize("hasRole('USER')")
-    fun deleteStoredResult(@PathVariable(value = "resolution_result_id") resolutionResultId: String) = runBlocking {
-        resolutionResultsServiceHandler.removeStoredResultById(resolutionResultId)
-    }
-
-}
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandler.kt
deleted file mode 100644 (file)
index 1fb34d7..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright © 2018-2019 Bell Canada 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.resolutionresults.api
-
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResult
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionResultService
-import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
-import org.springframework.stereotype.Service
-import java.util.*
-
-/**
- * Process Resolution Results API request to store and retrieve resource resolution results using database acess layer
- * ResourceResolutionResultService and corresponding entities
- *
- * @author Serge Simard
- * @version 1.0
- */
-@Service
-class ResolutionResultsServiceHandler(private val bluePrintCatalogService: BluePrintCatalogService,
-                                      private var resolutionResultService: ResourceResolutionResultService) {
-
-    suspend fun loadStoredResultById(resolutionResultId: String): String {
-
-        return resolutionResultService.readByKey(resolutionResultId)
-    }
-
-    suspend fun loadStoredResult(blueprintName : String, blueprintVersion : String, artifactTemplate: String,
-                                     resolutionKey: String): String {
-
-        val basePath = bluePrintCatalogService.getFromDatabase(blueprintName, blueprintVersion)
-        val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(UUID.randomUUID().toString(),
-                basePath.toString())
-
-        return resolutionResultService.read(blueprintRuntimeService, artifactTemplate, resolutionKey)
-    }
-
-    suspend fun saveNewStoredResult(blueprintName : String, blueprintVersion : String, artifactTemplate: String,
-                                    resolutionKey: String, result: String): ResourceResolutionResult {
-
-        val basePath = bluePrintCatalogService.getFromDatabase(blueprintName, blueprintVersion)
-        val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(UUID.randomUUID().toString(),
-                basePath.toString())
-
-        val properties = mapOf(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_KEY to resolutionKey)
-
-        val resultStored = resolutionResultService.write(properties, result, blueprintRuntimeService, artifactTemplate)
-
-        return resultStored
-    }
-
-    suspend fun removeStoredResultById(resolutionResultId: String): Unit {
-
-        return resolutionResultService.deleteByKey(resolutionResultId)
-    }
-}
\ 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/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResourceController.kt
deleted file mode 100644 (file)
index 40aa1a3..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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/resource/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt
new file mode 100644 (file)
index 0000000..3a708a9
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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.resource.api
+
+import com.fasterxml.jackson.databind.JsonNode
+import io.swagger.annotations.Api
+import io.swagger.annotations.ApiOperation
+import io.swagger.annotations.ApiParam
+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.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+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")
+@Api(value = "/api/v1/resources",
+    description = "Interaction with resolved resources.")
+open class ResourceController(private var resourceResolutionDBService: ResourceResolutionDBService) {
+
+    @RequestMapping(path = ["/health-check"],
+        method = [RequestMethod.GET],
+        produces = [MediaType.APPLICATION_JSON_VALUE])
+    @ResponseBody
+    @ApiOperation(value = "Health Check", hidden = true)
+    fun resourceControllerHealthCheck(): JsonNode = runBlocking {
+        JacksonUtils.getJsonNode("Success")
+    }
+
+    @RequestMapping(path = [""],
+        method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE])
+    @ApiOperation(value = "Get all resolved resources using the resolution key. ",
+        notes = "Retrieve all stored resolved resources using the blueprint name, blueprint version, " +
+                "artifact name and the resolution-key.",
+        response = ResourceResolution::class,
+        responseContainer = "List",
+        produces = MediaType.APPLICATION_JSON_VALUE)
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun getAllFromResolutionKeyOrFromResourceTypeAndId(
+        @ApiParam(value = "Name of the CBA.", required = true)
+        @RequestParam(value = "bpName", required = true) bpName: String,
+        @ApiParam(value = "Version of the CBA.", required = true)
+        @RequestParam(value = "bpVersion", required = true) bpVersion: String,
+        @ApiParam(value = "Artifact name for which to retrieve a resolved resource.", required = true)
+        @RequestParam(value = "artifactName", required = false, defaultValue = "") artifactName: String,
+        @ApiParam(value = "Resolution Key associated with the resolution.", required = false)
+        @RequestParam(value = "resolutionKey", required = false, defaultValue = "") resolutionKey: String,
+        @ApiParam(value = "Resource Type associated with the resolution.", required = false)
+        @RequestParam(value = "resourceType", required = false, defaultValue = "") resourceType: String,
+        @ApiParam(value = "Resource Id associated with the resolution.", required = false)
+        @RequestParam(value = "resourceId", required = false, defaultValue = "") resourceId: String)
+            : ResponseEntity<List<ResourceResolution>> = runBlocking {
+
+        if ((resolutionKey.isNotEmpty() || artifactName.isNotEmpty()) && (resourceId.isNotEmpty() || resourceType.isNotEmpty())) {
+            throw ResolutionException("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 ResolutionException("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(@ApiParam(value = "Name of the CBA.", required = true)
+                                @RequestParam(value = "bpName", required = true) bpName: String,
+                                @ApiParam(value = "Version of the CBA.", required = true)
+                                @RequestParam(value = "bpVersion", required = true) bpVersion: String,
+                                @ApiParam(value = "Artifact name for which to retrieve a resolved resource.", required = true)
+                                @RequestParam(value = "artifactName", required = true) artifactName: String,
+                                @ApiParam(value = "Resolution Key associated with the resolution.", required = true)
+                                @RequestParam(value = "resolutionKey", required = true) resolutionKey: String,
+                                @ApiParam(value = "Name of the resource to retrieve.", required = true)
+                                @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
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2018-2019 Bell Canada Intellectual Property.
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api
+package org.onap.ccsdk.cds.blueprintsprocessor.resource.api
 
 import com.fasterxml.jackson.annotation.JsonFormat
 import com.fasterxml.jackson.annotation.JsonInclude
@@ -27,6 +27,7 @@ import org.springframework.http.HttpStatus
 import org.springframework.http.ResponseEntity
 import org.springframework.orm.jpa.JpaObjectRetrievalFailureException
 import org.springframework.dao.EmptyResultDataAccessException
+import org.springframework.dao.IncorrectResultSizeDataAccessException
 import org.springframework.web.server.ServerWebInputException
 import org.springframework.web.bind.annotation.ExceptionHandler
 import org.springframework.web.bind.annotation.RestControllerAdvice
@@ -34,61 +35,65 @@ import java.io.Serializable
 import java.util.*
 
 /**
- * Handle exceptions in Resolution Results API and provide relevant HTTP status codes and messages
+ * Handle exceptions in Resolution API and provide relevant HTTP status codes and messages
  *
  * @author Serge Simard
  * @version 1.0
  */
-@RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults")
-open class ResolutionResultsServiceExceptionHandler {
+@RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.resource.api")
+open class ResourceExceptionHandler {
 
-    private val log = LoggerFactory.getLogger(ResolutionResultsServiceExceptionHandler::class.toString())
+    private val log = LoggerFactory.getLogger(ExceptionHandler::class.toString())
 
-    private val debugMsg = "ResolutionResultsService_Error_Message"
+    private val debugMsg = "Resolution_Service_Error_Message"
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> {
-        log.error(e.message, e)
+    fun resolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> {
         val errorCode = ErrorCode.BLUEPRINT_PATH_MISSING
-        val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg)
-        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode))
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> {
-        log.error(e.message, e)
+    fun resolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> {
         val errorCode = ErrorCode.INVALID_REQUEST_FORMAT
-        val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg)
-        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode))
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> {
-        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))
+    fun resolutionResultsServiceExceptionHandler(e: IncorrectResultSizeDataAccessException): ResponseEntity<ErrorMessage> {
+        val errorCode = ErrorCode.DUPLICATE_DATA
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorMessage> {
-        log.error(e.message, e)
+    fun resolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> {
+        val errorCode = ErrorCode.RESOURCE_NOT_FOUND
+        return returnError(e, errorCode)
+    }
 
-        var errorCode = ErrorCode.RESOURCE_NOT_FOUND
-        val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg)
-        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode))
+    @ExceptionHandler
+    fun resolutionResultsServiceExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorMessage> {
+        val errorCode = ErrorCode.RESOURCE_NOT_FOUND
+        return returnError(e, errorCode)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> {
+    fun resolutionResultsServiceExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> {
+        val errorCode = ErrorCode.GENERIC_FAILURE
+        return returnError(e, errorCode)
+    }
+
+    fun returnError(e: Exception, errorCode: ErrorCode): ResponseEntity<ErrorMessage> {
         log.error(e.message, e)
-        var errorCode = ErrorCode.GENERIC_FAILURE
-        val errorMessage = ErrorMessage(errorCode.message(e.message!!), errorCode.value, debugMsg)
-        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode))
+        val errorMessage =
+            ErrorMessage(errorCode.message(e.message!!),
+                errorCode.value,
+                debugMsg)
+        return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)!!)
     }
 
     @ExceptionHandler
-    fun ResolutionResultsServiceExceptionHandler(e: ResourceException): ResponseEntity<ErrorMessage> {
+    fun ResolutionResultsServiceExceptionHandler(e: ResolutionException): ResponseEntity<ErrorMessage> {
         log.error(e.message, e)
         return ResponseEntity(ErrorMessage(e.message, e.code, debugMsg), HttpStatus.resolve(e.code))
     }
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt
new file mode 100644 (file)
index 0000000..de5843a
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 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.resource.api
+
+import com.fasterxml.jackson.databind.JsonNode
+import io.swagger.annotations.Api
+import io.swagger.annotations.ApiOperation
+import io.swagger.annotations.ApiParam
+import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolution
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.springframework.dao.EmptyResultDataAccessException
+import org.springframework.http.MediaType
+import org.springframework.http.ResponseEntity
+import org.springframework.security.access.prepost.PreAuthorize
+import org.springframework.web.bind.annotation.*
+
+/**
+ * Exposes Template Resolution API to store and retrieve rendered template results.
+ *
+ * @author Serge Simard
+ * @version 1.0
+ */
+@RestController
+@RequestMapping("/api/v1/template")
+@Api(value = "/api/v1/template",
+    description = "Interaction with resolved template.")
+open class TemplateController(private val templateResolutionService: TemplateResolutionService) {
+
+    @RequestMapping(path = ["/health-check"],
+        method = [RequestMethod.GET],
+        produces = [MediaType.APPLICATION_JSON_VALUE])
+    @ResponseBody
+    @ApiOperation(value = "Health Check", hidden = true)
+    fun templateControllerHealthCheck(): JsonNode = runBlocking {
+        JacksonUtils.getJsonNode("Success")
+    }
+
+    @RequestMapping(path = [""],
+        method = [RequestMethod.GET],
+        produces = [MediaType.TEXT_PLAIN_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE])
+    @ApiOperation(value = "Retrieve a resolved template.",
+        notes = "Retrieve a config template for a given CBA's action, identified by its blueprint name, blueprint version, " +
+                "artifact name and resolution key. An extra 'format' parameter can be passed to tell what content-type" +
+                " to expect in return")
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun get(
+        @ApiParam(value = "Name of the CBA.", required = true)
+        @RequestParam(value = "bpName") bpName: String,
+        @ApiParam(value = "Version of the CBA.", required = true)
+        @RequestParam(value = "bpVersion") bpVersion: String,
+        @ApiParam(value = "Artifact name for which to retrieve a resolved resource.", required = true)
+        @RequestParam(value = "artifactName") artifactName: String,
+        @ApiParam(value = "Resolution Key associated with the resolution.", required = false)
+        @RequestParam(value = "resolutionKey") resolutionKey: String,
+        @ApiParam(value = "Resource Type associated with the resolution.", required = false)
+        @RequestParam(value = "resourceType", required = false, defaultValue = "") resourceType: String,
+        @ApiParam(value = "Resource Id associated with the resolution.", required = false)
+        @RequestParam(value = "resourceId", required = false, defaultValue = "") resourceId: String,
+        @ApiParam(value = "Expected format of the template being retrieved.",
+            defaultValue = MediaType.TEXT_PLAIN_VALUE,
+            required = true)
+        @RequestParam(value = "format", required = false, defaultValue = MediaType.TEXT_PLAIN_VALUE) format: String)
+            : ResponseEntity<String> = runBlocking {
+
+        var result = ""
+
+        if ((resolutionKey.isNotEmpty() || artifactName.isNotEmpty()) && (resourceId.isNotEmpty() || resourceType.isNotEmpty())) {
+            throw ResolutionException("Either retrieve resolved template using artifact name and resolution-key OR using resource-id and resource-type.")
+        } else if (resolutionKey.isNotEmpty() && artifactName.isNotEmpty()) {
+            result = templateResolutionService.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName(
+                bpName,
+                bpVersion,
+                artifactName,
+                resolutionKey)
+        } else if (resourceType.isNotEmpty() && resourceId.isNotEmpty()) {
+            result =
+                templateResolutionService.findByResoureIdAndResourceTypeAndBlueprintNameAndBlueprintVersionAndArtifactName(
+                    bpName,
+                    bpVersion,
+                    artifactName,
+                    resourceId,
+                    resourceType)
+        } else {
+            throw ResolutionException("Missing param. Either retrieve resolved template using artifact name and resolution-key OR using resource-id and resource-type.")
+        }
+
+
+        var expectedContentType = format
+        if (expectedContentType.indexOf('/') < 0) {
+            expectedContentType = "application/$expectedContentType"
+        }
+        val expectedMediaType: MediaType = MediaType.valueOf(expectedContentType)
+
+        ResponseEntity.ok().contentType(expectedMediaType).body(result)
+    }
+
+
+    @PostMapping("/{bpName}/{bpVersion}/{artifactName}/{resolutionKey}", produces = [MediaType.APPLICATION_JSON_VALUE])
+    @ApiOperation(value = "Store a resolved template w/ resolution-key",
+        notes = "Store a template for a given CBA's action, identified by its blueprint name, blueprint version, " +
+                "artifact name and resolution key.",
+        response = TemplateResolution::class,
+        produces = MediaType.APPLICATION_JSON_VALUE)
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun postWithResolutionKey(
+        @ApiParam(value = "Name of the CBA.", required = true)
+        @PathVariable(value = "bpName") bpName: String,
+        @ApiParam(value = "Version of the CBA.", required = true)
+        @PathVariable(value = "bpVersion") bpVersion: String,
+        @ApiParam(value = "Artifact name for which to retrieve a resolved resource.", required = true)
+        @PathVariable(value = "artifactName") artifactName: String,
+        @ApiParam(value = "Resolution Key associated with the resolution.", required = true)
+        @PathVariable(value = "resolutionKey") resolutionKey: String,
+        @ApiParam(value = "Template to store.", required = true)
+        @RequestBody result: String): ResponseEntity<TemplateResolution> = runBlocking {
+
+        val resultStored =
+            templateResolutionService.write(bpName, bpVersion, artifactName, result, resolutionKey = resolutionKey)
+
+        ResponseEntity.ok().body(resultStored)
+    }
+
+    @PostMapping("/{bpName}/{bpVersion}/{artifactName}/{resourceType}/{resourceId}",
+        produces = [MediaType.APPLICATION_JSON_VALUE])
+    @ApiOperation(value = "Store a resolved template w/ resourceId and resourceType",
+        notes = "Store a template for a given CBA's action, identified by its blueprint name, blueprint version, " +
+                "artifact name, resourceId and resourceType.",
+        response = TemplateResolution::class,
+        produces = MediaType.APPLICATION_JSON_VALUE)
+    @ResponseBody
+    @PreAuthorize("hasRole('USER')")
+    fun postWithResourceIdAndResourceType(
+        @ApiParam(value = "Name of the CBA.", required = true)
+        @PathVariable(value = "bpName") bpName: String,
+        @ApiParam(value = "Version of the CBA.", required = true)
+        @PathVariable(value = "bpVersion") bpVersion: String,
+        @ApiParam(value = "Artifact name for which to retrieve a resolved resource.", required = true)
+        @PathVariable(value = "artifactName") artifactName: String,
+        @ApiParam(value = "Resource Type associated with the resolution.", required = false)
+        @PathVariable(value = "resourceType", required = true) resourceType: String,
+        @ApiParam(value = "Resource Id associated with the resolution.", required = false)
+        @PathVariable(value = "resourceId", required = true) resourceId: String,
+        @ApiParam(value = "Template to store.", required = true)
+        @RequestBody result: String): ResponseEntity<TemplateResolution> = runBlocking {
+
+        val resultStored =
+            templateResolutionService.write(bpName, bpVersion, artifactName, result, resourceId = resourceId, resourceType = resourceType)
+
+        ResponseEntity.ok().body(resultStored)
+    }
+}
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resolutionresults/api/ResolutionResultsServiceHandlerTest.kt
deleted file mode 100644 (file)
index 813c900..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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 kotlinx.coroutines.runBlocking
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration
-import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir
-import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
-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.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.io.File
-import java.nio.file.Paths
-import java.util.*
-import kotlin.test.AfterTest
-import kotlin.test.BeforeTest
-import kotlin.test.assertTrue
-
-@RunWith(SpringRunner::class)
-@WebFluxTest
-@ContextConfiguration(classes = [ResolutionResultsServiceHandler::class, BluePrintCoreConfiguration::class,
-    BluePrintCatalogService::class, SecurityProperties::class])
-@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
-@TestPropertySource(locations = ["classpath:application-test.properties"])
-class ResolutionResultsServiceHandlerTest {
-
-    private val log = LoggerFactory.getLogger(ResolutionResultsServiceHandlerTest::class.toString())
-
-    @Autowired
-    lateinit var blueprintCatalog: BluePrintCatalogService
-    @Autowired
-    lateinit var webTestClient: WebTestClient
-
-    var resolutionKey = "7cafa9f3-bbc8-49ec-8f25-fcaa6ac3ff08"
-    val blueprintName =  "baseconfiguration"
-    val blueprintVersion = "1.0.0"
-    val templatePrefix = "activate"
-    val payloadDummyTemplateData = "PAYLOAD DATA"
-
-    @BeforeTest
-    fun init() {
-        runBlocking {
-            deleteDir("target", "blueprints")
-            blueprintCatalog.saveToDatabase(UUID.randomUUID().toString(), loadTestCbaFile())
-        }
-    }
-
-    @AfterTest
-    fun cleanDir() {
-        deleteDir("target", "blueprints")
-    }
-
-    @Test
-    fun `ping return Success`() {
-        runBlocking {
-
-            webTestClient.get().uri("/api/v1/resolution-results/ping")
-                    .exchange()
-                        .expectStatus().isOk
-                        .expectBody().equals("Success")
-        }
-    }
-
-    @Test
-    fun `store-retrieve-delete result by path or UUID`() {
-        runBlocking {
-            createRetrieveDelete()
-        }
-    }
-
-    @Test
-    fun `get returns requested JSON content-type`() {
-        runBlocking {
-            createRetrieveDelete("json")
-        }
-    }
-
-    @Test
-    fun `get returns requested XML content-type`() {
-        runBlocking {
-            createRetrieveDelete("xml")
-        }
-    }
-
-    private fun createRetrieveDelete(expectedType : String? = null): WebTestClient.ResponseSpec {
-        var uuid = "MISSING"
-
-        // Store new result for blueprint/artifact/resolutionkey
-        webTestClient
-                .post()
-                .uri("/api/v1/resolution-results/$blueprintName/$blueprintVersion/$templatePrefix/$resolutionKey/")
-                .body(BodyInserters.fromObject(payloadDummyTemplateData))
-                .exchange()
-                .expectStatus().is2xxSuccessful
-                .expectBody()
-                .consumeWith {
-                    uuid = String(it.responseBody)
-                    log.info("Stored result under UUID $uuid")
-                }
-        // Retrieve same payload
-        var requestArguments = "bpName=$blueprintName&bpVersion=$blueprintVersion" +
-                "&artifactName=$templatePrefix&resolutionKey=$resolutionKey"
-        if (expectedType != null) {
-            requestArguments = "$requestArguments&format=$expectedType"
-            webTestClient
-                    .get()
-                    .uri("/api/v1/resolution-results/?$requestArguments")
-                    .exchange()
-                    .expectStatus().is2xxSuccessful
-                    .expectHeader().contentType(MediaType.valueOf("application/$expectedType"))
-                    .expectBody().equals(payloadDummyTemplateData)
-        } else {
-            webTestClient
-                    .get()
-                    .uri("/api/v1/resolution-results/?$requestArguments")
-                    .exchange()
-                    .expectStatus().is2xxSuccessful
-                    .expectHeader().contentType(MediaType.TEXT_PLAIN)
-                    .expectBody().equals(payloadDummyTemplateData)
-        }
-        // And delete by UUID
-        return webTestClient
-                .delete()
-                .uri("/api/v1/resolution-results/$uuid/")
-                .exchange()
-                .expectStatus().is2xxSuccessful
-    }
-
-    /*
-     * Error cases
-     */
-    @Test
-    fun `get returns 400 error if missing arg`() {
-        runBlocking {
-            val arguments = "bpBADName=$blueprintName" +
-                    "&bpBADVersion=$blueprintVersion" +
-                    "&artifactName=$templatePrefix" +
-                    "&resolutionKey=$resolutionKey"
-
-            webTestClient.get().uri("/api/v1/resolution-results/?$arguments")
-                    .exchange()
-                        .expectStatus().isBadRequest
-        }
-    }
-
-    @Test
-    fun `get returns 503 error if Blueprint not found`() {
-        runBlocking {
-            val arguments = "bpName=BAD_BP_NAME" +
-                    "&bpVersion=BAD_BP_VERSION" +
-                    "&artifactName=$templatePrefix" +
-                    "&resolutionKey=$resolutionKey"
-
-            webTestClient.get().uri("/api/v1/resolution-results/?$arguments")
-                    .exchange()
-                    .expectStatus().isEqualTo(HttpStatus.SERVICE_UNAVAILABLE)
-        }
-    }
-
-    @Test
-    fun `get returns 404 if entry not found`() {
-        runBlocking {
-
-            webTestClient
-                    .get()
-                    .uri("/api/v1/resolution-results/?bpName=$blueprintName&bpVersion=$blueprintVersion" +
-                            "&artifactName=$templatePrefix&resolutionKey=$resolutionKey")
-                    .exchange()
-                    .expectStatus().isNotFound
-        }
-    }
-
-    @Test
-    fun `get returns 404 if UUID not found`() {
-        runBlocking {
-
-            webTestClient
-                    .get()
-                    .uri("/api/v1/resolution-results/234234234234/")
-                    .exchange()
-                    .expectStatus().isNotFound
-        }
-    }
-
-    private fun loadTestCbaFile(): File {
-        val testCbaFile = Paths.get("./src/test/resources/test-cba.zip").toFile()
-        assertTrue(testCbaFile.exists(), "couldn't get file ${testCbaFile.absolutePath}")
-        return testCbaFile
-    }
-}
\ No newline at end of file
  * limitations under the License.
  */
 
-package org.onap.ccsdk.cds.blueprintsprocessor.resolutionresults.api
+package org.onap.ccsdk.cds.blueprintsprocessor.resource.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
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 
 
 @RunWith(SpringRunner::class)
@@ -75,7 +59,7 @@ class ResourceControllerTest {
     @Test
     fun `ping return Success`() {
         runBlocking {
-            webTestClient.get().uri("/api/v1/resources/ping")
+            webTestClient.get().uri("/api/v1/resources/health-check")
                 .exchange()
                 .expectStatus().isOk
                 .expectBody()
@@ -231,7 +215,7 @@ class ResourceControllerTest {
         resourceAssignment.dictionaryName = "dd$prefix"
         resourceAssignment.dictionarySource = "source$prefix"
         resourceAssignment.version = 2
-        resourceAssignment.status = "SUCCESS"
+        resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS
         resourceAssignment.property = property
         return resourceAssignment
     }
diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt
new file mode 100644 (file)
index 0000000..c3a718e
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * 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.resource.api
+
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration
+import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir
+import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
+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.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 kotlin.test.AfterTest
+
+@RunWith(SpringRunner::class)
+@WebFluxTest
+@ContextConfiguration(classes = [BluePrintCoreConfiguration::class,
+    BluePrintCatalogService::class, SecurityProperties::class])
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
+@TestPropertySource(locations = ["classpath:application-test.properties"])
+class TemplateControllerTest {
+
+    private val log = LoggerFactory.getLogger(TemplateControllerTest::class.toString())
+
+    @Autowired
+    lateinit var webTestClient: WebTestClient
+
+    var resolutionKey = "7cafa9f3-bbc8-49ec-8f25-fcaa6ac3ff08"
+    val blueprintName = "baseconfiguration"
+    val blueprintVersion = "1.0.0"
+    val templatePrefix = "activate"
+    val payloadDummyTemplateData = "PAYLOAD DATA"
+
+    var requestArguments = "bpName=$blueprintName&bpVersion=$blueprintVersion" +
+            "&artifactName=$templatePrefix&resolutionKey=$resolutionKey"
+
+    @AfterTest
+    fun cleanDir() {
+        deleteDir("target", "blueprints")
+    }
+
+    @Test
+    fun `ping return Success`() {
+        runBlocking {
+            webTestClient.get().uri("/api/v1/template/health-check")
+                .exchange()
+                .expectStatus().isOk
+                .expectBody()
+                .equals("Success")
+        }
+    }
+
+    @Test
+    fun `store same value and tries to retrieve - duplicate entry execption`() {
+        runBlocking {
+
+            resolutionKey = "1"
+
+            post(resolutionKey)
+            post(resolutionKey)
+
+            webTestClient
+                .get()
+                .uri("/api/v1/template?$requestArguments")
+                .exchange()
+                .expectStatus().is4xxClientError
+                .expectBody().equals(payloadDummyTemplateData)
+        }
+    }
+
+    @Test
+    fun `get returns requested JSON content-type`() {
+        runBlocking {
+            resolutionKey = "2"
+            post(resolutionKey)
+            get("json", resolutionKey)
+        }
+    }
+
+    @Test
+    fun `get returns requested XML content-type`() {
+        runBlocking {
+            resolutionKey = "3"
+            post(resolutionKey)
+            get("xml", resolutionKey)
+        }
+    }
+
+    @Test
+    fun `get returns 400 error if missing arg`() {
+        runBlocking {
+            val arguments = "bpBADName=$blueprintName" +
+                    "&bpBADVersion=$blueprintVersion" +
+                    "&artifactName=$templatePrefix" +
+                    "&resolutionKey=$resolutionKey"
+
+            webTestClient.get().uri("/api/v1/template?$arguments")
+                .exchange()
+                .expectStatus().isBadRequest
+        }
+    }
+
+    @Test
+    fun `get returns 404 if entry not found`() {
+        runBlocking {
+
+            webTestClient
+                .get()
+                .uri("/api/v1/template?bpName=$blueprintName&bpVersion=$blueprintVersion" +
+                        "&artifactName=$templatePrefix&resolutionKey=notFound")
+                .exchange()
+                .expectStatus().isNotFound
+        }
+    }
+
+    private fun post(resKey: String) {
+        webTestClient
+            .post()
+            .uri("/api/v1/template/$blueprintName/$blueprintVersion/$templatePrefix/$resKey")
+            .body(BodyInserters.fromObject(payloadDummyTemplateData))
+            .exchange()
+            .expectStatus().is2xxSuccessful
+            .expectBody()
+            .consumeWith {
+                log.info("Stored result under UUID ${it.responseBody}")
+            }
+    }
+
+    private fun get(expectedType: String, resKey: String) {
+        var requestArguments = "bpName=$blueprintName&bpVersion=$blueprintVersion" +
+                "&artifactName=$templatePrefix&resolutionKey=$resKey"
+
+        if (expectedType.isNotEmpty()) {
+            requestArguments = "$requestArguments&format=$expectedType"
+            webTestClient
+                .get()
+                .uri("/api/v1/template?$requestArguments")
+                .exchange()
+                .expectStatus().is2xxSuccessful
+                .expectHeader().contentType(MediaType.valueOf("application/$expectedType"))
+                .expectBody().equals(payloadDummyTemplateData)
+        } else {
+            webTestClient
+                .get()
+                .uri("/api/v1/template?$requestArguments")
+                .exchange()
+                .expectStatus().is2xxSuccessful
+                .expectHeader().contentType(MediaType.TEXT_PLAIN)
+                .expectBody().equals(payloadDummyTemplateData)
+        }
+    }
+}
\ No newline at end of file
index 340f2c6..89ad720 100755 (executable)
@@ -42,6 +42,7 @@
             <artifactId>proto-definition</artifactId>
             <version>${project.version}</version>
         </dependency>
+
         <dependency>
             <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
             <artifactId>blueprint-core</artifactId>
             <artifactId>h2</artifactId>
             <scope>test</scope>
         </dependency>
+
+        <!-- For Message libraries -->
+        <dependency>
+            <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
+            <artifactId>message-lib</artifactId>
+        </dependency>
+
+        <!-- For spring-kafka -->
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Apache Kafka -->
+        <dependency>
+            <groupId>org.apache.kafka</groupId>
+            <artifactId>kafka_2.11</artifactId>
+            <version>${kafka.version}</version>
+        </dependency>
     </dependencies>
 
 </project>
index eff9773..60016fb 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api
 
+import com.fasterxml.jackson.databind.JsonNode
+import io.swagger.annotations.Api
 import io.swagger.annotations.ApiOperation
+import io.swagger.annotations.ApiParam
 import kotlinx.coroutines.runBlocking
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ACTION_MODE_ASYNC
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput
 import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.utils.determineHttpStatusCode
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.http.HttpStatus
 import org.springframework.http.MediaType
 import org.springframework.http.ResponseEntity
 import org.springframework.http.codec.multipart.FilePart
@@ -34,43 +36,59 @@ import org.springframework.web.bind.annotation.*
 
 @RestController
 @RequestMapping("/api/v1/execution-service")
+@Api(value = "/api/v1/execution-service",
+    description = "Interaction with CBA.")
 open class ExecutionServiceController {
 
     @Autowired
     lateinit var executionServiceHandler: ExecutionServiceHandler
 
-    @RequestMapping(path = ["/ping"], method = [RequestMethod.GET], produces = [MediaType.APPLICATION_JSON_VALUE])
+    @RequestMapping(path = ["/health-check"],
+        method = [RequestMethod.GET],
+        produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
-    fun ping(): String = runBlocking {
-        "Success"
+    @ApiOperation(value = "Health Check", hidden = true)
+    fun executionServiceControllerHealthCheck(): JsonNode = runBlocking {
+        JacksonUtils.getJsonNode("Success")
     }
 
     @PostMapping(path = ["/upload"], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
-    @ApiOperation(value = "Upload CBA", notes = "Takes a File and load it in the runtime database")
     @ResponseBody
     @PreAuthorize("hasRole('USER')")
-    fun upload(@RequestPart("file") filePart: FilePart): String = runBlocking {
-        executionServiceHandler.upload(filePart)
+    @ApiOperation(value = "Upload a CBA",
+        notes = "Upload the CBA package. This will also run validation on the CBA.",
+        produces = MediaType.APPLICATION_JSON_VALUE)
+    fun upload(@ApiParam(value = "The ZIP file containing the overall CBA package.", required = true)
+               @RequestPart("file") filePart: FilePart): JsonNode = runBlocking {
+        JacksonUtils.getJsonNode(executionServiceHandler.upload(filePart))
     }
 
     @DeleteMapping("/name/{name}/version/{version}")
-    @Throws(BluePrintException::class)
+    @ApiOperation(value = "Delete a CBA",
+        notes = "Delete the CBA package identified by its name and version.",
+        produces = MediaType.APPLICATION_JSON_VALUE)
     @PreAuthorize("hasRole('USER')")
-    fun deleteBlueprint(@PathVariable(value = "name") name: String,
+    fun deleteBlueprint(@ApiParam(value = "Name of the CBA.", required = true)
+                        @PathVariable(value = "name") name: String,
+                        @ApiParam(value = "Version of the CBA.", required = true)
                         @PathVariable(value = "version") version: String) = runBlocking {
         executionServiceHandler.remove(name, version)
     }
 
     @RequestMapping(path = ["/process"], method = [RequestMethod.POST], produces = [MediaType.APPLICATION_JSON_VALUE])
-    @ApiOperation(value = "Resolve Resource Mappings",
-            notes = "Takes the blueprint information and process as per the payload")
+    @ApiOperation(value = "Execute a CBA workflow (action)",
+        notes = "Execute the appropriate CBA's action based on the ExecutionServiceInput object passed as input.",
+        produces = MediaType.APPLICATION_JSON_VALUE,
+        response = ExecutionServiceOutput::class)
     @ResponseBody
     @PreAuthorize("hasRole('USER')")
-    fun process(@RequestBody executionServiceInput: ExecutionServiceInput): ResponseEntity<ExecutionServiceOutput> = runBlocking {
-        if (executionServiceInput.actionIdentifiers.mode == ACTION_MODE_ASYNC) {
-            throw IllegalStateException("Can't process async request through the REST endpoint. Use gRPC for async processing.")
+    fun process(@ApiParam(value = "ExecutionServiceInput payload.", required = true)
+                @RequestBody executionServiceInput: ExecutionServiceInput): ResponseEntity<ExecutionServiceOutput> =
+        runBlocking {
+            if (executionServiceInput.actionIdentifiers.mode == ACTION_MODE_ASYNC) {
+                throw IllegalStateException("Can't process async request through the REST endpoint. Use gRPC for async processing.")
+            }
+            val processResult = executionServiceHandler.doProcess(executionServiceInput)
+            ResponseEntity(processResult, determineHttpStatusCode(processResult.status.code))
         }
-        val processResult = executionServiceHandler.doProcess(executionServiceInput)
-        ResponseEntity(processResult, determineHttpStatusCode(processResult.status.code))
-    }
 }
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingConfig.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingConfig.kt
new file mode 100644 (file)
index 0000000..a04a799
--- /dev/null
@@ -0,0 +1,47 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api
+
+import org.apache.kafka.clients.CommonClientConfigs
+import org.apache.kafka.clients.consumer.ConsumerConfig
+import org.apache.kafka.common.serialization.StringDeserializer
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.kafka.annotation.EnableKafka
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory
+import org.springframework.kafka.core.ConsumerFactory
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory
+import org.springframework.kafka.support.serializer.JsonDeserializer
+
+@Configuration
+open class MessagingConfig {
+
+    @Value("\${blueprintsprocessor.messageclient.self-service-api.groupId}")
+    lateinit var groupId: String
+
+    @Value("\${blueprintsprocessor.messageclient.self-service-api.bootstrapServers}")
+    lateinit var bootstrapServers: String
+
+    open fun consumerFactory(): ConsumerFactory<String, ExecutionServiceInput>? {
+        val configProperties = hashMapOf<String, Any>()
+        configProperties[CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers
+        configProperties[ConsumerConfig.GROUP_ID_CONFIG] = groupId
+        configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java.name
+        configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = JsonDeserializer::class.java.name
+        configProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest")
+
+        return DefaultKafkaConsumerFactory(configProperties, StringDeserializer(), JsonDeserializer(ExecutionServiceInput::class.java))
+    }
+
+    /**
+     *  Creation of a Kafka MessageListener Container
+     *
+     *  @return KafkaListener instance.
+     */
+    @Bean
+    open fun kafkaListenerContainerFactory(): ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput> {
+        val factory = ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput>()
+        factory.consumerFactory = consumerFactory()
+        return factory
+    }
+}
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingController.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingController.kt
new file mode 100644 (file)
index 0000000..1d219a8
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.selfservice.api
+
+import kotlinx.coroutines.async
+import kotlinx.coroutines.runBlocking
+import org.apache.commons.lang3.builder.ToStringBuilder
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BluePrintMessageLibPropertyService
+import org.slf4j.LoggerFactory
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
+import org.springframework.kafka.annotation.KafkaListener
+import org.springframework.stereotype.Service
+
+@ConditionalOnProperty(name = ["blueprintsprocessor.messageclient.self-service-api.kafkaEnable"], havingValue = "true")
+@Service
+open class MessagingController(private val propertyService: BluePrintMessageLibPropertyService,
+                               private val executionServiceHandler: ExecutionServiceHandler) {
+
+    private val log = LoggerFactory.getLogger(MessagingController::class.java)!!
+
+    companion object {
+        // TODO PREFIX should be retrieved from model or from request.
+        const val PREFIX = "self-service-api"
+        const val EXECUTION_STATUS = 200
+    }
+
+    @KafkaListener(topics = ["\${blueprintsprocessor.messageclient.self-service-api.consumerTopic}"])
+    open fun receive(input: ExecutionServiceInput) {
+
+        log.info("Successfully received a message: {}", ToStringBuilder.reflectionToString(input))
+
+        runBlocking {
+            log.info("Successfully received a message: {}", ToStringBuilder.reflectionToString(input))
+
+            // Process the message.
+            async {
+                processMessage(input)
+            }
+        }
+    }
+
+    private suspend fun processMessage(executionServiceInput: ExecutionServiceInput) {
+
+        val executionServiceOutput = executionServiceHandler.doProcess(executionServiceInput)
+
+       if (executionServiceOutput.status.code == EXECUTION_STATUS) {
+           val bluePrintMessageClientService = propertyService
+                   .blueprintMessageClientService(PREFIX)
+
+           val payload = executionServiceOutput.payload
+
+           log.info("The payload to publish is {}", payload)
+
+            bluePrintMessageClientService.sendMessage(payload)
+       }
+        else {
+           log.error("Fail to process the given event due to {}", executionServiceOutput.status.errorMessage)
+       }
+    }
+}
index fd764d7..e084c60 100644 (file)
@@ -23,6 +23,8 @@ import io.grpc.testing.GrpcServerRule
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.messaginglib.MessagingControllerTest
+import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.messaginglib.ProducerConfiguration
 import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader
 import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir
 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
@@ -33,6 +35,7 @@ import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.annotation.FilterType
 import org.springframework.test.annotation.DirtiesContext
 import org.springframework.test.context.TestPropertySource
 import org.springframework.test.context.junit4.SpringRunner
@@ -44,7 +47,9 @@ import kotlin.test.assertTrue
 @RunWith(SpringRunner::class)
 @EnableAutoConfiguration
 @DirtiesContext
-@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"],
+        excludeFilters = [ComponentScan.Filter(value = [MessagingConfig::class, MessagingController::class, ProducerConfiguration::class,
+            MessagingControllerTest.ConsumerConfiguration::class, MessagingControllerTest::class], type = FilterType.ASSIGNABLE_TYPE)])
 @TestPropertySource(locations = ["classpath:application-test.properties"])
 class BluePrintManagementGRPCHandlerTest {
 
index f8b972e..5072b3c 100644 (file)
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.annotation.FilterType
 import org.springframework.test.annotation.DirtiesContext
 import org.springframework.test.context.TestPropertySource
 import org.springframework.test.context.junit4.SpringRunner
@@ -45,7 +46,8 @@ import kotlin.test.BeforeTest
 @RunWith(SpringRunner::class)
 @DirtiesContext
 @EnableAutoConfiguration
-@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"],
+        excludeFilters =arrayOf(ComponentScan.Filter(value = [(MessagingController::class)], type = FilterType.ASSIGNABLE_TYPE)))
 @TestPropertySource(locations = ["classpath:application-test.properties"])
 class BluePrintProcessingGRPCHandlerTest {
     private val log = LoggerFactory.getLogger(BluePrintProcessingGRPCHandlerTest::class.java)
index 9cbd898..65b4126 100644 (file)
@@ -30,6 +30,7 @@ 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.context.annotation.FilterType
 import org.springframework.core.io.ByteArrayResource
 import org.springframework.http.client.MultipartBodyBuilder
 import org.springframework.test.context.ContextConfiguration
@@ -49,7 +50,8 @@ import kotlin.test.assertTrue
 @RunWith(SpringRunner::class)
 @WebFluxTest
 @ContextConfiguration(classes = [ExecutionServiceHandler::class, BluePrintCoreConfiguration::class, BluePrintCatalogService::class, SecurityProperties::class])
-@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"],
+        excludeFilters =arrayOf(ComponentScan.Filter(value = [(MessagingController::class)], type = FilterType.ASSIGNABLE_TYPE)))
 @TestPropertySource(locations = ["classpath:application-test.properties"])
 class ExecutionServiceHandlerTest {
 
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/MessagingControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/MessagingControllerTest.kt
new file mode 100644 (file)
index 0000000..f7459f5
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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.selfservice.api.messaginglib
+
+import com.fasterxml.jackson.databind.node.ObjectNode
+import kotlinx.coroutines.reactive.awaitSingle
+import kotlinx.coroutines.runBlocking
+import org.apache.commons.lang.builder.ToStringBuilder
+import org.apache.kafka.clients.CommonClientConfigs
+import org.apache.kafka.clients.consumer.ConsumerConfig
+import org.apache.kafka.common.serialization.StringDeserializer
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
+import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.MessagingController
+import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.autoconfigure.security.SecurityProperties
+import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.annotation.Configuration
+import org.springframework.core.io.ByteArrayResource
+import org.springframework.http.client.MultipartBodyBuilder
+import org.springframework.kafka.annotation.EnableKafka
+import org.springframework.kafka.annotation.KafkaListener
+import org.springframework.kafka.annotation.PartitionOffset
+import org.springframework.kafka.annotation.TopicPartition
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory
+import org.springframework.kafka.core.ConsumerFactory
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory
+import org.springframework.kafka.core.KafkaTemplate
+import org.springframework.kafka.support.serializer.JsonDeserializer
+import org.springframework.kafka.test.context.EmbeddedKafka
+import org.springframework.test.annotation.DirtiesContext
+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.test.web.reactive.server.returnResult
+import org.springframework.web.reactive.function.BodyInserters
+import java.io.File
+import java.nio.file.Files
+import java.nio.file.Paths
+import kotlin.test.assertNotNull
+
+@RunWith(SpringRunner::class)
+@EnableAutoConfiguration
+@ContextConfiguration(classes = [MessagingControllerTest::class, SecurityProperties::class])
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"])
+@TestPropertySource(locations = ["classpath:application-test.properties"])
+@DirtiesContext
+@EmbeddedKafka(ports = [9092])
+@WebFluxTest
+class MessagingControllerTest {
+
+    private val log = LoggerFactory.getLogger(MessagingControllerTest::class.java)!!
+
+    @Autowired
+    lateinit var controller: MessagingController
+
+    @Value("\${blueprintsprocessor.messageclient.self-service-api.consumerTopic}")
+    lateinit var topicUsedForConsumer: String
+
+    @Autowired
+    lateinit var kt: KafkaTemplate<String, ExecutionServiceInput>
+
+    @Autowired
+    lateinit var webTestClient: WebTestClient
+
+    var receivedEvent: String? = null
+
+    @Before
+    fun setup() {
+        deleteDir("target", "blueprints")
+        uploadBluePrint()
+    }
+
+    @After
+    fun clean() {
+        deleteDir("target", "blueprints")
+    }
+
+    @Test
+    fun testReceive() {
+        val samplePayload = "{\n" +
+                "    \"resource-assignment-request\": {\n" +
+                "      \"artifact-name\": [\"hostname\"],\n" +
+                "      \"store-result\": true,\n" +
+                "      \"resource-assignment-properties\" : {\n" +
+                "        \"hostname\": \"demo123\"\n" +
+                "      }\n" +
+                "    }\n" +
+                "  }"
+
+        kt.defaultTopic = topicUsedForConsumer
+
+        val input = ExecutionServiceInput().apply {
+            commonHeader = CommonHeader().apply {
+                originatorId = "1"
+                requestId = "1234"
+                subRequestId = "1234-1234"
+            }
+
+            actionIdentifiers = ActionIdentifiers().apply {
+                blueprintName = "golden"
+                blueprintVersion = "1.0.0"
+                actionName = "resource-assignment"
+                mode = "sync"
+            }
+
+            stepData = StepData().apply {
+                name = "resource-assignment"
+            }
+
+            payload = JacksonUtils.jsonNode(samplePayload) as ObjectNode
+        }
+
+        kt.sendDefault(input)
+        log.info("test-sender sent message='{}'", ToStringBuilder.reflectionToString(input))
+
+        Thread.sleep(1000)
+    }
+
+    @KafkaListener(topicPartitions = [TopicPartition(topic = "\${blueprintsprocessor.messageclient.self-service-api.topic}", partitionOffsets = [PartitionOffset(partition = "0", initialOffset = "0")])])
+    fun receivedEventFromBluePrintProducer(event: ExecutionServiceInput) {
+        assertNotNull(event)
+    }
+
+    private fun uploadBluePrint() {
+        runBlocking {
+            val body = MultipartBodyBuilder().apply {
+                part("file", object : ByteArrayResource(Files.readAllBytes(loadCbaArchive().toPath())) {
+                    override fun getFilename(): String {
+                        return "test-cba.zip"
+                    }
+                })
+            }.build()
+
+            webTestClient
+                    .post()
+                    .uri("/api/v1/execution-service/upload")
+                    .body(BodyInserters.fromMultipartData(body))
+                    .exchange()
+                    .expectStatus().isOk
+                    .returnResult<String>()
+                    .responseBody
+                    .awaitSingle()
+        }
+    }
+
+    private fun loadCbaArchive():File {
+        return Paths.get("./src/test/resources/cba-for-kafka-integration.zip").toFile()
+    }
+
+    @Configuration
+    @EnableKafka
+    open class ConsumerConfiguration {
+
+        @Value("\${blueprintsprocessor.messageclient.self-service-api.bootstrapServers}")
+        lateinit var bootstrapServers: String
+
+        @Value("\${blueprintsprocessor.messageclient.self-service-api.groupId}")
+        lateinit var groupId:String
+
+        @Bean
+        open fun consumerFactory2(): ConsumerFactory<String, ExecutionServiceInput>? {
+            val configProperties = hashMapOf<String, Any>()
+            configProperties[CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers
+            configProperties[ConsumerConfig.GROUP_ID_CONFIG] = groupId
+            configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java.name
+            configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = JsonDeserializer::class.java.name
+            configProperties[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = "earliest"
+            configProperties[ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG] = 1000
+
+            return DefaultKafkaConsumerFactory(configProperties, StringDeserializer(),
+                    JsonDeserializer(ExecutionServiceInput::class.java))
+        }
+
+        @Bean
+        open fun listenerFactory(): ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput> {
+            val factory = ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput>()
+            factory.consumerFactory = consumerFactory2()
+            return factory
+        }
+    }
+}
+
+
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/ProducerConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/ProducerConfiguration.kt
new file mode 100644 (file)
index 0000000..dc1f38a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.selfservice.api.messaginglib
+
+import org.apache.kafka.clients.producer.ProducerConfig
+import org.apache.kafka.common.serialization.StringSerializer
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.kafka.annotation.EnableKafka
+import org.springframework.kafka.core.DefaultKafkaProducerFactory
+import org.springframework.kafka.core.KafkaTemplate
+import org.springframework.kafka.core.ProducerFactory
+import org.springframework.kafka.support.serializer.JsonSerializer
+
+@Configuration
+open class ProducerConfiguration {
+
+    @Value("\${blueprintsprocessor.messageclient.self-service-api.bootstrapServers}")
+    lateinit var bootstrapServers: String
+
+    open fun kpf(): ProducerFactory<String, ExecutionServiceInput> {
+        val configs = HashMap<String, Any>()
+        configs[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers
+        configs[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java
+        configs[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = JsonSerializer::class.java
+        return DefaultKafkaProducerFactory(configs)
+    }
+
+    @Bean
+    open fun kt(): KafkaTemplate<String, ExecutionServiceInput> {
+        return KafkaTemplate<String, ExecutionServiceInput>(kpf())
+    }
+}
\ No newline at end of file
index 6705523..d532b15 100644 (file)
@@ -31,3 +31,12 @@ blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive
 # Python executor
 blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints
 blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints
+
+# Kafka-message-lib Configuration
+blueprintsprocessor.messageclient.self-service-api.kafkaEnable=true
+blueprintsprocessor.messageclient.self-service-api.topic=producer.t
+blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t
+blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration.zip b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration.zip
new file mode 100644 (file)
index 0000000..2307038
Binary files /dev/null and b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration.zip differ
index 23588d2..408bb58 100644 (file)
@@ -27,6 +27,7 @@ import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType
 import org.onap.ccsdk.cds.controllerblueprints.core.*
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintFunctionNode
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService
 import org.slf4j.LoggerFactory
 
 /**
@@ -146,4 +147,19 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic
         bluePrintRuntimeService.getBluePrintError().addError(error)
     }
 
+    fun artifactContent(artifactName: String): String {
+        return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName)
+    }
+
+    suspend fun mashTemplateNData(artifactName: String, json: String): String {
+        val content = artifactContent(artifactName)
+        return BluePrintVelocityTemplateService.generateContent(content, json)
+    }
+
+    suspend fun readLinesFromArtifact(artifactName: String): List<String> {
+        val artifactDefinition = bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName)
+        val file = normalizedFile(bluePrintRuntimeService.bluePrintContext().rootPath, artifactDefinition.file)
+        return file.readNBLines()
+    }
+
 }
\ No newline at end of file
index 27cde8a..f17085e 100644 (file)
@@ -36,11 +36,13 @@ abstract class AbstractScriptComponentFunction : AbstractComponentFunction() {
     /**
      * Store Dynamic Script Dependency Instances, Objects present inside won't be persisted or state maintained.
      */
+    @Deprecated("Dependencies will be resolved dynamically")
     var functionDependencyInstances: MutableMap<String, Any> = hashMapOf()
 
     /**
      * This will be called from the scripts to serve instance from runtime to scripts.
      */
+    @Deprecated("Dependencies will be resolved dynamically")
     open fun <T> functionDependencyInstanceAsType(name: String): T {
         return functionDependencyInstances[name] as? T
                 ?: throw BluePrintProcessorException("couldn't get script property instance ($name)")
diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt
new file mode 100644 (file)
index 0000000..056f7e9
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *  Copyright © 2019 IBM.
+ *
+ *  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.services.execution
+
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeType
+import org.onap.ccsdk.cds.controllerblueprints.core.dsl.nodeType
+import org.onap.ccsdk.cds.controllerblueprints.core.getAsString
+import org.springframework.beans.factory.config.ConfigurableBeanFactory
+import org.springframework.context.annotation.Scope
+import org.springframework.stereotype.Component
+
+/**
+ * This is generic Script Component Executor function
+ * @author Brinda Santh
+ */
+@Component("component-script-executor")
+@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+open class ComponentScriptExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService)
+    : AbstractComponentFunction() {
+
+    companion object {
+        const val SCRIPT_TYPE = "script-type"
+        const val SCRIPT_CLASS_REFERENCE = "script-class-reference"
+        const val DYNAMIC_PROPERTIES = "dynamic-properties"
+        const val RESPONSE_DATA = "response-data"
+        const val STATUS = "status"
+    }
+
+    lateinit var scriptComponentFunction: AbstractScriptComponentFunction
+
+    override suspend fun processNB(executionRequest: ExecutionServiceInput) {
+
+        val scriptType = operationInputs.getAsString(SCRIPT_TYPE)
+        val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE)
+
+        val scriptDependencies: MutableList<String> = arrayListOf()
+        populateScriptDependencies(scriptDependencies)
+
+        scriptComponentFunction = componentFunctionScriptingService.scriptInstance(this, scriptType,
+                scriptClassReference, scriptDependencies)
+
+        // Handles both script processing and error handling
+        scriptComponentFunction.executeScript(executionServiceInput)
+    }
+
+    override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
+        bluePrintRuntimeService.getBluePrintError()
+                .addError("Failed in ComponentCliExecutor : ${runtimeException.message}")
+
+    }
+
+    open fun populateScriptDependencies(scriptDependencies: MutableList<String>) {
+        /** Place holder for Child to add extra dependencies */
+    }
+}
+
+/** Component Extensions **/
+
+fun BluePrintTypes.componentScriptExecutor(): NodeType {
+    return nodeType(id = "component-script-executor", version = BluePrintConstants.DEFAULT_VERSION_NUMBER,
+            derivedFrom = BluePrintConstants.MODEL_TYPE_NODES_ROOT,
+            description = "Generic Script Component Executor") {
+        attribute(ComponentScriptExecutor.RESPONSE_DATA, BluePrintConstants.DATA_TYPE_JSON, false)
+        attribute(ComponentScriptExecutor.STATUS, BluePrintConstants.DATA_TYPE_STRING, true)
+
+        operation("ComponentScriptExecutor", "ComponentScriptExecutor Operation") {
+            inputs {
+                property(ComponentScriptExecutor.SCRIPT_TYPE, BluePrintConstants.DATA_TYPE_STRING, true,
+                        "Script Type") {
+                    defaultValue(BluePrintConstants.SCRIPT_INTERNAL)
+                    constrains {
+                        validValues(listOf(BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive(),
+                                BluePrintConstants.SCRIPT_JYTHON.asJsonPrimitive(),
+                                BluePrintConstants.SCRIPT_KOTLIN.asJsonPrimitive()))
+                    }
+                }
+                property(ComponentScriptExecutor.SCRIPT_CLASS_REFERENCE, BluePrintConstants.DATA_TYPE_STRING,
+                        true, "Kotlin Script class name or jython script name.")
+                property(ComponentScriptExecutor.DYNAMIC_PROPERTIES, BluePrintConstants.DATA_TYPE_JSON, false,
+                        "Dynamic Json Content or DSL Json reference.")
+            }
+            outputs {
+                property(ComponentScriptExecutor.RESPONSE_DATA, BluePrintConstants.DATA_TYPE_JSON, false,
+                        "Output Response")
+                property(ComponentScriptExecutor.STATUS, BluePrintConstants.DATA_TYPE_STRING, true,
+                        "Status of the Component Execution ( success or failure )")
+            }
+        }
+    }
+}
\ No newline at end of file
index b404fbe..224319c 100644 (file)
@@ -34,7 +34,9 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInpu
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
+import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.componentScriptExecutor
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
@@ -53,7 +55,7 @@ import kotlin.test.assertNotNull
  */
 @RunWith(SpringRunner::class)
 @ContextConfiguration(classes = [ComponentFunctionScriptingService::class,
-    BluePrintScriptsServiceImpl::class,PythonExecutorProperty::class,
+    BluePrintScriptsServiceImpl::class, PythonExecutorProperty::class,
     BlueprintJythonService::class])
 class AbstractComponentFunctionTest {
 
@@ -183,5 +185,10 @@ class AbstractComponentFunctionTest {
         return executionServiceInput
     }
 
+    @Test
+    fun testComponentScriptExecutorNodeType() {
+        val componentScriptExecutor = BluePrintTypes.componentScriptExecutor()
+        assertNotNull(componentScriptExecutor.interfaces, "failed to get interface operations")
+    }
 }
 
index 82c2e61..686be49 100755 (executable)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright © 2017-2018 AT&T Intellectual Property.
-  ~
-  ~  Modifications Copyright © 2018 - 2019 IBM, Bell Canada
+  ~  Copyright © 2017-2019 AT&T, 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.
@@ -16,7 +14,8 @@
   ~  See the License for the specific language governing permissions and
   ~  limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
@@ -45,7 +44,9 @@
         <sli.version>${ccsdk.sli.core.version}</sli.version>
         <guava.version>27.0.1-jre</guava.version>
         <jython.version>2.7.1</jython.version>
-        <springfox.swagger2.version>2.9.2</springfox.swagger2.version>
+        <!--        Should be using released artifact as soon as available:-->
+        <!--        https://github.com/springfox/springfox/milestone/44-->
+        <springfox.swagger2.version>3.0.0-SNAPSHOT</springfox.swagger2.version>
         <h2database.version>1.4.197</h2database.version>
         <onap.logger.slf4j>1.2.2</onap.logger.slf4j>
         <powermock.version>1.7.4</powermock.version>
                 <artifactId>springfox-swagger-ui</artifactId>
                 <version>${springfox.swagger2.version}</version>
             </dependency>
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-spring-webflux</artifactId>
+                <version>${springfox.swagger2.version}</version>
+            </dependency>
 
             <!-- Common Utils Dependencies -->
             <dependency>
                 <scope>test</scope>
             </dependency>
 
+            <!-- message-lib dependency -->
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>message-lib</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
 
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-spring-webflux</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.springfox</groupId>
             <artifactId>springfox-swagger-ui</artifactId>
         </dependency>
     </dependencies>
 
+    <repositories>
+        <repository>
+            <id>spring-libs-milestone</id>
+            <name>Spring Milestone Maven Repository</name>
+            <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
+        </repository>
+    </repositories>
+
     <build>
         <plugins>
             <plugin>
index 365c001..305c83e 100644 (file)
@@ -163,9 +163,16 @@ class CommandExecutorHandler():
     def activate_venv(self):
         self.logger.info("{} - Activate Python Virtual Environment".format(self.blueprint_id))
 
+        # Fix: The python generated activate_this.py script concatenates the env bin dir to PATH on every call
+        #      eventually this process PATH variable was so big (128Kb) that no child process could be spawn
+        #      This script will remove all duplicates; while keeping the order of the PATH folders
+        fixpathenvvar = "os.environ['PATH']=os.pathsep.join(list(dict.fromkeys(os.environ['PATH'].split(':'))))"
+
         path = "%s/bin/activate_this.py" % self.venv_home
         try:
             exec (open(path).read(), {'__file__': path})
+            exec (fixpathenvvar)
+            self.logger.info("Running with PATH : {}".format(os.environ['PATH']))
             return True
         except Exception as err:
             self.logger.info(
index 3596a0e..6266141 100644 (file)
@@ -53,5 +53,5 @@ class CommandExecutorServer(CommandExecutor_pb2_grpc.CommandExecutorServiceServi
         if not handler.execute_command(request, results):
             self.logger.info("{} - Failed to executeCommand. {}".format(blueprint_id, results))
             return utils.build_response(request, results, False)
-        self.logger.info("{} - Execute command logs: {}".format(blueprint_id, results))
+        self.logger.info("{} - Execution finished successfully.".format(blueprint_id))
         return utils.build_response(request, results)
index 79ef395..51d088e 100644 (file)
@@ -76,6 +76,11 @@ enum class ErrorCode (val value: Int, val httpCode: Int) {
         override fun message(detailMsg: String): String {
             return "Duplicated entry while saving Blueprint. Details : {$detailMsg}"
         }
+    },
+    DUPLICATE_DATA(11, 409) {
+        override fun message(detailMsg: String): String {
+            return "Duplicated data - was expecting one result, got more than one. Details : {$detailMsg}"
+        }
     };
 
     abstract fun message(detailMsg: String): String
index 07cc20e..0f01194 100644 (file)
@@ -18,6 +18,7 @@ package org.onap.ccsdk.cds.controllerblueprints.core.dsl
 
 import com.fasterxml.jackson.databind.JsonNode
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
 import org.onap.ccsdk.cds.controllerblueprints.core.data.*
 
 
@@ -266,16 +267,16 @@ class OperationDefinitionBuilder(private val id: String,
 class AttributesDefinitionBuilder {
     private val attributes: MutableMap<String, AttributeDefinition> = hashMapOf()
 
-    fun property(id: String, attribute: AttributeDefinition) {
+    fun attribute(id: String, attribute: AttributeDefinition) {
         attributes[id] = attribute
     }
 
-    fun property(id: String, type: String?, required: Boolean?, description: String?) {
+    fun attribute(id: String, type: String?, required: Boolean?, description: String?) {
         val attribute = AttributeDefinitionBuilder(id, type, required, description).build()
         attributes[id] = attribute
     }
 
-    fun property(id: String, type: String?, required: Boolean?, description: String?,
+    fun attribute(id: String, type: String?, required: Boolean?, description: String?,
                  block: AttributeDefinitionBuilder.() -> Unit) {
         val attribute = AttributeDefinitionBuilder(id, type, required, description).apply(block).build()
         attributes[id] = attribute
@@ -353,7 +354,14 @@ class PropertyDefinitionBuilder(private val id: String,
     fun entrySchema(entrySchemaType: String, block: EntrySchemaBuilder.() -> Unit) {
         propertyDefinition.entrySchema = EntrySchemaBuilder(entrySchemaType).apply(block).build()
     }
-    // TODO("Constrains")
+
+    fun constrains(block: ConstraintClauseBuilder.() -> Unit) {
+        propertyDefinition.constraints = ConstraintClauseBuilder().apply(block).build()
+    }
+
+    fun defaultValue(defaultValue: Any) {
+        defaultValue(defaultValue.asJsonType())
+    }
 
     fun defaultValue(defaultValue: JsonNode) {
         propertyDefinition.defaultValue = defaultValue
@@ -372,6 +380,22 @@ class PropertyDefinitionBuilder(private val id: String,
     }
 }
 
+class ConstraintClauseBuilder {
+    private val constraints: MutableList<ConstraintClause> = mutableListOf()
+    //TODO("Implementation")
+
+    fun validValues(values: List<JsonNode>) {
+        val constraintClause = ConstraintClause()
+        constraintClause.validValues = values.toMutableList()
+        constraints.add(constraintClause)
+    }
+
+    fun build(): MutableList<ConstraintClause> {
+        return constraints
+    }
+}
+
+
 class EntrySchemaBuilder(private val type: String) {
     private var entrySchema: EntrySchema = EntrySchema()
 
diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintDependencyService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintDependencyService.kt
new file mode 100644 (file)
index 0000000..fdaf25c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  Copyright © 2019 IBM.
+ *
+ *  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.controllerblueprints.core.service
+
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.springframework.context.ApplicationContext
+
+/**
+ * Generic Bluepring Dependency Service, which will be used mainly in scripts.
+ * This will be initialised only once during the Application startup.
+ * Function modules, shall add their own dependency function names as an extension function.
+ *
+ * @author Brinda Santh
+ */
+
+object BluePrintDependencyService {
+
+    lateinit var applicationContext: ApplicationContext
+
+    fun inject(applicationContext: ApplicationContext) {
+        BluePrintDependencyService.applicationContext = applicationContext
+    }
+
+    inline fun <reified T> instance(name: String): T {
+        return applicationContext.getBean(name) as? T
+                ?: throw BluePrintProcessorException("failed to get instance($name)")
+    }
+
+    inline fun <reified T> instance(type: Class<T>): T {
+        return applicationContext.getBean(type)
+                ?: throw BluePrintProcessorException("failed to get instance($type)")
+    }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 3ffafbe..2a227c7 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,8 @@ 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.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
     <parent>
         <groupId>org.onap.ccsdk.parent</groupId>
@@ -35,8 +36,8 @@ limitations under the License.
     <description>CCSDK Controller Design Studio</description>
 
     <modules>
-        <module>cds-ui</module>
         <module>components</module>
+        <module>cds-ui</module>
         <module>ms</module>
     </modules>
 
@@ -54,12 +55,7 @@ limitations under the License.
         <sonar.tests>src/test</sonar.tests>
         <!--Only include java and kt files to the scan-->
         <sonar.inclusions>**/*.java,**/*.kt</sonar.inclusions>
-        <!--Specify path to load jacoco XLM report, as Sonar can't load Kotlin coverage from binary report.
-        Note: coverage for now is invalid and is failing to load because of:
-        "Cannot import coverage information for file '{file}', coverage data is invalid."
-        see https://github.com/jacoco/jacoco/issues/763
-        That issue has been fixed in 0.8.3 , so we override the default ONAP
-        version here to pick up that fix -->
+        <!--Specify path to load jacoco XLM report, as Sonar can't load Kotlin coverage from binary report-->
         <sonar.coverage.jacoco.xmlReportPaths>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml
         </sonar.coverage.jacoco.xmlReportPaths>
         <jacoco.version>0.8.3</jacoco.version>